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$
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;
144214413Sdavidxu	size_t	kern_size;
145144518Sdavidxu
146214335Sdavidxu	if (pthread == NULL || dstattr == NULL || (dst = *dstattr) == NULL)
147112918Sjeff		return (EINVAL);
148214413Sdavidxu	kern_size = _get_kern_cpuset_size();
149214413Sdavidxu	if (dst->cpuset == NULL) {
150214413Sdavidxu		dst->cpuset = calloc(1, kern_size);
151214413Sdavidxu		dst->cpusetsize = kern_size;
152214334Sdavidxu	}
153144518Sdavidxu	curthread = _get_curthread();
154212536Sdavidxu	if ((ret = _thr_find_thread(curthread, pthread, /*include dead*/0)) != 0)
155144518Sdavidxu		return (ret);
156212536Sdavidxu	attr = pthread->attr;
157212536Sdavidxu	if (pthread->flags & THR_FLAGS_DETACHED)
158154126Sdavidxu		attr.flags |= PTHREAD_DETACHED;
159214334Sdavidxu	ret = cpuset_getaffinity(CPU_LEVEL_WHICH, CPU_WHICH_TID, TID(pthread),
160214334Sdavidxu		dst->cpusetsize, dst->cpuset);
161214334Sdavidxu	if (ret == -1)
162214334Sdavidxu		ret = errno;
163212536Sdavidxu	THR_THREAD_UNLOCK(curthread, pthread);
164214334Sdavidxu	if (ret == 0) {
165214334Sdavidxu		memcpy(&dst->pthread_attr_start_copy,
166214334Sdavidxu			&attr.pthread_attr_start_copy,
167214334Sdavidxu			offsetof(struct pthread_attr, pthread_attr_end_copy) -
168214334Sdavidxu			offsetof(struct pthread_attr, pthread_attr_start_copy));
169214334Sdavidxu	}
170214334Sdavidxu	return (ret);
171112918Sjeff}
172112918Sjeff
173144518Sdavidxu__weak_reference(_pthread_attr_getdetachstate, pthread_attr_getdetachstate);
174144518Sdavidxu
175112918Sjeffint
176144518Sdavidxu_pthread_attr_getdetachstate(const pthread_attr_t *attr, int *detachstate)
177112918Sjeff{
178144518Sdavidxu	int	ret;
179144518Sdavidxu
180144518Sdavidxu	/* Check for invalid arguments: */
181144518Sdavidxu	if (attr == NULL || *attr == NULL || detachstate == NULL)
182144518Sdavidxu		ret = EINVAL;
183144518Sdavidxu	else {
184144518Sdavidxu		/* Check if the detached flag is set: */
185144518Sdavidxu		if ((*attr)->flags & PTHREAD_DETACHED)
186144518Sdavidxu			/* Return detached: */
187144518Sdavidxu			*detachstate = PTHREAD_CREATE_DETACHED;
188144518Sdavidxu		else
189144518Sdavidxu			/* Return joinable: */
190144518Sdavidxu			*detachstate = PTHREAD_CREATE_JOINABLE;
191144518Sdavidxu		ret = 0;
192112918Sjeff	}
193144518Sdavidxu	return(ret);
194112918Sjeff}
195112918Sjeff
196144518Sdavidxu__weak_reference(_pthread_attr_getguardsize, pthread_attr_getguardsize);
197144518Sdavidxu
198112918Sjeffint
199144518Sdavidxu_pthread_attr_getguardsize(const pthread_attr_t *attr, size_t *guardsize)
200112918Sjeff{
201144518Sdavidxu	int	ret;
202112918Sjeff
203144518Sdavidxu	/* Check for invalid arguments: */
204144518Sdavidxu	if (attr == NULL || *attr == NULL || guardsize == NULL)
205144518Sdavidxu		ret = EINVAL;
206144518Sdavidxu	else {
207144518Sdavidxu		/* Return the guard size: */
208144518Sdavidxu		*guardsize = (*attr)->guardsize_attr;
209144518Sdavidxu		ret = 0;
210144518Sdavidxu	}
211144518Sdavidxu	return(ret);
212112918Sjeff}
213112918Sjeff
214144518Sdavidxu__weak_reference(_pthread_attr_getinheritsched, pthread_attr_getinheritsched);
215144518Sdavidxu
216112918Sjeffint
217144518Sdavidxu_pthread_attr_getinheritsched(const pthread_attr_t *attr, int *sched_inherit)
218112918Sjeff{
219144518Sdavidxu	int ret = 0;
220112918Sjeff
221144518Sdavidxu	if ((attr == NULL) || (*attr == NULL))
222144518Sdavidxu		ret = EINVAL;
223144518Sdavidxu	else
224144518Sdavidxu		*sched_inherit = (*attr)->sched_inherit;
225112918Sjeff
226144518Sdavidxu	return(ret);
227112918Sjeff}
228112918Sjeff
229144518Sdavidxu__weak_reference(_pthread_attr_getschedparam, pthread_attr_getschedparam);
230144518Sdavidxu
231112918Sjeffint
232144518Sdavidxu_pthread_attr_getschedparam(const pthread_attr_t *attr, struct sched_param *param)
233112918Sjeff{
234144518Sdavidxu	int ret = 0;
235112918Sjeff
236144518Sdavidxu	if ((attr == NULL) || (*attr == NULL) || (param == NULL))
237144518Sdavidxu		ret = EINVAL;
238144518Sdavidxu	else
239144518Sdavidxu		param->sched_priority = (*attr)->prio;
240112918Sjeff
241144518Sdavidxu	return(ret);
242112918Sjeff}
243112918Sjeff
244144518Sdavidxu__weak_reference(_pthread_attr_getschedpolicy, pthread_attr_getschedpolicy);
245144518Sdavidxu
246112918Sjeffint
247144518Sdavidxu_pthread_attr_getschedpolicy(const pthread_attr_t *attr, int *policy)
248112918Sjeff{
249144518Sdavidxu	int ret = 0;
250112918Sjeff
251144518Sdavidxu	if ((attr == NULL) || (*attr == NULL) || (policy == NULL))
252144518Sdavidxu		ret = EINVAL;
253144518Sdavidxu	else
254144518Sdavidxu		*policy = (*attr)->sched_policy;
255112918Sjeff
256144518Sdavidxu	return(ret);
257144518Sdavidxu}
258112918Sjeff
259144518Sdavidxu__weak_reference(_pthread_attr_getscope, pthread_attr_getscope);
260112918Sjeff
261112918Sjeffint
262144518Sdavidxu_pthread_attr_getscope(const pthread_attr_t *attr, int *contentionscope)
263112918Sjeff{
264144518Sdavidxu	int ret = 0;
265112918Sjeff
266144518Sdavidxu	if ((attr == NULL) || (*attr == NULL) || (contentionscope == NULL))
267144518Sdavidxu		/* Return an invalid argument: */
268144518Sdavidxu		ret = EINVAL;
269112918Sjeff
270144518Sdavidxu	else
271144518Sdavidxu		*contentionscope = (*attr)->flags & PTHREAD_SCOPE_SYSTEM ?
272144518Sdavidxu		    PTHREAD_SCOPE_SYSTEM : PTHREAD_SCOPE_PROCESS;
273112918Sjeff
274144518Sdavidxu	return(ret);
275112918Sjeff}
276112918Sjeff
277144518Sdavidxu__weak_reference(_pthread_attr_getstack, pthread_attr_getstack);
278144518Sdavidxu
279112918Sjeffint
280144518Sdavidxu_pthread_attr_getstack(const pthread_attr_t * __restrict attr,
281144518Sdavidxu                        void ** __restrict stackaddr,
282144518Sdavidxu                        size_t * __restrict stacksize)
283112918Sjeff{
284144518Sdavidxu	int     ret;
285112918Sjeff
286144518Sdavidxu	/* Check for invalid arguments: */
287144518Sdavidxu	if (attr == NULL || *attr == NULL || stackaddr == NULL
288144518Sdavidxu	    || stacksize == NULL )
289144518Sdavidxu		ret = EINVAL;
290144518Sdavidxu	else {
291144518Sdavidxu		/* Return the stack address and size */
292144518Sdavidxu		*stackaddr = (*attr)->stackaddr_attr;
293144518Sdavidxu		*stacksize = (*attr)->stacksize_attr;
294144518Sdavidxu		ret = 0;
295144518Sdavidxu	}
296144518Sdavidxu	return(ret);
297144518Sdavidxu}
298112918Sjeff
299144518Sdavidxu__weak_reference(_pthread_attr_getstackaddr, pthread_attr_getstackaddr);
300112918Sjeff
301112918Sjeffint
302144518Sdavidxu_pthread_attr_getstackaddr(const pthread_attr_t *attr, void **stackaddr)
303112918Sjeff{
304144518Sdavidxu	int	ret;
305112918Sjeff
306144518Sdavidxu	/* Check for invalid arguments: */
307144518Sdavidxu	if (attr == NULL || *attr == NULL || stackaddr == NULL)
308144518Sdavidxu		ret = EINVAL;
309144518Sdavidxu	else {
310144518Sdavidxu		/* Return the stack address: */
311144518Sdavidxu		*stackaddr = (*attr)->stackaddr_attr;
312144518Sdavidxu		ret = 0;
313144518Sdavidxu	}
314144518Sdavidxu	return(ret);
315112918Sjeff}
316112918Sjeff
317144518Sdavidxu__weak_reference(_pthread_attr_getstacksize, pthread_attr_getstacksize);
318144518Sdavidxu
319112918Sjeffint
320144518Sdavidxu_pthread_attr_getstacksize(const pthread_attr_t *attr, size_t *stacksize)
321112918Sjeff{
322144518Sdavidxu	int	ret;
323112918Sjeff
324144518Sdavidxu	/* Check for invalid arguments: */
325144518Sdavidxu	if (attr == NULL || *attr == NULL || stacksize  == NULL)
326144518Sdavidxu		ret = EINVAL;
327144518Sdavidxu	else {
328144518Sdavidxu		/* Return the stack size: */
329144518Sdavidxu		*stacksize = (*attr)->stacksize_attr;
330144518Sdavidxu		ret = 0;
331144518Sdavidxu	}
332144518Sdavidxu	return(ret);
333112918Sjeff}
334112918Sjeff
335144518Sdavidxu__weak_reference(_pthread_attr_init, pthread_attr_init);
336144518Sdavidxu
337112918Sjeffint
338144518Sdavidxu_pthread_attr_init(pthread_attr_t *attr)
339112918Sjeff{
340144518Sdavidxu	int	ret;
341144518Sdavidxu	pthread_attr_t	pattr;
342112918Sjeff
343144518Sdavidxu	_thr_check_init();
344112918Sjeff
345144518Sdavidxu	/* Allocate memory for the attribute object: */
346144518Sdavidxu	if ((pattr = (pthread_attr_t) malloc(sizeof(struct pthread_attr))) == NULL)
347144518Sdavidxu		/* Insufficient memory: */
348144518Sdavidxu		ret = ENOMEM;
349144518Sdavidxu	else {
350144518Sdavidxu		/* Initialise the attribute object with the defaults: */
351144518Sdavidxu		memcpy(pattr, &_pthread_attr_default, sizeof(struct pthread_attr));
352144518Sdavidxu
353144518Sdavidxu		/* Return a pointer to the attribute object: */
354144518Sdavidxu		*attr = pattr;
355144518Sdavidxu		ret = 0;
356144518Sdavidxu	}
357144518Sdavidxu	return(ret);
358112918Sjeff}
359112918Sjeff
360144518Sdavidxu__weak_reference(_pthread_attr_setcreatesuspend_np, pthread_attr_setcreatesuspend_np);
361144518Sdavidxu
362112918Sjeffint
363144518Sdavidxu_pthread_attr_setcreatesuspend_np(pthread_attr_t *attr)
364112918Sjeff{
365112918Sjeff	int	ret;
366112918Sjeff
367144518Sdavidxu	if (attr == NULL || *attr == NULL) {
368144518Sdavidxu		ret = EINVAL;
369144518Sdavidxu	} else {
370144518Sdavidxu		(*attr)->suspend = THR_CREATE_SUSPENDED;
371144518Sdavidxu		ret = 0;
372144518Sdavidxu	}
373144518Sdavidxu	return(ret);
374144518Sdavidxu}
375112918Sjeff
376144518Sdavidxu__weak_reference(_pthread_attr_setdetachstate, pthread_attr_setdetachstate);
377112918Sjeff
378112918Sjeffint
379144518Sdavidxu_pthread_attr_setdetachstate(pthread_attr_t *attr, int detachstate)
380112918Sjeff{
381144518Sdavidxu	int	ret;
382112918Sjeff
383144518Sdavidxu	/* Check for invalid arguments: */
384144518Sdavidxu	if (attr == NULL || *attr == NULL ||
385144518Sdavidxu	    (detachstate != PTHREAD_CREATE_DETACHED &&
386144518Sdavidxu	    detachstate != PTHREAD_CREATE_JOINABLE))
387144518Sdavidxu		ret = EINVAL;
388144518Sdavidxu	else {
389144518Sdavidxu		/* Check if detached state: */
390144518Sdavidxu		if (detachstate == PTHREAD_CREATE_DETACHED)
391144518Sdavidxu			/* Set the detached flag: */
392144518Sdavidxu			(*attr)->flags |= PTHREAD_DETACHED;
393144518Sdavidxu		else
394144518Sdavidxu			/* Reset the detached flag: */
395144518Sdavidxu			(*attr)->flags &= ~PTHREAD_DETACHED;
396144518Sdavidxu		ret = 0;
397144518Sdavidxu	}
398144518Sdavidxu	return(ret);
399144518Sdavidxu}
400112918Sjeff
401144518Sdavidxu__weak_reference(_pthread_attr_setguardsize, pthread_attr_setguardsize);
402112918Sjeff
403112918Sjeffint
404144518Sdavidxu_pthread_attr_setguardsize(pthread_attr_t *attr, size_t guardsize)
405112918Sjeff{
406144518Sdavidxu	int	ret;
407112918Sjeff
408144518Sdavidxu	/* Check for invalid arguments. */
409144518Sdavidxu	if (attr == NULL || *attr == NULL)
410144518Sdavidxu		ret = EINVAL;
411144518Sdavidxu	else {
412144518Sdavidxu		/* Save the stack size. */
413144518Sdavidxu		(*attr)->guardsize_attr = guardsize;
414144518Sdavidxu		ret = 0;
415144518Sdavidxu	}
416144518Sdavidxu	return(ret);
417112918Sjeff}
418112918Sjeff
419144518Sdavidxu__weak_reference(_pthread_attr_setinheritsched, pthread_attr_setinheritsched);
420144518Sdavidxu
421112918Sjeffint
422144518Sdavidxu_pthread_attr_setinheritsched(pthread_attr_t *attr, int sched_inherit)
423112918Sjeff{
424144518Sdavidxu	int ret = 0;
425112918Sjeff
426144518Sdavidxu	if ((attr == NULL) || (*attr == NULL))
427144518Sdavidxu		ret = EINVAL;
428144518Sdavidxu	else if (sched_inherit != PTHREAD_INHERIT_SCHED &&
429144518Sdavidxu		 sched_inherit != PTHREAD_EXPLICIT_SCHED)
430144518Sdavidxu		ret = ENOTSUP;
431144518Sdavidxu	else
432144518Sdavidxu		(*attr)->sched_inherit = sched_inherit;
433112918Sjeff
434144518Sdavidxu	return(ret);
435112918Sjeff}
436112918Sjeff
437144518Sdavidxu__weak_reference(_pthread_attr_setschedparam, pthread_attr_setschedparam);
438144518Sdavidxu
439112918Sjeffint
440144518Sdavidxu_pthread_attr_setschedparam(pthread_attr_t *attr, const struct sched_param *param)
441112918Sjeff{
442158073Sdavidxu	int policy;
443112918Sjeff
444144518Sdavidxu	if ((attr == NULL) || (*attr == NULL))
445158073Sdavidxu		return (EINVAL);
446112918Sjeff
447158073Sdavidxu	if (param == NULL)
448158073Sdavidxu		return (ENOTSUP);
449158073Sdavidxu
450158073Sdavidxu	policy = (*attr)->sched_policy;
451158073Sdavidxu
452160287Sdavidxu	if (policy == SCHED_FIFO || policy == SCHED_RR) {
453160287Sdavidxu		if (param->sched_priority < _thr_priorities[policy-1].pri_min ||
454160287Sdavidxu		    param->sched_priority > _thr_priorities[policy-1].pri_max)
455158073Sdavidxu		return (ENOTSUP);
456160287Sdavidxu	} else {
457160287Sdavidxu		/*
458160287Sdavidxu		 * Ignore it for SCHED_OTHER now, patches for glib ports
459160287Sdavidxu		 * are wrongly using M:N thread library's internal macro
460160287Sdavidxu		 * THR_MIN_PRIORITY and THR_MAX_PRIORITY.
461160287Sdavidxu		 */
462160287Sdavidxu	}
463158073Sdavidxu
464158073Sdavidxu	(*attr)->prio = param->sched_priority;
465158073Sdavidxu
466158073Sdavidxu	return (0);
467112918Sjeff}
468112918Sjeff
469144518Sdavidxu__weak_reference(_pthread_attr_setschedpolicy, pthread_attr_setschedpolicy);
470144518Sdavidxu
471112918Sjeffint
472144518Sdavidxu_pthread_attr_setschedpolicy(pthread_attr_t *attr, int policy)
473112918Sjeff{
474144518Sdavidxu	int ret = 0;
475112918Sjeff
476144518Sdavidxu	if ((attr == NULL) || (*attr == NULL))
477144518Sdavidxu		ret = EINVAL;
478144518Sdavidxu	else if ((policy < SCHED_FIFO) || (policy > SCHED_RR)) {
479144518Sdavidxu		ret = ENOTSUP;
480158073Sdavidxu	} else {
481144518Sdavidxu		(*attr)->sched_policy = policy;
482158073Sdavidxu		(*attr)->prio = _thr_priorities[policy-1].pri_default;
483158073Sdavidxu	}
484144518Sdavidxu	return(ret);
485112918Sjeff}
486112918Sjeff
487144518Sdavidxu__weak_reference(_pthread_attr_setscope, pthread_attr_setscope);
488144518Sdavidxu
489112918Sjeffint
490144518Sdavidxu_pthread_attr_setscope(pthread_attr_t *attr, int contentionscope)
491112918Sjeff{
492144518Sdavidxu	int ret = 0;
493112918Sjeff
494144518Sdavidxu	if ((attr == NULL) || (*attr == NULL)) {
495144518Sdavidxu		/* Return an invalid argument: */
496144518Sdavidxu		ret = EINVAL;
497144518Sdavidxu	} else if ((contentionscope != PTHREAD_SCOPE_PROCESS) &&
498144518Sdavidxu	    (contentionscope != PTHREAD_SCOPE_SYSTEM)) {
499144518Sdavidxu		ret = EINVAL;
500144518Sdavidxu	} else if (contentionscope == PTHREAD_SCOPE_SYSTEM) {
501144518Sdavidxu		(*attr)->flags |= contentionscope;
502144518Sdavidxu	} else {
503144518Sdavidxu		(*attr)->flags &= ~PTHREAD_SCOPE_SYSTEM;
504144518Sdavidxu	}
505144518Sdavidxu	return (ret);
506112918Sjeff}
507112918Sjeff
508144518Sdavidxu__weak_reference(_pthread_attr_setstack, pthread_attr_setstack);
509144518Sdavidxu
510112918Sjeffint
511144518Sdavidxu_pthread_attr_setstack(pthread_attr_t *attr, void *stackaddr,
512144518Sdavidxu                        size_t stacksize)
513112918Sjeff{
514144518Sdavidxu	int     ret;
515144518Sdavidxu
516144518Sdavidxu	/* Check for invalid arguments: */
517112918Sjeff	if (attr == NULL || *attr == NULL || stackaddr == NULL
518144518Sdavidxu	    || stacksize < PTHREAD_STACK_MIN)
519144518Sdavidxu		ret = EINVAL;
520144518Sdavidxu	else {
521144518Sdavidxu		/* Save the stack address and stack size */
522144518Sdavidxu		(*attr)->stackaddr_attr = stackaddr;
523144518Sdavidxu		(*attr)->stacksize_attr = stacksize;
524144518Sdavidxu		ret = 0;
525144518Sdavidxu	}
526144518Sdavidxu	return(ret);
527144518Sdavidxu}
528112918Sjeff
529144518Sdavidxu__weak_reference(_pthread_attr_setstackaddr, pthread_attr_setstackaddr);
530112918Sjeff
531112918Sjeffint
532144518Sdavidxu_pthread_attr_setstackaddr(pthread_attr_t *attr, void *stackaddr)
533112918Sjeff{
534144518Sdavidxu	int	ret;
535144518Sdavidxu
536144518Sdavidxu	/* Check for invalid arguments: */
537112918Sjeff	if (attr == NULL || *attr == NULL || stackaddr == NULL)
538144518Sdavidxu		ret = EINVAL;
539144518Sdavidxu	else {
540144518Sdavidxu		/* Save the stack address: */
541144518Sdavidxu		(*attr)->stackaddr_attr = stackaddr;
542144518Sdavidxu		ret = 0;
543144518Sdavidxu	}
544144518Sdavidxu	return(ret);
545144518Sdavidxu}
546112918Sjeff
547144518Sdavidxu__weak_reference(_pthread_attr_setstacksize, pthread_attr_setstacksize);
548112918Sjeff
549112918Sjeffint
550144518Sdavidxu_pthread_attr_setstacksize(pthread_attr_t *attr, size_t stacksize)
551112918Sjeff{
552144518Sdavidxu	int	ret;
553112918Sjeff
554144518Sdavidxu	/* Check for invalid arguments: */
555144518Sdavidxu	if (attr == NULL || *attr == NULL || stacksize < PTHREAD_STACK_MIN)
556144518Sdavidxu		ret = EINVAL;
557144518Sdavidxu	else {
558144518Sdavidxu		/* Save the stack size: */
559144518Sdavidxu		(*attr)->stacksize_attr = stacksize;
560144518Sdavidxu		ret = 0;
561144518Sdavidxu	}
562144518Sdavidxu	return(ret);
563112918Sjeff}
564176781Sdavidxu
565177605Srustatic size_t
566177605Sru_get_kern_cpuset_size(void)
567176815Sdavidxu{
568176815Sdavidxu	static int kern_cpuset_size = 0;
569176815Sdavidxu
570176815Sdavidxu	if (kern_cpuset_size == 0) {
571177605Sru		size_t len;
572176815Sdavidxu
573214653Sdavidxu		len = sizeof(kern_cpuset_size);
574214653Sdavidxu		if (sysctlbyname("kern.sched.cpusetsize", &kern_cpuset_size,
575214653Sdavidxu		    &len, NULL, 0))
576214653Sdavidxu			PANIC("failed to get sysctl kern.sched.cpusetsize");
577176815Sdavidxu	}
578176815Sdavidxu
579176815Sdavidxu	return (kern_cpuset_size);
580176815Sdavidxu}
581176815Sdavidxu
582176815Sdavidxu__weak_reference(_pthread_attr_setaffinity_np, pthread_attr_setaffinity_np);
583176781Sdavidxuint
584176815Sdavidxu_pthread_attr_setaffinity_np(pthread_attr_t *pattr, size_t cpusetsize,
585178446Sdelphij	const cpuset_t *cpusetp)
586176781Sdavidxu{
587176781Sdavidxu	pthread_attr_t attr;
588176781Sdavidxu	int ret;
589176781Sdavidxu
590176781Sdavidxu	if (pattr == NULL || (attr = (*pattr)) == NULL)
591176781Sdavidxu		ret = EINVAL;
592176781Sdavidxu	else {
593178446Sdelphij		if (cpusetsize == 0 || cpusetp == NULL) {
594176781Sdavidxu			if (attr->cpuset != NULL) {
595176781Sdavidxu				free(attr->cpuset);
596176781Sdavidxu				attr->cpuset = NULL;
597176781Sdavidxu				attr->cpusetsize = 0;
598176781Sdavidxu			}
599176781Sdavidxu			return (0);
600176781Sdavidxu		}
601214413Sdavidxu		size_t kern_size = _get_kern_cpuset_size();
602214413Sdavidxu		/* Kernel rejects small set, we check it here too. */
603214413Sdavidxu		if (cpusetsize < kern_size)
604214413Sdavidxu			return (ERANGE);
605214413Sdavidxu		if (cpusetsize > kern_size) {
606214413Sdavidxu			/* Kernel checks invalid bits, we check it here too. */
607214413Sdavidxu			size_t i;
608214413Sdavidxu			for (i = kern_size; i < cpusetsize; ++i) {
609214413Sdavidxu				if (((char *)cpusetp)[i])
610214413Sdavidxu					return (EINVAL);
611176815Sdavidxu			}
612176781Sdavidxu		}
613214413Sdavidxu		if (attr->cpuset == NULL) {
614214413Sdavidxu			attr->cpuset = calloc(1, kern_size);
615214413Sdavidxu			if (attr->cpuset == NULL)
616214413Sdavidxu				return (errno);
617214413Sdavidxu			attr->cpusetsize = kern_size;
618214413Sdavidxu		}
619214413Sdavidxu		memcpy(attr->cpuset, cpusetp, kern_size);
620176781Sdavidxu		ret = 0;
621176781Sdavidxu	}
622176781Sdavidxu	return (ret);
623176781Sdavidxu}
624176781Sdavidxu
625176815Sdavidxu__weak_reference(_pthread_attr_getaffinity_np, pthread_attr_getaffinity_np);
626176781Sdavidxuint
627176815Sdavidxu_pthread_attr_getaffinity_np(const pthread_attr_t *pattr, size_t cpusetsize,
628178446Sdelphij	cpuset_t *cpusetp)
629176781Sdavidxu{
630176781Sdavidxu	pthread_attr_t attr;
631176781Sdavidxu	int ret = 0;
632176781Sdavidxu
633176781Sdavidxu	if (pattr == NULL || (attr = (*pattr)) == NULL)
634176781Sdavidxu		ret = EINVAL;
635214413Sdavidxu	else {
636214413Sdavidxu		/* Kernel rejects small set, we check it here too. */
637177605Sru		size_t kern_size = _get_kern_cpuset_size();
638214413Sdavidxu		if (cpusetsize < kern_size)
639214413Sdavidxu			return (ERANGE);
640214413Sdavidxu		if (attr->cpuset != NULL)
641214413Sdavidxu			memcpy(cpusetp, attr->cpuset, MIN(cpusetsize,
642214413Sdavidxu			   attr->cpusetsize));
643214413Sdavidxu		else
644214413Sdavidxu			memset(cpusetp, -1, kern_size);
645176815Sdavidxu		if (cpusetsize > kern_size)
646214413Sdavidxu			memset(((char *)cpusetp) + kern_size, 0,
647176815Sdavidxu				cpusetsize - kern_size);
648176781Sdavidxu	}
649176781Sdavidxu	return (ret);
650176781Sdavidxu}
651