1*99451b44SJordan Rupprecht //===-- main.cpp ------------------------------------------------*- C++ -*-===// 2*99451b44SJordan Rupprecht // 3*99451b44SJordan Rupprecht // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4*99451b44SJordan Rupprecht // See https://llvm.org/LICENSE.txt for license information. 5*99451b44SJordan Rupprecht // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6*99451b44SJordan Rupprecht // 7*99451b44SJordan Rupprecht //===----------------------------------------------------------------------===// 8*99451b44SJordan Rupprecht 9*99451b44SJordan Rupprecht // C includes 10*99451b44SJordan Rupprecht #include <stdio.h> 11*99451b44SJordan Rupprecht #include <stdint.h> 12*99451b44SJordan Rupprecht #include <stdlib.h> 13*99451b44SJordan Rupprecht 14*99451b44SJordan Rupprecht // C++ includes 15*99451b44SJordan Rupprecht #include <chrono> 16*99451b44SJordan Rupprecht #include <mutex> 17*99451b44SJordan Rupprecht #include <random> 18*99451b44SJordan Rupprecht #include <thread> 19*99451b44SJordan Rupprecht 20*99451b44SJordan Rupprecht std::thread g_thread_1; 21*99451b44SJordan Rupprecht std::thread g_thread_2; 22*99451b44SJordan Rupprecht std::thread g_thread_3; 23*99451b44SJordan Rupprecht std::mutex g_mask_mutex; 24*99451b44SJordan Rupprecht 25*99451b44SJordan Rupprecht enum MaskAction { 26*99451b44SJordan Rupprecht eGet, 27*99451b44SJordan Rupprecht eAssign, 28*99451b44SJordan Rupprecht eClearBits 29*99451b44SJordan Rupprecht }; 30*99451b44SJordan Rupprecht 31*99451b44SJordan Rupprecht uint32_t mask_access (MaskAction action, uint32_t mask = 0); 32*99451b44SJordan Rupprecht 33*99451b44SJordan Rupprecht uint32_t 34*99451b44SJordan Rupprecht mask_access (MaskAction action, uint32_t mask) 35*99451b44SJordan Rupprecht { 36*99451b44SJordan Rupprecht static uint32_t g_mask = 0; 37*99451b44SJordan Rupprecht 38*99451b44SJordan Rupprecht std::lock_guard<std::mutex> lock(g_mask_mutex); 39*99451b44SJordan Rupprecht switch (action) 40*99451b44SJordan Rupprecht { 41*99451b44SJordan Rupprecht case eGet: 42*99451b44SJordan Rupprecht break; 43*99451b44SJordan Rupprecht 44*99451b44SJordan Rupprecht case eAssign: 45*99451b44SJordan Rupprecht g_mask |= mask; 46*99451b44SJordan Rupprecht break; 47*99451b44SJordan Rupprecht 48*99451b44SJordan Rupprecht case eClearBits: 49*99451b44SJordan Rupprecht g_mask &= ~mask; 50*99451b44SJordan Rupprecht break; 51*99451b44SJordan Rupprecht } 52*99451b44SJordan Rupprecht return g_mask; 53*99451b44SJordan Rupprecht } 54*99451b44SJordan Rupprecht 55*99451b44SJordan Rupprecht void * 56*99451b44SJordan Rupprecht thread_func (void *arg) 57*99451b44SJordan Rupprecht { 58*99451b44SJordan Rupprecht uint32_t thread_index = *((uint32_t *)arg); 59*99451b44SJordan Rupprecht uint32_t thread_mask = (1u << (thread_index)); 60*99451b44SJordan Rupprecht printf ("%s (thread index = %u) startng...\n", __FUNCTION__, thread_index); 61*99451b44SJordan Rupprecht 62*99451b44SJordan Rupprecht std::default_random_engine generator; 63*99451b44SJordan Rupprecht std::uniform_int_distribution<int> distribution(0, 3000000); 64*99451b44SJordan Rupprecht 65*99451b44SJordan Rupprecht while (mask_access(eGet) & thread_mask) 66*99451b44SJordan Rupprecht { 67*99451b44SJordan Rupprecht // random micro second sleep from zero to 3 seconds 68*99451b44SJordan Rupprecht int usec = distribution(generator); 69*99451b44SJordan Rupprecht printf ("%s (thread = %u) doing a usleep (%d)...\n", __FUNCTION__, thread_index, usec); 70*99451b44SJordan Rupprecht 71*99451b44SJordan Rupprecht std::chrono::microseconds duration(usec); 72*99451b44SJordan Rupprecht std::this_thread::sleep_for(duration); 73*99451b44SJordan Rupprecht printf ("%s (thread = %u) after usleep ...\n", __FUNCTION__, thread_index); // Set break point at this line. 74*99451b44SJordan Rupprecht } 75*99451b44SJordan Rupprecht printf ("%s (thread index = %u) exiting...\n", __FUNCTION__, thread_index); 76*99451b44SJordan Rupprecht return NULL; 77*99451b44SJordan Rupprecht } 78*99451b44SJordan Rupprecht 79*99451b44SJordan Rupprecht 80*99451b44SJordan Rupprecht int main (int argc, char const *argv[]) 81*99451b44SJordan Rupprecht { 82*99451b44SJordan Rupprecht uint32_t thread_index_1 = 1; 83*99451b44SJordan Rupprecht uint32_t thread_index_2 = 2; 84*99451b44SJordan Rupprecht uint32_t thread_index_3 = 3; 85*99451b44SJordan Rupprecht uint32_t thread_mask_1 = (1u << thread_index_1); 86*99451b44SJordan Rupprecht uint32_t thread_mask_2 = (1u << thread_index_2); 87*99451b44SJordan Rupprecht uint32_t thread_mask_3 = (1u << thread_index_3); 88*99451b44SJordan Rupprecht 89*99451b44SJordan Rupprecht // Make a mask that will keep all threads alive 90*99451b44SJordan Rupprecht mask_access (eAssign, thread_mask_1 | thread_mask_2 | thread_mask_3); // And that line. 91*99451b44SJordan Rupprecht 92*99451b44SJordan Rupprecht // Create 3 threads 93*99451b44SJordan Rupprecht g_thread_1 = std::thread(thread_func, (void*)&thread_index_1); 94*99451b44SJordan Rupprecht g_thread_2 = std::thread(thread_func, (void*)&thread_index_2); 95*99451b44SJordan Rupprecht g_thread_3 = std::thread(thread_func, (void*)&thread_index_3); 96*99451b44SJordan Rupprecht 97*99451b44SJordan Rupprecht char line[64]; 98*99451b44SJordan Rupprecht while (mask_access(eGet) != 0) 99*99451b44SJordan Rupprecht { 100*99451b44SJordan Rupprecht printf ("Enter thread index to kill or ENTER for all:\n"); 101*99451b44SJordan Rupprecht fflush (stdout); 102*99451b44SJordan Rupprecht // Kill threads by index, or ENTER for all threads 103*99451b44SJordan Rupprecht 104*99451b44SJordan Rupprecht if (fgets (line, sizeof(line), stdin)) 105*99451b44SJordan Rupprecht { 106*99451b44SJordan Rupprecht if (line[0] == '\n' || line[0] == '\r' || line[0] == '\0') 107*99451b44SJordan Rupprecht { 108*99451b44SJordan Rupprecht printf ("Exiting all threads...\n"); 109*99451b44SJordan Rupprecht break; 110*99451b44SJordan Rupprecht } 111*99451b44SJordan Rupprecht int32_t index = strtoul (line, NULL, 0); 112*99451b44SJordan Rupprecht switch (index) 113*99451b44SJordan Rupprecht { 114*99451b44SJordan Rupprecht case 1: mask_access (eClearBits, thread_mask_1); break; 115*99451b44SJordan Rupprecht case 2: mask_access (eClearBits, thread_mask_2); break; 116*99451b44SJordan Rupprecht case 3: mask_access (eClearBits, thread_mask_3); break; 117*99451b44SJordan Rupprecht } 118*99451b44SJordan Rupprecht continue; 119*99451b44SJordan Rupprecht } 120*99451b44SJordan Rupprecht 121*99451b44SJordan Rupprecht break; 122*99451b44SJordan Rupprecht } 123*99451b44SJordan Rupprecht 124*99451b44SJordan Rupprecht // Clear all thread bits to they all exit 125*99451b44SJordan Rupprecht mask_access (eClearBits, UINT32_MAX); 126*99451b44SJordan Rupprecht 127*99451b44SJordan Rupprecht // Join all of our threads 128*99451b44SJordan Rupprecht g_thread_1.join(); 129*99451b44SJordan Rupprecht g_thread_2.join(); 130*99451b44SJordan Rupprecht g_thread_3.join(); 131*99451b44SJordan Rupprecht 132*99451b44SJordan Rupprecht return 0; 133*99451b44SJordan Rupprecht } 134