1/* pthread_getattr_np test.
2 Copyright (C) 2003-2022 Free Software Foundation, Inc.
3 This file is part of the GNU C Library.
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
16 License along with the GNU C Library; if not, see
17 <https://www.gnu.org/licenses/>. */
18
19#include <errno.h>
20#include <error.h>
21#include <pthread.h>
22#include <stdio.h>
23#include <stdlib.h>
24#include <string.h>
25#include <unistd.h>
26
27#include <stackinfo.h>
28#include <libc-diag.h>
29
30static void *
31tf (void *arg)
32{
33 pthread_attr_t a, *ap, a2;
34 int err;
35 void *result = NULL;
36
37 if (arg == NULL)
38 {
39 ap = &a2;
40 err = pthread_attr_init (attr: ap);
41 if (err)
42 {
43 error (status: 0, errnum: err, format: "pthread_attr_init failed");
44 return tf;
45 }
46 }
47 else
48 ap = (pthread_attr_t *) arg;
49
50 err = pthread_getattr_np (th: pthread_self (), attr: &a);
51 if (err)
52 {
53 error (status: 0, errnum: err, format: "pthread_getattr_np failed");
54 result = tf;
55 }
56
57 int detachstate1, detachstate2;
58 err = pthread_attr_getdetachstate (attr: &a, detachstate: &detachstate1);
59 if (err)
60 {
61 error (status: 0, errnum: err, format: "pthread_attr_getdetachstate failed");
62 result = tf;
63 }
64 else
65 {
66 err = pthread_attr_getdetachstate (attr: ap, detachstate: &detachstate2);
67 if (err)
68 {
69 error (status: 0, errnum: err, format: "pthread_attr_getdetachstate failed");
70 result = tf;
71 }
72 else if (detachstate1 != detachstate2)
73 {
74 error (status: 0, errnum: 0, format: "detachstate differs %d != %d",
75 detachstate1, detachstate2);
76 result = tf;
77 }
78 }
79
80 void *stackaddr;
81 size_t stacksize;
82 err = pthread_attr_getstack (attr: &a, stackaddr: &stackaddr, stacksize: &stacksize);
83 if (err)
84 {
85 error (status: 0, errnum: err, format: "pthread_attr_getstack failed");
86 result = tf;
87 }
88 else if ((void *) &a < stackaddr
89 || (void *) &a >= stackaddr + stacksize)
90 {
91 error (status: 0, errnum: 0, format: "pthread_attr_getstack returned range does not cover thread's stack");
92 result = tf;
93 }
94 else
95 printf (format: "thread stack %p-%p (0x%zx)\n", stackaddr, stackaddr + stacksize,
96 stacksize);
97
98 size_t guardsize1, guardsize2;
99 err = pthread_attr_getguardsize (attr: &a, guardsize: &guardsize1);
100 if (err)
101 {
102 error (status: 0, errnum: err, format: "pthread_attr_getguardsize failed");
103 result = tf;
104 }
105 else
106 {
107 err = pthread_attr_getguardsize (attr: ap, guardsize: &guardsize2);
108 if (err)
109 {
110 error (status: 0, errnum: err, format: "pthread_attr_getguardsize failed");
111 result = tf;
112 }
113 else if (guardsize1 != guardsize2)
114 {
115 error (status: 0, errnum: 0, format: "guardsize differs %zd != %zd",
116 guardsize1, guardsize2);
117 result = tf;
118 }
119 else
120 printf (format: "thread guardsize %zd\n", guardsize1);
121 }
122
123 int scope1, scope2;
124 err = pthread_attr_getscope (attr: &a, scope: &scope1);
125 if (err)
126 {
127 error (status: 0, errnum: err, format: "pthread_attr_getscope failed");
128 result = tf;
129 }
130 else
131 {
132 err = pthread_attr_getscope (attr: ap, scope: &scope2);
133 if (err)
134 {
135 error (status: 0, errnum: err, format: "pthread_attr_getscope failed");
136 result = tf;
137 }
138 else if (scope1 != scope2)
139 {
140 error (status: 0, errnum: 0, format: "scope differs %d != %d",
141 scope1, scope2);
142 result = tf;
143 }
144 }
145
146 int inheritsched1, inheritsched2;
147 err = pthread_attr_getinheritsched (attr: &a, inherit: &inheritsched1);
148 if (err)
149 {
150 error (status: 0, errnum: err, format: "pthread_attr_getinheritsched failed");
151 result = tf;
152 }
153 else
154 {
155 err = pthread_attr_getinheritsched (attr: ap, inherit: &inheritsched2);
156 if (err)
157 {
158 error (status: 0, errnum: err, format: "pthread_attr_getinheritsched failed");
159 result = tf;
160 }
161 else if (inheritsched1 != inheritsched2)
162 {
163 error (status: 0, errnum: 0, format: "inheritsched differs %d != %d",
164 inheritsched1, inheritsched2);
165 result = tf;
166 }
167 }
168
169 cpu_set_t c1, c2;
170 err = pthread_getaffinity_np (th: pthread_self (), cpusetsize: sizeof (c1), cpuset: &c1);
171 if (err == 0)
172 {
173 err = pthread_attr_getaffinity_np (attr: &a, cpusetsize: sizeof (c2), cpuset: &c2);
174 if (err)
175 {
176 error (status: 0, errnum: err, format: "pthread_attr_getaffinity_np failed");
177 result = tf;
178 }
179 else if (memcmp (&c1, &c2, sizeof (c1)))
180 {
181 error (status: 0, errnum: 0, format: "pthread_attr_getaffinity_np returned different CPU mask than pthread_getattr_np");
182 result = tf;
183 }
184 }
185
186 err = pthread_attr_destroy (attr: &a);
187 if (err)
188 {
189 error (status: 0, errnum: err, format: "pthread_attr_destroy failed");
190 result = tf;
191 }
192
193 if (ap == &a2)
194 {
195 err = pthread_attr_destroy (attr: ap);
196 if (err)
197 {
198 error (status: 0, errnum: err, format: "pthread_attr_destroy failed");
199 result = tf;
200 }
201 }
202
203 return result;
204}
205
206
207static int
208do_test (void)
209{
210 int result = 0;
211 pthread_attr_t a;
212 cpu_set_t c1, c2;
213
214 int err = pthread_attr_init (attr: &a);
215 if (err)
216 {
217 error (status: 0, errnum: err, format: "pthread_attr_init failed");
218 result = 1;
219 }
220
221 err = pthread_attr_getaffinity_np (attr: &a, cpusetsize: sizeof (c1), cpuset: &c1);
222 if (err && err != ENOSYS)
223 {
224 error (status: 0, errnum: err, format: "pthread_attr_getaffinity_np failed");
225 result = 1;
226 }
227
228 err = pthread_attr_destroy (attr: &a);
229 if (err)
230 {
231 error (status: 0, errnum: err, format: "pthread_attr_destroy failed");
232 result = 1;
233 }
234
235 err = pthread_getattr_np (th: pthread_self (), attr: &a);
236 if (err)
237 {
238 error (status: 0, errnum: err, format: "pthread_getattr_np failed");
239 result = 1;
240 }
241
242 int detachstate;
243 err = pthread_attr_getdetachstate (attr: &a, detachstate: &detachstate);
244 if (err)
245 {
246 error (status: 0, errnum: err, format: "pthread_attr_getdetachstate failed");
247 result = 1;
248 }
249 else if (detachstate != PTHREAD_CREATE_JOINABLE)
250 {
251 error (status: 0, errnum: 0, format: "initial thread not joinable");
252 result = 1;
253 }
254
255 void *stackaddr;
256 size_t stacksize;
257 err = pthread_attr_getstack (attr: &a, stackaddr: &stackaddr, stacksize: &stacksize);
258 if (err)
259 {
260 error (status: 0, errnum: err, format: "pthread_attr_getstack failed");
261 result = 1;
262 }
263 else if ((void *) &a < stackaddr
264 || (void *) &a >= stackaddr + stacksize)
265 {
266 error (status: 0, errnum: 0, format: "pthread_attr_getstack returned range does not cover main's stack");
267 result = 1;
268 }
269 else
270 printf (format: "initial thread stack %p-%p (0x%zx)\n", stackaddr,
271 stackaddr + stacksize, stacksize);
272
273 size_t guardsize;
274 err = pthread_attr_getguardsize (attr: &a, guardsize: &guardsize);
275 if (err)
276 {
277 error (status: 0, errnum: err, format: "pthread_attr_getguardsize failed");
278 result = 1;
279 }
280 else if (guardsize != 0)
281 {
282 error (status: 0, errnum: 0, format: "pthread_attr_getguardsize returned %zd != 0",
283 guardsize);
284 result = 1;
285 }
286
287 int scope;
288 err = pthread_attr_getscope (attr: &a, scope: &scope);
289 if (err)
290 {
291 error (status: 0, errnum: err, format: "pthread_attr_getscope failed");
292 result = 1;
293 }
294 else if (scope != PTHREAD_SCOPE_SYSTEM)
295 {
296 error (status: 0, errnum: 0, format: "pthread_attr_getscope returned %d != PTHREAD_SCOPE_SYSTEM",
297 scope);
298 result = 1;
299 }
300
301 int inheritsched;
302 err = pthread_attr_getinheritsched (attr: &a, inherit: &inheritsched);
303 if (err)
304 {
305 error (status: 0, errnum: err, format: "pthread_attr_getinheritsched failed");
306 result = 1;
307 }
308 else if (inheritsched != PTHREAD_INHERIT_SCHED)
309 {
310 error (status: 0, errnum: 0, format: "pthread_attr_getinheritsched returned %d != PTHREAD_INHERIT_SCHED",
311 inheritsched);
312 result = 1;
313 }
314
315 err = pthread_getaffinity_np (th: pthread_self (), cpusetsize: sizeof (c1), cpuset: &c1);
316 if (err == 0)
317 {
318 err = pthread_attr_getaffinity_np (attr: &a, cpusetsize: sizeof (c2), cpuset: &c2);
319 if (err)
320 {
321 error (status: 0, errnum: err, format: "pthread_attr_getaffinity_np failed");
322 result = 1;
323 }
324 else if (memcmp (&c1, &c2, sizeof (c1)))
325 {
326 error (status: 0, errnum: 0, format: "pthread_attr_getaffinity_np returned different CPU mask than pthread_getattr_np");
327 result = 1;
328 }
329 }
330
331 err = pthread_attr_destroy (attr: &a);
332 if (err)
333 {
334 error (status: 0, errnum: err, format: "pthread_attr_destroy failed");
335 result = 1;
336 }
337
338 pthread_t th;
339 err = pthread_create (newthread: &th, NULL, start_routine: tf, NULL);
340 if (err)
341 {
342 error (status: 0, errnum: err, format: "pthread_create #1 failed");
343 result = 1;
344 }
345 else
346 {
347 void *ret;
348 err = pthread_join (th: th, thread_return: &ret);
349 if (err)
350 {
351 error (status: 0, errnum: err, format: "pthread_join #1 failed");
352 result = 1;
353 }
354 else if (ret != NULL)
355 result = 1;
356 }
357
358 err = pthread_attr_init (attr: &a);
359 if (err)
360 {
361 error (status: 0, errnum: err, format: "pthread_attr_init failed");
362 result = 1;
363 }
364
365 DIAG_PUSH_NEEDS_COMMENT;
366#if __GNUC_PREREQ (7, 0)
367 /* GCC 8 warns about aliasing of the restrict-qualified arguments
368 passed &a. Since pthread_create does not dereference its fourth
369 argument, this aliasing, which is deliberate in this test, cannot
370 in fact cause problems. */
371 DIAG_IGNORE_NEEDS_COMMENT (8, "-Wrestrict");
372#endif
373 err = pthread_create (newthread: &th, attr: &a, start_routine: tf, arg: &a);
374 DIAG_POP_NEEDS_COMMENT;
375 if (err)
376 {
377 error (status: 0, errnum: err, format: "pthread_create #2 failed");
378 result = 1;
379 }
380 else
381 {
382 void *ret;
383 err = pthread_join (th: th, thread_return: &ret);
384 if (err)
385 {
386 error (status: 0, errnum: err, format: "pthread_join #2 failed");
387 result = 1;
388 }
389 else if (ret != NULL)
390 result = 1;
391 }
392
393 err = pthread_attr_setguardsize (attr: &a, guardsize: 16 * sysconf (_SC_PAGESIZE));
394 if (err)
395 {
396 error (status: 0, errnum: err, format: "pthread_attr_setguardsize failed");
397 result = 1;
398 }
399
400 DIAG_PUSH_NEEDS_COMMENT;
401#if __GNUC_PREREQ (7, 0)
402 /* GCC 8 warns about aliasing of the restrict-qualified arguments
403 passed &a. Since pthread_create does not dereference its fourth
404 argument, this aliasing, which is deliberate in this test, cannot
405 in fact cause problems. */
406 DIAG_IGNORE_NEEDS_COMMENT (8, "-Wrestrict");
407#endif
408 err = pthread_create (newthread: &th, attr: &a, start_routine: tf, arg: &a);
409 DIAG_POP_NEEDS_COMMENT;
410 if (err)
411 {
412 error (status: 0, errnum: err, format: "pthread_create #3 failed");
413 result = 1;
414 }
415 else
416 {
417 void *ret;
418 err = pthread_join (th: th, thread_return: &ret);
419 if (err)
420 {
421 error (status: 0, errnum: err, format: "pthread_join #3 failed");
422 result = 1;
423 }
424 else if (ret != NULL)
425 result = 1;
426 }
427
428 err = pthread_attr_destroy (attr: &a);
429 if (err)
430 {
431 error (status: 0, errnum: err, format: "pthread_attr_destroy failed");
432 result = 1;
433 }
434
435 return result;
436}
437
438#define TEST_FUNCTION do_test ()
439#include "../test-skeleton.c"
440

source code of glibc/nptl/tst-attr3.c