subthreadcreate.c raw
1
2 #ifdef HAVE_CONFIG_H
3 /* For `GC_THREADS` and `PARALLEL_MARK` macros. */
4 # include "config.h"
5 #endif
6
7 #ifdef GC_THREADS
8 # undef GC_NO_THREAD_REDIRECTS
9 # include "gc.h"
10
11 # ifdef PARALLEL_MARK
12 # define AO_REQUIRE_CAS
13 # if !defined(__GNUC__) && !defined(AO_ASSUME_WINDOWS98)
14 # define AO_ASSUME_WINDOWS98
15 # endif
16 # endif
17 # include "private/gc_atomic_ops.h"
18 #endif /* GC_THREADS */
19
20 #include <stdio.h>
21
22 #ifdef AO_HAVE_fetch_and_add1
23
24 # ifdef GC_PTHREADS
25 # include <errno.h> /*< for `EAGAIN` */
26 # include <pthread.h>
27 # else
28 # ifndef WIN32_LEAN_AND_MEAN
29 # define WIN32_LEAN_AND_MEAN 1
30 # endif
31 # define NOSERVICE
32 # include <windows.h>
33 # endif /* !GC_PTHREADS */
34
35 # include <stdlib.h>
36
37 # ifndef NTHREADS
38 # define NTHREADS 5
39 # endif
40
41 /* Number of threads to create. */
42 # define NTHREADS_INNER (NTHREADS * 6)
43
44 # ifndef MAX_SUBTHREAD_DEPTH
45 # define MAX_ALIVE_THREAD_COUNT 55
46 # define MAX_SUBTHREAD_DEPTH 7
47 # define MAX_SUBTHREAD_COUNT 200
48 # endif
49
50 # ifndef DECAY_NUMER
51 # define DECAY_NUMER 15
52 # define DECAY_DENOM 16
53 # endif
54
55 volatile AO_t thread_created_cnt = 0;
56 volatile AO_t thread_ended_cnt = 0;
57
58 # ifdef GC_PTHREADS
59 static void *
60 entry(void *arg)
61 # else
62 static DWORD WINAPI
63 entry(LPVOID arg)
64 # endif
65 {
66 int thread_num = (int)AO_fetch_and_add1(&thread_created_cnt);
67 GC_word my_depth = (GC_word)(GC_uintptr_t)arg + 1;
68
69 if (my_depth <= MAX_SUBTHREAD_DEPTH && thread_num < MAX_SUBTHREAD_COUNT
70 && (thread_num % DECAY_DENOM) < DECAY_NUMER
71 && thread_num - (int)AO_load(&thread_ended_cnt)
72 <= MAX_ALIVE_THREAD_COUNT) {
73 # ifdef GC_PTHREADS
74 int err;
75 pthread_t th;
76
77 err = pthread_create(&th, NULL, entry, (void *)(GC_uintptr_t)my_depth);
78 if (err != 0) {
79 fprintf(stderr,
80 "Thread #%d creation failed from other thread, errno= %d\n",
81 thread_num, err);
82 if (err != EAGAIN)
83 exit(2);
84 } else {
85 err = pthread_detach(th);
86 if (err != 0) {
87 fprintf(stderr, "Thread #%d detach failed, errno= %d\n", thread_num,
88 err);
89 exit(2);
90 }
91 }
92 # else
93 HANDLE th;
94 DWORD thread_id;
95
96 th = CreateThread(NULL, 0, entry, (LPVOID)my_depth, 0, &thread_id);
97 if (th == NULL) {
98 fprintf(stderr, "Thread #%d creation failed, errcode= %d\n", thread_num,
99 (int)GetLastError());
100 exit(2);
101 }
102 CloseHandle(th);
103 # endif
104 }
105
106 (void)AO_fetch_and_add1(&thread_ended_cnt);
107 return 0;
108 }
109
110 int
111 main(void)
112 {
113 # if NTHREADS > 0
114 int i, n;
115 # ifdef GC_PTHREADS
116 int err;
117 pthread_t th[NTHREADS_INNER];
118 # else
119 HANDLE th[NTHREADS_INNER];
120 # endif
121 int th_nums[NTHREADS_INNER];
122
123 GC_INIT();
124 for (i = 0; i < NTHREADS_INNER; ++i) {
125 th_nums[i] = (int)AO_fetch_and_add1(&thread_created_cnt);
126 # ifdef GC_PTHREADS
127 err = pthread_create(&th[i], NULL, entry, 0);
128 if (err != 0) {
129 fprintf(stderr, "Thread #%d creation failed, errno= %d\n", th_nums[i],
130 err);
131 if (i > 0 && EAGAIN == err)
132 break;
133 exit(1);
134 }
135 # else
136 {
137 DWORD thread_id;
138
139 th[i] = CreateThread(NULL, 0, entry, 0, 0, &thread_id);
140 }
141 if (th[i] == NULL) {
142 fprintf(stderr, "Thread #%d creation failed, errcode= %d\n", th_nums[i],
143 (int)GetLastError());
144 exit(1);
145 }
146 # endif
147 }
148 n = i;
149 for (i = 0; i < n; ++i) {
150 # ifdef GC_PTHREADS
151 void *res;
152
153 err = pthread_join(th[i], &res);
154 if (err != 0) {
155 fprintf(stderr, "Thread #%d join failed, errno= %d\n", th_nums[i], err);
156 exit(1);
157 }
158 # else
159 if (WaitForSingleObject(th[i], INFINITE) != WAIT_OBJECT_0) {
160 fprintf(stderr, "Thread #%d join failed, errcode= %d\n", th_nums[i],
161 (int)GetLastError());
162 CloseHandle(th[i]);
163 exit(1);
164 }
165 CloseHandle(th[i]);
166 # endif
167 }
168 # else
169 (void)entry(NULL);
170 # endif
171 printf("Created %d threads (%d ended)\n", (int)AO_load(&thread_created_cnt),
172 (int)AO_load(&thread_ended_cnt));
173 return 0;
174 }
175
176 #else
177
178 int
179 main(void)
180 {
181 printf("test skipped\n");
182 return 0;
183 }
184
185 #endif /* !AO_HAVE_fetch_and_add1 */
186