1ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/** 2ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * Test whether detached threads are handled properly. 3ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * This test program is based on pth_detached.c, with the difference that 4ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * in this test program the main thread uses a counting semaphore instead 5ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * of a counter protected by a mutex to wait until all detached threads 6ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * finished. 7ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown */ 8ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 9ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 10ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include <assert.h> 11ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include <pthread.h> 12ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include <semaphore.h> 13ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include <stdio.h> 14ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include <stdlib.h> 15ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include <unistd.h> 16ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 17ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 18ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic sem_t s_sem; 19ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 20ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 21ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void increment_finished_count() 22ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 23ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown sem_post(&s_sem); 24ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 25ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 26ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void* thread_func1(void* arg) 27ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 28ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown write(STDOUT_FILENO, ".", 1); 29ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown increment_finished_count(); 30ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return 0; 31ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 32ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 33ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void* thread_func2(void* arg) 34ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 35ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown pthread_detach(pthread_self()); 36ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown write(STDOUT_FILENO, ".", 1); 37ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown increment_finished_count(); 38ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return 0; 39ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 40ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 41ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownint main(int argc, char** argv) 42ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 43ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown const int count1 = argc > 1 ? atoi(argv[1]) : 100; 44ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown const int count2 = argc > 2 ? atoi(argv[2]) : 100; 45ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown int thread_arg[count1 > count2 ? count1 : count2]; 46ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown int i; 47ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown int detachstate; 48ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown pthread_attr_t attr; 49ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 50ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown for (i = 0; i < count1 || i < count2; i++) 51ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown thread_arg[i] = i; 52ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 53ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown sem_init(&s_sem, 0, 0); 54ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 55ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown pthread_attr_init(&attr); 56ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); 57ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown assert(pthread_attr_getdetachstate(&attr, &detachstate) == 0); 58ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown assert(detachstate == PTHREAD_CREATE_DETACHED); 59ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown pthread_attr_setstacksize(&attr, 16384); 60ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // Create count1 detached threads by setting the "detached" property via 61ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // thread attributes. 62ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown for (i = 0; i < count1; i++) 63ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown { 64ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown pthread_t thread; 65ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown pthread_create(&thread, &attr, thread_func1, &thread_arg[i]); 66ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 67ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // Create count2 detached threads by letting the threads detach themselves. 68ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE); 69ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown assert(pthread_attr_getdetachstate(&attr, &detachstate) == 0); 70ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown assert(detachstate == PTHREAD_CREATE_JOINABLE); 71ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown for (i = 0; i < count2; i++) 72ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown { 73ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown pthread_t thread; 74ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown pthread_create(&thread, &attr, thread_func2, &thread_arg[i]); 75ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 76ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown pthread_attr_destroy(&attr); 77ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 78ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // Wait until all detached threads have written their output to stdout. 79ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown for (i = 0; i < count1 + count2; i++) 80ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown { 81ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown sem_wait(&s_sem); 82ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 83ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 84ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown write(STDOUT_FILENO, "\n", 1); 85b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov fprintf(stderr, "Done.\n"); 86ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 87ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown sem_destroy(&s_sem); 88ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 89ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return 0; 90ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 91