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 is intended to create a situation in which one thread will exit
113bd2ebd670677dae45010bf53084ff85da7c6a5eAndrew Kaylor// while a the debugger is stepping in another thread.
123bd2ebd670677dae45010bf53084ff85da7c6a5eAndrew Kaylor
133bd2ebd670677dae45010bf53084ff85da7c6a5eAndrew Kaylor#include <pthread.h>
143bd2ebd670677dae45010bf53084ff85da7c6a5eAndrew Kaylor#include <unistd.h>
153bd2ebd670677dae45010bf53084ff85da7c6a5eAndrew Kaylor
163bd2ebd670677dae45010bf53084ff85da7c6a5eAndrew Kaylor// Note that although hogging the CPU while waiting for a variable to change
173bd2ebd670677dae45010bf53084ff85da7c6a5eAndrew Kaylor// would be terrible in production code, it's great for testing since it
183bd2ebd670677dae45010bf53084ff85da7c6a5eAndrew Kaylor// avoids a lot of messy context switching to get multiple threads synchronized.
193bd2ebd670677dae45010bf53084ff85da7c6a5eAndrew Kaylor#define do_nothing()
203bd2ebd670677dae45010bf53084ff85da7c6a5eAndrew Kaylor
213bd2ebd670677dae45010bf53084ff85da7c6a5eAndrew Kaylor#define pseudo_barrier_wait(bar) \
223bd2ebd670677dae45010bf53084ff85da7c6a5eAndrew Kaylor    --bar;                       \
233bd2ebd670677dae45010bf53084ff85da7c6a5eAndrew Kaylor    while (bar > 0)              \
243bd2ebd670677dae45010bf53084ff85da7c6a5eAndrew Kaylor        do_nothing();
253bd2ebd670677dae45010bf53084ff85da7c6a5eAndrew Kaylor
263bd2ebd670677dae45010bf53084ff85da7c6a5eAndrew Kaylor#define pseudo_barrier_init(bar, count) (bar = count)
273bd2ebd670677dae45010bf53084ff85da7c6a5eAndrew Kaylor
283bd2ebd670677dae45010bf53084ff85da7c6a5eAndrew Kaylor// A barrier to synchronize thread start.
293bd2ebd670677dae45010bf53084ff85da7c6a5eAndrew Kaylorvolatile int g_barrier;
303bd2ebd670677dae45010bf53084ff85da7c6a5eAndrew Kaylor
313bd2ebd670677dae45010bf53084ff85da7c6a5eAndrew Kaylorvolatile int g_thread_exited = 0;
323bd2ebd670677dae45010bf53084ff85da7c6a5eAndrew Kaylor
333bd2ebd670677dae45010bf53084ff85da7c6a5eAndrew Kaylorvolatile int g_test = 0;
343bd2ebd670677dae45010bf53084ff85da7c6a5eAndrew Kaylor
353bd2ebd670677dae45010bf53084ff85da7c6a5eAndrew Kaylorvoid *
363bd2ebd670677dae45010bf53084ff85da7c6a5eAndrew Kaylorstep_thread_func (void *input)
373bd2ebd670677dae45010bf53084ff85da7c6a5eAndrew Kaylor{
383bd2ebd670677dae45010bf53084ff85da7c6a5eAndrew Kaylor    // Wait until both threads are started.
393bd2ebd670677dae45010bf53084ff85da7c6a5eAndrew Kaylor    pseudo_barrier_wait(g_barrier);
403bd2ebd670677dae45010bf53084ff85da7c6a5eAndrew Kaylor
413bd2ebd670677dae45010bf53084ff85da7c6a5eAndrew Kaylor    g_test = 0;         // Set breakpoint here
423bd2ebd670677dae45010bf53084ff85da7c6a5eAndrew Kaylor
433bd2ebd670677dae45010bf53084ff85da7c6a5eAndrew Kaylor    while (!g_thread_exited)
443bd2ebd670677dae45010bf53084ff85da7c6a5eAndrew Kaylor        g_test++;
453bd2ebd670677dae45010bf53084ff85da7c6a5eAndrew Kaylor
463bd2ebd670677dae45010bf53084ff85da7c6a5eAndrew Kaylor    // One more time to provide a continue point
473bd2ebd670677dae45010bf53084ff85da7c6a5eAndrew Kaylor    g_test++;           // Continue from here
483bd2ebd670677dae45010bf53084ff85da7c6a5eAndrew Kaylor
493bd2ebd670677dae45010bf53084ff85da7c6a5eAndrew Kaylor    // Return
503bd2ebd670677dae45010bf53084ff85da7c6a5eAndrew Kaylor    return NULL;
513bd2ebd670677dae45010bf53084ff85da7c6a5eAndrew Kaylor}
523bd2ebd670677dae45010bf53084ff85da7c6a5eAndrew Kaylor
533bd2ebd670677dae45010bf53084ff85da7c6a5eAndrew Kaylorvoid *
543bd2ebd670677dae45010bf53084ff85da7c6a5eAndrew Kaylorexit_thread_func (void *input)
553bd2ebd670677dae45010bf53084ff85da7c6a5eAndrew Kaylor{
563bd2ebd670677dae45010bf53084ff85da7c6a5eAndrew Kaylor    // Wait until both threads are started.
573bd2ebd670677dae45010bf53084ff85da7c6a5eAndrew Kaylor    pseudo_barrier_wait(g_barrier);
583bd2ebd670677dae45010bf53084ff85da7c6a5eAndrew Kaylor
593bd2ebd670677dae45010bf53084ff85da7c6a5eAndrew Kaylor    // Wait until the other thread is stepping.
603bd2ebd670677dae45010bf53084ff85da7c6a5eAndrew Kaylor    while (g_test == 0)
613bd2ebd670677dae45010bf53084ff85da7c6a5eAndrew Kaylor      do_nothing();
623bd2ebd670677dae45010bf53084ff85da7c6a5eAndrew Kaylor
633bd2ebd670677dae45010bf53084ff85da7c6a5eAndrew Kaylor    // Return
643bd2ebd670677dae45010bf53084ff85da7c6a5eAndrew Kaylor    return NULL;
653bd2ebd670677dae45010bf53084ff85da7c6a5eAndrew Kaylor}
663bd2ebd670677dae45010bf53084ff85da7c6a5eAndrew Kaylor
673bd2ebd670677dae45010bf53084ff85da7c6a5eAndrew Kaylorint main ()
683bd2ebd670677dae45010bf53084ff85da7c6a5eAndrew Kaylor{
693bd2ebd670677dae45010bf53084ff85da7c6a5eAndrew Kaylor    pthread_t thread_1;
703bd2ebd670677dae45010bf53084ff85da7c6a5eAndrew Kaylor    pthread_t thread_2;
713bd2ebd670677dae45010bf53084ff85da7c6a5eAndrew Kaylor
723bd2ebd670677dae45010bf53084ff85da7c6a5eAndrew Kaylor    // Synchronize thread start so that doesn't happen during stepping.
733bd2ebd670677dae45010bf53084ff85da7c6a5eAndrew Kaylor    pseudo_barrier_init(g_barrier, 2);
743bd2ebd670677dae45010bf53084ff85da7c6a5eAndrew Kaylor
753bd2ebd670677dae45010bf53084ff85da7c6a5eAndrew Kaylor    // Create a thread to hit the breakpoint.
763bd2ebd670677dae45010bf53084ff85da7c6a5eAndrew Kaylor    pthread_create (&thread_1, NULL, step_thread_func, NULL);
773bd2ebd670677dae45010bf53084ff85da7c6a5eAndrew Kaylor
783bd2ebd670677dae45010bf53084ff85da7c6a5eAndrew Kaylor    // Create a thread to exit while we're stepping.
793bd2ebd670677dae45010bf53084ff85da7c6a5eAndrew Kaylor    pthread_create (&thread_2, NULL, exit_thread_func, NULL);
803bd2ebd670677dae45010bf53084ff85da7c6a5eAndrew Kaylor
813bd2ebd670677dae45010bf53084ff85da7c6a5eAndrew Kaylor    // Wait for the exit thread to finish.
823bd2ebd670677dae45010bf53084ff85da7c6a5eAndrew Kaylor    pthread_join(thread_2, NULL);
833bd2ebd670677dae45010bf53084ff85da7c6a5eAndrew Kaylor
843bd2ebd670677dae45010bf53084ff85da7c6a5eAndrew Kaylor    // Let the stepping thread know the other thread is gone.
853bd2ebd670677dae45010bf53084ff85da7c6a5eAndrew Kaylor    g_thread_exited = 1;
863bd2ebd670677dae45010bf53084ff85da7c6a5eAndrew Kaylor
873bd2ebd670677dae45010bf53084ff85da7c6a5eAndrew Kaylor    // Wait for the stepping thread to finish.
883bd2ebd670677dae45010bf53084ff85da7c6a5eAndrew Kaylor    pthread_join(thread_1, NULL);
893bd2ebd670677dae45010bf53084ff85da7c6a5eAndrew Kaylor
903bd2ebd670677dae45010bf53084ff85da7c6a5eAndrew Kaylor    return 0;
913bd2ebd670677dae45010bf53084ff85da7c6a5eAndrew Kaylor}
92