13bd2ebd670677dae45010bf53084ff85da7c6a5eAndrew Kaylor//===-- main.cpp ------------------------------------------------*- C++ -*-===//
23bd2ebd670677dae45010bf53084ff85da7c6a5eAndrew Kaylor//
33bd2ebd670677dae45010bf53084ff85da7c6a5eAndrew Kaylor//                     The LLVM Compiler Infrastructure
43bd2ebd670677dae45010bf53084ff85da7c6a5eAndrew Kaylor//
53bd2ebd670677dae45010bf53084ff85da7c6a5eAndrew Kaylor// This file is distributed under the University of Illinois Open Source
63bd2ebd670677dae45010bf53084ff85da7c6a5eAndrew Kaylor// License. See LICENSE.TXT for details.
73bd2ebd670677dae45010bf53084ff85da7c6a5eAndrew Kaylor//
83bd2ebd670677dae45010bf53084ff85da7c6a5eAndrew Kaylor//===----------------------------------------------------------------------===//
93bd2ebd670677dae45010bf53084ff85da7c6a5eAndrew Kaylor
103bd2ebd670677dae45010bf53084ff85da7c6a5eAndrew Kaylor// This test verifies the correct handling of child thread exits.
113bd2ebd670677dae45010bf53084ff85da7c6a5eAndrew Kaylor
123bd2ebd670677dae45010bf53084ff85da7c6a5eAndrew Kaylor#include <pthread.h>
133bd2ebd670677dae45010bf53084ff85da7c6a5eAndrew Kaylor#include <atomic>
143bd2ebd670677dae45010bf53084ff85da7c6a5eAndrew Kaylor
153bd2ebd670677dae45010bf53084ff85da7c6a5eAndrew Kaylor// Note that although hogging the CPU while waiting for a variable to change
163bd2ebd670677dae45010bf53084ff85da7c6a5eAndrew Kaylor// would be terrible in production code, it's great for testing since it
173bd2ebd670677dae45010bf53084ff85da7c6a5eAndrew Kaylor// avoids a lot of messy context switching to get multiple threads synchronized.
183bd2ebd670677dae45010bf53084ff85da7c6a5eAndrew Kaylor#define do_nothing()
193bd2ebd670677dae45010bf53084ff85da7c6a5eAndrew Kaylor
203bd2ebd670677dae45010bf53084ff85da7c6a5eAndrew Kaylor#define pseudo_barrier_wait(bar) \
213bd2ebd670677dae45010bf53084ff85da7c6a5eAndrew Kaylor    --bar;                       \
223bd2ebd670677dae45010bf53084ff85da7c6a5eAndrew Kaylor    while (bar > 0)              \
233bd2ebd670677dae45010bf53084ff85da7c6a5eAndrew Kaylor        do_nothing();
243bd2ebd670677dae45010bf53084ff85da7c6a5eAndrew Kaylor
253bd2ebd670677dae45010bf53084ff85da7c6a5eAndrew Kaylor#define pseudo_barrier_init(bar, count) (bar = count)
263bd2ebd670677dae45010bf53084ff85da7c6a5eAndrew Kaylor
273bd2ebd670677dae45010bf53084ff85da7c6a5eAndrew Kaylorstd::atomic_int g_barrier1;
283bd2ebd670677dae45010bf53084ff85da7c6a5eAndrew Kaylorstd::atomic_int g_barrier2;
293bd2ebd670677dae45010bf53084ff85da7c6a5eAndrew Kaylorstd::atomic_int g_barrier3;
303bd2ebd670677dae45010bf53084ff85da7c6a5eAndrew Kaylor
313bd2ebd670677dae45010bf53084ff85da7c6a5eAndrew Kaylorvoid *
323bd2ebd670677dae45010bf53084ff85da7c6a5eAndrew Kaylorthread1 (void *input)
333bd2ebd670677dae45010bf53084ff85da7c6a5eAndrew Kaylor{
343bd2ebd670677dae45010bf53084ff85da7c6a5eAndrew Kaylor    // Synchronize with the main thread.
353bd2ebd670677dae45010bf53084ff85da7c6a5eAndrew Kaylor    pseudo_barrier_wait(g_barrier1);
363bd2ebd670677dae45010bf53084ff85da7c6a5eAndrew Kaylor
373bd2ebd670677dae45010bf53084ff85da7c6a5eAndrew Kaylor    // Synchronize with the main thread and thread2.
383bd2ebd670677dae45010bf53084ff85da7c6a5eAndrew Kaylor    pseudo_barrier_wait(g_barrier2);
393bd2ebd670677dae45010bf53084ff85da7c6a5eAndrew Kaylor
403bd2ebd670677dae45010bf53084ff85da7c6a5eAndrew Kaylor    // Return
413bd2ebd670677dae45010bf53084ff85da7c6a5eAndrew Kaylor    return NULL;                                      // Set second breakpoint here
423bd2ebd670677dae45010bf53084ff85da7c6a5eAndrew Kaylor}
433bd2ebd670677dae45010bf53084ff85da7c6a5eAndrew Kaylor
443bd2ebd670677dae45010bf53084ff85da7c6a5eAndrew Kaylorvoid *
453bd2ebd670677dae45010bf53084ff85da7c6a5eAndrew Kaylorthread2 (void *input)
463bd2ebd670677dae45010bf53084ff85da7c6a5eAndrew Kaylor{
473bd2ebd670677dae45010bf53084ff85da7c6a5eAndrew Kaylor    // Synchronize with thread1 and the main thread.
483bd2ebd670677dae45010bf53084ff85da7c6a5eAndrew Kaylor    pseudo_barrier_wait(g_barrier2);
493bd2ebd670677dae45010bf53084ff85da7c6a5eAndrew Kaylor
503bd2ebd670677dae45010bf53084ff85da7c6a5eAndrew Kaylor    // Synchronize with the main thread.
513bd2ebd670677dae45010bf53084ff85da7c6a5eAndrew Kaylor    pseudo_barrier_wait(g_barrier3);
523bd2ebd670677dae45010bf53084ff85da7c6a5eAndrew Kaylor
533bd2ebd670677dae45010bf53084ff85da7c6a5eAndrew Kaylor    // Return
543bd2ebd670677dae45010bf53084ff85da7c6a5eAndrew Kaylor    return NULL;
553bd2ebd670677dae45010bf53084ff85da7c6a5eAndrew Kaylor}
563bd2ebd670677dae45010bf53084ff85da7c6a5eAndrew Kaylor
573bd2ebd670677dae45010bf53084ff85da7c6a5eAndrew Kaylorint main ()
583bd2ebd670677dae45010bf53084ff85da7c6a5eAndrew Kaylor{
593bd2ebd670677dae45010bf53084ff85da7c6a5eAndrew Kaylor    pthread_t thread_1;
603bd2ebd670677dae45010bf53084ff85da7c6a5eAndrew Kaylor    pthread_t thread_2;
613bd2ebd670677dae45010bf53084ff85da7c6a5eAndrew Kaylor    pthread_t thread_3;
623bd2ebd670677dae45010bf53084ff85da7c6a5eAndrew Kaylor
633bd2ebd670677dae45010bf53084ff85da7c6a5eAndrew Kaylor    pseudo_barrier_init(g_barrier1, 2);
643bd2ebd670677dae45010bf53084ff85da7c6a5eAndrew Kaylor    pseudo_barrier_init(g_barrier2, 3);
653bd2ebd670677dae45010bf53084ff85da7c6a5eAndrew Kaylor    pseudo_barrier_init(g_barrier3, 2);
663bd2ebd670677dae45010bf53084ff85da7c6a5eAndrew Kaylor
673bd2ebd670677dae45010bf53084ff85da7c6a5eAndrew Kaylor    // Create a thread.
683bd2ebd670677dae45010bf53084ff85da7c6a5eAndrew Kaylor    pthread_create (&thread_1, NULL, thread1, NULL);
693bd2ebd670677dae45010bf53084ff85da7c6a5eAndrew Kaylor
703bd2ebd670677dae45010bf53084ff85da7c6a5eAndrew Kaylor    // Wait for thread1 to start.
713bd2ebd670677dae45010bf53084ff85da7c6a5eAndrew Kaylor    pseudo_barrier_wait(g_barrier1);
723bd2ebd670677dae45010bf53084ff85da7c6a5eAndrew Kaylor
733bd2ebd670677dae45010bf53084ff85da7c6a5eAndrew Kaylor    // Create another thread.
743bd2ebd670677dae45010bf53084ff85da7c6a5eAndrew Kaylor    pthread_create (&thread_2, NULL, thread2, NULL);  // Set first breakpoint here
753bd2ebd670677dae45010bf53084ff85da7c6a5eAndrew Kaylor
763bd2ebd670677dae45010bf53084ff85da7c6a5eAndrew Kaylor    // Wait for thread2 to start.
773bd2ebd670677dae45010bf53084ff85da7c6a5eAndrew Kaylor    pseudo_barrier_wait(g_barrier2);
783bd2ebd670677dae45010bf53084ff85da7c6a5eAndrew Kaylor
793bd2ebd670677dae45010bf53084ff85da7c6a5eAndrew Kaylor    // Wait for the first thread to finish
803bd2ebd670677dae45010bf53084ff85da7c6a5eAndrew Kaylor    pthread_join(thread_1, NULL);
813bd2ebd670677dae45010bf53084ff85da7c6a5eAndrew Kaylor
823bd2ebd670677dae45010bf53084ff85da7c6a5eAndrew Kaylor    // Synchronize with the remaining thread
833bd2ebd670677dae45010bf53084ff85da7c6a5eAndrew Kaylor    pseudo_barrier_wait(g_barrier3);                  // Set third breakpoint here
843bd2ebd670677dae45010bf53084ff85da7c6a5eAndrew Kaylor
853bd2ebd670677dae45010bf53084ff85da7c6a5eAndrew Kaylor    // Wait for the second thread to finish
863bd2ebd670677dae45010bf53084ff85da7c6a5eAndrew Kaylor    pthread_join(thread_2, NULL);
873bd2ebd670677dae45010bf53084ff85da7c6a5eAndrew Kaylor
883bd2ebd670677dae45010bf53084ff85da7c6a5eAndrew Kaylor    return 0;                                         // Set fourth breakpoint here
893bd2ebd670677dae45010bf53084ff85da7c6a5eAndrew Kaylor}
90