blob: 721f4df8ac2315b2c9388a816eb54462c4bb0fd0 [file] [log] [blame]
bart25200ff2008-03-08 13:15:03 +00001/** Test whether detached threads are handled properly.
2 * Copyright (c) 2006-2008 by Bart Van Assche (bart.vanassche@gmail.com).
3 */
4
sewardjaf44c822007-11-25 14:01:38 +00005
6#include <assert.h>
7#include <pthread.h>
8#include <stdio.h>
9#include <stdlib.h>
10#include <unistd.h>
11#include "../drd_clientreq.h"
12
bart25200ff2008-03-08 13:15:03 +000013
sewardjaf44c822007-11-25 14:01:38 +000014static int s_finished_count;
bart25200ff2008-03-08 13:15:03 +000015static int s_set_thread_name;
sewardjaf44c822007-11-25 14:01:38 +000016static pthread_mutex_t s_mutex;
17
bart25200ff2008-03-08 13:15:03 +000018
19static void set_thread_name(const char* const fmt, const int arg)
20{
21 if (s_set_thread_name)
22 {
23 int res;
24 char name[32];
25 snprintf(name, sizeof(name), fmt, arg);
26 name[sizeof(name) - 1] = 0;
27 VALGRIND_DO_CLIENT_REQUEST(res, 0, VG_USERREQ__SET_THREAD_NAME,
28 name, 0, 0, 0, 0);
29 }
30}
31
sewardjaf44c822007-11-25 14:01:38 +000032void increment_finished_count()
33{
34 pthread_mutex_lock(&s_mutex);
35 s_finished_count++;
36 pthread_mutex_unlock(&s_mutex);
37}
38
39int get_finished_count()
40{
41 int result;
42 pthread_mutex_lock(&s_mutex);
43 result = s_finished_count;
44 pthread_mutex_unlock(&s_mutex);
45 return result;
46}
47
48static void* thread_func1(void* arg)
49{
bart25200ff2008-03-08 13:15:03 +000050 set_thread_name("thread_func1[%d]", *(int*)arg);
bart4d72f102008-03-07 18:44:26 +000051 write(STDOUT_FILENO, ".\n", 2);
sewardjaf44c822007-11-25 14:01:38 +000052 increment_finished_count();
53 return 0;
54}
55
56static void* thread_func2(void* arg)
57{
bart25200ff2008-03-08 13:15:03 +000058 set_thread_name("thread_func2[%d]", *(int*)arg);
sewardjaf44c822007-11-25 14:01:38 +000059 pthread_detach(pthread_self());
bart4d72f102008-03-07 18:44:26 +000060 write(STDOUT_FILENO, ".\n", 2);
sewardjaf44c822007-11-25 14:01:38 +000061 increment_finished_count();
62 return 0;
63}
64
65int main(int argc, char** argv)
66{
67 const int count1 = argc > 1 ? atoi(argv[1]) : 100;
68 const int count2 = argc > 2 ? atoi(argv[2]) : 100;
bart25200ff2008-03-08 13:15:03 +000069 const int do_set_thread_name = argc > 3 ? atoi(argv[3]) != 0 : 0;
sewardjaf44c822007-11-25 14:01:38 +000070 int thread_arg[count1 > count2 ? count1 : count2];
71 int i;
72 int detachstate;
73 pthread_attr_t attr;
74
bart25200ff2008-03-08 13:15:03 +000075 s_set_thread_name = do_set_thread_name;
76
77 set_thread_name("main", 0);
78
sewardjaf44c822007-11-25 14:01:38 +000079 for (i = 0; i < count1 || i < count2; i++)
80 thread_arg[i] = i;
81
82 pthread_mutex_init(&s_mutex, 0);
83
84 pthread_attr_init(&attr);
85 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
86 assert(pthread_attr_getdetachstate(&attr, &detachstate) == 0);
87 assert(detachstate == PTHREAD_CREATE_DETACHED);
88 pthread_attr_setstacksize(&attr, 16384);
89 // Create count1 detached threads by setting the "detached" property via
90 // thread attributes.
91 for (i = 0; i < count1; i++)
92 {
93 pthread_t thread;
94 pthread_create(&thread, &attr, thread_func1, &thread_arg[i]);
95 }
96 // Create count2 detached threads by letting the threads detach themselves.
97 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
98 assert(pthread_attr_getdetachstate(&attr, &detachstate) == 0);
99 assert(detachstate == PTHREAD_CREATE_JOINABLE);
100 for (i = 0; i < count2; i++)
101 {
102 pthread_t thread;
103 pthread_create(&thread, &attr, thread_func2, &thread_arg[i]);
104 }
105 pthread_attr_destroy(&attr);
106
107 // Wait until all detached threads have written their output to stdout.
108 while (get_finished_count() < count1 + count2)
109 {
110 struct timespec delay = { 0, 1 * 1000 * 1000 };
111 nanosleep(&delay, 0);
112 }
113
114 printf("\n");
115
116 pthread_mutex_destroy(&s_mutex);
117
118 return 0;
119}