]>
Commit | Line | Data |
---|---|---|
b168057a | 1 | /* Copyright (C) 2002-2015 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 | ||
28 | /* Number of different signalss to use. Also is the number of | |
29 | threads. */ | |
30 | #define N 10 | |
31 | /* Maximum number of threads in flight at any one time. */ | |
32 | #define INFLIGHT 5 | |
33 | /* Number of signals sent in total. */ | |
34 | #define ROUNDS 10000 | |
35 | ||
36 | ||
37 | static int received[N][N]; | |
38 | static int nsig[N]; | |
39 | static pthread_t th[N]; | |
40 | static sem_t sem; | |
41 | static pthread_mutex_t lock[N]; | |
42 | static pthread_t th_main; | |
43 | static int sig0; | |
44 | ||
45 | static void | |
46 | handler (int sig) | |
47 | { | |
48 | int i; | |
49 | for (i = 0; i < N; ++i) | |
50 | if (pthread_equal (pthread_self (), th[i])) | |
51 | break; | |
52 | ||
53 | if (i == N) | |
54 | { | |
55 | if (pthread_equal (pthread_self (), th_main)) | |
56 | puts ("signal received by main thread"); | |
57 | else | |
58 | printf ("signal received by unknown thread (%lx)\n", | |
59 | (unsigned long int) pthread_self ()); | |
60 | exit (1); | |
61 | } | |
62 | ||
63 | ++received[i][sig - sig0]; | |
64 | ||
65 | sem_post (&sem); | |
66 | } | |
67 | ||
68 | ||
69 | static void * | |
70 | tf (void *arg) | |
71 | { | |
72 | int idx = (long int) arg; | |
73 | ||
74 | sigset_t ss; | |
75 | sigemptyset (&ss); | |
76 | ||
77 | int i; | |
78 | for (i = 0; i <= idx; ++i) | |
79 | sigaddset (&ss, sig0 + i); | |
80 | ||
81 | if (pthread_sigmask (SIG_UNBLOCK, &ss, NULL) != 0) | |
82 | { | |
83 | printf ("thread %d: pthread_sigmask failed\n", i); | |
84 | exit (1); | |
85 | } | |
86 | ||
87 | pthread_mutex_lock (&lock[idx]); | |
88 | ||
89 | return NULL; | |
90 | } | |
91 | ||
92 | ||
93 | static int | |
94 | do_test (void) | |
95 | { | |
96 | /* Block all signals. */ | |
97 | sigset_t ss; | |
98 | sigfillset (&ss); | |
99 | ||
100 | th_main = pthread_self (); | |
101 | ||
102 | sig0 = SIGRTMIN; | |
103 | ||
104 | if (pthread_sigmask (SIG_SETMASK, &ss, NULL) != 0) | |
105 | { | |
106 | puts ("1st pthread_sigmask failed"); | |
107 | exit (1); | |
108 | } | |
109 | ||
110 | /* Install the handler. */ | |
111 | int i; | |
112 | for (i = 0; i < N; ++i) | |
113 | { | |
114 | struct sigaction sa = | |
115 | { | |
116 | .sa_handler = handler, | |
117 | .sa_flags = 0 | |
118 | }; | |
119 | sigfillset (&sa.sa_mask); | |
120 | ||
121 | if (sigaction (sig0 + i, &sa, NULL) != 0) | |
122 | { | |
123 | printf ("sigaction for signal %d failed\n", i); | |
124 | exit (1); | |
125 | } | |
126 | } | |
127 | ||
128 | if (sem_init (&sem, 0, INFLIGHT) != 0) | |
129 | { | |
130 | puts ("sem_init failed"); | |
131 | exit (1); | |
132 | } | |
133 | ||
4d1a02ef UD |
134 | pthread_attr_t a; |
135 | ||
136 | if (pthread_attr_init (&a) != 0) | |
137 | { | |
138 | puts ("attr_init failed"); | |
139 | exit (1); | |
140 | } | |
141 | ||
142 | if (pthread_attr_setstacksize (&a, 1 * 1024 * 1024) != 0) | |
143 | { | |
144 | puts ("attr_setstacksize failed"); | |
145 | return 1; | |
146 | } | |
147 | ||
76a50749 UD |
148 | for (i = 0; i < N; ++i) |
149 | { | |
150 | if (pthread_mutex_init (&lock[i], NULL) != 0) | |
151 | { | |
152 | printf ("mutex_init[%d] failed\n", i); | |
153 | } | |
154 | ||
155 | if (pthread_mutex_lock (&lock[i]) != 0) | |
156 | { | |
157 | printf ("mutex_lock[%d] failed\n", i); | |
158 | } | |
159 | ||
4d1a02ef | 160 | if (pthread_create (&th[i], &a, tf, (void *) (long int) i) != 0) |
76a50749 UD |
161 | { |
162 | printf ("create of thread %d failed\n", i); | |
163 | exit (1); | |
164 | } | |
165 | } | |
166 | ||
4d1a02ef UD |
167 | if (pthread_attr_destroy (&a) != 0) |
168 | { | |
169 | puts ("attr_destroy failed"); | |
170 | exit (1); | |
171 | } | |
172 | ||
76a50749 UD |
173 | int result = 0; |
174 | unsigned int r = 42; | |
175 | pid_t pid = getpid (); | |
176 | ||
177 | for (i = 0; i < ROUNDS; ++i) | |
178 | { | |
ccf1d573 | 179 | if (TEMP_FAILURE_RETRY (sem_wait (&sem)) != 0) |
76a50749 UD |
180 | { |
181 | printf ("sem_wait round %d failed: %m\n", i); | |
182 | exit (1); | |
183 | } | |
184 | ||
185 | int s = rand_r (&r) % N; | |
186 | ||
187 | kill (pid, sig0 + s); | |
188 | } | |
189 | ||
190 | void *status; | |
191 | for (i = 0; i < N; ++i) | |
192 | { | |
193 | if (pthread_mutex_unlock (&lock[i]) != 0) | |
194 | { | |
195 | printf ("unlock %d failed\n", i); | |
196 | exit (1); | |
197 | } | |
198 | ||
199 | if (pthread_join (th[i], &status) != 0) | |
200 | { | |
201 | printf ("join %d failed\n", i); | |
202 | result = 1; | |
203 | } | |
204 | else if (status != NULL) | |
205 | { | |
206 | printf ("%d: result != NULL\n", i); | |
207 | result = 1; | |
208 | } | |
209 | } | |
210 | ||
211 | int total = 0; | |
212 | for (i = 0; i < N; ++i) | |
213 | { | |
214 | int j; | |
215 | ||
216 | for (j = 0; j <= i; ++j) | |
217 | total += received[i][j]; | |
218 | ||
219 | for (j = i + 1; j < N; ++j) | |
220 | if (received[i][j] != 0) | |
221 | { | |
222 | printf ("thread %d received signal SIGRTMIN+%d\n", i, j); | |
223 | result = 1; | |
224 | } | |
225 | } | |
226 | ||
227 | if (total != ROUNDS) | |
228 | { | |
229 | printf ("total number of handled signals is %d, expected %d\n", | |
230 | total, ROUNDS); | |
231 | result = 1; | |
232 | } | |
233 | ||
234 | printf ("A total of %d signals sent and received\n", total); | |
235 | for (i = 0; i < N; ++i) | |
236 | { | |
237 | printf ("thread %2d:", i); | |
238 | ||
239 | int j; | |
240 | for (j = 0; j <= i; ++j) | |
241 | { | |
242 | printf (" %5d", received[i][j]); | |
243 | nsig[j] += received[i][j]; | |
244 | } | |
245 | ||
246 | putchar ('\n'); | |
247 | ||
248 | } | |
249 | ||
250 | printf ("\nTotal :"); | |
251 | for (i = 0; i < N; ++i) | |
252 | printf (" %5d", nsig[i]); | |
253 | putchar ('\n'); | |
254 | ||
255 | return result; | |
256 | } | |
257 | ||
258 | #define TIMEOUT 10 | |
259 | #define TEST_FUNCTION do_test () | |
260 | #include "../test-skeleton.c" |