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