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