pthread_attr.c revision 1.18.4.1 1 /* $NetBSD: pthread_attr.c,v 1.18.4.1 2020/04/08 14:07:15 martin Exp $ */
2
3 /*-
4 * Copyright (c) 2001, 2002, 2003, 2008 The NetBSD Foundation, Inc.
5 * All rights reserved.
6 *
7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Nathan J. Williams.
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE.
30 */
31
32 #include <sys/cdefs.h>
33 __RCSID("$NetBSD: pthread_attr.c,v 1.18.4.1 2020/04/08 14:07:15 martin Exp $");
34
35 #include <errno.h>
36 #include <stdio.h>
37 #include <stdlib.h>
38 #include <string.h>
39 #include <unistd.h>
40
41 #ifndef __lint__
42 #define pthread_attr_get_np _pthread_attr_get_np
43 #endif
44
45 #include "pthread.h"
46 #include "pthread_int.h"
47
48 __weak_alias(pthread_attr_get_np, _pthread_attr_get_np)
49
50 static struct pthread_attr_private *pthread__attr_init_private(
51 pthread_attr_t *);
52
53 static struct pthread_attr_private *
54 pthread__attr_init_private(pthread_attr_t *attr)
55 {
56 struct pthread_attr_private *p;
57
58 if ((p = attr->pta_private) != NULL)
59 return p;
60
61 p = calloc(1, sizeof(*p));
62 if (p != NULL) {
63 attr->pta_private = p;
64 p->ptap_policy = SCHED_OTHER;
65 p->ptap_stacksize = pthread__stacksize;
66 p->ptap_guardsize = pthread__guardsize;
67 }
68 return p;
69 }
70
71
72 int
73 pthread_attr_init(pthread_attr_t *attr)
74 {
75
76 attr->pta_magic = PT_ATTR_MAGIC;
77 attr->pta_flags = 0;
78 attr->pta_private = NULL;
79
80 return 0;
81 }
82
83
84 int
85 pthread_attr_destroy(pthread_attr_t *attr)
86 {
87 struct pthread_attr_private *p;
88
89 pthread__error(EINVAL, "Invalid attribute",
90 attr->pta_magic == PT_ATTR_MAGIC);
91
92 if ((p = attr->pta_private) != NULL)
93 free(p);
94
95 attr->pta_magic = PT_ATTR_DEAD;
96
97 return 0;
98 }
99
100
101 int
102 pthread_attr_get_np(pthread_t thread, pthread_attr_t *attr)
103 {
104 struct pthread_attr_private *p;
105
106 pthread__error(EINVAL, "Invalid attribute",
107 attr->pta_magic == PT_ATTR_MAGIC);
108
109 p = pthread__attr_init_private(attr);
110 if (p == NULL)
111 return ENOMEM;
112
113 attr->pta_flags = thread->pt_flags &
114 (PT_FLAG_DETACHED | PT_FLAG_SCOPE_SYSTEM | PT_FLAG_EXPLICIT_SCHED);
115
116 p->ptap_namearg = thread->pt_name;
117 p->ptap_stackaddr = thread->pt_stack.ss_sp;
118 p->ptap_stacksize = thread->pt_stack.ss_size;
119 p->ptap_guardsize = thread->pt_guardsize;
120 return pthread_getschedparam(thread, &p->ptap_policy, &p->ptap_sp);
121 }
122
123
124 int
125 pthread_attr_getdetachstate(const pthread_attr_t *attr, int *detachstate)
126 {
127
128 pthread__error(EINVAL, "Invalid attribute",
129 attr->pta_magic == PT_ATTR_MAGIC);
130
131 if (attr->pta_flags & PT_FLAG_DETACHED)
132 *detachstate = PTHREAD_CREATE_DETACHED;
133 else
134 *detachstate = PTHREAD_CREATE_JOINABLE;
135
136 return 0;
137 }
138
139
140 int
141 pthread_attr_setdetachstate(pthread_attr_t *attr, int detachstate)
142 {
143
144 pthread__error(EINVAL, "Invalid attribute",
145 attr->pta_magic == PT_ATTR_MAGIC);
146
147 switch (detachstate) {
148 case PTHREAD_CREATE_JOINABLE:
149 attr->pta_flags &= ~PT_FLAG_DETACHED;
150 break;
151 case PTHREAD_CREATE_DETACHED:
152 attr->pta_flags |= PT_FLAG_DETACHED;
153 break;
154 default:
155 return EINVAL;
156 }
157
158 return 0;
159 }
160
161
162 int
163 pthread_attr_getguardsize(const pthread_attr_t *attr, size_t *guard)
164 {
165 struct pthread_attr_private *p;
166
167 pthread__error(EINVAL, "Invalid attribute",
168 attr->pta_magic == PT_ATTR_MAGIC);
169
170 if ((p = attr->pta_private) == NULL)
171 *guard = pthread__guardsize;
172 else
173 *guard = p->ptap_guardsize;
174
175 return 0;
176 }
177
178
179 int
180 pthread_attr_setguardsize(pthread_attr_t *attr, size_t guard)
181 {
182 struct pthread_attr_private *p;
183
184 pthread__error(EINVAL, "Invalid attribute",
185 attr->pta_magic == PT_ATTR_MAGIC);
186
187 p = pthread__attr_init_private(attr);
188 if (p == NULL)
189 return ENOMEM;
190
191 p->ptap_guardsize = guard;
192
193 return 0;
194 }
195
196
197 int
198 pthread_attr_getinheritsched(const pthread_attr_t *attr, int *inherit)
199 {
200
201 pthread__error(EINVAL, "Invalid attribute",
202 attr->pta_magic == PT_ATTR_MAGIC);
203
204 if (attr->pta_flags & PT_FLAG_EXPLICIT_SCHED)
205 *inherit = PTHREAD_EXPLICIT_SCHED;
206 else
207 *inherit = PTHREAD_INHERIT_SCHED;
208
209 return 0;
210 }
211
212
213 int
214 pthread_attr_setinheritsched(pthread_attr_t *attr, int inherit)
215 {
216
217 pthread__error(EINVAL, "Invalid attribute",
218 attr->pta_magic == PT_ATTR_MAGIC);
219
220 switch (inherit) {
221 case PTHREAD_INHERIT_SCHED:
222 attr->pta_flags &= ~PT_FLAG_EXPLICIT_SCHED;
223 break;
224 case PTHREAD_EXPLICIT_SCHED:
225 attr->pta_flags |= PT_FLAG_EXPLICIT_SCHED;
226 break;
227 default:
228 return EINVAL;
229 }
230
231 return 0;
232 }
233
234
235 int
236 pthread_attr_getscope(const pthread_attr_t *attr, int *scope)
237 {
238
239 pthread__error(EINVAL, "Invalid attribute",
240 attr->pta_magic == PT_ATTR_MAGIC);
241
242 if (attr->pta_flags & PT_FLAG_SCOPE_SYSTEM)
243 *scope = PTHREAD_SCOPE_SYSTEM;
244 else
245 *scope = PTHREAD_SCOPE_PROCESS;
246
247 return 0;
248 }
249
250
251 int
252 pthread_attr_setscope(pthread_attr_t *attr, int scope)
253 {
254
255 pthread__error(EINVAL, "Invalid attribute",
256 attr->pta_magic == PT_ATTR_MAGIC);
257
258 switch (scope) {
259 case PTHREAD_SCOPE_PROCESS:
260 attr->pta_flags &= ~PT_FLAG_SCOPE_SYSTEM;
261 break;
262 case PTHREAD_SCOPE_SYSTEM:
263 attr->pta_flags |= PT_FLAG_SCOPE_SYSTEM;
264 break;
265 default:
266 return EINVAL;
267 }
268
269 return 0;
270 }
271
272
273 int
274 pthread_attr_setschedparam(pthread_attr_t *attr,
275 const struct sched_param *param)
276 {
277 struct pthread_attr_private *p;
278 int error;
279
280 pthread__error(EINVAL, "Invalid attribute",
281 attr->pta_magic == PT_ATTR_MAGIC);
282
283 if (param == NULL)
284 return EINVAL;
285 p = pthread__attr_init_private(attr);
286 if (p == NULL)
287 return ENOMEM;
288 error = pthread__checkpri(param->sched_priority);
289 if (error == 0)
290 p->ptap_sp = *param;
291 return error;
292 }
293
294
295 int
296 pthread_attr_getschedparam(const pthread_attr_t *attr,
297 struct sched_param *param)
298 {
299 struct pthread_attr_private *p;
300
301 pthread__error(EINVAL, "Invalid attribute",
302 attr->pta_magic == PT_ATTR_MAGIC);
303
304 if (param == NULL)
305 return EINVAL;
306 p = attr->pta_private;
307 if (p == NULL)
308 memset(param, 0, sizeof(*param));
309 else
310 *param = p->ptap_sp;
311 return 0;
312 }
313
314
315 int
316 pthread_attr_setschedpolicy(pthread_attr_t *attr, int policy)
317 {
318 struct pthread_attr_private *p;
319
320 pthread__error(EINVAL, "Invalid attribute",
321 attr->pta_magic == PT_ATTR_MAGIC);
322
323 switch (policy) {
324 case SCHED_OTHER:
325 case SCHED_FIFO:
326 case SCHED_RR:
327 p = pthread__attr_init_private(attr);
328 if (p == NULL)
329 return ENOMEM;
330 p->ptap_policy = policy;
331 return 0;
332 default:
333 return ENOTSUP;
334 }
335 }
336
337
338 int
339 pthread_attr_getschedpolicy(const pthread_attr_t *attr, int *policy)
340 {
341 struct pthread_attr_private *p;
342
343 pthread__error(EINVAL, "Invalid attribute",
344 attr->pta_magic == PT_ATTR_MAGIC);
345
346 p = attr->pta_private;
347 if (p == NULL) {
348 *policy = SCHED_OTHER;
349 return 0;
350 }
351 *policy = p->ptap_policy;
352 return 0;
353 }
354
355
356 int
357 pthread_attr_getstack(const pthread_attr_t *attr, void **addr, size_t *size)
358 {
359 struct pthread_attr_private *p;
360
361 pthread__error(EINVAL, "Invalid attribute",
362 attr->pta_magic == PT_ATTR_MAGIC);
363
364 if ((p = attr->pta_private) == NULL) {
365 *addr = NULL;
366 *size = pthread__stacksize;
367 } else {
368 *addr = p->ptap_stackaddr;
369 *size = p->ptap_stacksize;
370 }
371
372 return 0;
373 }
374
375
376 int
377 pthread_attr_setstack(pthread_attr_t *attr, void *addr, size_t size)
378 {
379 struct pthread_attr_private *p;
380
381 pthread__error(EINVAL, "Invalid attribute",
382 attr->pta_magic == PT_ATTR_MAGIC);
383
384 p = pthread__attr_init_private(attr);
385 if (p == NULL)
386 return ENOMEM;
387
388 p->ptap_stackaddr = addr;
389 p->ptap_stacksize = size;
390
391 return 0;
392 }
393
394
395 int
396 pthread_attr_getstacksize(const pthread_attr_t *attr, size_t *size)
397 {
398 struct pthread_attr_private *p;
399
400 pthread__error(EINVAL, "Invalid attribute",
401 attr->pta_magic == PT_ATTR_MAGIC);
402
403 if ((p = attr->pta_private) == NULL)
404 *size = pthread__stacksize;
405 else
406 *size = p->ptap_stacksize;
407
408 return 0;
409 }
410
411
412 int
413 pthread_attr_setstacksize(pthread_attr_t *attr, size_t size)
414 {
415 struct pthread_attr_private *p;
416
417 pthread__error(EINVAL, "Invalid attribute",
418 attr->pta_magic == PT_ATTR_MAGIC);
419
420 if (size < (size_t)sysconf(_SC_THREAD_STACK_MIN))
421 return EINVAL;
422
423 p = pthread__attr_init_private(attr);
424 if (p == NULL)
425 return ENOMEM;
426
427 p->ptap_stacksize = size;
428
429 return 0;
430 }
431
432
433 int
434 pthread_attr_getstackaddr(const pthread_attr_t *attr, void **addr)
435 {
436 struct pthread_attr_private *p;
437
438 pthread__error(EINVAL, "Invalid attribute",
439 attr->pta_magic == PT_ATTR_MAGIC);
440
441 if ((p = attr->pta_private) == NULL)
442 *addr = NULL;
443 else
444 *addr = p->ptap_stackaddr;
445
446 return 0;
447 }
448
449
450 int
451 pthread_attr_setstackaddr(pthread_attr_t *attr, void *addr)
452 {
453 struct pthread_attr_private *p;
454
455 pthread__error(EINVAL, "Invalid attribute",
456 attr->pta_magic == PT_ATTR_MAGIC);
457
458 p = pthread__attr_init_private(attr);
459 if (p == NULL)
460 return ENOMEM;
461
462 p->ptap_stackaddr = addr;
463
464 return 0;
465 }
466
467
468 int
469 pthread_attr_getname_np(const pthread_attr_t *attr, char *name, size_t len,
470 void **argp)
471 {
472 struct pthread_attr_private *p;
473
474 pthread__error(EINVAL, "Invalid attribute",
475 attr->pta_magic == PT_ATTR_MAGIC);
476
477 if ((p = attr->pta_private) == NULL) {
478 name[0] = '\0';
479 if (argp != NULL)
480 *argp = NULL;
481 } else {
482 strlcpy(name, p->ptap_name, len);
483 if (argp != NULL)
484 *argp = p->ptap_namearg;
485 }
486
487 return 0;
488 }
489
490
491 int
492 pthread_attr_setname_np(pthread_attr_t *attr, const char *name, void *arg)
493 {
494 struct pthread_attr_private *p;
495 int namelen;
496
497 pthread__error(EINVAL, "Invalid attribute",
498 attr->pta_magic == PT_ATTR_MAGIC);
499
500 p = pthread__attr_init_private(attr);
501 if (p == NULL)
502 return ENOMEM;
503
504 namelen = snprintf(p->ptap_name, PTHREAD_MAX_NAMELEN_NP, name, arg);
505 if (namelen >= PTHREAD_MAX_NAMELEN_NP) {
506 p->ptap_name[0] = '\0';
507 return EINVAL;
508 }
509 p->ptap_namearg = arg;
510
511 return 0;
512 }
513
514 int
515 pthread_attr_setcreatesuspend_np(pthread_attr_t *attr)
516 {
517
518 pthread__error(EINVAL, "Invalid attribute",
519 attr->pta_magic == PT_ATTR_MAGIC);
520
521 attr->pta_flags |= PT_FLAG_SUSPENDED;
522 return 0;
523 }
524
525 int
526 pthread_getattr_np(pthread_t thread, pthread_attr_t *attr)
527 {
528 int error;
529
530 if ((error = pthread_attr_init(attr)) != 0)
531 return error;
532 if ((error = pthread_attr_get_np(thread, attr)) != 0) {
533 (void)pthread_attr_destroy(attr);
534 return error;
535 }
536 return 0;
537 }
538