diff options
Diffstat (limited to 'lldb/test/functionalities/expr-doesnt-deadlock')
4 files changed, 82 insertions, 82 deletions
diff --git a/lldb/test/functionalities/expr-doesnt-deadlock/Makefile b/lldb/test/functionalities/expr-doesnt-deadlock/Makefile index a10791d5890..5f51b38ba13 100644 --- a/lldb/test/functionalities/expr-doesnt-deadlock/Makefile +++ b/lldb/test/functionalities/expr-doesnt-deadlock/Makefile @@ -1,6 +1,6 @@ LEVEL = ../../make -C_SOURCES := locking.c +CXX_SOURCES := locking.cpp ENABLE_THREADS := YES include $(LEVEL)/Makefile.rules diff --git a/lldb/test/functionalities/expr-doesnt-deadlock/TestExprDoesntBlock.py b/lldb/test/functionalities/expr-doesnt-deadlock/TestExprDoesntBlock.py index 3c8de16fa5a..bf317ff65ff 100644 --- a/lldb/test/functionalities/expr-doesnt-deadlock/TestExprDoesntBlock.py +++ b/lldb/test/functionalities/expr-doesnt-deadlock/TestExprDoesntBlock.py @@ -44,7 +44,7 @@ class ExprDoesntDeadlockTestCase(TestBase): # Now create a breakpoint at source line before call_me_to_get_lock gets called. - main_file_spec = lldb.SBFileSpec ("locking.c") + main_file_spec = lldb.SBFileSpec ("locking.cpp") breakpoint = target.BreakpointCreateBySourceRegex('Break here', main_file_spec) if self.TraceOn(): print "breakpoint:", breakpoint diff --git a/lldb/test/functionalities/expr-doesnt-deadlock/locking.c b/lldb/test/functionalities/expr-doesnt-deadlock/locking.c deleted file mode 100644 index fae9979611d..00000000000 --- a/lldb/test/functionalities/expr-doesnt-deadlock/locking.c +++ /dev/null @@ -1,80 +0,0 @@ -#include <pthread.h> -#include <stdlib.h> -#include <unistd.h> -#include <stdio.h> - -pthread_mutex_t contended_mutex = PTHREAD_MUTEX_INITIALIZER; - -pthread_mutex_t control_mutex = PTHREAD_MUTEX_INITIALIZER; -pthread_cond_t control_condition; - -pthread_mutex_t thread_started_mutex = PTHREAD_MUTEX_INITIALIZER; -pthread_cond_t thread_started_condition; - -// This function runs in a thread. The locking dance is to make sure that -// by the time the main thread reaches the pthread_join below, this thread -// has for sure acquired the contended_mutex. So then the call_me_to_get_lock -// function will block trying to get the mutex, and only succeed once it -// signals this thread, then lets it run to wake up from the cond_wait and -// release the mutex. - -void * -lock_acquirer_1 (void *input) -{ - pthread_mutex_lock (&contended_mutex); - - // Grab this mutex, that will ensure that the main thread - // is in its cond_wait for it (since that's when it drops the mutex. - - pthread_mutex_lock (&thread_started_mutex); - pthread_mutex_unlock(&thread_started_mutex); - - // Now signal the main thread that it can continue, we have the contended lock - // so the call to call_me_to_get_lock won't make any progress till this - // thread gets a chance to run. - - pthread_mutex_lock (&control_mutex); - - pthread_cond_signal (&thread_started_condition); - - pthread_cond_wait (&control_condition, &control_mutex); - - pthread_mutex_unlock (&contended_mutex); - return NULL; -} - -int -call_me_to_get_lock () -{ - pthread_cond_signal (&control_condition); - pthread_mutex_lock (&contended_mutex); - return 567; -} - -int main () -{ - pthread_t thread_1; - - pthread_cond_init (&control_condition, NULL); - pthread_cond_init (&thread_started_condition, NULL); - - pthread_mutex_lock (&thread_started_mutex); - - pthread_create (&thread_1, NULL, lock_acquirer_1, NULL); - - pthread_cond_wait (&thread_started_condition, &thread_started_mutex); - - pthread_mutex_lock (&control_mutex); - pthread_mutex_unlock (&control_mutex); - - // Break here. At this point the other thread will have the contended_mutex, - // and be sitting in its cond_wait for the control condition. So there is - // no way that our by-hand calling of call_me_to_get_lock will proceed - // without running the first thread at least somewhat. - - call_me_to_get_lock(); - pthread_join (thread_1, NULL); - - return 0; - -} diff --git a/lldb/test/functionalities/expr-doesnt-deadlock/locking.cpp b/lldb/test/functionalities/expr-doesnt-deadlock/locking.cpp new file mode 100644 index 00000000000..863fa832e29 --- /dev/null +++ b/lldb/test/functionalities/expr-doesnt-deadlock/locking.cpp @@ -0,0 +1,80 @@ +#include <stdlib.h> +#include <stdio.h> + +#include <condition_variable> +#include <mutex> +#include <thread> + +std::mutex contended_mutex; +std::mutex control_mutex; +std::mutex thread_started_mutex; + +std::unique_lock<std::mutex> *contended_lock = nullptr; +std::unique_lock<std::mutex> *control_lock = nullptr; +std::unique_lock<std::mutex> *thread_started_lock = nullptr; + +std::condition_variable control_condition; +std::condition_variable thread_started_condition; + +// This function runs in a thread. The locking dance is to make sure that +// by the time the main thread reaches the pthread_join below, this thread +// has for sure acquired the contended_mutex. So then the call_me_to_get_lock +// function will block trying to get the mutex, and only succeed once it +// signals this thread, then lets it run to wake up from the cond_wait and +// release the mutex. + +void * +lock_acquirer_1 () +{ + contended_lock->lock(); + + // Grab this mutex, that will ensure that the main thread + // is in its cond_wait for it (since that's when it drops the mutex. + thread_started_lock->lock(); + thread_started_lock->unlock(); + + // Now signal the main thread that it can continue, we have the contended lock + // so the call to call_me_to_get_lock won't make any progress till this + // thread gets a chance to run. + control_lock->lock(); + + thread_started_condition.notify_all(); + control_condition.wait(*control_lock); + + return NULL; +} + +int +call_me_to_get_lock () +{ + control_condition.notify_all(); + contended_lock->lock(); + return 567; +} + +int main () +{ + contended_lock = new std::unique_lock<std::mutex>(contended_mutex, std::defer_lock); + control_lock = new std::unique_lock<std::mutex>(control_mutex, std::defer_lock); + thread_started_lock = new std::unique_lock<std::mutex>(thread_started_mutex, std::defer_lock); + + thread_started_lock->lock(); + + std::thread thread_1(lock_acquirer_1); + + thread_started_condition.wait(*thread_started_lock); + + control_lock->lock(); + control_lock->unlock(); + + // Break here. At this point the other thread will have the contended_mutex, + // and be sitting in its cond_wait for the control condition. So there is + // no way that our by-hand calling of call_me_to_get_lock will proceed + // without running the first thread at least somewhat. + + call_me_to_get_lock(); + thread_1.join(); + + return 0; + +} |