33-39 If the specified thread identifier is not found in the array of suspended threads, then it is not suspended — again, return with success.
45-51 Send the resume signal, SIGUSR2. There's no need to wait — the thread will resume whenever it can, and the thread calling thd_continue doesn't need to know.
¦ susp.c part 4 thd_continue
1 /*
2 * Resume a suspended thread by sending it SIGUSR2 to break
3 * it out of the sigsuspend() in which it's waiting. If the
4 * target thread isn't suspended, return with success.
5 */
6 int
7 thd_continue (pthread_t target_thread)
8 {
9 int status;
10 int i = 0;
11
12 /*
13 * Serialize access to suspend, makes life easier.
14 */
15 status = pthread_mutex_lock (&mut);
16 if (status != 0)
17 return status;
18
19 /*
20 * If we haven't been initialized, then the thread must be
21 * 'resumed'; it couldn't have been suspended!
22 */
23 if (!inited) {
24 status = pthread_mutex_unlock (&mut);
25 return status;
26 }
27
28 /*
29 * Make sure the thread is in the suspend array. If not, it
30 * hasn't been suspended (or it has already been resumed) and
31 * we can just carry on.
32 */
33 while (array[i] != target_thread && i < bottom)
34 i++;
35
36 if (i >= bottom) {
37 pthread_mutex_unlock (&mut);
38 return 0;
39 }
40
41 /*
42 * Signal the thread to continue, and remove the thread from
43 * the suspended array.
44 */
45 status = pthread_kill (target_thread, SIGUSR2);
46 if (status != 0) {
47 pthread_mutex_unlock (&mut);
48 return status;
49 }
50
51 array[i] = 0; /* Clear array element */
52 status = pthread_mutex_unlock (&mut);
53 return status;
54 }
2-25 The thread_routine function is the thread start routine for each of the 'target' threads created by the program. It simply loops for a substantial period of time, periodically printing a status message. On each iteration, it yields to other threads to ensure that the processor time is apportioned 'fairly' across all the threads.
Notice that instead of calling printf
, the function formats a message with sprintf
and then displays it on stdout
(file descriptor 1) by calling write. This illustrates one of the problems with using suspend and resume (thd_suspend
and thd_continue
) for synchronization. Suspend and resume are scheduling functions, not synchronization functions, and using scheduling and synchronization controls together can have severe consequences.
Incautious use of suspend and resume can deadlock your application.
In this case, if a thread were suspended while modifying a
In general, you cannot suspend a thread that may possibly hold any resource, if that resource may be required by some other thread before the suspended thread is resumed. In particular, the result is a
36-42 Threads are created with an attributes object set to create threads detached, rather than joinable. The result is that threads will cease to exist as soon as they terminate, rather than remaining until main calls pthread_join
. The pthread_kill
function does not necessarily fail if you attempt to send a signal to a terminated thread (the standard is silent on this point), and you may be merely setting a pending signal in a thread that will never be able to act on it. If this were to occur, the thd_suspend
routine would hang waiting for the thread to respond. Although pthread_kill
may not fail when sending to a terminated thread, it will fail when sending to a thread that doesn't exist — so this attribute converts a possible hang, when the program is run with ITERATIONS set too low, into an abort with an error message.
51-85 The main thread sleeps for two seconds after creating the threads to allow them to reach a 'steady state.' It then loops through the first half of the threads, suspending each of them. It waits an additional two seconds and then resumes each of the threads it had suspended. It waits another two seconds, suspends each of the remaining threads (the second half), and then after another two seconds resumes them.
By watching the status messages printed by the individual threads, you can see the pattern of output change as the threads are suspended and resumed.
¦ susp.c part 5 sample program
1 static void *
2 thread_routine (void *arg)
3 {