thr_attr.c revision 214335
159612Sjasone/*
259612Sjasone * Copyright (c) 2003 Craig Rodrigues <rodrigc@attbi.com>.
359612Sjasone * All rights reserved.
459612Sjasone *
559612Sjasone * Redistribution and use in source and binary forms, with or without
659612Sjasone * modification, are permitted provided that the following conditions
759612Sjasone * are met:
859612Sjasone * 1. Redistributions of source code must retain the above copyright
959612Sjasone *    notice, this list of conditions and the following disclaimer.
1059612Sjasone * 2. Redistributions in binary form must reproduce the above copyright
1159612Sjasone *    notice, this list of conditions and the following disclaimer in the
1259612Sjasone *    documentation and/or other materials provided with the distribution.
1359612Sjasone * 3. All advertising materials mentioning features or use of this software
1459612Sjasone *    must display the following acknowledgement:
1559612Sjasone *	This product includes software developed by Craig Rodrigues.
1659612Sjasone * 4. Neither the name of the author nor the names of any co-contributors
1759612Sjasone *    may be used to endorse or promote products derived from this software
1859612Sjasone *    without specific prior written permission.
1959612Sjasone *
2059612Sjasone * THIS SOFTWARE IS PROVIDED BY CRAIG RODRIGUES AND CONTRIBUTORS ``AS IS'' AND
2159612Sjasone * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2259612Sjasone * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2359612Sjasone * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
2459612Sjasone * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2559612Sjasone * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2659612Sjasone * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2759612Sjasone * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2859612Sjasone * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2959612Sjasone * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
3059612Sjasone * SUCH DAMAGE.
3159612Sjasone *
3259612Sjasone */
3359612Sjasone
3459612Sjasone/*
3559612Sjasone * Copyright (c) 1998 Daniel Eischen <eischen@vigrid.com>.
3659612Sjasone * Copyright (C) 2001 Jason Evans <jasone@freebsd.org>.
3759612Sjasone * Copyright (c) 2002,2003 Alexey Zelkin <phantom@FreeBSD.org>
3859612Sjasone * All rights reserved.
3959612Sjasone *
4059612Sjasone * Redistribution and use in source and binary forms, with or without
4159612Sjasone * modification, are permitted provided that the following conditions
4259612Sjasone * are met:
4359612Sjasone * 1. Redistributions of source code must retain the above copyright
4459612Sjasone *    notice(s), this list of conditions and the following disclaimer
4559612Sjasone *    unmodified other than the allowable addition of one or more
4659612Sjasone *    copyright notices.
4759612Sjasone * 2. Redistributions in binary form must reproduce the above copyright
4859612Sjasone *    notice(s), this list of conditions and the following disclaimer in
4959612Sjasone *    the documentation and/or other materials provided with the
5059612Sjasone *    distribution.
5159612Sjasone *
5259612Sjasone * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) ``AS IS'' AND ANY
5359612Sjasone * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
5459612Sjasone * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
5559612Sjasone * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) BE
5659612Sjasone * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
5759612Sjasone * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
5859612Sjasone * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
5959612Sjasone * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
6059612Sjasone * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
6159612Sjasone * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
6281975Skris * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
6381975Skris */
6481975Skris
6559612Sjasone/*
6659612Sjasone * Copyright (c) 1996 John Birrell <jb@cimlogic.com.au>.
6759612Sjasone * All rights reserved.
6859612Sjasone *
6959612Sjasone * Redistribution and use in source and binary forms, with or without
7059612Sjasone * modification, are permitted provided that the following conditions
7159612Sjasone * are met:
7259612Sjasone * 1. Redistributions of source code must retain the above copyright
7359612Sjasone *    notice, this list of conditions and the following disclaimer.
7459612Sjasone * 2. Redistributions in binary form must reproduce the above copyright
7559612Sjasone *    notice, this list of conditions and the following disclaimer in the
7659612Sjasone *    documentation and/or other materials provided with the distribution.
7759612Sjasone * 3. Neither the name of the author nor the names of any co-contributors
7859612Sjasone *    may be used to endorse or promote products derived from this software
7959612Sjasone *    without specific prior written permission.
8059612Sjasone *
8159612Sjasone * THIS SOFTWARE IS PROVIDED BY JOHN BIRRELL AND CONTRIBUTORS ``AS IS'' AND
8259612Sjasone * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
8359612Sjasone * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
8459612Sjasone * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
8559612Sjasone * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
8659612Sjasone * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
8759612Sjasone * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
8859612Sjasone * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
8959612Sjasone * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
9059612Sjasone * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
9159612Sjasone * SUCH DAMAGE.
9259612Sjasone *
9359612Sjasone * $FreeBSD: head/lib/libthr/thread/thr_attr.c 214335 2010-10-25 11:16:50Z davidxu $
9459612Sjasone */
9559612Sjasone
9659612Sjasone#include "namespace.h"
9759612Sjasone#include <errno.h>
9859612Sjasone#include <pthread.h>
9959612Sjasone#include <stdlib.h>
10059612Sjasone#include <string.h>
10159612Sjasone#include <pthread_np.h>
10259612Sjasone#include <sys/sysctl.h>
10359612Sjasone#include "un-namespace.h"
10459612Sjasone
10559612Sjasone#include "thr_private.h"
10659612Sjasone
10759612Sjasonestatic size_t	_get_kern_cpuset_size(void);
10859612Sjasone
10959612Sjasone__weak_reference(_pthread_attr_destroy, pthread_attr_destroy);
11059612Sjasone
11159612Sjasoneint
11259612Sjasone_pthread_attr_destroy(pthread_attr_t *attr)
11359612Sjasone{
11459612Sjasone	int	ret;
11559612Sjasone
11659612Sjasone	/* Check for invalid arguments: */
11759612Sjasone	if (attr == NULL || *attr == NULL)
11859612Sjasone		/* Invalid argument: */
11959612Sjasone		ret = EINVAL;
12059612Sjasone	else {
12159612Sjasone		if ((*attr)->cpuset != NULL)
12259612Sjasone			free((*attr)->cpuset);
12359612Sjasone		/* Free the memory allocated to the attribute object: */
12459612Sjasone		free(*attr);
12559612Sjasone
12659612Sjasone		/*
12759612Sjasone		 * Leave the attribute pointer NULL now that the memory
12859612Sjasone		 * has been freed:
12959612Sjasone		 */
13059612Sjasone		*attr = NULL;
13159612Sjasone		ret = 0;
13259612Sjasone	}
13359612Sjasone	return(ret);
13459612Sjasone}
13559612Sjasone
13659612Sjasone__weak_reference(_pthread_attr_get_np, pthread_attr_get_np);
13759612Sjasone
13859612Sjasoneint
13959612Sjasone_pthread_attr_get_np(pthread_t pthread, pthread_attr_t *dstattr)
14059612Sjasone{
14159612Sjasone	struct pthread *curthread;
14259612Sjasone	struct pthread_attr attr, *dst;
14359612Sjasone	int	ret;
14459612Sjasone	size_t	cpusetsize;
14559612Sjasone
14659612Sjasone	if (pthread == NULL || dstattr == NULL || (dst = *dstattr) == NULL)
14759612Sjasone		return (EINVAL);
14859612Sjasone	cpusetsize = _get_kern_cpuset_size();
14959612Sjasone	if (dst->cpusetsize < cpusetsize) {
15059612Sjasone		char *newset = realloc(dst->cpuset, cpusetsize);
15159612Sjasone		if (newset == NULL)
15259612Sjasone			return (errno);
15359612Sjasone		memset(newset + dst->cpusetsize, 0, cpusetsize -
15459612Sjasone			dst->cpusetsize);
15559612Sjasone		dst->cpuset = (cpuset_t *)newset;
15659612Sjasone		dst->cpusetsize = cpusetsize;
15759612Sjasone	}
15859612Sjasone	curthread = _get_curthread();
15959612Sjasone	if ((ret = _thr_find_thread(curthread, pthread, /*include dead*/0)) != 0)
16059612Sjasone		return (ret);
16159612Sjasone	attr = pthread->attr;
16259612Sjasone	if (pthread->flags & THR_FLAGS_DETACHED)
16359612Sjasone		attr.flags |= PTHREAD_DETACHED;
16459612Sjasone	ret = cpuset_getaffinity(CPU_LEVEL_WHICH, CPU_WHICH_TID, TID(pthread),
16559612Sjasone		dst->cpusetsize, dst->cpuset);
16659612Sjasone	if (ret == -1)
16759612Sjasone		ret = errno;
16899239Sdeischen	THR_THREAD_UNLOCK(curthread, pthread);
16959612Sjasone	if (ret == 0) {
17059612Sjasone		memcpy(&dst->pthread_attr_start_copy,
17159612Sjasone			&attr.pthread_attr_start_copy,
17259612Sjasone			offsetof(struct pthread_attr, pthread_attr_end_copy) -
17359612Sjasone			offsetof(struct pthread_attr, pthread_attr_start_copy));
17459612Sjasone	}
17559612Sjasone	return (ret);
17659612Sjasone}
17759612Sjasone
17859612Sjasone__weak_reference(_pthread_attr_getdetachstate, pthread_attr_getdetachstate);
17959612Sjasone
18059612Sjasoneint
18159612Sjasone_pthread_attr_getdetachstate(const pthread_attr_t *attr, int *detachstate)
18259612Sjasone{
18359612Sjasone	int	ret;
18459612Sjasone
18559612Sjasone	/* Check for invalid arguments: */
18659612Sjasone	if (attr == NULL || *attr == NULL || detachstate == NULL)
18759612Sjasone		ret = EINVAL;
18859612Sjasone	else {
18959612Sjasone		/* Check if the detached flag is set: */
19059612Sjasone		if ((*attr)->flags & PTHREAD_DETACHED)
19159612Sjasone			/* Return detached: */
19259612Sjasone			*detachstate = PTHREAD_CREATE_DETACHED;
19359612Sjasone		else
19459612Sjasone			/* Return joinable: */
19559612Sjasone			*detachstate = PTHREAD_CREATE_JOINABLE;
19659612Sjasone		ret = 0;
19759612Sjasone	}
19859612Sjasone	return(ret);
19959612Sjasone}
20059612Sjasone
20159612Sjasone__weak_reference(_pthread_attr_getguardsize, pthread_attr_getguardsize);
20259612Sjasone
20359612Sjasoneint
20459612Sjasone_pthread_attr_getguardsize(const pthread_attr_t *attr, size_t *guardsize)
20559612Sjasone{
20659612Sjasone	int	ret;
20759612Sjasone
20859612Sjasone	/* Check for invalid arguments: */
20959612Sjasone	if (attr == NULL || *attr == NULL || guardsize == NULL)
21059612Sjasone		ret = EINVAL;
21159612Sjasone	else {
21259612Sjasone		/* Return the guard size: */
21359612Sjasone		*guardsize = (*attr)->guardsize_attr;
21459612Sjasone		ret = 0;
21559612Sjasone	}
21659612Sjasone	return(ret);
21759612Sjasone}
21859612Sjasone
21959612Sjasone__weak_reference(_pthread_attr_getinheritsched, pthread_attr_getinheritsched);
22059612Sjasone
22159612Sjasoneint
22259612Sjasone_pthread_attr_getinheritsched(const pthread_attr_t *attr, int *sched_inherit)
22359612Sjasone{
22459612Sjasone	int ret = 0;
22559612Sjasone
22659612Sjasone	if ((attr == NULL) || (*attr == NULL))
22759612Sjasone		ret = EINVAL;
22859612Sjasone	else
22959612Sjasone		*sched_inherit = (*attr)->sched_inherit;
23059612Sjasone
23159612Sjasone	return(ret);
23259612Sjasone}
23359612Sjasone
23459612Sjasone__weak_reference(_pthread_attr_getschedparam, pthread_attr_getschedparam);
23559612Sjasone
23659612Sjasoneint
23759612Sjasone_pthread_attr_getschedparam(const pthread_attr_t *attr, struct sched_param *param)
23859612Sjasone{
23959612Sjasone	int ret = 0;
24059612Sjasone
24159612Sjasone	if ((attr == NULL) || (*attr == NULL) || (param == NULL))
24259612Sjasone		ret = EINVAL;
24359612Sjasone	else
24459612Sjasone		param->sched_priority = (*attr)->prio;
24559612Sjasone
24659612Sjasone	return(ret);
24759612Sjasone}
24859612Sjasone
24959612Sjasone__weak_reference(_pthread_attr_getschedpolicy, pthread_attr_getschedpolicy);
25059612Sjasone
25159612Sjasoneint
25259612Sjasone_pthread_attr_getschedpolicy(const pthread_attr_t *attr, int *policy)
25359612Sjasone{
25459612Sjasone	int ret = 0;
25559612Sjasone
25659612Sjasone	if ((attr == NULL) || (*attr == NULL) || (policy == NULL))
25759612Sjasone		ret = EINVAL;
25859612Sjasone	else
25959612Sjasone		*policy = (*attr)->sched_policy;
26059612Sjasone
26159612Sjasone	return(ret);
26259612Sjasone}
26359612Sjasone
26459612Sjasone__weak_reference(_pthread_attr_getscope, pthread_attr_getscope);
26559612Sjasone
26659612Sjasoneint
26759612Sjasone_pthread_attr_getscope(const pthread_attr_t *attr, int *contentionscope)
26859612Sjasone{
26959612Sjasone	int ret = 0;
27059612Sjasone
27159612Sjasone	if ((attr == NULL) || (*attr == NULL) || (contentionscope == NULL))
27259612Sjasone		/* Return an invalid argument: */
27359612Sjasone		ret = EINVAL;
27459612Sjasone
27559612Sjasone	else
27659612Sjasone		*contentionscope = (*attr)->flags & PTHREAD_SCOPE_SYSTEM ?
27759612Sjasone		    PTHREAD_SCOPE_SYSTEM : PTHREAD_SCOPE_PROCESS;
27859612Sjasone
27959612Sjasone	return(ret);
28059612Sjasone}
28159612Sjasone
28259612Sjasone__weak_reference(_pthread_attr_getstack, pthread_attr_getstack);
28359612Sjasone
28459612Sjasoneint
28559612Sjasone_pthread_attr_getstack(const pthread_attr_t * __restrict attr,
28659612Sjasone                        void ** __restrict stackaddr,
28759612Sjasone                        size_t * __restrict stacksize)
28859612Sjasone{
28959612Sjasone	int     ret;
29059612Sjasone
29159612Sjasone	/* Check for invalid arguments: */
29259612Sjasone	if (attr == NULL || *attr == NULL || stackaddr == NULL
29359612Sjasone	    || stacksize == NULL )
29459612Sjasone		ret = EINVAL;
29559612Sjasone	else {
29659612Sjasone		/* Return the stack address and size */
29759612Sjasone		*stackaddr = (*attr)->stackaddr_attr;
29859612Sjasone		*stacksize = (*attr)->stacksize_attr;
29959612Sjasone		ret = 0;
30059612Sjasone	}
30159612Sjasone	return(ret);
30259612Sjasone}
30359612Sjasone
30459612Sjasone__weak_reference(_pthread_attr_getstackaddr, pthread_attr_getstackaddr);
30559612Sjasone
30659612Sjasoneint
30759612Sjasone_pthread_attr_getstackaddr(const pthread_attr_t *attr, void **stackaddr)
30859612Sjasone{
30959612Sjasone	int	ret;
31059612Sjasone
31159612Sjasone	/* Check for invalid arguments: */
31259612Sjasone	if (attr == NULL || *attr == NULL || stackaddr == NULL)
31359612Sjasone		ret = EINVAL;
31459612Sjasone	else {
31559612Sjasone		/* Return the stack address: */
31659612Sjasone		*stackaddr = (*attr)->stackaddr_attr;
31759612Sjasone		ret = 0;
31859612Sjasone	}
31959612Sjasone	return(ret);
32059612Sjasone}
32159612Sjasone
32259612Sjasone__weak_reference(_pthread_attr_getstacksize, pthread_attr_getstacksize);
32359612Sjasone
32459612Sjasoneint
32559612Sjasone_pthread_attr_getstacksize(const pthread_attr_t *attr, size_t *stacksize)
32659612Sjasone{
32759612Sjasone	int	ret;
32859612Sjasone
32959612Sjasone	/* Check for invalid arguments: */
33059612Sjasone	if (attr == NULL || *attr == NULL || stacksize  == NULL)
33159612Sjasone		ret = EINVAL;
33259612Sjasone	else {
33359612Sjasone		/* Return the stack size: */
33459612Sjasone		*stacksize = (*attr)->stacksize_attr;
33559612Sjasone		ret = 0;
33659612Sjasone	}
33759612Sjasone	return(ret);
33859612Sjasone}
33959612Sjasone
34059612Sjasone__weak_reference(_pthread_attr_init, pthread_attr_init);
34159612Sjasone
34259612Sjasoneint
34359612Sjasone_pthread_attr_init(pthread_attr_t *attr)
34459612Sjasone{
34559612Sjasone	int	ret;
34659612Sjasone	pthread_attr_t	pattr;
34759612Sjasone
34859612Sjasone	_thr_check_init();
34959612Sjasone
35059612Sjasone	/* Allocate memory for the attribute object: */
35159612Sjasone	if ((pattr = (pthread_attr_t) malloc(sizeof(struct pthread_attr))) == NULL)
35259612Sjasone		/* Insufficient memory: */
35359612Sjasone		ret = ENOMEM;
35459612Sjasone	else {
35559612Sjasone		/* Initialise the attribute object with the defaults: */
35659612Sjasone		memcpy(pattr, &_pthread_attr_default, sizeof(struct pthread_attr));
35799239Sdeischen
35859612Sjasone		/* Return a pointer to the attribute object: */
35959612Sjasone		*attr = pattr;
36059612Sjasone		ret = 0;
36159612Sjasone	}
36259612Sjasone	return(ret);
36359612Sjasone}
36459612Sjasone
36559612Sjasone__weak_reference(_pthread_attr_setcreatesuspend_np, pthread_attr_setcreatesuspend_np);
36659612Sjasone
36759612Sjasoneint
36859612Sjasone_pthread_attr_setcreatesuspend_np(pthread_attr_t *attr)
36959612Sjasone{
37059612Sjasone	int	ret;
37159612Sjasone
37259612Sjasone	if (attr == NULL || *attr == NULL) {
37359612Sjasone		ret = EINVAL;
37459612Sjasone	} else {
37559612Sjasone		(*attr)->suspend = THR_CREATE_SUSPENDED;
37659612Sjasone		ret = 0;
37759612Sjasone	}
37859612Sjasone	return(ret);
37959612Sjasone}
38059612Sjasone
38159612Sjasone__weak_reference(_pthread_attr_setdetachstate, pthread_attr_setdetachstate);
38259612Sjasone
38359612Sjasoneint
38459612Sjasone_pthread_attr_setdetachstate(pthread_attr_t *attr, int detachstate)
38559612Sjasone{
38659612Sjasone	int	ret;
38759612Sjasone
38859612Sjasone	/* Check for invalid arguments: */
38959612Sjasone	if (attr == NULL || *attr == NULL ||
39059612Sjasone	    (detachstate != PTHREAD_CREATE_DETACHED &&
39159612Sjasone	    detachstate != PTHREAD_CREATE_JOINABLE))
39259612Sjasone		ret = EINVAL;
39359612Sjasone	else {
39459612Sjasone		/* Check if detached state: */
39559612Sjasone		if (detachstate == PTHREAD_CREATE_DETACHED)
39659612Sjasone			/* Set the detached flag: */
39759612Sjasone			(*attr)->flags |= PTHREAD_DETACHED;
39859612Sjasone		else
39959612Sjasone			/* Reset the detached flag: */
40059612Sjasone			(*attr)->flags &= ~PTHREAD_DETACHED;
40159612Sjasone		ret = 0;
40259612Sjasone	}
40359612Sjasone	return(ret);
40459612Sjasone}
40559612Sjasone
40659612Sjasone__weak_reference(_pthread_attr_setguardsize, pthread_attr_setguardsize);
40759612Sjasone
40859612Sjasoneint
40959612Sjasone_pthread_attr_setguardsize(pthread_attr_t *attr, size_t guardsize)
41059612Sjasone{
41159612Sjasone	int	ret;
41259612Sjasone
41359612Sjasone	/* Check for invalid arguments. */
41459612Sjasone	if (attr == NULL || *attr == NULL)
41559612Sjasone		ret = EINVAL;
41659612Sjasone	else {
41759612Sjasone		/* Save the stack size. */
41859612Sjasone		(*attr)->guardsize_attr = guardsize;
41959612Sjasone		ret = 0;
42059612Sjasone	}
42159612Sjasone	return(ret);
42259612Sjasone}
42359612Sjasone
42459612Sjasone__weak_reference(_pthread_attr_setinheritsched, pthread_attr_setinheritsched);
42559612Sjasone
42659612Sjasoneint
42759612Sjasone_pthread_attr_setinheritsched(pthread_attr_t *attr, int sched_inherit)
42859612Sjasone{
42959612Sjasone	int ret = 0;
43059612Sjasone
43159612Sjasone	if ((attr == NULL) || (*attr == NULL))
43259612Sjasone		ret = EINVAL;
43359612Sjasone	else if (sched_inherit != PTHREAD_INHERIT_SCHED &&
43459612Sjasone		 sched_inherit != PTHREAD_EXPLICIT_SCHED)
43559612Sjasone		ret = ENOTSUP;
43659612Sjasone	else
43759612Sjasone		(*attr)->sched_inherit = sched_inherit;
43859612Sjasone
43959612Sjasone	return(ret);
44059612Sjasone}
44159612Sjasone
44259612Sjasone__weak_reference(_pthread_attr_setschedparam, pthread_attr_setschedparam);
44359612Sjasone
44459612Sjasoneint
44559612Sjasone_pthread_attr_setschedparam(pthread_attr_t *attr, const struct sched_param *param)
44659612Sjasone{
44759612Sjasone	int policy;
44859612Sjasone
44959612Sjasone	if ((attr == NULL) || (*attr == NULL))
45059612Sjasone		return (EINVAL);
45159612Sjasone
45259612Sjasone	if (param == NULL)
45359612Sjasone		return (ENOTSUP);
45459612Sjasone
45559612Sjasone	policy = (*attr)->sched_policy;
45659612Sjasone
45759612Sjasone	if (policy == SCHED_FIFO || policy == SCHED_RR) {
45859612Sjasone		if (param->sched_priority < _thr_priorities[policy-1].pri_min ||
45959612Sjasone		    param->sched_priority > _thr_priorities[policy-1].pri_max)
46059612Sjasone		return (ENOTSUP);
46159612Sjasone	} else {
46259612Sjasone		/*
46359612Sjasone		 * Ignore it for SCHED_OTHER now, patches for glib ports
46459612Sjasone		 * are wrongly using M:N thread library's internal macro
46559612Sjasone		 * THR_MIN_PRIORITY and THR_MAX_PRIORITY.
46659612Sjasone		 */
46759612Sjasone	}
46859612Sjasone
46959612Sjasone	(*attr)->prio = param->sched_priority;
47059612Sjasone
47159612Sjasone	return (0);
47259612Sjasone}
47359612Sjasone
47459612Sjasone__weak_reference(_pthread_attr_setschedpolicy, pthread_attr_setschedpolicy);
47559612Sjasone
47659612Sjasoneint
47759612Sjasone_pthread_attr_setschedpolicy(pthread_attr_t *attr, int policy)
47859612Sjasone{
47959612Sjasone	int ret = 0;
48059612Sjasone
48159612Sjasone	if ((attr == NULL) || (*attr == NULL))
48259612Sjasone		ret = EINVAL;
48359612Sjasone	else if ((policy < SCHED_FIFO) || (policy > SCHED_RR)) {
48459612Sjasone		ret = ENOTSUP;
48559612Sjasone	} else {
48659612Sjasone		(*attr)->sched_policy = policy;
48759612Sjasone		(*attr)->prio = _thr_priorities[policy-1].pri_default;
48859612Sjasone	}
48959612Sjasone	return(ret);
49059612Sjasone}
49159612Sjasone
49259612Sjasone__weak_reference(_pthread_attr_setscope, pthread_attr_setscope);
49359612Sjasone
49459612Sjasoneint
49559612Sjasone_pthread_attr_setscope(pthread_attr_t *attr, int contentionscope)
49659612Sjasone{
49759612Sjasone	int ret = 0;
49859612Sjasone
49959612Sjasone	if ((attr == NULL) || (*attr == NULL)) {
50059612Sjasone		/* Return an invalid argument: */
50159612Sjasone		ret = EINVAL;
50259612Sjasone	} else if ((contentionscope != PTHREAD_SCOPE_PROCESS) &&
50359612Sjasone	    (contentionscope != PTHREAD_SCOPE_SYSTEM)) {
50459612Sjasone		ret = EINVAL;
50559612Sjasone	} else if (contentionscope == PTHREAD_SCOPE_SYSTEM) {
50659612Sjasone		(*attr)->flags |= contentionscope;
50759612Sjasone	} else {
50859612Sjasone		(*attr)->flags &= ~PTHREAD_SCOPE_SYSTEM;
50959612Sjasone	}
51059612Sjasone	return (ret);
51159612Sjasone}
51259612Sjasone
51359612Sjasone__weak_reference(_pthread_attr_setstack, pthread_attr_setstack);
51459612Sjasone
51559612Sjasoneint
51659612Sjasone_pthread_attr_setstack(pthread_attr_t *attr, void *stackaddr,
51759612Sjasone                        size_t stacksize)
51859612Sjasone{
51959612Sjasone	int     ret;
52059612Sjasone
52159612Sjasone	/* Check for invalid arguments: */
52259612Sjasone	if (attr == NULL || *attr == NULL || stackaddr == NULL
52359612Sjasone	    || stacksize < PTHREAD_STACK_MIN)
52459612Sjasone		ret = EINVAL;
52559612Sjasone	else {
52659612Sjasone		/* Save the stack address and stack size */
52759612Sjasone		(*attr)->stackaddr_attr = stackaddr;
52859612Sjasone		(*attr)->stacksize_attr = stacksize;
52959612Sjasone		ret = 0;
53059612Sjasone	}
53159612Sjasone	return(ret);
53259612Sjasone}
53359612Sjasone
53459612Sjasone__weak_reference(_pthread_attr_setstackaddr, pthread_attr_setstackaddr);
53559612Sjasone
53659612Sjasoneint
53759612Sjasone_pthread_attr_setstackaddr(pthread_attr_t *attr, void *stackaddr)
53859612Sjasone{
53959612Sjasone	int	ret;
54059612Sjasone
54159612Sjasone	/* Check for invalid arguments: */
54259612Sjasone	if (attr == NULL || *attr == NULL || stackaddr == NULL)
54359612Sjasone		ret = EINVAL;
54459612Sjasone	else {
54559612Sjasone		/* Save the stack address: */
54659612Sjasone		(*attr)->stackaddr_attr = stackaddr;
54759612Sjasone		ret = 0;
54859612Sjasone	}
54959612Sjasone	return(ret);
55059612Sjasone}
55159612Sjasone
55259612Sjasone__weak_reference(_pthread_attr_setstacksize, pthread_attr_setstacksize);
55359612Sjasone
55459612Sjasoneint
55559612Sjasone_pthread_attr_setstacksize(pthread_attr_t *attr, size_t stacksize)
55659612Sjasone{
55759612Sjasone	int	ret;
55859612Sjasone
55959612Sjasone	/* Check for invalid arguments: */
56059612Sjasone	if (attr == NULL || *attr == NULL || stacksize < PTHREAD_STACK_MIN)
56159612Sjasone		ret = EINVAL;
56259612Sjasone	else {
56359612Sjasone		/* Save the stack size: */
56459612Sjasone		(*attr)->stacksize_attr = stacksize;
56559612Sjasone		ret = 0;
56659612Sjasone	}
56759612Sjasone	return(ret);
56859612Sjasone}
56959612Sjasone
57059612Sjasonestatic size_t
57159612Sjasone_get_kern_cpuset_size(void)
57259612Sjasone{
57359612Sjasone	static int kern_cpuset_size = 0;
57459612Sjasone
57559612Sjasone	if (kern_cpuset_size == 0) {
57659612Sjasone		size_t len;
57759612Sjasone
57859612Sjasone		len = sizeof(kern_cpuset_size);
57959612Sjasone		if (sysctlbyname("kern.smp.maxcpus", &kern_cpuset_size,
58059612Sjasone		    &len, NULL, 0))
58159612Sjasone			PANIC("failed to get sysctl kern.smp.maxcpus");
58259612Sjasone
58359612Sjasone		kern_cpuset_size = (kern_cpuset_size + 7) / 8;
58459612Sjasone	}
58559612Sjasone
58659612Sjasone	return (kern_cpuset_size);
58759612Sjasone}
58859612Sjasone
58959612Sjasone__weak_reference(_pthread_attr_setaffinity_np, pthread_attr_setaffinity_np);
59059612Sjasoneint
59159612Sjasone_pthread_attr_setaffinity_np(pthread_attr_t *pattr, size_t cpusetsize,
59259612Sjasone	const cpuset_t *cpusetp)
59359612Sjasone{
59459612Sjasone	pthread_attr_t attr;
59559612Sjasone	int ret;
59659612Sjasone
59759612Sjasone	if (pattr == NULL || (attr = (*pattr)) == NULL)
59859612Sjasone		ret = EINVAL;
59959612Sjasone	else {
60059612Sjasone		if (cpusetsize == 0 || cpusetp == NULL) {
60159612Sjasone			if (attr->cpuset != NULL) {
60259612Sjasone				free(attr->cpuset);
60359612Sjasone				attr->cpuset = NULL;
60459612Sjasone				attr->cpusetsize = 0;
60559612Sjasone			}
60659612Sjasone			return (0);
60759612Sjasone		}
60859612Sjasone
60959612Sjasone		if (cpusetsize > attr->cpusetsize) {
61059612Sjasone			size_t kern_size = _get_kern_cpuset_size();
61159612Sjasone			if (cpusetsize > kern_size) {
61259612Sjasone				size_t i;
61359612Sjasone				for (i = kern_size; i < cpusetsize; ++i) {
61459612Sjasone					if (((char *)cpusetp)[i])
61559612Sjasone						return (EINVAL);
61659612Sjasone				}
61759612Sjasone			}
61859612Sjasone			void *newset = realloc(attr->cpuset, cpusetsize);
61959612Sjasone       			if (newset == NULL)
62059612Sjasone		            return (ENOMEM);
62159612Sjasone			attr->cpuset = newset;
62259612Sjasone			attr->cpusetsize = cpusetsize;
62359612Sjasone		} else {
62459612Sjasone			memset(((char *)attr->cpuset) + cpusetsize, 0,
62559612Sjasone				attr->cpusetsize - cpusetsize);
62659612Sjasone			attr->cpusetsize = cpusetsize;
62759612Sjasone		}
62859612Sjasone		memcpy(attr->cpuset, cpusetp, cpusetsize);
62959612Sjasone		ret = 0;
63059612Sjasone	}
63159612Sjasone	return (ret);
63259612Sjasone}
63359612Sjasone
63459612Sjasone__weak_reference(_pthread_attr_getaffinity_np, pthread_attr_getaffinity_np);
63559612Sjasoneint
63659612Sjasone_pthread_attr_getaffinity_np(const pthread_attr_t *pattr, size_t cpusetsize,
63759612Sjasone	cpuset_t *cpusetp)
63859612Sjasone{
63959612Sjasone	pthread_attr_t attr;
64059612Sjasone	int ret = 0;
64159612Sjasone
64259612Sjasone	if (pattr == NULL || (attr = (*pattr)) == NULL)
64359612Sjasone		ret = EINVAL;
64459612Sjasone	else if (attr->cpuset != NULL) {
64559612Sjasone		memcpy(cpusetp, attr->cpuset, MIN(cpusetsize, attr->cpusetsize));
64659612Sjasone		if (cpusetsize > attr->cpusetsize)
64759612Sjasone			memset(((char *)cpusetp) + attr->cpusetsize, 0,
64859612Sjasone				cpusetsize - attr->cpusetsize);
64959612Sjasone	} else {
65059612Sjasone		size_t kern_size = _get_kern_cpuset_size();
65159612Sjasone		memset(cpusetp, -1, MIN(cpusetsize, kern_size));
65259612Sjasone		if (cpusetsize > kern_size)
65359612Sjasone			memset(((char *)cpusetp) + kern_size, 0,
65459612Sjasone				cpusetsize - kern_size);
65559612Sjasone	}
65659612Sjasone	return (ret);
65759612Sjasone}
65859612Sjasone