thr_attr.c revision 214335
1112918Sjeff/*
2112918Sjeff * Copyright (c) 2003 Craig Rodrigues <rodrigc@attbi.com>.
3112918Sjeff * All rights reserved.
4112918Sjeff *
5112918Sjeff * Redistribution and use in source and binary forms, with or without
6112918Sjeff * modification, are permitted provided that the following conditions
7112918Sjeff * are met:
8112918Sjeff * 1. Redistributions of source code must retain the above copyright
9112918Sjeff *    notice, this list of conditions and the following disclaimer.
10112918Sjeff * 2. Redistributions in binary form must reproduce the above copyright
11112918Sjeff *    notice, this list of conditions and the following disclaimer in the
12112918Sjeff *    documentation and/or other materials provided with the distribution.
13112918Sjeff * 3. All advertising materials mentioning features or use of this software
14112918Sjeff *    must display the following acknowledgement:
15112918Sjeff *	This product includes software developed by Craig Rodrigues.
16112918Sjeff * 4. Neither the name of the author nor the names of any co-contributors
17112918Sjeff *    may be used to endorse or promote products derived from this software
18112918Sjeff *    without specific prior written permission.
19112918Sjeff *
20112918Sjeff * THIS SOFTWARE IS PROVIDED BY CRAIG RODRIGUES AND CONTRIBUTORS ``AS IS'' AND
21112918Sjeff * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22112918Sjeff * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23112918Sjeff * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
24112918Sjeff * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25112918Sjeff * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26112918Sjeff * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27112918Sjeff * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28112918Sjeff * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29112918Sjeff * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30112918Sjeff * SUCH DAMAGE.
31112918Sjeff *
32112918Sjeff */
33112918Sjeff
34112918Sjeff/*
35112918Sjeff * Copyright (c) 1998 Daniel Eischen <eischen@vigrid.com>.
36112918Sjeff * Copyright (C) 2001 Jason Evans <jasone@freebsd.org>.
37112918Sjeff * Copyright (c) 2002,2003 Alexey Zelkin <phantom@FreeBSD.org>
38112918Sjeff * All rights reserved.
39112918Sjeff *
40112918Sjeff * Redistribution and use in source and binary forms, with or without
41112918Sjeff * modification, are permitted provided that the following conditions
42112918Sjeff * are met:
43112918Sjeff * 1. Redistributions of source code must retain the above copyright
44112918Sjeff *    notice(s), this list of conditions and the following disclaimer
45112918Sjeff *    unmodified other than the allowable addition of one or more
46112918Sjeff *    copyright notices.
47112918Sjeff * 2. Redistributions in binary form must reproduce the above copyright
48112918Sjeff *    notice(s), this list of conditions and the following disclaimer in
49112918Sjeff *    the documentation and/or other materials provided with the
50112918Sjeff *    distribution.
51112918Sjeff *
52112918Sjeff * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) ``AS IS'' AND ANY
53112918Sjeff * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
54112918Sjeff * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
55112918Sjeff * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) BE
56112918Sjeff * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
57112918Sjeff * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
58112918Sjeff * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
59112918Sjeff * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
60112918Sjeff * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
61112918Sjeff * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
62112918Sjeff * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
63112918Sjeff */
64112918Sjeff
65144518Sdavidxu/*
66144518Sdavidxu * Copyright (c) 1996 John Birrell <jb@cimlogic.com.au>.
67144518Sdavidxu * All rights reserved.
68144518Sdavidxu *
69144518Sdavidxu * Redistribution and use in source and binary forms, with or without
70144518Sdavidxu * modification, are permitted provided that the following conditions
71144518Sdavidxu * are met:
72144518Sdavidxu * 1. Redistributions of source code must retain the above copyright
73144518Sdavidxu *    notice, this list of conditions and the following disclaimer.
74144518Sdavidxu * 2. Redistributions in binary form must reproduce the above copyright
75144518Sdavidxu *    notice, this list of conditions and the following disclaimer in the
76144518Sdavidxu *    documentation and/or other materials provided with the distribution.
77165967Simp * 3. Neither the name of the author nor the names of any co-contributors
78144518Sdavidxu *    may be used to endorse or promote products derived from this software
79144518Sdavidxu *    without specific prior written permission.
80144518Sdavidxu *
81144518Sdavidxu * THIS SOFTWARE IS PROVIDED BY JOHN BIRRELL AND CONTRIBUTORS ``AS IS'' AND
82144518Sdavidxu * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
83144518Sdavidxu * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
84144518Sdavidxu * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
85144518Sdavidxu * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
86144518Sdavidxu * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
87144518Sdavidxu * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
88144518Sdavidxu * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
89144518Sdavidxu * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
90144518Sdavidxu * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
91144518Sdavidxu * SUCH DAMAGE.
92144518Sdavidxu *
93144518Sdavidxu * $FreeBSD: head/lib/libthr/thread/thr_attr.c 214335 2010-10-25 11:16:50Z davidxu $
94144518Sdavidxu */
95112918Sjeff
96157457Sdavidxu#include "namespace.h"
97112918Sjeff#include <errno.h>
98112918Sjeff#include <pthread.h>
99112918Sjeff#include <stdlib.h>
100112918Sjeff#include <string.h>
101144518Sdavidxu#include <pthread_np.h>
102176815Sdavidxu#include <sys/sysctl.h>
103157457Sdavidxu#include "un-namespace.h"
104112918Sjeff
105112918Sjeff#include "thr_private.h"
106112918Sjeff
107214334Sdavidxustatic size_t	_get_kern_cpuset_size(void);
108214334Sdavidxu
109125963Smtm__weak_reference(_pthread_attr_destroy, pthread_attr_destroy);
110112918Sjeff
111112918Sjeffint
112144518Sdavidxu_pthread_attr_destroy(pthread_attr_t *attr)
113112918Sjeff{
114144518Sdavidxu	int	ret;
115112918Sjeff
116144518Sdavidxu	/* Check for invalid arguments: */
117144518Sdavidxu	if (attr == NULL || *attr == NULL)
118144518Sdavidxu		/* Invalid argument: */
119144518Sdavidxu		ret = EINVAL;
120144518Sdavidxu	else {
121214334Sdavidxu		if ((*attr)->cpuset != NULL)
122214334Sdavidxu			free((*attr)->cpuset);
123144518Sdavidxu		/* Free the memory allocated to the attribute object: */
124144518Sdavidxu		free(*attr);
125112918Sjeff
126144518Sdavidxu		/*
127144518Sdavidxu		 * Leave the attribute pointer NULL now that the memory
128144518Sdavidxu		 * has been freed:
129144518Sdavidxu		 */
130144518Sdavidxu		*attr = NULL;
131144518Sdavidxu		ret = 0;
132144518Sdavidxu	}
133144518Sdavidxu	return(ret);
134112918Sjeff}
135112918Sjeff
136144518Sdavidxu__weak_reference(_pthread_attr_get_np, pthread_attr_get_np);
137144518Sdavidxu
138112918Sjeffint
139214334Sdavidxu_pthread_attr_get_np(pthread_t pthread, pthread_attr_t *dstattr)
140112918Sjeff{
141144518Sdavidxu	struct pthread *curthread;
142214334Sdavidxu	struct pthread_attr attr, *dst;
143144518Sdavidxu	int	ret;
144214334Sdavidxu	size_t	cpusetsize;
145144518Sdavidxu
146214335Sdavidxu	if (pthread == NULL || dstattr == NULL || (dst = *dstattr) == NULL)
147112918Sjeff		return (EINVAL);
148214334Sdavidxu	cpusetsize = _get_kern_cpuset_size();
149214334Sdavidxu	if (dst->cpusetsize < cpusetsize) {
150214334Sdavidxu		char *newset = realloc(dst->cpuset, cpusetsize);
151214334Sdavidxu		if (newset == NULL)
152214334Sdavidxu			return (errno);
153214334Sdavidxu		memset(newset + dst->cpusetsize, 0, cpusetsize -
154214334Sdavidxu			dst->cpusetsize);
155214334Sdavidxu		dst->cpuset = (cpuset_t *)newset;
156214334Sdavidxu		dst->cpusetsize = cpusetsize;
157214334Sdavidxu	}
158144518Sdavidxu	curthread = _get_curthread();
159212536Sdavidxu	if ((ret = _thr_find_thread(curthread, pthread, /*include dead*/0)) != 0)
160144518Sdavidxu		return (ret);
161212536Sdavidxu	attr = pthread->attr;
162212536Sdavidxu	if (pthread->flags & THR_FLAGS_DETACHED)
163154126Sdavidxu		attr.flags |= PTHREAD_DETACHED;
164214334Sdavidxu	ret = cpuset_getaffinity(CPU_LEVEL_WHICH, CPU_WHICH_TID, TID(pthread),
165214334Sdavidxu		dst->cpusetsize, dst->cpuset);
166214334Sdavidxu	if (ret == -1)
167214334Sdavidxu		ret = errno;
168212536Sdavidxu	THR_THREAD_UNLOCK(curthread, pthread);
169214334Sdavidxu	if (ret == 0) {
170214334Sdavidxu		memcpy(&dst->pthread_attr_start_copy,
171214334Sdavidxu			&attr.pthread_attr_start_copy,
172214334Sdavidxu			offsetof(struct pthread_attr, pthread_attr_end_copy) -
173214334Sdavidxu			offsetof(struct pthread_attr, pthread_attr_start_copy));
174214334Sdavidxu	}
175214334Sdavidxu	return (ret);
176112918Sjeff}
177112918Sjeff
178144518Sdavidxu__weak_reference(_pthread_attr_getdetachstate, pthread_attr_getdetachstate);
179144518Sdavidxu
180112918Sjeffint
181144518Sdavidxu_pthread_attr_getdetachstate(const pthread_attr_t *attr, int *detachstate)
182112918Sjeff{
183144518Sdavidxu	int	ret;
184144518Sdavidxu
185144518Sdavidxu	/* Check for invalid arguments: */
186144518Sdavidxu	if (attr == NULL || *attr == NULL || detachstate == NULL)
187144518Sdavidxu		ret = EINVAL;
188144518Sdavidxu	else {
189144518Sdavidxu		/* Check if the detached flag is set: */
190144518Sdavidxu		if ((*attr)->flags & PTHREAD_DETACHED)
191144518Sdavidxu			/* Return detached: */
192144518Sdavidxu			*detachstate = PTHREAD_CREATE_DETACHED;
193144518Sdavidxu		else
194144518Sdavidxu			/* Return joinable: */
195144518Sdavidxu			*detachstate = PTHREAD_CREATE_JOINABLE;
196144518Sdavidxu		ret = 0;
197112918Sjeff	}
198144518Sdavidxu	return(ret);
199112918Sjeff}
200112918Sjeff
201144518Sdavidxu__weak_reference(_pthread_attr_getguardsize, pthread_attr_getguardsize);
202144518Sdavidxu
203112918Sjeffint
204144518Sdavidxu_pthread_attr_getguardsize(const pthread_attr_t *attr, size_t *guardsize)
205112918Sjeff{
206144518Sdavidxu	int	ret;
207112918Sjeff
208144518Sdavidxu	/* Check for invalid arguments: */
209144518Sdavidxu	if (attr == NULL || *attr == NULL || guardsize == NULL)
210144518Sdavidxu		ret = EINVAL;
211144518Sdavidxu	else {
212144518Sdavidxu		/* Return the guard size: */
213144518Sdavidxu		*guardsize = (*attr)->guardsize_attr;
214144518Sdavidxu		ret = 0;
215144518Sdavidxu	}
216144518Sdavidxu	return(ret);
217112918Sjeff}
218112918Sjeff
219144518Sdavidxu__weak_reference(_pthread_attr_getinheritsched, pthread_attr_getinheritsched);
220144518Sdavidxu
221112918Sjeffint
222144518Sdavidxu_pthread_attr_getinheritsched(const pthread_attr_t *attr, int *sched_inherit)
223112918Sjeff{
224144518Sdavidxu	int ret = 0;
225112918Sjeff
226144518Sdavidxu	if ((attr == NULL) || (*attr == NULL))
227144518Sdavidxu		ret = EINVAL;
228144518Sdavidxu	else
229144518Sdavidxu		*sched_inherit = (*attr)->sched_inherit;
230112918Sjeff
231144518Sdavidxu	return(ret);
232112918Sjeff}
233112918Sjeff
234144518Sdavidxu__weak_reference(_pthread_attr_getschedparam, pthread_attr_getschedparam);
235144518Sdavidxu
236112918Sjeffint
237144518Sdavidxu_pthread_attr_getschedparam(const pthread_attr_t *attr, struct sched_param *param)
238112918Sjeff{
239144518Sdavidxu	int ret = 0;
240112918Sjeff
241144518Sdavidxu	if ((attr == NULL) || (*attr == NULL) || (param == NULL))
242144518Sdavidxu		ret = EINVAL;
243144518Sdavidxu	else
244144518Sdavidxu		param->sched_priority = (*attr)->prio;
245112918Sjeff
246144518Sdavidxu	return(ret);
247112918Sjeff}
248112918Sjeff
249144518Sdavidxu__weak_reference(_pthread_attr_getschedpolicy, pthread_attr_getschedpolicy);
250144518Sdavidxu
251112918Sjeffint
252144518Sdavidxu_pthread_attr_getschedpolicy(const pthread_attr_t *attr, int *policy)
253112918Sjeff{
254144518Sdavidxu	int ret = 0;
255112918Sjeff
256144518Sdavidxu	if ((attr == NULL) || (*attr == NULL) || (policy == NULL))
257144518Sdavidxu		ret = EINVAL;
258144518Sdavidxu	else
259144518Sdavidxu		*policy = (*attr)->sched_policy;
260112918Sjeff
261144518Sdavidxu	return(ret);
262144518Sdavidxu}
263112918Sjeff
264144518Sdavidxu__weak_reference(_pthread_attr_getscope, pthread_attr_getscope);
265112918Sjeff
266112918Sjeffint
267144518Sdavidxu_pthread_attr_getscope(const pthread_attr_t *attr, int *contentionscope)
268112918Sjeff{
269144518Sdavidxu	int ret = 0;
270112918Sjeff
271144518Sdavidxu	if ((attr == NULL) || (*attr == NULL) || (contentionscope == NULL))
272144518Sdavidxu		/* Return an invalid argument: */
273144518Sdavidxu		ret = EINVAL;
274112918Sjeff
275144518Sdavidxu	else
276144518Sdavidxu		*contentionscope = (*attr)->flags & PTHREAD_SCOPE_SYSTEM ?
277144518Sdavidxu		    PTHREAD_SCOPE_SYSTEM : PTHREAD_SCOPE_PROCESS;
278112918Sjeff
279144518Sdavidxu	return(ret);
280112918Sjeff}
281112918Sjeff
282144518Sdavidxu__weak_reference(_pthread_attr_getstack, pthread_attr_getstack);
283144518Sdavidxu
284112918Sjeffint
285144518Sdavidxu_pthread_attr_getstack(const pthread_attr_t * __restrict attr,
286144518Sdavidxu                        void ** __restrict stackaddr,
287144518Sdavidxu                        size_t * __restrict stacksize)
288112918Sjeff{
289144518Sdavidxu	int     ret;
290112918Sjeff
291144518Sdavidxu	/* Check for invalid arguments: */
292144518Sdavidxu	if (attr == NULL || *attr == NULL || stackaddr == NULL
293144518Sdavidxu	    || stacksize == NULL )
294144518Sdavidxu		ret = EINVAL;
295144518Sdavidxu	else {
296144518Sdavidxu		/* Return the stack address and size */
297144518Sdavidxu		*stackaddr = (*attr)->stackaddr_attr;
298144518Sdavidxu		*stacksize = (*attr)->stacksize_attr;
299144518Sdavidxu		ret = 0;
300144518Sdavidxu	}
301144518Sdavidxu	return(ret);
302144518Sdavidxu}
303112918Sjeff
304144518Sdavidxu__weak_reference(_pthread_attr_getstackaddr, pthread_attr_getstackaddr);
305112918Sjeff
306112918Sjeffint
307144518Sdavidxu_pthread_attr_getstackaddr(const pthread_attr_t *attr, void **stackaddr)
308112918Sjeff{
309144518Sdavidxu	int	ret;
310112918Sjeff
311144518Sdavidxu	/* Check for invalid arguments: */
312144518Sdavidxu	if (attr == NULL || *attr == NULL || stackaddr == NULL)
313144518Sdavidxu		ret = EINVAL;
314144518Sdavidxu	else {
315144518Sdavidxu		/* Return the stack address: */
316144518Sdavidxu		*stackaddr = (*attr)->stackaddr_attr;
317144518Sdavidxu		ret = 0;
318144518Sdavidxu	}
319144518Sdavidxu	return(ret);
320112918Sjeff}
321112918Sjeff
322144518Sdavidxu__weak_reference(_pthread_attr_getstacksize, pthread_attr_getstacksize);
323144518Sdavidxu
324112918Sjeffint
325144518Sdavidxu_pthread_attr_getstacksize(const pthread_attr_t *attr, size_t *stacksize)
326112918Sjeff{
327144518Sdavidxu	int	ret;
328112918Sjeff
329144518Sdavidxu	/* Check for invalid arguments: */
330144518Sdavidxu	if (attr == NULL || *attr == NULL || stacksize  == NULL)
331144518Sdavidxu		ret = EINVAL;
332144518Sdavidxu	else {
333144518Sdavidxu		/* Return the stack size: */
334144518Sdavidxu		*stacksize = (*attr)->stacksize_attr;
335144518Sdavidxu		ret = 0;
336144518Sdavidxu	}
337144518Sdavidxu	return(ret);
338112918Sjeff}
339112918Sjeff
340144518Sdavidxu__weak_reference(_pthread_attr_init, pthread_attr_init);
341144518Sdavidxu
342112918Sjeffint
343144518Sdavidxu_pthread_attr_init(pthread_attr_t *attr)
344112918Sjeff{
345144518Sdavidxu	int	ret;
346144518Sdavidxu	pthread_attr_t	pattr;
347112918Sjeff
348144518Sdavidxu	_thr_check_init();
349112918Sjeff
350144518Sdavidxu	/* Allocate memory for the attribute object: */
351144518Sdavidxu	if ((pattr = (pthread_attr_t) malloc(sizeof(struct pthread_attr))) == NULL)
352144518Sdavidxu		/* Insufficient memory: */
353144518Sdavidxu		ret = ENOMEM;
354144518Sdavidxu	else {
355144518Sdavidxu		/* Initialise the attribute object with the defaults: */
356144518Sdavidxu		memcpy(pattr, &_pthread_attr_default, sizeof(struct pthread_attr));
357144518Sdavidxu
358144518Sdavidxu		/* Return a pointer to the attribute object: */
359144518Sdavidxu		*attr = pattr;
360144518Sdavidxu		ret = 0;
361144518Sdavidxu	}
362144518Sdavidxu	return(ret);
363112918Sjeff}
364112918Sjeff
365144518Sdavidxu__weak_reference(_pthread_attr_setcreatesuspend_np, pthread_attr_setcreatesuspend_np);
366144518Sdavidxu
367112918Sjeffint
368144518Sdavidxu_pthread_attr_setcreatesuspend_np(pthread_attr_t *attr)
369112918Sjeff{
370112918Sjeff	int	ret;
371112918Sjeff
372144518Sdavidxu	if (attr == NULL || *attr == NULL) {
373144518Sdavidxu		ret = EINVAL;
374144518Sdavidxu	} else {
375144518Sdavidxu		(*attr)->suspend = THR_CREATE_SUSPENDED;
376144518Sdavidxu		ret = 0;
377144518Sdavidxu	}
378144518Sdavidxu	return(ret);
379144518Sdavidxu}
380112918Sjeff
381144518Sdavidxu__weak_reference(_pthread_attr_setdetachstate, pthread_attr_setdetachstate);
382112918Sjeff
383112918Sjeffint
384144518Sdavidxu_pthread_attr_setdetachstate(pthread_attr_t *attr, int detachstate)
385112918Sjeff{
386144518Sdavidxu	int	ret;
387112918Sjeff
388144518Sdavidxu	/* Check for invalid arguments: */
389144518Sdavidxu	if (attr == NULL || *attr == NULL ||
390144518Sdavidxu	    (detachstate != PTHREAD_CREATE_DETACHED &&
391144518Sdavidxu	    detachstate != PTHREAD_CREATE_JOINABLE))
392144518Sdavidxu		ret = EINVAL;
393144518Sdavidxu	else {
394144518Sdavidxu		/* Check if detached state: */
395144518Sdavidxu		if (detachstate == PTHREAD_CREATE_DETACHED)
396144518Sdavidxu			/* Set the detached flag: */
397144518Sdavidxu			(*attr)->flags |= PTHREAD_DETACHED;
398144518Sdavidxu		else
399144518Sdavidxu			/* Reset the detached flag: */
400144518Sdavidxu			(*attr)->flags &= ~PTHREAD_DETACHED;
401144518Sdavidxu		ret = 0;
402144518Sdavidxu	}
403144518Sdavidxu	return(ret);
404144518Sdavidxu}
405112918Sjeff
406144518Sdavidxu__weak_reference(_pthread_attr_setguardsize, pthread_attr_setguardsize);
407112918Sjeff
408112918Sjeffint
409144518Sdavidxu_pthread_attr_setguardsize(pthread_attr_t *attr, size_t guardsize)
410112918Sjeff{
411144518Sdavidxu	int	ret;
412112918Sjeff
413144518Sdavidxu	/* Check for invalid arguments. */
414144518Sdavidxu	if (attr == NULL || *attr == NULL)
415144518Sdavidxu		ret = EINVAL;
416144518Sdavidxu	else {
417144518Sdavidxu		/* Save the stack size. */
418144518Sdavidxu		(*attr)->guardsize_attr = guardsize;
419144518Sdavidxu		ret = 0;
420144518Sdavidxu	}
421144518Sdavidxu	return(ret);
422112918Sjeff}
423112918Sjeff
424144518Sdavidxu__weak_reference(_pthread_attr_setinheritsched, pthread_attr_setinheritsched);
425144518Sdavidxu
426112918Sjeffint
427144518Sdavidxu_pthread_attr_setinheritsched(pthread_attr_t *attr, int sched_inherit)
428112918Sjeff{
429144518Sdavidxu	int ret = 0;
430112918Sjeff
431144518Sdavidxu	if ((attr == NULL) || (*attr == NULL))
432144518Sdavidxu		ret = EINVAL;
433144518Sdavidxu	else if (sched_inherit != PTHREAD_INHERIT_SCHED &&
434144518Sdavidxu		 sched_inherit != PTHREAD_EXPLICIT_SCHED)
435144518Sdavidxu		ret = ENOTSUP;
436144518Sdavidxu	else
437144518Sdavidxu		(*attr)->sched_inherit = sched_inherit;
438112918Sjeff
439144518Sdavidxu	return(ret);
440112918Sjeff}
441112918Sjeff
442144518Sdavidxu__weak_reference(_pthread_attr_setschedparam, pthread_attr_setschedparam);
443144518Sdavidxu
444112918Sjeffint
445144518Sdavidxu_pthread_attr_setschedparam(pthread_attr_t *attr, const struct sched_param *param)
446112918Sjeff{
447158073Sdavidxu	int policy;
448112918Sjeff
449144518Sdavidxu	if ((attr == NULL) || (*attr == NULL))
450158073Sdavidxu		return (EINVAL);
451112918Sjeff
452158073Sdavidxu	if (param == NULL)
453158073Sdavidxu		return (ENOTSUP);
454158073Sdavidxu
455158073Sdavidxu	policy = (*attr)->sched_policy;
456158073Sdavidxu
457160287Sdavidxu	if (policy == SCHED_FIFO || policy == SCHED_RR) {
458160287Sdavidxu		if (param->sched_priority < _thr_priorities[policy-1].pri_min ||
459160287Sdavidxu		    param->sched_priority > _thr_priorities[policy-1].pri_max)
460158073Sdavidxu		return (ENOTSUP);
461160287Sdavidxu	} else {
462160287Sdavidxu		/*
463160287Sdavidxu		 * Ignore it for SCHED_OTHER now, patches for glib ports
464160287Sdavidxu		 * are wrongly using M:N thread library's internal macro
465160287Sdavidxu		 * THR_MIN_PRIORITY and THR_MAX_PRIORITY.
466160287Sdavidxu		 */
467160287Sdavidxu	}
468158073Sdavidxu
469158073Sdavidxu	(*attr)->prio = param->sched_priority;
470158073Sdavidxu
471158073Sdavidxu	return (0);
472112918Sjeff}
473112918Sjeff
474144518Sdavidxu__weak_reference(_pthread_attr_setschedpolicy, pthread_attr_setschedpolicy);
475144518Sdavidxu
476112918Sjeffint
477144518Sdavidxu_pthread_attr_setschedpolicy(pthread_attr_t *attr, int policy)
478112918Sjeff{
479144518Sdavidxu	int ret = 0;
480112918Sjeff
481144518Sdavidxu	if ((attr == NULL) || (*attr == NULL))
482144518Sdavidxu		ret = EINVAL;
483144518Sdavidxu	else if ((policy < SCHED_FIFO) || (policy > SCHED_RR)) {
484144518Sdavidxu		ret = ENOTSUP;
485158073Sdavidxu	} else {
486144518Sdavidxu		(*attr)->sched_policy = policy;
487158073Sdavidxu		(*attr)->prio = _thr_priorities[policy-1].pri_default;
488158073Sdavidxu	}
489144518Sdavidxu	return(ret);
490112918Sjeff}
491112918Sjeff
492144518Sdavidxu__weak_reference(_pthread_attr_setscope, pthread_attr_setscope);
493144518Sdavidxu
494112918Sjeffint
495144518Sdavidxu_pthread_attr_setscope(pthread_attr_t *attr, int contentionscope)
496112918Sjeff{
497144518Sdavidxu	int ret = 0;
498112918Sjeff
499144518Sdavidxu	if ((attr == NULL) || (*attr == NULL)) {
500144518Sdavidxu		/* Return an invalid argument: */
501144518Sdavidxu		ret = EINVAL;
502144518Sdavidxu	} else if ((contentionscope != PTHREAD_SCOPE_PROCESS) &&
503144518Sdavidxu	    (contentionscope != PTHREAD_SCOPE_SYSTEM)) {
504144518Sdavidxu		ret = EINVAL;
505144518Sdavidxu	} else if (contentionscope == PTHREAD_SCOPE_SYSTEM) {
506144518Sdavidxu		(*attr)->flags |= contentionscope;
507144518Sdavidxu	} else {
508144518Sdavidxu		(*attr)->flags &= ~PTHREAD_SCOPE_SYSTEM;
509144518Sdavidxu	}
510144518Sdavidxu	return (ret);
511112918Sjeff}
512112918Sjeff
513144518Sdavidxu__weak_reference(_pthread_attr_setstack, pthread_attr_setstack);
514144518Sdavidxu
515112918Sjeffint
516144518Sdavidxu_pthread_attr_setstack(pthread_attr_t *attr, void *stackaddr,
517144518Sdavidxu                        size_t stacksize)
518112918Sjeff{
519144518Sdavidxu	int     ret;
520144518Sdavidxu
521144518Sdavidxu	/* Check for invalid arguments: */
522112918Sjeff	if (attr == NULL || *attr == NULL || stackaddr == NULL
523144518Sdavidxu	    || stacksize < PTHREAD_STACK_MIN)
524144518Sdavidxu		ret = EINVAL;
525144518Sdavidxu	else {
526144518Sdavidxu		/* Save the stack address and stack size */
527144518Sdavidxu		(*attr)->stackaddr_attr = stackaddr;
528144518Sdavidxu		(*attr)->stacksize_attr = stacksize;
529144518Sdavidxu		ret = 0;
530144518Sdavidxu	}
531144518Sdavidxu	return(ret);
532144518Sdavidxu}
533112918Sjeff
534144518Sdavidxu__weak_reference(_pthread_attr_setstackaddr, pthread_attr_setstackaddr);
535112918Sjeff
536112918Sjeffint
537144518Sdavidxu_pthread_attr_setstackaddr(pthread_attr_t *attr, void *stackaddr)
538112918Sjeff{
539144518Sdavidxu	int	ret;
540144518Sdavidxu
541144518Sdavidxu	/* Check for invalid arguments: */
542112918Sjeff	if (attr == NULL || *attr == NULL || stackaddr == NULL)
543144518Sdavidxu		ret = EINVAL;
544144518Sdavidxu	else {
545144518Sdavidxu		/* Save the stack address: */
546144518Sdavidxu		(*attr)->stackaddr_attr = stackaddr;
547144518Sdavidxu		ret = 0;
548144518Sdavidxu	}
549144518Sdavidxu	return(ret);
550144518Sdavidxu}
551112918Sjeff
552144518Sdavidxu__weak_reference(_pthread_attr_setstacksize, pthread_attr_setstacksize);
553112918Sjeff
554112918Sjeffint
555144518Sdavidxu_pthread_attr_setstacksize(pthread_attr_t *attr, size_t stacksize)
556112918Sjeff{
557144518Sdavidxu	int	ret;
558112918Sjeff
559144518Sdavidxu	/* Check for invalid arguments: */
560144518Sdavidxu	if (attr == NULL || *attr == NULL || stacksize < PTHREAD_STACK_MIN)
561144518Sdavidxu		ret = EINVAL;
562144518Sdavidxu	else {
563144518Sdavidxu		/* Save the stack size: */
564144518Sdavidxu		(*attr)->stacksize_attr = stacksize;
565144518Sdavidxu		ret = 0;
566144518Sdavidxu	}
567144518Sdavidxu	return(ret);
568112918Sjeff}
569176781Sdavidxu
570177605Srustatic size_t
571177605Sru_get_kern_cpuset_size(void)
572176815Sdavidxu{
573176815Sdavidxu	static int kern_cpuset_size = 0;
574176815Sdavidxu
575176815Sdavidxu	if (kern_cpuset_size == 0) {
576177605Sru		size_t len;
577176815Sdavidxu
578176815Sdavidxu		len = sizeof(kern_cpuset_size);
579176815Sdavidxu		if (sysctlbyname("kern.smp.maxcpus", &kern_cpuset_size,
580176815Sdavidxu		    &len, NULL, 0))
581176815Sdavidxu			PANIC("failed to get sysctl kern.smp.maxcpus");
582176815Sdavidxu
583176815Sdavidxu		kern_cpuset_size = (kern_cpuset_size + 7) / 8;
584176815Sdavidxu	}
585176815Sdavidxu
586176815Sdavidxu	return (kern_cpuset_size);
587176815Sdavidxu}
588176815Sdavidxu
589176815Sdavidxu__weak_reference(_pthread_attr_setaffinity_np, pthread_attr_setaffinity_np);
590176781Sdavidxuint
591176815Sdavidxu_pthread_attr_setaffinity_np(pthread_attr_t *pattr, size_t cpusetsize,
592178446Sdelphij	const cpuset_t *cpusetp)
593176781Sdavidxu{
594176781Sdavidxu	pthread_attr_t attr;
595176781Sdavidxu	int ret;
596176781Sdavidxu
597176781Sdavidxu	if (pattr == NULL || (attr = (*pattr)) == NULL)
598176781Sdavidxu		ret = EINVAL;
599176781Sdavidxu	else {
600178446Sdelphij		if (cpusetsize == 0 || cpusetp == NULL) {
601176781Sdavidxu			if (attr->cpuset != NULL) {
602176781Sdavidxu				free(attr->cpuset);
603176781Sdavidxu				attr->cpuset = NULL;
604176781Sdavidxu				attr->cpusetsize = 0;
605176781Sdavidxu			}
606176781Sdavidxu			return (0);
607176781Sdavidxu		}
608176781Sdavidxu
609176815Sdavidxu		if (cpusetsize > attr->cpusetsize) {
610177605Sru			size_t kern_size = _get_kern_cpuset_size();
611176815Sdavidxu			if (cpusetsize > kern_size) {
612177605Sru				size_t i;
613176815Sdavidxu				for (i = kern_size; i < cpusetsize; ++i) {
614178446Sdelphij					if (((char *)cpusetp)[i])
615176815Sdavidxu						return (EINVAL);
616176815Sdavidxu				}
617176815Sdavidxu			}
618176781Sdavidxu			void *newset = realloc(attr->cpuset, cpusetsize);
619176781Sdavidxu       			if (newset == NULL)
620176781Sdavidxu		            return (ENOMEM);
621176781Sdavidxu			attr->cpuset = newset;
622176781Sdavidxu			attr->cpusetsize = cpusetsize;
623176815Sdavidxu		} else {
624176815Sdavidxu			memset(((char *)attr->cpuset) + cpusetsize, 0,
625176864Sdavidxu				attr->cpusetsize - cpusetsize);
626176815Sdavidxu			attr->cpusetsize = cpusetsize;
627176781Sdavidxu		}
628178446Sdelphij		memcpy(attr->cpuset, cpusetp, cpusetsize);
629176781Sdavidxu		ret = 0;
630176781Sdavidxu	}
631176781Sdavidxu	return (ret);
632176781Sdavidxu}
633176781Sdavidxu
634176815Sdavidxu__weak_reference(_pthread_attr_getaffinity_np, pthread_attr_getaffinity_np);
635176781Sdavidxuint
636176815Sdavidxu_pthread_attr_getaffinity_np(const pthread_attr_t *pattr, size_t cpusetsize,
637178446Sdelphij	cpuset_t *cpusetp)
638176781Sdavidxu{
639176781Sdavidxu	pthread_attr_t attr;
640176781Sdavidxu	int ret = 0;
641176781Sdavidxu
642176781Sdavidxu	if (pattr == NULL || (attr = (*pattr)) == NULL)
643176781Sdavidxu		ret = EINVAL;
644176781Sdavidxu	else if (attr->cpuset != NULL) {
645178446Sdelphij		memcpy(cpusetp, attr->cpuset, MIN(cpusetsize, attr->cpusetsize));
646176781Sdavidxu		if (cpusetsize > attr->cpusetsize)
647178446Sdelphij			memset(((char *)cpusetp) + attr->cpusetsize, 0,
648176781Sdavidxu				cpusetsize - attr->cpusetsize);
649176781Sdavidxu	} else {
650177605Sru		size_t kern_size = _get_kern_cpuset_size();
651178446Sdelphij		memset(cpusetp, -1, MIN(cpusetsize, kern_size));
652176815Sdavidxu		if (cpusetsize > kern_size)
653178446Sdelphij			memset(((char *)cpusetp) + kern_size, 0,
654176815Sdavidxu				cpusetsize - kern_size);
655176781Sdavidxu	}
656176781Sdavidxu	return (ret);
657176781Sdavidxu}
658