1#include <pthread.h>
2#include <stdlib.h>
3#include <unistd.h>
4#include <stdio.h>
5
6pthread_mutex_t contended_mutex = PTHREAD_MUTEX_INITIALIZER;
7
8pthread_mutex_t control_mutex = PTHREAD_MUTEX_INITIALIZER;
9pthread_cond_t  control_condition;
10
11pthread_mutex_t thread_started_mutex = PTHREAD_MUTEX_INITIALIZER;
12pthread_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
21void *
22lock_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
46int
47call_me_to_get_lock ()
48{
49  pthread_cond_signal (&control_condition);
50  pthread_mutex_lock (&contended_mutex);
51  return 567;
52}
53
54int 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