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