Home | History | Annotate | Download | only in exit_during_step
      1 //===-- main.cpp ------------------------------------------------*- C++ -*-===//
      2 //
      3 //                     The LLVM Compiler Infrastructure
      4 //
      5 // This file is distributed under the University of Illinois Open Source
      6 // License. See LICENSE.TXT for details.
      7 //
      8 //===----------------------------------------------------------------------===//
      9 
     10 // This test is intended to create a situation in which one thread will exit
     11 // while a the debugger is stepping in another thread.
     12 
     13 #include <pthread.h>
     14 #include <unistd.h>
     15 
     16 // Note that although hogging the CPU while waiting for a variable to change
     17 // would be terrible in production code, it's great for testing since it
     18 // avoids a lot of messy context switching to get multiple threads synchronized.
     19 #define do_nothing()
     20 
     21 #define pseudo_barrier_wait(bar) \
     22     --bar;                       \
     23     while (bar > 0)              \
     24         do_nothing();
     25 
     26 #define pseudo_barrier_init(bar, count) (bar = count)
     27 
     28 // A barrier to synchronize thread start.
     29 volatile int g_barrier;
     30 
     31 volatile int g_thread_exited = 0;
     32 
     33 volatile int g_test = 0;
     34 
     35 void *
     36 step_thread_func (void *input)
     37 {
     38     // Wait until both threads are started.
     39     pseudo_barrier_wait(g_barrier);
     40 
     41     g_test = 0;         // Set breakpoint here
     42 
     43     while (!g_thread_exited)
     44         g_test++;
     45 
     46     // One more time to provide a continue point
     47     g_test++;           // Continue from here
     48 
     49     // Return
     50     return NULL;
     51 }
     52 
     53 void *
     54 exit_thread_func (void *input)
     55 {
     56     // Wait until both threads are started.
     57     pseudo_barrier_wait(g_barrier);
     58 
     59     // Wait until the other thread is stepping.
     60     while (g_test == 0)
     61       do_nothing();
     62 
     63     // Return
     64     return NULL;
     65 }
     66 
     67 int main ()
     68 {
     69     pthread_t thread_1;
     70     pthread_t thread_2;
     71 
     72     // Synchronize thread start so that doesn't happen during stepping.
     73     pseudo_barrier_init(g_barrier, 2);
     74 
     75     // Create a thread to hit the breakpoint.
     76     pthread_create (&thread_1, NULL, step_thread_func, NULL);
     77 
     78     // Create a thread to exit while we're stepping.
     79     pthread_create (&thread_2, NULL, exit_thread_func, NULL);
     80 
     81     // Wait for the exit thread to finish.
     82     pthread_join(thread_2, NULL);
     83 
     84     // Let the stepping thread know the other thread is gone.
     85     g_thread_exited = 1;
     86 
     87     // Wait for the stepping thread to finish.
     88     pthread_join(thread_1, NULL);
     89 
     90     return 0;
     91 }
     92