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 // C includes 11 #include <pthread.h> 12 #include <stdio.h> 13 #include <stdint.h> 14 #include <stdlib.h> 15 #include <unistd.h> 16 17 pthread_t g_thread_1 = NULL; 18 pthread_t g_thread_2 = NULL; 19 pthread_t g_thread_3 = NULL; 20 21 typedef enum { 22 eGet, 23 eAssign, 24 eClearBits 25 } MaskAction; 26 27 uint32_t mask_access (MaskAction action, uint32_t mask = 0); 28 29 uint32_t 30 mask_access (MaskAction action, uint32_t mask) 31 { 32 static pthread_mutex_t g_mask_mutex = PTHREAD_MUTEX_INITIALIZER; 33 static uint32_t g_mask = 0; 34 ::pthread_mutex_lock (&g_mask_mutex); 35 switch (action) 36 { 37 case eGet: 38 break; 39 40 case eAssign: 41 g_mask |= mask; 42 break; 43 44 case eClearBits: 45 g_mask &= ~mask; 46 break; 47 } 48 uint32_t new_mask = g_mask; 49 ::pthread_mutex_unlock (&g_mask_mutex); 50 return new_mask; 51 } 52 53 void * 54 thread_func (void *arg) 55 { 56 uint32_t thread_index = *((uint32_t *)arg); 57 uint32_t thread_mask = (1u << (thread_index)); 58 printf ("%s (thread index = %u) startng...\n", __FUNCTION__, thread_index); 59 60 while (mask_access(eGet) & thread_mask) 61 { 62 // random micro second sleep from zero to 3 seconds 63 int usec = ::rand() % 3000000; 64 printf ("%s (thread = %u) doing a usleep (%d)...\n", __FUNCTION__, thread_index, usec); 65 ::usleep (usec); 66 printf ("%s (thread = %u) after usleep ...\n", __FUNCTION__, thread_index); // Set break point at this line. 67 } 68 printf ("%s (thread index = %u) exiting...\n", __FUNCTION__, thread_index); 69 return NULL; 70 } 71 72 73 int main (int argc, char const *argv[]) 74 { 75 int err; 76 void *thread_result = NULL; 77 uint32_t thread_index_1 = 1; 78 uint32_t thread_index_2 = 2; 79 uint32_t thread_index_3 = 3; 80 uint32_t thread_mask_1 = (1u << thread_index_1); 81 uint32_t thread_mask_2 = (1u << thread_index_2); 82 uint32_t thread_mask_3 = (1u << thread_index_3); 83 84 // Make a mask that will keep all threads alive 85 mask_access (eAssign, thread_mask_1 | thread_mask_2 | thread_mask_3); // And that line. 86 87 // Create 3 threads 88 err = ::pthread_create (&g_thread_1, NULL, thread_func, &thread_index_1); 89 err = ::pthread_create (&g_thread_2, NULL, thread_func, &thread_index_2); 90 err = ::pthread_create (&g_thread_3, NULL, thread_func, &thread_index_3); 91 92 char line[64]; 93 while (mask_access(eGet) != 0) 94 { 95 printf ("Enter thread index to kill or ENTER for all:\n"); 96 fflush (stdout); 97 // Kill threads by index, or ENTER for all threads 98 99 if (fgets (line, sizeof(line), stdin)) 100 { 101 if (line[0] == '\n' || line[0] == '\r' || line[0] == '\0') 102 { 103 printf ("Exiting all threads...\n"); 104 break; 105 } 106 int32_t index = strtoul (line, NULL, 0); 107 switch (index) 108 { 109 case 1: mask_access (eClearBits, thread_mask_1); break; 110 case 2: mask_access (eClearBits, thread_mask_2); break; 111 case 3: mask_access (eClearBits, thread_mask_3); break; 112 } 113 continue; 114 } 115 116 break; 117 } 118 119 // Clear all thread bits to they all exit 120 mask_access (eClearBits, UINT32_MAX); 121 122 // Join all of our threads 123 err = ::pthread_join (g_thread_1, &thread_result); 124 err = ::pthread_join (g_thread_2, &thread_result); 125 err = ::pthread_join (g_thread_3, &thread_result); 126 127 return 0; 128 } 129