blob: f0af0d110b977569ba3ce46d357b1772362f1403 [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);
Johnny Chen7ea9aee2010-10-07 21:38:28 +000068 printf ("%s (thread = %u) after usleep ...\n", __FUNCTION__, thread_index);
Chris Lattner30fdc8d2010-06-08 16:52:24 +000069 }
70 printf ("%s (thread index = %u) exiting...\n", __FUNCTION__, thread_index);
71
72}
73
74
75int main (int argc, char const *argv[])
76{
77 int err;
78 void *thread_result = NULL;
79 uint32_t thread_index_1 = 1;
80 uint32_t thread_index_2 = 2;
81 uint32_t thread_index_3 = 3;
82 uint32_t thread_mask_1 = (1u << thread_index_1);
83 uint32_t thread_mask_2 = (1u << thread_index_2);
84 uint32_t thread_mask_3 = (1u << thread_index_3);
85
86 // Make a mask that will keep all threads alive
87 mask_access (eAssign, thread_mask_1 | thread_mask_2 | thread_mask_3);
88
89 // Create 3 threads
90 err = ::pthread_create (&g_thread_1, NULL, thread_func, &thread_index_1);
91 err = ::pthread_create (&g_thread_2, NULL, thread_func, &thread_index_2);
92 err = ::pthread_create (&g_thread_3, NULL, thread_func, &thread_index_3);
93
94 char line[64];
95 while (mask_access(eGet) != 0)
96 {
97 printf ("Enter thread index to kill or ENTER for all:\n");
98 fflush (stdout);
99 // Kill threads by index, or ENTER for all threads
100
101 if (fgets (line, sizeof(line), stdin))
102 {
103 if (line[0] == '\n' || line[0] == '\r' || line[0] == '\0')
104 {
105 printf ("Exiting all threads...\n");
106 break;
107 }
108 int32_t index = strtoul (line, NULL, 0);
109 switch (index)
110 {
111 case 1: mask_access (eClearBits, thread_mask_1); break;
112 case 2: mask_access (eClearBits, thread_mask_2); break;
113 case 3: mask_access (eClearBits, thread_mask_3); break;
114 }
115 continue;
116 }
117
118 break;
119 }
120
121 // Clear all thread bits to they all exit
122 mask_access (eClearBits, UINT32_MAX);
123
124 // Join all of our threads
125 err = ::pthread_join (g_thread_1, &thread_result);
126 err = ::pthread_join (g_thread_2, &thread_result);
127 err = ::pthread_join (g_thread_3, &thread_result);
128
129 return 0;
Johnny Chen7ea9aee2010-10-07 21:38:28 +0000130}