diff options
author | Andrew Kaylor <andrew.kaylor@intel.com> | 2013-05-28 23:04:25 +0000 |
---|---|---|
committer | Andrew Kaylor <andrew.kaylor@intel.com> | 2013-05-28 23:04:25 +0000 |
commit | 93132f504f0d29ef1e1d90360977aa31c548d28e (patch) | |
tree | 52dec72376e6db0dc1ec0dd54325980ba61c9bab /lldb/test/functionalities/thread/break_after_join/main.cpp | |
parent | 6477e97af73a6bc036888d68b79d919f8b11cd2a (diff) | |
download | bcm5719-llvm-93132f504f0d29ef1e1d90360977aa31c548d28e.tar.gz bcm5719-llvm-93132f504f0d29ef1e1d90360977aa31c548d28e.zip |
Adding support for stopping all threads of multithreaded inferiors on Linux. Also adding multithreaded test cases.
llvm-svn: 182809
Diffstat (limited to 'lldb/test/functionalities/thread/break_after_join/main.cpp')
-rw-r--r-- | lldb/test/functionalities/thread/break_after_join/main.cpp | 125 |
1 files changed, 125 insertions, 0 deletions
diff --git a/lldb/test/functionalities/thread/break_after_join/main.cpp b/lldb/test/functionalities/thread/break_after_join/main.cpp new file mode 100644 index 00000000000..97649761e0d --- /dev/null +++ b/lldb/test/functionalities/thread/break_after_join/main.cpp @@ -0,0 +1,125 @@ +//===-- main.cpp ------------------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// This test is intended to create a situation in which one thread will exit +// while a breakpoint is being handled in another thread. This may not always +// happen because it's possible that the exiting thread will exit before the +// breakpoint is hit. The test case should be flexible enough to treat that +// as success. + +#include <pthread.h> +#include <unistd.h> +#include <atomic> + +volatile int g_test = 0; + +// Note that although hogging the CPU while waiting for a variable to change +// would be terrible in production code, it's great for testing since it +// avoids a lot of messy context switching to get multiple threads synchronized. +#define do_nothing() + +#define pseudo_barrier_wait(bar) \ + --bar; \ + while (bar > 0) \ + do_nothing(); + +#define pseudo_barrier_init(bar, count) (bar = count) + +// A barrier to synchronize all the threads. +std::atomic_int g_barrier1; + +// A barrier to keep the threads from exiting until after the breakpoint has +// been passed. +std::atomic_int g_barrier2; + +void * +break_thread_func (void *input) +{ + // Wait until all the threads are running + pseudo_barrier_wait(g_barrier1); + + // Wait for the join thread to join + usleep(50); + + // Do something + g_test++; // Set breakpoint here + + // Synchronize after the breakpoint + pseudo_barrier_wait(g_barrier2); + + // Return + return NULL; +} + +void * +wait_thread_func (void *input) +{ + // Wait until the entire first group of threads is running + pseudo_barrier_wait(g_barrier1); + + // Wait until the breakpoint has been passed + pseudo_barrier_wait(g_barrier2); + + // Return + return NULL; +} + +void * +join_thread_func (void *input) +{ + pthread_t *thread_to_join = (pthread_t*)input; + + // Sync up with the rest of the threads. + pseudo_barrier_wait(g_barrier1); + + // Join the other thread + pthread_join(*thread_to_join, NULL); + + // Return + return NULL; +} + +int main () +{ + pthread_t thread_1; + pthread_t thread_2; + pthread_t thread_3; + pthread_t thread_4; + pthread_t thread_5; + + // The first barrier waits for the non-joining threads to start. + // This thread will also participate in that barrier. + // The idea here is to guarantee that the joining thread will be + // last in the internal list maintained by the debugger. + pseudo_barrier_init(g_barrier1, 5); + + // The second barrier keeps the waiting threads around until the breakpoint + // has been passed. + pseudo_barrier_init(g_barrier2, 4); + + // Create a thread to hit the breakpoint + pthread_create (&thread_1, NULL, break_thread_func, NULL); + + // Create more threads to slow the debugger down during processing. + pthread_create (&thread_2, NULL, wait_thread_func, NULL); + pthread_create (&thread_3, NULL, wait_thread_func, NULL); + pthread_create (&thread_4, NULL, wait_thread_func, NULL); + + // Create a thread to join the breakpoint thread + pthread_create (&thread_5, NULL, join_thread_func, &thread_4); + + // Wait for the threads to finish + pthread_join(thread_5, NULL); + pthread_join(thread_4, NULL); + pthread_join(thread_3, NULL); + pthread_join(thread_2, NULL); + pthread_join(thread_1, NULL); + + return 0; +} |