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