1 #include <pthread.h>
2 #include <stdlib.h>
3 #include <unistd.h>
4 #include <stdio.h>
5
6 pthread_mutex_t contended_mutex = PTHREAD_MUTEX_INITIALIZER;
7
8 pthread_mutex_t control_mutex = PTHREAD_MUTEX_INITIALIZER;
9 pthread_cond_t control_condition;
10
11 pthread_mutex_t thread_started_mutex = PTHREAD_MUTEX_INITIALIZER;
12 pthread_cond_t thread_started_condition;
13
14 // This function runs in a thread. The locking dance is to make sure that
15 // by the time the main thread reaches the pthread_join below, this thread
16 // has for sure acquired the contended_mutex. So then the call_me_to_get_lock
17 // function will block trying to get the mutex, and only succeed once it
18 // signals this thread, then lets it run to wake up from the cond_wait and
19 // release the mutex.
20
21 void *
lock_acquirer_1(void * input)22 lock_acquirer_1 (void *input)
23 {
24 pthread_mutex_lock (&contended_mutex);
25
26 // Grab this mutex, that will ensure that the main thread
27 // is in its cond_wait for it (since that's when it drops the mutex.
28
29 pthread_mutex_lock (&thread_started_mutex);
30 pthread_mutex_unlock(&thread_started_mutex);
31
32 // Now signal the main thread that it can continue, we have the contended lock
33 // so the call to call_me_to_get_lock won't make any progress till this
34 // thread gets a chance to run.
35
36 pthread_mutex_lock (&control_mutex);
37
38 pthread_cond_signal (&thread_started_condition);
39
40 pthread_cond_wait (&control_condition, &control_mutex);
41
42 pthread_mutex_unlock (&contended_mutex);
43 return NULL;
44 }
45
46 int
call_me_to_get_lock()47 call_me_to_get_lock ()
48 {
49 pthread_cond_signal (&control_condition);
50 pthread_mutex_lock (&contended_mutex);
51 return 567;
52 }
53
main()54 int main ()
55 {
56 pthread_t thread_1;
57
58 pthread_cond_init (&control_condition, NULL);
59 pthread_cond_init (&thread_started_condition, NULL);
60
61 pthread_mutex_lock (&thread_started_mutex);
62
63 pthread_create (&thread_1, NULL, lock_acquirer_1, NULL);
64
65 pthread_cond_wait (&thread_started_condition, &thread_started_mutex);
66
67 pthread_mutex_lock (&control_mutex);
68 pthread_mutex_unlock (&control_mutex);
69
70 // Break here. At this point the other thread will have the contended_mutex,
71 // and be sitting in its cond_wait for the control condition. So there is
72 // no way that our by-hand calling of call_me_to_get_lock will proceed
73 // without running the first thread at least somewhat.
74
75 call_me_to_get_lock();
76 pthread_join (thread_1, NULL);
77
78 return 0;
79
80 }
81