thr_attr.c revision 214653
1169689Skan/*
2169689Skan * Copyright (c) 2003 Craig Rodrigues <rodrigc@attbi.com>.
3169689Skan * All rights reserved.
4169689Skan *
5169689Skan * Redistribution and use in source and binary forms, with or without
6169689Skan * modification, are permitted provided that the following conditions
7169689Skan * are met:
8169689Skan * 1. Redistributions of source code must retain the above copyright
9169689Skan *    notice, this list of conditions and the following disclaimer.
10169689Skan * 2. Redistributions in binary form must reproduce the above copyright
11169689Skan *    notice, this list of conditions and the following disclaimer in the
12169689Skan *    documentation and/or other materials provided with the distribution.
13169689Skan * 3. All advertising materials mentioning features or use of this software
14169689Skan *    must display the following acknowledgement:
15169689Skan *	This product includes software developed by Craig Rodrigues.
16169689Skan * 4. Neither the name of the author nor the names of any co-contributors
17169689Skan *    may be used to endorse or promote products derived from this software
18169689Skan *    without specific prior written permission.
19169689Skan *
20169689Skan * THIS SOFTWARE IS PROVIDED BY CRAIG RODRIGUES AND CONTRIBUTORS ``AS IS'' AND
21169689Skan * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22169689Skan * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23169689Skan * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
24169689Skan * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25169689Skan * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26169689Skan * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27169689Skan * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28169689Skan * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29169689Skan * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30169689Skan * SUCH DAMAGE.
31169689Skan *
32169689Skan */
33169689Skan
34169689Skan/*
35169689Skan * Copyright (c) 1998 Daniel Eischen <eischen@vigrid.com>.
36169689Skan * Copyright (C) 2001 Jason Evans <jasone@freebsd.org>.
37169689Skan * Copyright (c) 2002,2003 Alexey Zelkin <phantom@FreeBSD.org>
38169689Skan * All rights reserved.
39169689Skan *
40169689Skan * Redistribution and use in source and binary forms, with or without
41169689Skan * modification, are permitted provided that the following conditions
42169689Skan * are met:
43169689Skan * 1. Redistributions of source code must retain the above copyright
44169689Skan *    notice(s), this list of conditions and the following disclaimer
45169689Skan *    unmodified other than the allowable addition of one or more
46169689Skan *    copyright notices.
47169689Skan * 2. Redistributions in binary form must reproduce the above copyright
48169689Skan *    notice(s), this list of conditions and the following disclaimer in
49169689Skan *    the documentation and/or other materials provided with the
50169689Skan *    distribution.
51169689Skan *
52169689Skan * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) ``AS IS'' AND ANY
53169689Skan * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
54169689Skan * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
55169689Skan * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) BE
56169689Skan * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
57169689Skan * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
58169689Skan * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
59169689Skan * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
60169689Skan * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
61169689Skan * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
62169689Skan * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
63169689Skan */
64169689Skan
65169689Skan/*
66169689Skan * Copyright (c) 1996 John Birrell <jb@cimlogic.com.au>.
67169689Skan * All rights reserved.
68169689Skan *
69169689Skan * Redistribution and use in source and binary forms, with or without
70169689Skan * modification, are permitted provided that the following conditions
71169689Skan * are met:
72169689Skan * 1. Redistributions of source code must retain the above copyright
73169689Skan *    notice, this list of conditions and the following disclaimer.
74169689Skan * 2. Redistributions in binary form must reproduce the above copyright
75169689Skan *    notice, this list of conditions and the following disclaimer in the
76169689Skan *    documentation and/or other materials provided with the distribution.
77169689Skan * 3. Neither the name of the author nor the names of any co-contributors
78169689Skan *    may be used to endorse or promote products derived from this software
79169689Skan *    without specific prior written permission.
80169689Skan *
81169689Skan * THIS SOFTWARE IS PROVIDED BY JOHN BIRRELL AND CONTRIBUTORS ``AS IS'' AND
82169689Skan * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
83169689Skan * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
84169689Skan * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
85169689Skan * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
86169689Skan * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
87169689Skan * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
88169689Skan * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
89169689Skan * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
90169689Skan * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
91169689Skan * SUCH DAMAGE.
92169689Skan *
93169689Skan * $FreeBSD: head/lib/libthr/thread/thr_attr.c 214653 2010-11-02 02:13:13Z davidxu $
94169689Skan */
95169689Skan
96169689Skan#include "namespace.h"
97169689Skan#include <errno.h>
98169689Skan#include <pthread.h>
99169689Skan#include <stdlib.h>
100169689Skan#include <string.h>
101169689Skan#include <pthread_np.h>
102169689Skan#include <sys/sysctl.h>
103169689Skan#include "un-namespace.h"
104169689Skan
105169689Skan#include "thr_private.h"
106169689Skan
107169689Skanstatic size_t	_get_kern_cpuset_size(void);
108169689Skan
109169689Skan__weak_reference(_pthread_attr_destroy, pthread_attr_destroy);
110169689Skan
111169689Skanint
112169689Skan_pthread_attr_destroy(pthread_attr_t *attr)
113169689Skan{
114169689Skan	int	ret;
115169689Skan
116169689Skan	/* Check for invalid arguments: */
117169689Skan	if (attr == NULL || *attr == NULL)
118169689Skan		/* Invalid argument: */
119169689Skan		ret = EINVAL;
120169689Skan	else {
121169689Skan		if ((*attr)->cpuset != NULL)
122169689Skan			free((*attr)->cpuset);
123169689Skan		/* Free the memory allocated to the attribute object: */
124169689Skan		free(*attr);
125169689Skan
126169689Skan		/*
127169689Skan		 * Leave the attribute pointer NULL now that the memory
128169689Skan		 * has been freed:
129169689Skan		 */
130169689Skan		*attr = NULL;
131169689Skan		ret = 0;
132169689Skan	}
133169689Skan	return(ret);
134169689Skan}
135169689Skan
136169689Skan__weak_reference(_pthread_attr_get_np, pthread_attr_get_np);
137169689Skan
138169689Skanint
139169689Skan_pthread_attr_get_np(pthread_t pthread, pthread_attr_t *dstattr)
140169689Skan{
141169689Skan	struct pthread *curthread;
142169689Skan	struct pthread_attr attr, *dst;
143169689Skan	int	ret;
144169689Skan	size_t	kern_size;
145169689Skan
146169689Skan	if (pthread == NULL || dstattr == NULL || (dst = *dstattr) == NULL)
147169689Skan		return (EINVAL);
148169689Skan	kern_size = _get_kern_cpuset_size();
149169689Skan	if (dst->cpuset == NULL) {
150169689Skan		dst->cpuset = calloc(1, kern_size);
151169689Skan		dst->cpusetsize = kern_size;
152169689Skan	}
153169689Skan	curthread = _get_curthread();
154169689Skan	if ((ret = _thr_find_thread(curthread, pthread, /*include dead*/0)) != 0)
155169689Skan		return (ret);
156169689Skan	attr = pthread->attr;
157169689Skan	if (pthread->flags & THR_FLAGS_DETACHED)
158169689Skan		attr.flags |= PTHREAD_DETACHED;
159169689Skan	ret = cpuset_getaffinity(CPU_LEVEL_WHICH, CPU_WHICH_TID, TID(pthread),
160169689Skan		dst->cpusetsize, dst->cpuset);
161169689Skan	if (ret == -1)
162169689Skan		ret = errno;
163169689Skan	THR_THREAD_UNLOCK(curthread, pthread);
164169689Skan	if (ret == 0) {
165169689Skan		memcpy(&dst->pthread_attr_start_copy,
166169689Skan			&attr.pthread_attr_start_copy,
167169689Skan			offsetof(struct pthread_attr, pthread_attr_end_copy) -
168169689Skan			offsetof(struct pthread_attr, pthread_attr_start_copy));
169169689Skan	}
170169689Skan	return (ret);
171169689Skan}
172169689Skan
173169689Skan__weak_reference(_pthread_attr_getdetachstate, pthread_attr_getdetachstate);
174169689Skan
175169689Skanint
176169689Skan_pthread_attr_getdetachstate(const pthread_attr_t *attr, int *detachstate)
177169689Skan{
178169689Skan	int	ret;
179169689Skan
180169689Skan	/* Check for invalid arguments: */
181169689Skan	if (attr == NULL || *attr == NULL || detachstate == NULL)
182169689Skan		ret = EINVAL;
183169689Skan	else {
184169689Skan		/* Check if the detached flag is set: */
185169689Skan		if ((*attr)->flags & PTHREAD_DETACHED)
186169689Skan			/* Return detached: */
187169689Skan			*detachstate = PTHREAD_CREATE_DETACHED;
188169689Skan		else
189169689Skan			/* Return joinable: */
190169689Skan			*detachstate = PTHREAD_CREATE_JOINABLE;
191169689Skan		ret = 0;
192169689Skan	}
193169689Skan	return(ret);
194169689Skan}
195169689Skan
196169689Skan__weak_reference(_pthread_attr_getguardsize, pthread_attr_getguardsize);
197169689Skan
198169689Skanint
199169689Skan_pthread_attr_getguardsize(const pthread_attr_t *attr, size_t *guardsize)
200169689Skan{
201169689Skan	int	ret;
202169689Skan
203169689Skan	/* Check for invalid arguments: */
204169689Skan	if (attr == NULL || *attr == NULL || guardsize == NULL)
205169689Skan		ret = EINVAL;
206169689Skan	else {
207169689Skan		/* Return the guard size: */
208169689Skan		*guardsize = (*attr)->guardsize_attr;
209169689Skan		ret = 0;
210169689Skan	}
211169689Skan	return(ret);
212169689Skan}
213169689Skan
214169689Skan__weak_reference(_pthread_attr_getinheritsched, pthread_attr_getinheritsched);
215169689Skan
216169689Skanint
217169689Skan_pthread_attr_getinheritsched(const pthread_attr_t *attr, int *sched_inherit)
218169689Skan{
219169689Skan	int ret = 0;
220169689Skan
221169689Skan	if ((attr == NULL) || (*attr == NULL))
222169689Skan		ret = EINVAL;
223169689Skan	else
224169689Skan		*sched_inherit = (*attr)->sched_inherit;
225169689Skan
226169689Skan	return(ret);
227169689Skan}
228169689Skan
229169689Skan__weak_reference(_pthread_attr_getschedparam, pthread_attr_getschedparam);
230169689Skan
231169689Skanint
232169689Skan_pthread_attr_getschedparam(const pthread_attr_t *attr, struct sched_param *param)
233169689Skan{
234169689Skan	int ret = 0;
235169689Skan
236169689Skan	if ((attr == NULL) || (*attr == NULL) || (param == NULL))
237169689Skan		ret = EINVAL;
238169689Skan	else
239169689Skan		param->sched_priority = (*attr)->prio;
240169689Skan
241169689Skan	return(ret);
242169689Skan}
243169689Skan
244169689Skan__weak_reference(_pthread_attr_getschedpolicy, pthread_attr_getschedpolicy);
245169689Skan
246169689Skanint
247169689Skan_pthread_attr_getschedpolicy(const pthread_attr_t *attr, int *policy)
248169689Skan{
249169689Skan	int ret = 0;
250169689Skan
251169689Skan	if ((attr == NULL) || (*attr == NULL) || (policy == NULL))
252169689Skan		ret = EINVAL;
253169689Skan	else
254169689Skan		*policy = (*attr)->sched_policy;
255169689Skan
256169689Skan	return(ret);
257169689Skan}
258169689Skan
259169689Skan__weak_reference(_pthread_attr_getscope, pthread_attr_getscope);
260169689Skan
261169689Skanint
262169689Skan_pthread_attr_getscope(const pthread_attr_t *attr, int *contentionscope)
263169689Skan{
264169689Skan	int ret = 0;
265169689Skan
266169689Skan	if ((attr == NULL) || (*attr == NULL) || (contentionscope == NULL))
267169689Skan		/* Return an invalid argument: */
268169689Skan		ret = EINVAL;
269169689Skan
270169689Skan	else
271169689Skan		*contentionscope = (*attr)->flags & PTHREAD_SCOPE_SYSTEM ?
272169689Skan		    PTHREAD_SCOPE_SYSTEM : PTHREAD_SCOPE_PROCESS;
273169689Skan
274169689Skan	return(ret);
275169689Skan}
276169689Skan
277169689Skan__weak_reference(_pthread_attr_getstack, pthread_attr_getstack);
278169689Skan
279169689Skanint
280169689Skan_pthread_attr_getstack(const pthread_attr_t * __restrict attr,
281169689Skan                        void ** __restrict stackaddr,
282169689Skan                        size_t * __restrict stacksize)
283169689Skan{
284169689Skan	int     ret;
285169689Skan
286169689Skan	/* Check for invalid arguments: */
287169689Skan	if (attr == NULL || *attr == NULL || stackaddr == NULL
288169689Skan	    || stacksize == NULL )
289169689Skan		ret = EINVAL;
290169689Skan	else {
291169689Skan		/* Return the stack address and size */
292169689Skan		*stackaddr = (*attr)->stackaddr_attr;
293169689Skan		*stacksize = (*attr)->stacksize_attr;
294169689Skan		ret = 0;
295169689Skan	}
296169689Skan	return(ret);
297169689Skan}
298169689Skan
299169689Skan__weak_reference(_pthread_attr_getstackaddr, pthread_attr_getstackaddr);
300169689Skan
301169689Skanint
302169689Skan_pthread_attr_getstackaddr(const pthread_attr_t *attr, void **stackaddr)
303169689Skan{
304169689Skan	int	ret;
305169689Skan
306169689Skan	/* Check for invalid arguments: */
307169689Skan	if (attr == NULL || *attr == NULL || stackaddr == NULL)
308169689Skan		ret = EINVAL;
309169689Skan	else {
310169689Skan		/* Return the stack address: */
311169689Skan		*stackaddr = (*attr)->stackaddr_attr;
312169689Skan		ret = 0;
313169689Skan	}
314169689Skan	return(ret);
315169689Skan}
316169689Skan
317169689Skan__weak_reference(_pthread_attr_getstacksize, pthread_attr_getstacksize);
318169689Skan
319169689Skanint
320169689Skan_pthread_attr_getstacksize(const pthread_attr_t *attr, size_t *stacksize)
321169689Skan{
322169689Skan	int	ret;
323169689Skan
324169689Skan	/* Check for invalid arguments: */
325169689Skan	if (attr == NULL || *attr == NULL || stacksize  == NULL)
326169689Skan		ret = EINVAL;
327169689Skan	else {
328169689Skan		/* Return the stack size: */
329169689Skan		*stacksize = (*attr)->stacksize_attr;
330169689Skan		ret = 0;
331169689Skan	}
332169689Skan	return(ret);
333169689Skan}
334169689Skan
335169689Skan__weak_reference(_pthread_attr_init, pthread_attr_init);
336169689Skan
337169689Skanint
338169689Skan_pthread_attr_init(pthread_attr_t *attr)
339169689Skan{
340169689Skan	int	ret;
341169689Skan	pthread_attr_t	pattr;
342169689Skan
343169689Skan	_thr_check_init();
344169689Skan
345169689Skan	/* Allocate memory for the attribute object: */
346169689Skan	if ((pattr = (pthread_attr_t) malloc(sizeof(struct pthread_attr))) == NULL)
347169689Skan		/* Insufficient memory: */
348169689Skan		ret = ENOMEM;
349169689Skan	else {
350169689Skan		/* Initialise the attribute object with the defaults: */
351169689Skan		memcpy(pattr, &_pthread_attr_default, sizeof(struct pthread_attr));
352169689Skan
353169689Skan		/* Return a pointer to the attribute object: */
354169689Skan		*attr = pattr;
355169689Skan		ret = 0;
356169689Skan	}
357169689Skan	return(ret);
358169689Skan}
359169689Skan
360169689Skan__weak_reference(_pthread_attr_setcreatesuspend_np, pthread_attr_setcreatesuspend_np);
361169689Skan
362169689Skanint
363169689Skan_pthread_attr_setcreatesuspend_np(pthread_attr_t *attr)
364169689Skan{
365169689Skan	int	ret;
366169689Skan
367169689Skan	if (attr == NULL || *attr == NULL) {
368169689Skan		ret = EINVAL;
369169689Skan	} else {
370169689Skan		(*attr)->suspend = THR_CREATE_SUSPENDED;
371169689Skan		ret = 0;
372169689Skan	}
373169689Skan	return(ret);
374169689Skan}
375169689Skan
376169689Skan__weak_reference(_pthread_attr_setdetachstate, pthread_attr_setdetachstate);
377169689Skan
378169689Skanint
379169689Skan_pthread_attr_setdetachstate(pthread_attr_t *attr, int detachstate)
380169689Skan{
381169689Skan	int	ret;
382169689Skan
383169689Skan	/* Check for invalid arguments: */
384169689Skan	if (attr == NULL || *attr == NULL ||
385169689Skan	    (detachstate != PTHREAD_CREATE_DETACHED &&
386169689Skan	    detachstate != PTHREAD_CREATE_JOINABLE))
387169689Skan		ret = EINVAL;
388169689Skan	else {
389169689Skan		/* Check if detached state: */
390169689Skan		if (detachstate == PTHREAD_CREATE_DETACHED)
391169689Skan			/* Set the detached flag: */
392169689Skan			(*attr)->flags |= PTHREAD_DETACHED;
393169689Skan		else
394169689Skan			/* Reset the detached flag: */
395169689Skan			(*attr)->flags &= ~PTHREAD_DETACHED;
396169689Skan		ret = 0;
397169689Skan	}
398169689Skan	return(ret);
399169689Skan}
400169689Skan
401169689Skan__weak_reference(_pthread_attr_setguardsize, pthread_attr_setguardsize);
402169689Skan
403169689Skanint
404169689Skan_pthread_attr_setguardsize(pthread_attr_t *attr, size_t guardsize)
405169689Skan{
406169689Skan	int	ret;
407169689Skan
408169689Skan	/* Check for invalid arguments. */
409169689Skan	if (attr == NULL || *attr == NULL)
410169689Skan		ret = EINVAL;
411169689Skan	else {
412169689Skan		/* Save the stack size. */
413169689Skan		(*attr)->guardsize_attr = guardsize;
414169689Skan		ret = 0;
415169689Skan	}
416169689Skan	return(ret);
417169689Skan}
418169689Skan
419169689Skan__weak_reference(_pthread_attr_setinheritsched, pthread_attr_setinheritsched);
420169689Skan
421169689Skanint
422169689Skan_pthread_attr_setinheritsched(pthread_attr_t *attr, int sched_inherit)
423169689Skan{
424169689Skan	int ret = 0;
425169689Skan
426169689Skan	if ((attr == NULL) || (*attr == NULL))
427169689Skan		ret = EINVAL;
428169689Skan	else if (sched_inherit != PTHREAD_INHERIT_SCHED &&
429169689Skan		 sched_inherit != PTHREAD_EXPLICIT_SCHED)
430169689Skan		ret = ENOTSUP;
431169689Skan	else
432169689Skan		(*attr)->sched_inherit = sched_inherit;
433169689Skan
434169689Skan	return(ret);
435169689Skan}
436169689Skan
437169689Skan__weak_reference(_pthread_attr_setschedparam, pthread_attr_setschedparam);
438169689Skan
439169689Skanint
440169689Skan_pthread_attr_setschedparam(pthread_attr_t *attr, const struct sched_param *param)
441169689Skan{
442169689Skan	int policy;
443169689Skan
444169689Skan	if ((attr == NULL) || (*attr == NULL))
445169689Skan		return (EINVAL);
446169689Skan
447169689Skan	if (param == NULL)
448169689Skan		return (ENOTSUP);
449169689Skan
450169689Skan	policy = (*attr)->sched_policy;
451169689Skan
452169689Skan	if (policy == SCHED_FIFO || policy == SCHED_RR) {
453169689Skan		if (param->sched_priority < _thr_priorities[policy-1].pri_min ||
454169689Skan		    param->sched_priority > _thr_priorities[policy-1].pri_max)
455169689Skan		return (ENOTSUP);
456169689Skan	} else {
457169689Skan		/*
458169689Skan		 * Ignore it for SCHED_OTHER now, patches for glib ports
459169689Skan		 * are wrongly using M:N thread library's internal macro
460169689Skan		 * THR_MIN_PRIORITY and THR_MAX_PRIORITY.
461169689Skan		 */
462169689Skan	}
463169689Skan
464169689Skan	(*attr)->prio = param->sched_priority;
465169689Skan
466169689Skan	return (0);
467169689Skan}
468169689Skan
469169689Skan__weak_reference(_pthread_attr_setschedpolicy, pthread_attr_setschedpolicy);
470169689Skan
471169689Skanint
472169689Skan_pthread_attr_setschedpolicy(pthread_attr_t *attr, int policy)
473169689Skan{
474169689Skan	int ret = 0;
475169689Skan
476169689Skan	if ((attr == NULL) || (*attr == NULL))
477169689Skan		ret = EINVAL;
478169689Skan	else if ((policy < SCHED_FIFO) || (policy > SCHED_RR)) {
479169689Skan		ret = ENOTSUP;
480169689Skan	} else {
481169689Skan		(*attr)->sched_policy = policy;
482169689Skan		(*attr)->prio = _thr_priorities[policy-1].pri_default;
483169689Skan	}
484169689Skan	return(ret);
485169689Skan}
486169689Skan
487169689Skan__weak_reference(_pthread_attr_setscope, pthread_attr_setscope);
488169689Skan
489169689Skanint
490169689Skan_pthread_attr_setscope(pthread_attr_t *attr, int contentionscope)
491169689Skan{
492169689Skan	int ret = 0;
493169689Skan
494169689Skan	if ((attr == NULL) || (*attr == NULL)) {
495169689Skan		/* Return an invalid argument: */
496169689Skan		ret = EINVAL;
497169689Skan	} else if ((contentionscope != PTHREAD_SCOPE_PROCESS) &&
498169689Skan	    (contentionscope != PTHREAD_SCOPE_SYSTEM)) {
499169689Skan		ret = EINVAL;
500169689Skan	} else if (contentionscope == PTHREAD_SCOPE_SYSTEM) {
501169689Skan		(*attr)->flags |= contentionscope;
502169689Skan	} else {
503169689Skan		(*attr)->flags &= ~PTHREAD_SCOPE_SYSTEM;
504169689Skan	}
505169689Skan	return (ret);
506169689Skan}
507169689Skan
508169689Skan__weak_reference(_pthread_attr_setstack, pthread_attr_setstack);
509169689Skan
510169689Skanint
511169689Skan_pthread_attr_setstack(pthread_attr_t *attr, void *stackaddr,
512169689Skan                        size_t stacksize)
513169689Skan{
514169689Skan	int     ret;
515169689Skan
516169689Skan	/* Check for invalid arguments: */
517169689Skan	if (attr == NULL || *attr == NULL || stackaddr == NULL
518169689Skan	    || stacksize < PTHREAD_STACK_MIN)
519169689Skan		ret = EINVAL;
520169689Skan	else {
521169689Skan		/* Save the stack address and stack size */
522169689Skan		(*attr)->stackaddr_attr = stackaddr;
523169689Skan		(*attr)->stacksize_attr = stacksize;
524169689Skan		ret = 0;
525169689Skan	}
526169689Skan	return(ret);
527169689Skan}
528169689Skan
529169689Skan__weak_reference(_pthread_attr_setstackaddr, pthread_attr_setstackaddr);
530169689Skan
531169689Skanint
532169689Skan_pthread_attr_setstackaddr(pthread_attr_t *attr, void *stackaddr)
533169689Skan{
534169689Skan	int	ret;
535169689Skan
536169689Skan	/* Check for invalid arguments: */
537169689Skan	if (attr == NULL || *attr == NULL || stackaddr == NULL)
538169689Skan		ret = EINVAL;
539169689Skan	else {
540169689Skan		/* Save the stack address: */
541169689Skan		(*attr)->stackaddr_attr = stackaddr;
542169689Skan		ret = 0;
543169689Skan	}
544169689Skan	return(ret);
545169689Skan}
546169689Skan
547169689Skan__weak_reference(_pthread_attr_setstacksize, pthread_attr_setstacksize);
548169689Skan
549169689Skanint
550169689Skan_pthread_attr_setstacksize(pthread_attr_t *attr, size_t stacksize)
551169689Skan{
552169689Skan	int	ret;
553169689Skan
554169689Skan	/* Check for invalid arguments: */
555169689Skan	if (attr == NULL || *attr == NULL || stacksize < PTHREAD_STACK_MIN)
556169689Skan		ret = EINVAL;
557169689Skan	else {
558169689Skan		/* Save the stack size: */
559169689Skan		(*attr)->stacksize_attr = stacksize;
560169689Skan		ret = 0;
561169689Skan	}
562169689Skan	return(ret);
563169689Skan}
564169689Skan
565169689Skanstatic size_t
566169689Skan_get_kern_cpuset_size(void)
567169689Skan{
568169689Skan	static int kern_cpuset_size = 0;
569169689Skan
570169689Skan	if (kern_cpuset_size == 0) {
571169689Skan		size_t len;
572169689Skan
573169689Skan		len = sizeof(kern_cpuset_size);
574169689Skan		if (sysctlbyname("kern.sched.cpusetsize", &kern_cpuset_size,
575169689Skan		    &len, NULL, 0))
576169689Skan			PANIC("failed to get sysctl kern.sched.cpusetsize");
577169689Skan	}
578169689Skan
579169689Skan	return (kern_cpuset_size);
580169689Skan}
581169689Skan
582169689Skan__weak_reference(_pthread_attr_setaffinity_np, pthread_attr_setaffinity_np);
583169689Skanint
584169689Skan_pthread_attr_setaffinity_np(pthread_attr_t *pattr, size_t cpusetsize,
585169689Skan	const cpuset_t *cpusetp)
586169689Skan{
587169689Skan	pthread_attr_t attr;
588169689Skan	int ret;
589169689Skan
590169689Skan	if (pattr == NULL || (attr = (*pattr)) == NULL)
591169689Skan		ret = EINVAL;
592169689Skan	else {
593169689Skan		if (cpusetsize == 0 || cpusetp == NULL) {
594169689Skan			if (attr->cpuset != NULL) {
595169689Skan				free(attr->cpuset);
596169689Skan				attr->cpuset = NULL;
597169689Skan				attr->cpusetsize = 0;
598169689Skan			}
599169689Skan			return (0);
600169689Skan		}
601169689Skan		size_t kern_size = _get_kern_cpuset_size();
602169689Skan		/* Kernel rejects small set, we check it here too. */
603169689Skan		if (cpusetsize < kern_size)
604169689Skan			return (ERANGE);
605169689Skan		if (cpusetsize > kern_size) {
606169689Skan			/* Kernel checks invalid bits, we check it here too. */
607169689Skan			size_t i;
608169689Skan			for (i = kern_size; i < cpusetsize; ++i) {
609169689Skan				if (((char *)cpusetp)[i])
610169689Skan					return (EINVAL);
611169689Skan			}
612169689Skan		}
613169689Skan		if (attr->cpuset == NULL) {
614169689Skan			attr->cpuset = calloc(1, kern_size);
615169689Skan			if (attr->cpuset == NULL)
616169689Skan				return (errno);
617169689Skan			attr->cpusetsize = kern_size;
618169689Skan		}
619169689Skan		memcpy(attr->cpuset, cpusetp, kern_size);
620169689Skan		ret = 0;
621169689Skan	}
622169689Skan	return (ret);
623169689Skan}
624169689Skan
625169689Skan__weak_reference(_pthread_attr_getaffinity_np, pthread_attr_getaffinity_np);
626169689Skanint
627169689Skan_pthread_attr_getaffinity_np(const pthread_attr_t *pattr, size_t cpusetsize,
628169689Skan	cpuset_t *cpusetp)
629169689Skan{
630169689Skan	pthread_attr_t attr;
631169689Skan	int ret = 0;
632169689Skan
633169689Skan	if (pattr == NULL || (attr = (*pattr)) == NULL)
634169689Skan		ret = EINVAL;
635169689Skan	else {
636169689Skan		/* Kernel rejects small set, we check it here too. */
637169689Skan		size_t kern_size = _get_kern_cpuset_size();
638169689Skan		if (cpusetsize < kern_size)
639169689Skan			return (ERANGE);
640169689Skan		if (attr->cpuset != NULL)
641169689Skan			memcpy(cpusetp, attr->cpuset, MIN(cpusetsize,
642169689Skan			   attr->cpusetsize));
643169689Skan		else
644169689Skan			memset(cpusetp, -1, kern_size);
645169689Skan		if (cpusetsize > kern_size)
646169689Skan			memset(((char *)cpusetp) + kern_size, 0,
647169689Skan				cpusetsize - kern_size);
648169689Skan	}
649169689Skan	return (ret);
650169689Skan}
651169689Skan