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 be
11// created while a the debugger is stepping in another thread.
12
13#include <pthread.h>
14#include <atomic>
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
28std::atomic_int g_barrier;
29
30volatile int g_thread_created = 0;
31volatile int g_test = 0;
32
33void *
34step_thread_func (void *input)
35{
36    g_test = 0;         // Set breakpoint here
37
38    while (!g_thread_created)
39        g_test++;
40
41    // One more time to provide a continue point
42    g_test++;           // Continue from here
43
44    // Return
45    return NULL;
46}
47
48void *
49create_thread_func (void *input)
50{
51    pthread_t *step_thread = (pthread_t*)input;
52
53    // Wait until the main thread knows this thread is started.
54    pseudo_barrier_wait(g_barrier);
55
56    // Wait until the other thread is done.
57    pthread_join(*step_thread, NULL);
58
59    // Return
60    return NULL;
61}
62
63int main ()
64{
65    pthread_t thread_1;
66    pthread_t thread_2;
67
68    // Use a simple count to simulate a barrier.
69    pseudo_barrier_init(g_barrier, 2);
70
71    // Create a thread to hit the breakpoint.
72    pthread_create (&thread_1, NULL, step_thread_func, NULL);
73
74    // Wait until the step thread is stepping
75    while (g_test < 1)
76        do_nothing();
77
78    // Create a thread to exit while we're stepping.
79    pthread_create (&thread_2, NULL, create_thread_func, &thread_1);
80
81    // Wait until that thread is started
82    pseudo_barrier_wait(g_barrier);
83
84    // Let the stepping thread know the other thread is there
85    g_thread_created = 1;
86
87    // Wait for the threads to finish.
88    pthread_join(thread_2, NULL);
89    pthread_join(thread_1, NULL);
90
91    return 0;
92}
93