]>
Commit | Line | Data |
---|---|---|
bfff8b1b | 1 | /* Copyright (C) 2002-2017 Free Software Foundation, Inc. |
76a50749 UD |
2 | This file is part of the GNU C Library. |
3 | Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. | |
4 | ||
5 | The GNU C Library is free software; you can redistribute it and/or | |
6 | modify it under the terms of the GNU Lesser General Public | |
7 | License as published by the Free Software Foundation; either | |
8 | version 2.1 of the License, or (at your option) any later version. | |
9 | ||
10 | The GNU C Library is distributed in the hope that it will be useful, | |
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of | |
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
13 | Lesser General Public License for more details. | |
14 | ||
15 | You should have received a copy of the GNU Lesser General Public | |
59ba27a6 PE |
16 | License along with the GNU C Library; if not, see |
17 | <http://www.gnu.org/licenses/>. */ | |
76a50749 | 18 | |
ccf1d573 | 19 | #include <errno.h> |
76a50749 UD |
20 | #include <pthread.h> |
21 | #include <semaphore.h> | |
22 | #include <signal.h> | |
23 | #include <stdio.h> | |
24 | #include <stdlib.h> | |
25 | #include <unistd.h> | |
26 | ||
27 | ||
2cfe32bc RM |
28 | #ifdef SIGRTMIN |
29 | ||
30 | /* Number of different signals to use. Also is the number of threads. */ | |
31 | # define N 10 | |
76a50749 | 32 | /* Maximum number of threads in flight at any one time. */ |
2cfe32bc | 33 | # define INFLIGHT 5 |
76a50749 | 34 | /* Number of signals sent in total. */ |
2cfe32bc | 35 | # define ROUNDS 10000 |
76a50749 UD |
36 | |
37 | ||
38 | static int received[N][N]; | |
39 | static int nsig[N]; | |
40 | static pthread_t th[N]; | |
41 | static sem_t sem; | |
42 | static pthread_mutex_t lock[N]; | |
43 | static pthread_t th_main; | |
44 | static int sig0; | |
45 | ||
46 | static void | |
47 | handler (int sig) | |
48 | { | |
49 | int i; | |
50 | for (i = 0; i < N; ++i) | |
51 | if (pthread_equal (pthread_self (), th[i])) | |
52 | break; | |
53 | ||
54 | if (i == N) | |
55 | { | |
56 | if (pthread_equal (pthread_self (), th_main)) | |
57 | puts ("signal received by main thread"); | |
58 | else | |
59 | printf ("signal received by unknown thread (%lx)\n", | |
60 | (unsigned long int) pthread_self ()); | |
61 | exit (1); | |
62 | } | |
63 | ||
64 | ++received[i][sig - sig0]; | |
65 | ||
66 | sem_post (&sem); | |
67 | } | |
68 | ||
69 | ||
70 | static void * | |
71 | tf (void *arg) | |
72 | { | |
73 | int idx = (long int) arg; | |
74 | ||
75 | sigset_t ss; | |
76 | sigemptyset (&ss); | |
77 | ||
78 | int i; | |
79 | for (i = 0; i <= idx; ++i) | |
80 | sigaddset (&ss, sig0 + i); | |
81 | ||
82 | if (pthread_sigmask (SIG_UNBLOCK, &ss, NULL) != 0) | |
83 | { | |
84 | printf ("thread %d: pthread_sigmask failed\n", i); | |
85 | exit (1); | |
86 | } | |
87 | ||
88 | pthread_mutex_lock (&lock[idx]); | |
89 | ||
90 | return NULL; | |
91 | } | |
92 | ||
93 | ||
94 | static int | |
95 | do_test (void) | |
96 | { | |
97 | /* Block all signals. */ | |
98 | sigset_t ss; | |
99 | sigfillset (&ss); | |
100 | ||
101 | th_main = pthread_self (); | |
102 | ||
103 | sig0 = SIGRTMIN; | |
104 | ||
105 | if (pthread_sigmask (SIG_SETMASK, &ss, NULL) != 0) | |
106 | { | |
107 | puts ("1st pthread_sigmask failed"); | |
108 | exit (1); | |
109 | } | |
110 | ||
111 | /* Install the handler. */ | |
112 | int i; | |
113 | for (i = 0; i < N; ++i) | |
114 | { | |
115 | struct sigaction sa = | |
116 | { | |
117 | .sa_handler = handler, | |
118 | .sa_flags = 0 | |
119 | }; | |
120 | sigfillset (&sa.sa_mask); | |
121 | ||
122 | if (sigaction (sig0 + i, &sa, NULL) != 0) | |
123 | { | |
124 | printf ("sigaction for signal %d failed\n", i); | |
125 | exit (1); | |
126 | } | |
127 | } | |
128 | ||
129 | if (sem_init (&sem, 0, INFLIGHT) != 0) | |
130 | { | |
131 | puts ("sem_init failed"); | |
132 | exit (1); | |
133 | } | |
134 | ||
4d1a02ef UD |
135 | pthread_attr_t a; |
136 | ||
137 | if (pthread_attr_init (&a) != 0) | |
138 | { | |
139 | puts ("attr_init failed"); | |
140 | exit (1); | |
141 | } | |
142 | ||
143 | if (pthread_attr_setstacksize (&a, 1 * 1024 * 1024) != 0) | |
144 | { | |
145 | puts ("attr_setstacksize failed"); | |
146 | return 1; | |
147 | } | |
148 | ||
76a50749 UD |
149 | for (i = 0; i < N; ++i) |
150 | { | |
151 | if (pthread_mutex_init (&lock[i], NULL) != 0) | |
152 | { | |
153 | printf ("mutex_init[%d] failed\n", i); | |
154 | } | |
155 | ||
156 | if (pthread_mutex_lock (&lock[i]) != 0) | |
157 | { | |
158 | printf ("mutex_lock[%d] failed\n", i); | |
159 | } | |
160 | ||
4d1a02ef | 161 | if (pthread_create (&th[i], &a, tf, (void *) (long int) i) != 0) |
76a50749 UD |
162 | { |
163 | printf ("create of thread %d failed\n", i); | |
164 | exit (1); | |
165 | } | |
166 | } | |
167 | ||
4d1a02ef UD |
168 | if (pthread_attr_destroy (&a) != 0) |
169 | { | |
170 | puts ("attr_destroy failed"); | |
171 | exit (1); | |
172 | } | |
173 | ||
76a50749 UD |
174 | int result = 0; |
175 | unsigned int r = 42; | |
176 | pid_t pid = getpid (); | |
177 | ||
178 | for (i = 0; i < ROUNDS; ++i) | |
179 | { | |
ccf1d573 | 180 | if (TEMP_FAILURE_RETRY (sem_wait (&sem)) != 0) |
76a50749 UD |
181 | { |
182 | printf ("sem_wait round %d failed: %m\n", i); | |
183 | exit (1); | |
184 | } | |
185 | ||
186 | int s = rand_r (&r) % N; | |
187 | ||
188 | kill (pid, sig0 + s); | |
189 | } | |
190 | ||
191 | void *status; | |
192 | for (i = 0; i < N; ++i) | |
193 | { | |
194 | if (pthread_mutex_unlock (&lock[i]) != 0) | |
195 | { | |
196 | printf ("unlock %d failed\n", i); | |
197 | exit (1); | |
198 | } | |
199 | ||
200 | if (pthread_join (th[i], &status) != 0) | |
201 | { | |
202 | printf ("join %d failed\n", i); | |
203 | result = 1; | |
204 | } | |
205 | else if (status != NULL) | |
206 | { | |
207 | printf ("%d: result != NULL\n", i); | |
208 | result = 1; | |
209 | } | |
210 | } | |
211 | ||
212 | int total = 0; | |
213 | for (i = 0; i < N; ++i) | |
214 | { | |
215 | int j; | |
216 | ||
217 | for (j = 0; j <= i; ++j) | |
218 | total += received[i][j]; | |
219 | ||
220 | for (j = i + 1; j < N; ++j) | |
221 | if (received[i][j] != 0) | |
222 | { | |
223 | printf ("thread %d received signal SIGRTMIN+%d\n", i, j); | |
224 | result = 1; | |
225 | } | |
226 | } | |
227 | ||
228 | if (total != ROUNDS) | |
229 | { | |
230 | printf ("total number of handled signals is %d, expected %d\n", | |
231 | total, ROUNDS); | |
232 | result = 1; | |
233 | } | |
234 | ||
235 | printf ("A total of %d signals sent and received\n", total); | |
236 | for (i = 0; i < N; ++i) | |
237 | { | |
238 | printf ("thread %2d:", i); | |
239 | ||
240 | int j; | |
241 | for (j = 0; j <= i; ++j) | |
242 | { | |
243 | printf (" %5d", received[i][j]); | |
244 | nsig[j] += received[i][j]; | |
245 | } | |
246 | ||
247 | putchar ('\n'); | |
248 | ||
249 | } | |
250 | ||
251 | printf ("\nTotal :"); | |
252 | for (i = 0; i < N; ++i) | |
253 | printf (" %5d", nsig[i]); | |
254 | putchar ('\n'); | |
255 | ||
256 | return result; | |
257 | } | |
258 | ||
2cfe32bc RM |
259 | # define TIMEOUT 10 |
260 | # define TEST_FUNCTION do_test () | |
261 | ||
262 | #else | |
263 | # define TEST_FUNCTION 0 | |
264 | #endif | |
265 | ||
76a50749 | 266 | #include "../test-skeleton.c" |