xref: /onnv-gate/usr/src/lib/libc/port/threads/pthr_attr.c (revision 7657:59d4b80e7a88)
10Sstevel@tonic-gate /*
20Sstevel@tonic-gate  * CDDL HEADER START
30Sstevel@tonic-gate  *
40Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
51885Sraf  * Common Development and Distribution License (the "License").
61885Sraf  * You may not use this file except in compliance with the License.
70Sstevel@tonic-gate  *
80Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
90Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
100Sstevel@tonic-gate  * See the License for the specific language governing permissions
110Sstevel@tonic-gate  * and limitations under the License.
120Sstevel@tonic-gate  *
130Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
140Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
150Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
160Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
170Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
180Sstevel@tonic-gate  *
190Sstevel@tonic-gate  * CDDL HEADER END
200Sstevel@tonic-gate  */
211885Sraf 
220Sstevel@tonic-gate /*
236247Sraf  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
240Sstevel@tonic-gate  * Use is subject to license terms.
250Sstevel@tonic-gate  */
260Sstevel@tonic-gate 
270Sstevel@tonic-gate #include "lint.h"
280Sstevel@tonic-gate #include "thr_uberdata.h"
290Sstevel@tonic-gate #include <sched.h>
300Sstevel@tonic-gate 
310Sstevel@tonic-gate /*
321885Sraf  * Default attribute object for pthread_create() with NULL attr pointer.
331885Sraf  * Note that the 'guardsize' field is initialized on the first call.
341885Sraf  */
351885Sraf const thrattr_t *
def_thrattr(void)361885Sraf def_thrattr(void)
371885Sraf {
381885Sraf 	static thrattr_t thrattr = {
391885Sraf 		0,				/* stksize */
401885Sraf 		NULL,				/* stkaddr */
411885Sraf 		PTHREAD_CREATE_JOINABLE,	/* detachstate */
421885Sraf 		PTHREAD_CREATE_NONDAEMON_NP,	/* daemonstate */
431885Sraf 		PTHREAD_SCOPE_PROCESS,		/* scope */
441885Sraf 		0,				/* prio */
451885Sraf 		SCHED_OTHER,			/* policy */
466247Sraf 		PTHREAD_INHERIT_SCHED,		/* inherit */
471885Sraf 		0				/* guardsize */
481885Sraf 	};
491885Sraf 	if (thrattr.guardsize == 0)
501885Sraf 		thrattr.guardsize = _sysconf(_SC_PAGESIZE);
511885Sraf 	return (&thrattr);
521885Sraf }
531885Sraf 
541885Sraf /*
550Sstevel@tonic-gate  * pthread_attr_init: allocates the attribute object and initializes it
560Sstevel@tonic-gate  * with the default values.
570Sstevel@tonic-gate  */
586812Sraf #pragma weak _pthread_attr_init = pthread_attr_init
590Sstevel@tonic-gate int
pthread_attr_init(pthread_attr_t * attr)606812Sraf pthread_attr_init(pthread_attr_t *attr)
610Sstevel@tonic-gate {
620Sstevel@tonic-gate 	thrattr_t *ap;
630Sstevel@tonic-gate 
640Sstevel@tonic-gate 	if ((ap = lmalloc(sizeof (thrattr_t))) != NULL) {
651885Sraf 		*ap = *def_thrattr();
660Sstevel@tonic-gate 		attr->__pthread_attrp = ap;
670Sstevel@tonic-gate 		return (0);
680Sstevel@tonic-gate 	}
690Sstevel@tonic-gate 	return (ENOMEM);
700Sstevel@tonic-gate }
710Sstevel@tonic-gate 
720Sstevel@tonic-gate /*
730Sstevel@tonic-gate  * pthread_attr_destroy: frees the attribute object and invalidates it
740Sstevel@tonic-gate  * with NULL value.
750Sstevel@tonic-gate  */
760Sstevel@tonic-gate int
pthread_attr_destroy(pthread_attr_t * attr)776812Sraf pthread_attr_destroy(pthread_attr_t *attr)
780Sstevel@tonic-gate {
790Sstevel@tonic-gate 	if (attr == NULL || attr->__pthread_attrp == NULL)
800Sstevel@tonic-gate 		return (EINVAL);
810Sstevel@tonic-gate 	lfree(attr->__pthread_attrp, sizeof (thrattr_t));
820Sstevel@tonic-gate 	attr->__pthread_attrp = NULL;
830Sstevel@tonic-gate 	return (0);
840Sstevel@tonic-gate }
850Sstevel@tonic-gate 
860Sstevel@tonic-gate /*
876812Sraf  * pthread_attr_clone: make a copy of a pthread_attr_t.
881885Sraf  */
891885Sraf int
pthread_attr_clone(pthread_attr_t * attr,const pthread_attr_t * old_attr)906812Sraf pthread_attr_clone(pthread_attr_t *attr, const pthread_attr_t *old_attr)
911885Sraf {
921885Sraf 	thrattr_t *ap;
931885Sraf 	const thrattr_t *old_ap =
946247Sraf 	    old_attr? old_attr->__pthread_attrp : def_thrattr();
951885Sraf 
961885Sraf 	if (old_ap == NULL)
971885Sraf 		return (EINVAL);
981885Sraf 	if ((ap = lmalloc(sizeof (thrattr_t))) == NULL)
991885Sraf 		return (ENOMEM);
1001885Sraf 	*ap = *old_ap;
1011885Sraf 	attr->__pthread_attrp = ap;
1021885Sraf 	return (0);
1031885Sraf }
1041885Sraf 
1051885Sraf /*
1066812Sraf  * pthread_attr_equal: compare two pthread_attr_t's, return 1 if equal.
1071885Sraf  * A NULL pthread_attr_t pointer implies default attributes.
1081885Sraf  * This is a consolidation-private interface, for librt.
1091885Sraf  */
1101885Sraf int
pthread_attr_equal(const pthread_attr_t * attr1,const pthread_attr_t * attr2)1116812Sraf pthread_attr_equal(const pthread_attr_t *attr1, const pthread_attr_t *attr2)
1121885Sraf {
1131885Sraf 	const thrattr_t *ap1 = attr1? attr1->__pthread_attrp : def_thrattr();
1141885Sraf 	const thrattr_t *ap2 = attr2? attr2->__pthread_attrp : def_thrattr();
1151885Sraf 
1161885Sraf 	if (ap1 == NULL || ap2 == NULL)
1171885Sraf 		return (0);
1186515Sraf 	return (ap1 == ap2 || memcmp(ap1, ap2, sizeof (thrattr_t)) == 0);
1191885Sraf }
1201885Sraf 
1211885Sraf /*
1220Sstevel@tonic-gate  * pthread_attr_setstacksize: sets the user stack size, minimum should
1230Sstevel@tonic-gate  * be PTHREAD_STACK_MIN (MINSTACK).
1240Sstevel@tonic-gate  * This is equivalent to stksize argument in thr_create().
1250Sstevel@tonic-gate  */
1260Sstevel@tonic-gate int
pthread_attr_setstacksize(pthread_attr_t * attr,size_t stacksize)1276812Sraf pthread_attr_setstacksize(pthread_attr_t *attr, size_t stacksize)
1280Sstevel@tonic-gate {
1290Sstevel@tonic-gate 	thrattr_t *ap;
1300Sstevel@tonic-gate 
1310Sstevel@tonic-gate 	if (attr != NULL && (ap = attr->__pthread_attrp) != NULL &&
1320Sstevel@tonic-gate 	    stacksize >= MINSTACK) {
1330Sstevel@tonic-gate 		ap->stksize = stacksize;
1340Sstevel@tonic-gate 		return (0);
1350Sstevel@tonic-gate 	}
1360Sstevel@tonic-gate 	return (EINVAL);
1370Sstevel@tonic-gate }
1380Sstevel@tonic-gate 
1390Sstevel@tonic-gate /*
1400Sstevel@tonic-gate  * pthread_attr_getstacksize: gets the user stack size.
1410Sstevel@tonic-gate  */
1426812Sraf #pragma weak _pthread_attr_getstacksize = pthread_attr_getstacksize
1430Sstevel@tonic-gate int
pthread_attr_getstacksize(const pthread_attr_t * attr,size_t * stacksize)1446812Sraf pthread_attr_getstacksize(const pthread_attr_t *attr, size_t *stacksize)
1450Sstevel@tonic-gate {
1460Sstevel@tonic-gate 	thrattr_t *ap;
1470Sstevel@tonic-gate 
1480Sstevel@tonic-gate 	if (attr != NULL && (ap = attr->__pthread_attrp) != NULL &&
1490Sstevel@tonic-gate 	    stacksize != NULL) {
1500Sstevel@tonic-gate 		*stacksize = ap->stksize;
1510Sstevel@tonic-gate 		return (0);
1520Sstevel@tonic-gate 	}
1530Sstevel@tonic-gate 	return (EINVAL);
1540Sstevel@tonic-gate }
1550Sstevel@tonic-gate 
1560Sstevel@tonic-gate /*
1570Sstevel@tonic-gate  * pthread_attr_setstackaddr: sets the user stack addr.
1580Sstevel@tonic-gate  * This is equivalent to stkaddr argument in thr_create().
1590Sstevel@tonic-gate  */
1600Sstevel@tonic-gate int
pthread_attr_setstackaddr(pthread_attr_t * attr,void * stackaddr)1616812Sraf pthread_attr_setstackaddr(pthread_attr_t *attr, void *stackaddr)
1620Sstevel@tonic-gate {
1630Sstevel@tonic-gate 	thrattr_t *ap;
1640Sstevel@tonic-gate 
1650Sstevel@tonic-gate 	if (attr != NULL && (ap = attr->__pthread_attrp) != NULL) {
1660Sstevel@tonic-gate 		ap->stkaddr = stackaddr;
1670Sstevel@tonic-gate 		return (0);
1680Sstevel@tonic-gate 	}
1690Sstevel@tonic-gate 	return (EINVAL);
1700Sstevel@tonic-gate }
1710Sstevel@tonic-gate 
1720Sstevel@tonic-gate /*
1730Sstevel@tonic-gate  * pthread_attr_getstackaddr: gets the user stack addr.
1740Sstevel@tonic-gate  */
1756812Sraf #pragma weak _pthread_attr_getstackaddr = pthread_attr_getstackaddr
1760Sstevel@tonic-gate int
pthread_attr_getstackaddr(const pthread_attr_t * attr,void ** stackaddr)1776812Sraf pthread_attr_getstackaddr(const pthread_attr_t *attr, void **stackaddr)
1780Sstevel@tonic-gate {
1790Sstevel@tonic-gate 	thrattr_t *ap;
1800Sstevel@tonic-gate 
1810Sstevel@tonic-gate 	if (attr != NULL && (ap = attr->__pthread_attrp) != NULL &&
1820Sstevel@tonic-gate 	    stackaddr != NULL) {
1830Sstevel@tonic-gate 		*stackaddr = ap->stkaddr;
1840Sstevel@tonic-gate 		return (0);
1850Sstevel@tonic-gate 	}
1860Sstevel@tonic-gate 	return (EINVAL);
1870Sstevel@tonic-gate }
1880Sstevel@tonic-gate 
1890Sstevel@tonic-gate /*
1901885Sraf  * pthread_attr_setdetachstate: sets the detach state to DETACHED or JOINABLE.
1911885Sraf  * PTHREAD_CREATE_DETACHED is equivalent to thr_create(THR_DETACHED).
1920Sstevel@tonic-gate  */
1930Sstevel@tonic-gate int
pthread_attr_setdetachstate(pthread_attr_t * attr,int detachstate)1946812Sraf pthread_attr_setdetachstate(pthread_attr_t *attr, int detachstate)
1950Sstevel@tonic-gate {
1960Sstevel@tonic-gate 	thrattr_t *ap;
1970Sstevel@tonic-gate 
1980Sstevel@tonic-gate 	if (attr != NULL && (ap = attr->__pthread_attrp) != NULL &&
1990Sstevel@tonic-gate 	    (detachstate == PTHREAD_CREATE_DETACHED ||
2000Sstevel@tonic-gate 	    detachstate == PTHREAD_CREATE_JOINABLE)) {
2010Sstevel@tonic-gate 		ap->detachstate = detachstate;
2020Sstevel@tonic-gate 		return (0);
2030Sstevel@tonic-gate 	}
2040Sstevel@tonic-gate 	return (EINVAL);
2050Sstevel@tonic-gate }
2060Sstevel@tonic-gate 
2070Sstevel@tonic-gate /*
2080Sstevel@tonic-gate  * pthread_attr_getdetachstate: gets the detach state.
2090Sstevel@tonic-gate  */
2106812Sraf #pragma weak _pthread_attr_getdetachstate = pthread_attr_getdetachstate
2110Sstevel@tonic-gate int
pthread_attr_getdetachstate(const pthread_attr_t * attr,int * detachstate)2126812Sraf pthread_attr_getdetachstate(const pthread_attr_t *attr, int *detachstate)
2130Sstevel@tonic-gate {
2140Sstevel@tonic-gate 	thrattr_t *ap;
2150Sstevel@tonic-gate 
2160Sstevel@tonic-gate 	if (attr != NULL && (ap = attr->__pthread_attrp) != NULL &&
2170Sstevel@tonic-gate 	    detachstate != NULL) {
2180Sstevel@tonic-gate 		*detachstate = ap->detachstate;
2190Sstevel@tonic-gate 		return (0);
2200Sstevel@tonic-gate 	}
2210Sstevel@tonic-gate 	return (EINVAL);
2220Sstevel@tonic-gate }
2230Sstevel@tonic-gate 
2240Sstevel@tonic-gate /*
2251885Sraf  * pthread_attr_setdaemonstate_np: sets the daemon state to DAEMON or NONDAEMON.
2261885Sraf  * PTHREAD_CREATE_DAEMON is equivalent to thr_create(THR_DAEMON).
2272248Sraf  * For now, this is a private interface in libc.
2281885Sraf  */
2291885Sraf int
pthread_attr_setdaemonstate_np(pthread_attr_t * attr,int daemonstate)2306812Sraf pthread_attr_setdaemonstate_np(pthread_attr_t *attr, int daemonstate)
2311885Sraf {
2321885Sraf 	thrattr_t *ap;
2331885Sraf 
2341885Sraf 	if (attr != NULL && (ap = attr->__pthread_attrp) != NULL &&
2351885Sraf 	    (daemonstate == PTHREAD_CREATE_DAEMON_NP ||
2361885Sraf 	    daemonstate == PTHREAD_CREATE_NONDAEMON_NP)) {
2371885Sraf 		ap->daemonstate = daemonstate;
2381885Sraf 		return (0);
2391885Sraf 	}
2401885Sraf 	return (EINVAL);
2411885Sraf }
2421885Sraf 
2431885Sraf /*
2441885Sraf  * pthread_attr_getdaemonstate_np: gets the daemon state.
2452248Sraf  * For now, this is a private interface in libc.
2461885Sraf  */
2471885Sraf int
pthread_attr_getdaemonstate_np(const pthread_attr_t * attr,int * daemonstate)2486812Sraf pthread_attr_getdaemonstate_np(const pthread_attr_t *attr, int *daemonstate)
2491885Sraf {
2501885Sraf 	thrattr_t *ap;
2511885Sraf 
2521885Sraf 	if (attr != NULL && (ap = attr->__pthread_attrp) != NULL &&
2531885Sraf 	    daemonstate != NULL) {
2541885Sraf 		*daemonstate = ap->daemonstate;
2551885Sraf 		return (0);
2561885Sraf 	}
2571885Sraf 	return (EINVAL);
2581885Sraf }
2591885Sraf 
2601885Sraf /*
2610Sstevel@tonic-gate  * pthread_attr_setscope: sets the scope to SYSTEM or PROCESS.
2620Sstevel@tonic-gate  * This is equivalent to setting THR_BOUND flag in thr_create().
2630Sstevel@tonic-gate  */
2640Sstevel@tonic-gate int
pthread_attr_setscope(pthread_attr_t * attr,int scope)2656812Sraf pthread_attr_setscope(pthread_attr_t *attr, int scope)
2660Sstevel@tonic-gate {
2670Sstevel@tonic-gate 	thrattr_t *ap;
2680Sstevel@tonic-gate 
2690Sstevel@tonic-gate 	if (attr != NULL && (ap = attr->__pthread_attrp) != NULL &&
2700Sstevel@tonic-gate 	    (scope == PTHREAD_SCOPE_SYSTEM ||
2710Sstevel@tonic-gate 	    scope == PTHREAD_SCOPE_PROCESS)) {
2720Sstevel@tonic-gate 		ap->scope = scope;
2730Sstevel@tonic-gate 		return (0);
2740Sstevel@tonic-gate 	}
2750Sstevel@tonic-gate 	return (EINVAL);
2760Sstevel@tonic-gate }
2770Sstevel@tonic-gate 
2780Sstevel@tonic-gate /*
2790Sstevel@tonic-gate  * pthread_attr_getscope: gets the scheduling scope.
2800Sstevel@tonic-gate  */
2816812Sraf #pragma weak _pthread_attr_getscope = pthread_attr_getscope
2820Sstevel@tonic-gate int
pthread_attr_getscope(const pthread_attr_t * attr,int * scope)2836812Sraf pthread_attr_getscope(const pthread_attr_t *attr, int *scope)
2840Sstevel@tonic-gate {
2850Sstevel@tonic-gate 	thrattr_t *ap;
2860Sstevel@tonic-gate 
2870Sstevel@tonic-gate 	if (attr != NULL && (ap = attr->__pthread_attrp) != NULL &&
2880Sstevel@tonic-gate 	    scope != NULL) {
2890Sstevel@tonic-gate 		*scope = ap->scope;
2900Sstevel@tonic-gate 		return (0);
2910Sstevel@tonic-gate 	}
2920Sstevel@tonic-gate 	return (EINVAL);
2930Sstevel@tonic-gate }
2940Sstevel@tonic-gate 
2950Sstevel@tonic-gate /*
2960Sstevel@tonic-gate  * pthread_attr_setinheritsched: sets the scheduling parameters to be
2970Sstevel@tonic-gate  * EXPLICIT or INHERITED from parent thread.
2980Sstevel@tonic-gate  */
2990Sstevel@tonic-gate int
pthread_attr_setinheritsched(pthread_attr_t * attr,int inherit)3006812Sraf pthread_attr_setinheritsched(pthread_attr_t *attr, int inherit)
3010Sstevel@tonic-gate {
3020Sstevel@tonic-gate 	thrattr_t *ap;
3030Sstevel@tonic-gate 
3040Sstevel@tonic-gate 	if (attr != NULL && (ap = attr->__pthread_attrp) != NULL &&
3050Sstevel@tonic-gate 	    (inherit == PTHREAD_EXPLICIT_SCHED ||
3060Sstevel@tonic-gate 	    inherit == PTHREAD_INHERIT_SCHED)) {
3070Sstevel@tonic-gate 		ap->inherit = inherit;
3080Sstevel@tonic-gate 		return (0);
3090Sstevel@tonic-gate 	}
3100Sstevel@tonic-gate 	return (EINVAL);
3110Sstevel@tonic-gate }
3120Sstevel@tonic-gate 
3130Sstevel@tonic-gate /*
3140Sstevel@tonic-gate  * pthread_attr_getinheritsched: gets the scheduling inheritance.
3150Sstevel@tonic-gate  */
3166812Sraf #pragma weak _pthread_attr_getinheritsched = pthread_attr_getinheritsched
3170Sstevel@tonic-gate int
pthread_attr_getinheritsched(const pthread_attr_t * attr,int * inherit)3186812Sraf pthread_attr_getinheritsched(const pthread_attr_t *attr, int *inherit)
3190Sstevel@tonic-gate {
3200Sstevel@tonic-gate 	thrattr_t *ap;
3210Sstevel@tonic-gate 
3220Sstevel@tonic-gate 	if (attr != NULL && (ap = attr->__pthread_attrp) != NULL &&
3230Sstevel@tonic-gate 	    inherit != NULL) {
3240Sstevel@tonic-gate 		*inherit = ap->inherit;
3250Sstevel@tonic-gate 		return (0);
3260Sstevel@tonic-gate 	}
3270Sstevel@tonic-gate 	return (EINVAL);
3280Sstevel@tonic-gate }
3290Sstevel@tonic-gate 
3300Sstevel@tonic-gate /*
3316247Sraf  * pthread_attr_setschedpolicy: sets the scheduling policy.
3320Sstevel@tonic-gate  */
3330Sstevel@tonic-gate int
pthread_attr_setschedpolicy(pthread_attr_t * attr,int policy)3346812Sraf pthread_attr_setschedpolicy(pthread_attr_t *attr, int policy)
3350Sstevel@tonic-gate {
3360Sstevel@tonic-gate 	thrattr_t *ap;
3370Sstevel@tonic-gate 
3380Sstevel@tonic-gate 	if (attr != NULL && (ap = attr->__pthread_attrp) != NULL &&
3396247Sraf 	    policy != SCHED_SYS && get_info_by_policy(policy) != NULL) {
3400Sstevel@tonic-gate 		ap->policy = policy;
3410Sstevel@tonic-gate 		return (0);
3420Sstevel@tonic-gate 	}
3430Sstevel@tonic-gate 	return (EINVAL);
3440Sstevel@tonic-gate }
3450Sstevel@tonic-gate 
3460Sstevel@tonic-gate /*
3470Sstevel@tonic-gate  * pthread_attr_getpolicy: gets the scheduling policy.
3480Sstevel@tonic-gate  */
3496812Sraf #pragma weak _pthread_attr_getschedpolicy = pthread_attr_getschedpolicy
3500Sstevel@tonic-gate int
pthread_attr_getschedpolicy(const pthread_attr_t * attr,int * policy)3516812Sraf pthread_attr_getschedpolicy(const pthread_attr_t *attr, int *policy)
3520Sstevel@tonic-gate {
3530Sstevel@tonic-gate 	thrattr_t *ap;
3540Sstevel@tonic-gate 
3550Sstevel@tonic-gate 	if (attr != NULL && (ap = attr->__pthread_attrp) != NULL &&
3560Sstevel@tonic-gate 	    policy != NULL) {
3570Sstevel@tonic-gate 		*policy = ap->policy;
3580Sstevel@tonic-gate 		return (0);
3590Sstevel@tonic-gate 	}
3600Sstevel@tonic-gate 	return (EINVAL);
3610Sstevel@tonic-gate }
3620Sstevel@tonic-gate 
3630Sstevel@tonic-gate /*
3640Sstevel@tonic-gate  * pthread_attr_setschedparam: sets the scheduling parameters.
3650Sstevel@tonic-gate  * Currently, we support priority only.
3660Sstevel@tonic-gate  */
3670Sstevel@tonic-gate int
pthread_attr_setschedparam(pthread_attr_t * attr,const struct sched_param * param)3686812Sraf pthread_attr_setschedparam(pthread_attr_t *attr,
3690Sstevel@tonic-gate 	const struct sched_param *param)
3700Sstevel@tonic-gate {
3710Sstevel@tonic-gate 	thrattr_t *ap;
3720Sstevel@tonic-gate 
3736247Sraf 	if (attr != NULL && (ap = attr->__pthread_attrp) != NULL &&
3746247Sraf 	    param != NULL) {
3756247Sraf 		ap->prio = param->sched_priority;
3766247Sraf 		return (0);
3770Sstevel@tonic-gate 	}
3786247Sraf 	return (EINVAL);
3790Sstevel@tonic-gate }
3800Sstevel@tonic-gate 
3810Sstevel@tonic-gate /*
3820Sstevel@tonic-gate  * pthread_attr_getschedparam: gets the scheduling parameters.
3830Sstevel@tonic-gate  * Currently, only priority is defined as sched parameter.
3840Sstevel@tonic-gate  */
3856812Sraf #pragma weak _pthread_attr_getschedparam = pthread_attr_getschedparam
3860Sstevel@tonic-gate int
pthread_attr_getschedparam(const pthread_attr_t * attr,struct sched_param * param)3876812Sraf pthread_attr_getschedparam(const pthread_attr_t *attr,
3880Sstevel@tonic-gate 					struct sched_param *param)
3890Sstevel@tonic-gate {
3900Sstevel@tonic-gate 	thrattr_t *ap;
3910Sstevel@tonic-gate 
3920Sstevel@tonic-gate 	if (attr != NULL && (ap = attr->__pthread_attrp) != NULL &&
3930Sstevel@tonic-gate 	    param != NULL) {
3940Sstevel@tonic-gate 		param->sched_priority = ap->prio;
3950Sstevel@tonic-gate 		return (0);
3960Sstevel@tonic-gate 	}
3970Sstevel@tonic-gate 	return (EINVAL);
3980Sstevel@tonic-gate }
3990Sstevel@tonic-gate 
4000Sstevel@tonic-gate /*
4010Sstevel@tonic-gate  * UNIX98
4020Sstevel@tonic-gate  * pthread_attr_setguardsize: sets the guardsize
4030Sstevel@tonic-gate  */
4040Sstevel@tonic-gate int
pthread_attr_setguardsize(pthread_attr_t * attr,size_t guardsize)4056812Sraf pthread_attr_setguardsize(pthread_attr_t *attr, size_t guardsize)
4060Sstevel@tonic-gate {
4070Sstevel@tonic-gate 	thrattr_t *ap;
4080Sstevel@tonic-gate 
4090Sstevel@tonic-gate 	if (attr != NULL && (ap = attr->__pthread_attrp) != NULL) {
4100Sstevel@tonic-gate 		ap->guardsize = guardsize;
4110Sstevel@tonic-gate 		return (0);
4120Sstevel@tonic-gate 	}
4130Sstevel@tonic-gate 	return (EINVAL);
4140Sstevel@tonic-gate }
4150Sstevel@tonic-gate 
4160Sstevel@tonic-gate /*
4170Sstevel@tonic-gate  * UNIX98
4180Sstevel@tonic-gate  * pthread_attr_getguardsize: gets the guardsize
4190Sstevel@tonic-gate  */
4200Sstevel@tonic-gate int
pthread_attr_getguardsize(const pthread_attr_t * attr,size_t * guardsize)4216812Sraf pthread_attr_getguardsize(const pthread_attr_t *attr, size_t *guardsize)
4220Sstevel@tonic-gate {
4230Sstevel@tonic-gate 	thrattr_t *ap;
4240Sstevel@tonic-gate 
4250Sstevel@tonic-gate 	if (attr != NULL && (ap = attr->__pthread_attrp) != NULL &&
4260Sstevel@tonic-gate 	    guardsize != NULL) {
4270Sstevel@tonic-gate 		*guardsize = ap->guardsize;
4280Sstevel@tonic-gate 		return (0);
4290Sstevel@tonic-gate 	}
4300Sstevel@tonic-gate 	return (EINVAL);
4310Sstevel@tonic-gate }
4320Sstevel@tonic-gate 
4330Sstevel@tonic-gate /*
4340Sstevel@tonic-gate  * pthread_attr_setstack: sets the user stack addr and stack size.
4350Sstevel@tonic-gate  * This is equivalent to the stack_base and stack_size arguments
4360Sstevel@tonic-gate  * to thr_create().
4370Sstevel@tonic-gate  */
4380Sstevel@tonic-gate int
pthread_attr_setstack(pthread_attr_t * attr,void * stackaddr,size_t stacksize)4396812Sraf pthread_attr_setstack(pthread_attr_t *attr,
4400Sstevel@tonic-gate 	void *stackaddr, size_t stacksize)
4410Sstevel@tonic-gate {
4420Sstevel@tonic-gate 	thrattr_t *ap;
4430Sstevel@tonic-gate 
4440Sstevel@tonic-gate 	if (attr != NULL && (ap = attr->__pthread_attrp) != NULL &&
4450Sstevel@tonic-gate 	    stacksize >= MINSTACK) {
4460Sstevel@tonic-gate 		ap->stkaddr = stackaddr;
4470Sstevel@tonic-gate 		ap->stksize = stacksize;
448*7657SRoger.Faulkner@Sun.COM 		if (stackaddr != NULL &&
449*7657SRoger.Faulkner@Sun.COM 		    setup_top_frame(stackaddr, stacksize, NULL) == NULL)
450*7657SRoger.Faulkner@Sun.COM 			return (EACCES);
4510Sstevel@tonic-gate 		return (0);
4520Sstevel@tonic-gate 	}
4530Sstevel@tonic-gate 	return (EINVAL);
4540Sstevel@tonic-gate }
4550Sstevel@tonic-gate 
4560Sstevel@tonic-gate /*
4570Sstevel@tonic-gate  * pthread_attr_getstack: gets the user stack addr and stack size.
4580Sstevel@tonic-gate  */
4590Sstevel@tonic-gate int
pthread_attr_getstack(const pthread_attr_t * attr,void ** stackaddr,size_t * stacksize)4606812Sraf pthread_attr_getstack(const pthread_attr_t *attr,
4610Sstevel@tonic-gate 	void **stackaddr, size_t *stacksize)
4620Sstevel@tonic-gate {
4630Sstevel@tonic-gate 	thrattr_t *ap;
4640Sstevel@tonic-gate 
4650Sstevel@tonic-gate 	if (attr != NULL && (ap = attr->__pthread_attrp) != NULL &&
4660Sstevel@tonic-gate 	    stackaddr != NULL && stacksize != NULL) {
4670Sstevel@tonic-gate 		*stackaddr = ap->stkaddr;
4680Sstevel@tonic-gate 		*stacksize = ap->stksize;
4690Sstevel@tonic-gate 		return (0);
4700Sstevel@tonic-gate 	}
4710Sstevel@tonic-gate 	return (EINVAL);
4720Sstevel@tonic-gate }
473