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