sem_close()
?
(1) | _____ |
A signal is said to be pending: |
|
||
(2) | _____ |
A signal may have which of the following dispositions? |
|
||
(3) | _____ |
A function is reentrant if: |
|
||
(4) | _____ |
When a pipe/FIFO is empty: |
|
||
(5) | _____ |
sem_post() : |
|
||
(6) | _____ |
Which of the following are shared by all of the threads in a process? |
|
(1) | _____ |
Interrupt handlers can be interrupted by signals |
(2) | _____ |
Pipes/FIFOs guarantee writes (up to a certain size) are atomic |
(3) | _____ |
Threads are often preferred to processes because they are easier to use with signals |
(4) | _____ |
To avoid wasting resources, one must either call pthread_join() or pthread_detach() for every thread |
(5) | _____ |
All thread-safe functions are reentrant |
volatile int should = 0; static void sighandler(int sig) { should = 1; } int main(void) { float rate, sales, tax; int status; pid_t pid; rate = 0.05; pid = fork(); signal(SIGUSR1, sighandler); switch(pid) { case -1: exit(1); case 0: if (should_tax()) { // Add your code here } break; default: sales = total_sales(); wait(&status); if (should) tax = sales * rate; else tax = 0.0; printf("Tax: %5.2f\n", tax); break; } }
wait()
?
waitpid()
in this case?
total_sales()
is 100.00
?
should_tax()
returns "true", this program is
supposed to print Tax: 5.00
. What will be printed if
you replace the line // Add your code here
with
should = 1
? Why?
//Add your code here
with one or
more statements that will make the program work correctly.
Task 1
before
it prints Task 2
.
static void handle_continue(int sig) { // Nothing to do } int main(void) { // Setup the signal handler signal(SIGCONT, handle_continue); pid_t pid = fork(); switch(pid) { case -1: exit(1); case 0: printf("Task 1\n"); kill(getppid(), SIGCONT); exit(0); default: pause(); printf("Task 2\n"); exit(0); } }
pause()
?
pause()
return?
int main(void) { char msg[20]; int fd_pipe[2]; int n, status; pid_t pid; pipe(fd_pipe); pid = fork(); switch(pid) { case -1: exit(1); case 0: close(fd_pipe[1]); read(fd_pipe[0], msg, 20); close(fd_pipe[0]); write(STDOUT_FILENO, msg, 20); exit(0); default: close(fd_pipe[0]); write(fd_pipe[1], "Because I said so!\n\0", 20); close(fd_pipe[1]); wait(&status); exit(0); } }
close(fd_pipe[1])
before the call to read()
?
close(fd_pipe[0])
after the call to read()
?
fd_pipe
contain two elements? In
other words, what are the two elements used for?
close(fd_pipe[1])
before the parent process
executes write(fd_pipe[1], "Because I said so!\n\0", 20)
,
will the call to write()
fail? Why or why not?
int main(void) { pid_t pid = fork(); switch(pid) { case -1: exit(1); case 0: write(STDOUT_FILENO, "A1 ", 3); write(STDOUT_FILENO, "A2 ", 3); exit(0); default: write(STDOUT_FILENO, "B1 ", 3); write(STDOUT_FILENO, "B2 ", 3); exit(0); } }
static void *count(void *arg) { char *s; void *result; s = (char *)arg; result = (void *)(strlen(s)); return result; } int main(void) { char *s; int i; long len; pthread_t helper[5]; void *result; s = "James Madison University"; len = strlen(s); for (i=0; i<5; i++) { pthread_create(&helper[i], NULL, count, s+(i*2)); } for (i=0; i<5; i++) { pthread_join(helper[i], &result); len += (long)result; } printf("Characters printed: %ld\n", len); exit(0); }
pthread_detach()
rather than
pthread_join()
?
int count; static void *thread_entry(void *arg) { count += 5; return NULL; } int main(void) { pthread_t thread1; count = 10; printf("Before: %d\n", count); pthread_create(&thread1, NULL, code_for_thread1, NULL); pthread_join(thread1, NULL); printf("After: %d\n", count); exit(0); }
static volatile int global_counter = 0; static void* counter(void *arg) { int i, limit, local_counter; limit = *((int *) arg); for (i=0; i<limit; i++) { local_counter = global_counter; ++local_counter; global_counter = local_counter; } return NULL; } int main(int argc, char *argv[]) { int limit; pthread_t thread_a, thread_b; if (argc <= 1) limit = 100; else limit = atoi(argv[1]); // Start two threads counting pthread_create(&thread_a, NULL, counter, &limit); pthread_create(&thread_b, NULL, counter, &limit); // Wait for both threads to terminate pthread_join(thread_a, NULL); pthread_join(thread_b, NULL); // Display the result printf("Expected: %d\n", limit*2); printf("Actual: %d\n", global_counter); exit(0); }
but contains a defect known as a read-modify-write condition (a particular
kind of race condition). Use one or more pthread_mutex_t
variables to eliminate this defect.
static int should = -1; // Shared variable static void *thread_entry(void *arg) { if (should_tax()) should = 1; else should = 0; record_status(); // This takes a long time return NULL; } int main(void) { float rate, sales, tax; pthread_t helper; void *result; pthread_create(&helper, NULL, thread_entry, NULL); rate = 0.05; sales = total_sales(); if (should) tax = sales * rate; else tax = 0.0; printf("Tax: %5.2f\n", tax); pthread_join(helper, &result); exit(0); }
Specifically, the main thread may use the shared variable
named should
before the helper thread assigns a value to it.
pthread_mutex_t
variable and polling.
pthread_cond_t
variable.
Copyright 2017