xref: /onnv-gate/usr/src/lib/libc/port/rt/sched.c (revision 6812:febeba71273d)
12248Sraf /*
22248Sraf  * CDDL HEADER START
32248Sraf  *
42248Sraf  * The contents of this file are subject to the terms of the
52248Sraf  * Common Development and Distribution License (the "License").
62248Sraf  * You may not use this file except in compliance with the License.
72248Sraf  *
82248Sraf  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
92248Sraf  * or http://www.opensolaris.org/os/licensing.
102248Sraf  * See the License for the specific language governing permissions
112248Sraf  * and limitations under the License.
122248Sraf  *
132248Sraf  * When distributing Covered Code, include this CDDL HEADER in each
142248Sraf  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
152248Sraf  * If applicable, add the following below this CDDL HEADER, with the
162248Sraf  * fields enclosed by brackets "[]" replaced with your own identifying
172248Sraf  * information: Portions Copyright [yyyy] [name of copyright owner]
182248Sraf  *
192248Sraf  * CDDL HEADER END
202248Sraf  */
212248Sraf 
222248Sraf /*
236247Sraf  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
242248Sraf  * Use is subject to license terms.
252248Sraf  */
262248Sraf 
272248Sraf #pragma ident	"%Z%%M%	%I%	%E% SMI"
282248Sraf 
29*6812Sraf #include "lint.h"
306247Sraf #include "thr_uberdata.h"
312248Sraf #include <sched.h>
326247Sraf #include <sys/tspriocntl.h>
332248Sraf #include <sys/rtpriocntl.h>
346247Sraf #include <sys/fxpriocntl.h>
352248Sraf 
362248Sraf /*
376247Sraf  * The following array is used for caching information
382248Sraf  * for priocntl scheduling classes.
392248Sraf  */
406247Sraf static pcclass_t sched_class[] = {
416247Sraf 	{0, SCHED_OTHER, 0, 0, {-1, "TS",  0}},
426247Sraf 	{0, SCHED_FIFO,	 0, 0, {-1, "RT",  0}},
436247Sraf 	{0, SCHED_RR,	 0, 0, {-1, "RT",  0}},
446247Sraf 	{0, SCHED_SYS,	 0, 0, {0,  "SYS", 0}},
456247Sraf 	{0, SCHED_IA,	 0, 0, {-1, "IA",  0}},
466247Sraf 	{0, SCHED_FSS,	 0, 0, {-1, "FSS", 0}},
476247Sraf 	{0, SCHED_FX,	 0, 0, {-1, "FX",  0}},
486247Sraf 	/*
496247Sraf 	 * Allow unknown (to us) scheduling classes.
506247Sraf 	 * The kernel allows space for exactly 10 scheduling classes
516247Sraf 	 * (see the definitions of 'sclass' and 'nclass' in the kernel).
526247Sraf 	 * We need that number of available slots here.
536247Sraf 	 * If the kernel space is changed, this has to change too.
546247Sraf 	 */
556247Sraf 	{0, -1,		 0, 0, {-1, "",	   0}},
566247Sraf 	{0, -1,		 0, 0, {-1, "",	   0}},
576247Sraf 	{0, -1,		 0, 0, {-1, "",	   0}},
586247Sraf 	{0, -1,		 0, 0, {-1, "",	   0}},
596247Sraf 	{0, -1,		 0, 0, {-1, "",	   0}},
606247Sraf 	{0, -1,		 0, 0, {-1, "",	   0}},
616247Sraf 	{0, -1,		 0, 0, {-1, "",	   0}},
626247Sraf 	{0, -1,		 0, 0, {-1, "",	   0}},
636247Sraf 	{0, -1,		 0, 0, {-1, "",	   0}},
646247Sraf 	{0, -1,		 0, 0, {-1, "",	   0}},
656247Sraf };
662248Sraf 
676247Sraf #define	NPOLICY	(sizeof (sched_class) / sizeof (pcclass_t))
686247Sraf 
696247Sraf #if _SCHED_NEXT != SCHED_FX + 1
706247Sraf #error "fatal: _SCHED_NEXT != SCHED_FX + 1"
716247Sraf #endif
726247Sraf 
736247Sraf static mutex_t class_lock = DEFAULTMUTEX;	/* protects sched_class[] */
742248Sraf 
756247Sraf /*
766247Sraf  * Helper function for get_info_by_policy(), below.
776247Sraf  * Don't let a manufactured policy number duplicate
786247Sraf  * the class of one of our base policy numbers.
796247Sraf  */
806247Sraf static int
is_base_class(const char * clname)816247Sraf is_base_class(const char *clname)
826247Sraf {
836247Sraf 	const pcclass_t	*pccp;
846247Sraf 	int		policy;
852248Sraf 
866247Sraf 	for (policy = 0, pccp = sched_class;
876247Sraf 	    policy < _SCHED_NEXT;
886247Sraf 	    policy++, pccp++) {
896247Sraf 		if (strcmp(clname, pccp->pcc_info.pc_clname) == 0)
906247Sraf 			return (1);
916247Sraf 	}
926247Sraf 	return (0);
936247Sraf }
942248Sraf 
952248Sraf /*
966247Sraf  * Cache priocntl information on scheduling class by policy.
972248Sraf  */
986247Sraf const pcclass_t *
get_info_by_policy(int policy)992248Sraf get_info_by_policy(int policy)
1002248Sraf {
1016247Sraf 	pcclass_t *pccp = &sched_class[policy];
1026247Sraf 	pcpri_t pcpri;
1036247Sraf 	pri_t prio;
1046247Sraf 	int base = 0;
1056247Sraf 
1066247Sraf 	if ((uint_t)policy >= NPOLICY || pccp->pcc_state < 0) {
1076247Sraf 		errno = EINVAL;
1086247Sraf 		return (NULL);
1096247Sraf 	}
1106247Sraf 
1116247Sraf 	if (pccp->pcc_state > 0)
1126247Sraf 		return (pccp);
1136247Sraf 
1146247Sraf 	lmutex_lock(&class_lock);
1156247Sraf 
1166247Sraf 	/* get class info (the system class is known to have class-id == 0) */
1176247Sraf 	if (pccp->pcc_policy == -1) {
1186247Sraf 		/* policy number not defined in <sched.h> */
1196247Sraf 		ASSERT(policy >= _SCHED_NEXT);
1206247Sraf 		pccp->pcc_info.pc_cid = policy - _SCHED_NEXT;
1216515Sraf 		if (priocntl(0, 0, PC_GETCLINFO, &pccp->pcc_info) == -1 ||
1226247Sraf 		    (base = is_base_class(pccp->pcc_info.pc_clname)) != 0) {
1236247Sraf 			pccp->pcc_info.pc_clname[0] = '\0';
1246247Sraf 			pccp->pcc_info.pc_cid = -1;
1256247Sraf 			/*
1266247Sraf 			 * If we duplicated a base class, permanently
1276247Sraf 			 * disable this policy entry.  Else allow for
1286247Sraf 			 * dynamic loading of scheduling classes.
1296247Sraf 			 */
1306247Sraf 			if (base) {
131*6812Sraf 				membar_producer();
1326247Sraf 				pccp->pcc_state = -1;
1336247Sraf 			}
1346247Sraf 			errno = EINVAL;
1356247Sraf 			lmutex_unlock(&class_lock);
1366247Sraf 			return (NULL);
1376247Sraf 		}
1386247Sraf 		pccp->pcc_policy = policy;
1396247Sraf 	} else if (policy != SCHED_SYS &&
1406515Sraf 	    priocntl(0, 0, PC_GETCID, &pccp->pcc_info) == -1) {
141*6812Sraf 		membar_producer();
1426247Sraf 		pccp->pcc_state = -1;
1436247Sraf 		errno = EINVAL;
1446247Sraf 		lmutex_unlock(&class_lock);
1456247Sraf 		return (NULL);
1466247Sraf 	}
1476247Sraf 
1486247Sraf 	switch (policy) {
1496247Sraf 	case SCHED_OTHER:
1506247Sraf 		prio = ((tsinfo_t *)pccp->pcc_info.pc_clinfo)->ts_maxupri;
1516247Sraf 		pccp->pcc_primin = -prio;
1526247Sraf 		pccp->pcc_primax = prio;
1536247Sraf 		break;
1546247Sraf 	case SCHED_FIFO:
1556247Sraf 	case SCHED_RR:
1566247Sraf 		prio = ((rtinfo_t *)pccp->pcc_info.pc_clinfo)->rt_maxpri;
1576247Sraf 		pccp->pcc_primin = 0;
1586247Sraf 		pccp->pcc_primax = prio;
1596247Sraf 		break;
1606247Sraf 	default:
1616247Sraf 		/*
1626247Sraf 		 * All other policy numbers, including policy numbers
1636247Sraf 		 * not defined in <sched.h>.
1646247Sraf 		 */
1656247Sraf 		pcpri.pc_cid = pccp->pcc_info.pc_cid;
1666515Sraf 		if (priocntl(0, 0, PC_GETPRIRANGE, &pcpri) == 0) {
1676247Sraf 			pccp->pcc_primin = pcpri.pc_clpmin;
1686247Sraf 			pccp->pcc_primax = pcpri.pc_clpmax;
1696247Sraf 		}
1706247Sraf 		break;
1716247Sraf 	}
1726247Sraf 
173*6812Sraf 	membar_producer();
1746247Sraf 	pccp->pcc_state = 1;
1756247Sraf 	lmutex_unlock(&class_lock);
1766247Sraf 	return (pccp);
1776247Sraf }
1786247Sraf 
1796247Sraf const pcclass_t *
get_info_by_class(id_t classid)1806247Sraf get_info_by_class(id_t classid)
1816247Sraf {
1826247Sraf 	pcinfo_t	pcinfo;
1836247Sraf 	pcclass_t	*pccp;
1846247Sraf 	int		policy;
1856247Sraf 
1866247Sraf 	if (classid < 0) {
1876247Sraf 		errno = EINVAL;
1886247Sraf 		return (NULL);
1896247Sraf 	}
1906247Sraf 
1916247Sraf 	/* determine if we already know this classid */
1926247Sraf 	for (policy = 0, pccp = sched_class;
1936247Sraf 	    policy < NPOLICY;
1946247Sraf 	    policy++, pccp++) {
1956247Sraf 		if (pccp->pcc_state > 0 && pccp->pcc_info.pc_cid == classid)
1966247Sraf 			return (pccp);
1976247Sraf 	}
1982248Sraf 
1996247Sraf 	pcinfo.pc_cid = classid;
2006515Sraf 	if (priocntl(0, 0, PC_GETCLINFO, &pcinfo) == -1) {
2016247Sraf 		if (classid == 0)	/* no kernel info for sys class */
2026247Sraf 			return (get_info_by_policy(SCHED_SYS));
2036247Sraf 		return (NULL);
2046247Sraf 	}
2056247Sraf 
2066247Sraf 	for (policy = 0, pccp = sched_class;
2076247Sraf 	    policy < NPOLICY;
2086247Sraf 	    policy++, pccp++) {
2096247Sraf 		if (pccp->pcc_state == 0 &&
2106247Sraf 		    strcmp(pcinfo.pc_clname, pccp->pcc_info.pc_clname) == 0)
2116247Sraf 			return (get_info_by_policy(pccp->pcc_policy));
2126247Sraf 	}
2136247Sraf 
2146247Sraf 	/*
2156247Sraf 	 * We have encountered an unknown (to us) scheduling class.
2166247Sraf 	 * Manufacture a policy number for it.  Hopefully we still
2176247Sraf 	 * have room in the sched_class[] table.
2186247Sraf 	 */
2196247Sraf 	policy = _SCHED_NEXT + classid;
2206247Sraf 	if (policy >= NPOLICY) {
2216247Sraf 		errno = EINVAL;
2226247Sraf 		return (NULL);
2236247Sraf 	}
2246247Sraf 	lmutex_lock(&class_lock);
2256247Sraf 	pccp = &sched_class[policy];
2266247Sraf 	pccp->pcc_policy = policy;
2276247Sraf 	(void) strlcpy(pccp->pcc_info.pc_clname, pcinfo.pc_clname, PC_CLNMSZ);
2286247Sraf 	lmutex_unlock(&class_lock);
2296247Sraf 	return (get_info_by_policy(pccp->pcc_policy));
2306247Sraf }
2316247Sraf 
2326247Sraf /*
2336247Sraf  * Helper function: get process or lwp current scheduling policy.
2346247Sraf  */
2356247Sraf static const pcclass_t *
get_parms(idtype_t idtype,id_t id,pcparms_t * pcparmp)2366247Sraf get_parms(idtype_t idtype, id_t id, pcparms_t *pcparmp)
2376247Sraf {
2386247Sraf 	pcparmp->pc_cid = PC_CLNULL;
2396515Sraf 	if (priocntl(idtype, id, PC_GETPARMS, pcparmp) == -1)
2406247Sraf 		return (NULL);
2416247Sraf 	return (get_info_by_class(pcparmp->pc_cid));
2426247Sraf }
2436247Sraf 
2446247Sraf /*
2456247Sraf  * Helper function for setprio() and setparam(), below.
2466247Sraf  */
2476247Sraf static int
set_priority(idtype_t idtype,id_t id,int policy,int prio,pcparms_t * pcparmp,int settq)2486247Sraf set_priority(idtype_t idtype, id_t id, int policy, int prio,
2496247Sraf     pcparms_t *pcparmp, int settq)
2506247Sraf {
2516247Sraf 	int rv;
2526247Sraf 
2536247Sraf 	switch (policy) {
2546247Sraf 	case SCHED_OTHER:
2556247Sraf 	{
2566247Sraf 		tsparms_t *tsp = (tsparms_t *)pcparmp->pc_clparms;
2576247Sraf 		tsp->ts_uprilim = prio;
2586247Sraf 		tsp->ts_upri = prio;
2596247Sraf 		break;
2606247Sraf 	}
2616247Sraf 	case SCHED_FIFO:
2626247Sraf 	case SCHED_RR:
2636247Sraf 	{
2646247Sraf 		rtparms_t *rtp = (rtparms_t *)pcparmp->pc_clparms;
2656247Sraf 		rtp->rt_tqnsecs = settq?
2666247Sraf 		    (policy == SCHED_FIFO? RT_TQINF : RT_TQDEF) :
2676247Sraf 		    RT_NOCHANGE;
2686247Sraf 		rtp->rt_pri = prio;
2696247Sraf 		break;
2706247Sraf 	}
2716247Sraf 	default:
2726247Sraf 	{
2736247Sraf 		/*
2746247Sraf 		 * Class-independent method for setting the priority.
2756247Sraf 		 */
2766247Sraf 		pcprio_t pcprio;
2776247Sraf 
2786247Sraf 		pcprio.pc_op = PC_SETPRIO;
2796247Sraf 		pcprio.pc_cid = pcparmp->pc_cid;
2806247Sraf 		pcprio.pc_val = prio;
2816247Sraf 		do {
2826515Sraf 			rv = priocntl(idtype, id, PC_DOPRIO, &pcprio);
2836247Sraf 		} while (rv == -1 && errno == ENOMEM);
2846247Sraf 		return (rv);
2856247Sraf 	}
2866247Sraf 	}
2876247Sraf 
2886247Sraf 	do {
2896515Sraf 		rv = priocntl(idtype, id, PC_SETPARMS, pcparmp);
2906247Sraf 	} while (rv == -1 && errno == ENOMEM);
2916247Sraf 	return (rv);
2926247Sraf }
2936247Sraf 
2946247Sraf /*
2956247Sraf  * Utility function, private to libc, used by sched_setparam()
2966247Sraf  * and posix_spawn().  Because it is called by the vfork() child of
2976247Sraf  * posix_spawn(), we must not call any functions exported from libc.
2986247Sraf  */
2996247Sraf id_t
setprio(idtype_t idtype,id_t id,int prio,int * policyp)3006247Sraf setprio(idtype_t idtype, id_t id, int prio, int *policyp)
3016247Sraf {
3026247Sraf 	pcparms_t	pcparm;
3036247Sraf 	int		policy;
3046247Sraf 	const pcclass_t	*pccp;
3056247Sraf 
3066247Sraf 	if ((pccp = get_parms(idtype, id, &pcparm)) == NULL)
3076247Sraf 		return (-1);
3086247Sraf 	if (prio < pccp->pcc_primin || prio > pccp->pcc_primax) {
3092248Sraf 		errno = EINVAL;
3102248Sraf 		return (-1);
3112248Sraf 	}
3122248Sraf 
3136247Sraf 	policy = pccp->pcc_policy;
3146247Sraf 	if (policyp != NULL &&
3156247Sraf 	    (policy == SCHED_FIFO || policy == SCHED_RR)) {
3166247Sraf 		rtparms_t *rtp = (rtparms_t *)pcparm.pc_clparms;
3176247Sraf 		policy = (rtp->rt_tqnsecs == RT_TQINF? SCHED_FIFO : SCHED_RR);
3182248Sraf 	}
3192248Sraf 
3206247Sraf 	if (set_priority(idtype, id, policy, prio, &pcparm, 0) == -1)
3212389Strevtom 		return (-1);
3226247Sraf 	if (policyp != NULL)
3236247Sraf 		*policyp = policy;
3246247Sraf 	return (pccp->pcc_info.pc_cid);
3252248Sraf }
3262248Sraf 
3272248Sraf int
sched_setparam(pid_t pid,const struct sched_param * param)3282248Sraf sched_setparam(pid_t pid, const struct sched_param *param)
3292248Sraf {
3306247Sraf 	if (pid < 0) {
3316247Sraf 		errno = ESRCH;
3326247Sraf 		return (-1);
3336247Sraf 	}
3346247Sraf 	if (pid == 0)
3356247Sraf 		pid = P_MYID;
3366247Sraf 
3376247Sraf 	if (setprio(P_PID, pid, param->sched_priority, NULL) == -1)
3386247Sraf 		return (-1);
3396247Sraf 	return (0);
3406247Sraf }
3416247Sraf 
3426247Sraf id_t
getparam(idtype_t idtype,id_t id,int * policyp,struct sched_param * param)3436247Sraf getparam(idtype_t idtype, id_t id, int *policyp, struct sched_param *param)
3446247Sraf {
3456247Sraf 	pcparms_t pcparm;
3466247Sraf 	const pcclass_t *pccp;
3476247Sraf 	int policy;
3486247Sraf 	int priority;
3496247Sraf 
3506247Sraf 	if ((pccp = get_parms(idtype, id, &pcparm)) == NULL)
3516247Sraf 		return (-1);
3526247Sraf 
3536247Sraf 	switch (policy = pccp->pcc_policy) {
3546247Sraf 	case SCHED_OTHER:
3556247Sraf 	{
3566247Sraf 		tsparms_t *tsp = (tsparms_t *)pcparm.pc_clparms;
3576247Sraf 		priority = tsp->ts_upri;
3586247Sraf 		break;
3596247Sraf 	}
3606247Sraf 	case SCHED_FIFO:
3616247Sraf 	case SCHED_RR:
3626247Sraf 	{
3636247Sraf 		rtparms_t *rtp = (rtparms_t *)pcparm.pc_clparms;
3646247Sraf 		priority = rtp->rt_pri;
3656247Sraf 		policy = (rtp->rt_tqnsecs == RT_TQINF? SCHED_FIFO : SCHED_RR);
3666247Sraf 		break;
3676247Sraf 	}
3686247Sraf 	default:
3696247Sraf 	{
3706247Sraf 		/*
3716247Sraf 		 * Class-independent method for getting the priority.
3726247Sraf 		 */
3736247Sraf 		pcprio_t pcprio;
3746247Sraf 
3756247Sraf 		pcprio.pc_op = PC_GETPRIO;
3766247Sraf 		pcprio.pc_cid = 0;
3776247Sraf 		pcprio.pc_val = 0;
3786515Sraf 		if (priocntl(idtype, id, PC_DOPRIO, &pcprio) == 0)
3796247Sraf 			priority = pcprio.pc_val;
3806247Sraf 		else
3816247Sraf 			priority = 0;
3826247Sraf 		break;
3836247Sraf 	}
3846247Sraf 	}
3856247Sraf 
3866247Sraf 	*policyp = policy;
3876247Sraf 	(void) memset(param, 0, sizeof (*param));
3886247Sraf 	param->sched_priority = priority;
3896247Sraf 
3906247Sraf 	return (pcparm.pc_cid);
3916247Sraf }
3926247Sraf 
3936247Sraf int
sched_getparam(pid_t pid,struct sched_param * param)3946247Sraf sched_getparam(pid_t pid, struct sched_param *param)
3956247Sraf {
3966247Sraf 	int policy;
3972248Sraf 
3982248Sraf 	if (pid < 0) {
3992248Sraf 		errno = ESRCH;
4002248Sraf 		return (-1);
4012248Sraf 	}
4022248Sraf 	if (pid == 0)
4032248Sraf 		pid = P_MYID;
4042248Sraf 
4056247Sraf 	if (getparam(P_PID, pid, &policy, param) == -1)
4062248Sraf 		return (-1);
4076247Sraf 	return (0);
4082248Sraf }
4092248Sraf 
4106247Sraf /*
4116247Sraf  * Utility function, private to libc, used by sched_setscheduler()
4126247Sraf  * and posix_spawn().  Because it is called by the vfork() child of
4136247Sraf  * posix_spawn(), we must not call any functions exported from libc.
4146247Sraf  */
4156247Sraf id_t
setparam(idtype_t idtype,id_t id,int policy,int prio)4166247Sraf setparam(idtype_t idtype, id_t id, int policy, int prio)
4172248Sraf {
4182248Sraf 	pcparms_t	pcparm;
4196247Sraf 	const pcclass_t	*pccp;
4202248Sraf 
4216247Sraf 	if (policy == SCHED_SYS ||
4226247Sraf 	    (pccp = get_info_by_policy(policy)) == NULL ||
4236247Sraf 	    prio < pccp->pcc_primin || prio > pccp->pcc_primax) {
4246247Sraf 		errno = EINVAL;
4252248Sraf 		return (-1);
4262248Sraf 	}
4272248Sraf 
4286247Sraf 	pcparm.pc_cid = pccp->pcc_info.pc_cid;
4296247Sraf 	if (set_priority(idtype, id, policy, prio, &pcparm, 1) == -1)
4302248Sraf 		return (-1);
4316247Sraf 	return (pccp->pcc_info.pc_cid);
4322248Sraf }
4332248Sraf 
4342248Sraf int
sched_setscheduler(pid_t pid,int policy,const struct sched_param * param)4352248Sraf sched_setscheduler(pid_t pid, int policy, const struct sched_param *param)
4362248Sraf {
4372248Sraf 	pri_t		prio = param->sched_priority;
4382248Sraf 	int		oldpolicy;
4392248Sraf 
4402248Sraf 	if ((oldpolicy = sched_getscheduler(pid)) < 0)
4412248Sraf 		return (-1);
4422248Sraf 
4432248Sraf 	if (pid == 0)
4442248Sraf 		pid = P_MYID;
4452248Sraf 
4466247Sraf 	if (setparam(P_PID, pid, policy, prio) == -1)
4472248Sraf 		return (-1);
4482248Sraf 
4492248Sraf 	return (oldpolicy);
4502248Sraf }
4512248Sraf 
4522248Sraf int
sched_getscheduler(pid_t pid)4532248Sraf sched_getscheduler(pid_t pid)
4542248Sraf {
4552248Sraf 	pcparms_t	pcparm;
4566247Sraf 	const pcclass_t	*pccp;
4572248Sraf 	int		policy;
4582248Sraf 
4592248Sraf 	if (pid < 0) {
4602248Sraf 		errno = ESRCH;
4612248Sraf 		return (-1);
4622248Sraf 	}
4632248Sraf 	if (pid == 0)
4642248Sraf 		pid = P_MYID;
4652248Sraf 
4666247Sraf 	if ((pccp = get_parms(P_PID, pid, &pcparm)) == NULL)
4672248Sraf 		return (-1);
4682248Sraf 
4696247Sraf 	if ((policy = pccp->pcc_policy) == SCHED_FIFO || policy == SCHED_RR) {
4706247Sraf 		policy =
4716247Sraf 		    (((rtparms_t *)pcparm.pc_clparms)->rt_tqnsecs == RT_TQINF?
4726247Sraf 		    SCHED_FIFO : SCHED_RR);
4732248Sraf 	}
4742248Sraf 
4752248Sraf 	return (policy);
4762248Sraf }
4772248Sraf 
4782248Sraf int
sched_yield(void)4792248Sraf sched_yield(void)
4802248Sraf {
4816515Sraf 	yield();
4822248Sraf 	return (0);
4832248Sraf }
4842248Sraf 
4852248Sraf int
sched_get_priority_max(int policy)4862248Sraf sched_get_priority_max(int policy)
4872248Sraf {
4886247Sraf 	const pcclass_t *pccp;
4892248Sraf 
4906247Sraf 	if ((pccp = get_info_by_policy(policy)) != NULL)
4916247Sraf 		return (pccp->pcc_primax);
4922248Sraf 	errno = EINVAL;
4932248Sraf 	return (-1);
4942248Sraf }
4952248Sraf 
4962248Sraf int
sched_get_priority_min(int policy)4972248Sraf sched_get_priority_min(int policy)
4982248Sraf {
4996247Sraf 	const pcclass_t *pccp;
5002248Sraf 
5016247Sraf 	if ((pccp = get_info_by_policy(policy)) != NULL)
5026247Sraf 		return (pccp->pcc_primin);
5032248Sraf 	errno = EINVAL;
5042248Sraf 	return (-1);
5052248Sraf }
5062248Sraf 
5072248Sraf int
sched_rr_get_interval(pid_t pid,timespec_t * interval)5082248Sraf sched_rr_get_interval(pid_t pid, timespec_t *interval)
5092248Sraf {
5102248Sraf 	pcparms_t pcparm;
5116247Sraf 	const pcclass_t *pccp;
5122248Sraf 
5132248Sraf 	if (pid < 0) {
5142248Sraf 		errno = ESRCH;
5152248Sraf 		return (-1);
5162248Sraf 	}
5172248Sraf 	if (pid == 0)
5182248Sraf 		pid = P_MYID;
5192248Sraf 
5206247Sraf 	if ((pccp = get_parms(P_PID, pid, &pcparm)) == NULL)
5212248Sraf 		return (-1);
5222248Sraf 
5236247Sraf 	/*
5246247Sraf 	 * At the moment, we have no class-independent method to fetch
5256247Sraf 	 * the process/lwp time quantum.  Since SUSv3 does not restrict
5266247Sraf 	 * this operation to the real-time class, we return an indefinite
5276247Sraf 	 * quantum (tv_sec == 0 and tv_nsec == 0) for scheduling policies
5286247Sraf 	 * for which this information isn't available.
5296247Sraf 	 */
5306247Sraf 	interval->tv_sec = 0;
5316247Sraf 	interval->tv_nsec = 0;
5326247Sraf 
5336247Sraf 	switch (pccp->pcc_policy) {
5346247Sraf 	case SCHED_FIFO:
5356247Sraf 	case SCHED_RR:
5366247Sraf 		{
5376247Sraf 			rtparms_t *rtp = (rtparms_t *)pcparm.pc_clparms;
5386247Sraf 			if (rtp->rt_tqnsecs != RT_TQINF) {
5396247Sraf 				interval->tv_sec = rtp->rt_tqsecs;
5406247Sraf 				interval->tv_nsec = rtp->rt_tqnsecs;
5416247Sraf 			}
5426247Sraf 		}
5436247Sraf 		break;
5446247Sraf 	case SCHED_FX:
5456247Sraf 		{
5466247Sraf 			fxparms_t *fxp = (fxparms_t *)pcparm.pc_clparms;
5476247Sraf 			if (fxp->fx_tqnsecs != FX_TQINF) {
5486247Sraf 				interval->tv_sec = fxp->fx_tqsecs;
5496247Sraf 				interval->tv_nsec = fxp->fx_tqnsecs;
5506247Sraf 			}
5516247Sraf 		}
5526247Sraf 		break;
5532248Sraf 	}
5542248Sraf 
5556247Sraf 	return (0);
5562248Sraf }
5576247Sraf 
5586247Sraf /*
5596247Sraf  * Initialize or update ul_policy, ul_cid, and ul_pri.
5606247Sraf  */
5616247Sraf void
update_sched(ulwp_t * self)5626247Sraf update_sched(ulwp_t *self)
5636247Sraf {
5646247Sraf 	volatile sc_shared_t *scp;
5656247Sraf 	pcparms_t pcparm;
5666247Sraf 	pcprio_t pcprio;
5676247Sraf 	const pcclass_t *pccp;
5686247Sraf 	int priority;
5696247Sraf 	int policy;
5706247Sraf 
5716247Sraf 	ASSERT(self == curthread);
5726247Sraf 
5736247Sraf 	enter_critical(self);
5746247Sraf 
5756247Sraf 	if ((scp = self->ul_schedctl) == NULL &&
5766247Sraf 	    (scp = setup_schedctl()) == NULL) {		/* can't happen? */
5776247Sraf 		if (self->ul_policy < 0) {
5786247Sraf 			self->ul_cid = 0;
5796247Sraf 			self->ul_pri = 0;
580*6812Sraf 			membar_producer();
5816247Sraf 			self->ul_policy = SCHED_OTHER;
5826247Sraf 		}
5836247Sraf 		exit_critical(self);
5846247Sraf 		return;
5856247Sraf 	}
5866247Sraf 
5876247Sraf 	if (self->ul_policy >= 0 &&
5886247Sraf 	    self->ul_cid == scp->sc_cid &&
5896247Sraf 	    (self->ul_pri == scp->sc_cpri ||
5906247Sraf 	    (self->ul_epri > 0 && self->ul_epri == scp->sc_cpri))) {
5916247Sraf 		exit_critical(self);
5926247Sraf 		return;
5936247Sraf 	}
5946247Sraf 
5956247Sraf 	pccp = get_parms(P_LWPID, P_MYID, &pcparm);
5966247Sraf 	if (pccp == NULL) {		/* can't happen? */
5976247Sraf 		self->ul_cid = scp->sc_cid;
5986247Sraf 		self->ul_pri = scp->sc_cpri;
599*6812Sraf 		membar_producer();
6006247Sraf 		self->ul_policy = SCHED_OTHER;
6016247Sraf 		exit_critical(self);
6026247Sraf 		return;
6036247Sraf 	}
6046247Sraf 
6056247Sraf 	switch (policy = pccp->pcc_policy) {
6066247Sraf 	case SCHED_OTHER:
6076247Sraf 		priority = ((tsparms_t *)pcparm.pc_clparms)->ts_upri;
6086247Sraf 		break;
6096247Sraf 	case SCHED_FIFO:
6106247Sraf 	case SCHED_RR:
6116296Sraf 		self->ul_rtclassid = pccp->pcc_info.pc_cid;
6126247Sraf 		priority = ((rtparms_t *)pcparm.pc_clparms)->rt_pri;
6136247Sraf 		policy =
6146247Sraf 		    ((rtparms_t *)pcparm.pc_clparms)->rt_tqnsecs == RT_TQINF?
6156247Sraf 		    SCHED_FIFO : SCHED_RR;
6166247Sraf 		break;
6176247Sraf 	default:
6186247Sraf 		/*
6196247Sraf 		 * Class-independent method for getting the priority.
6206247Sraf 		 */
6216247Sraf 		pcprio.pc_op = PC_GETPRIO;
6226247Sraf 		pcprio.pc_cid = 0;
6236247Sraf 		pcprio.pc_val = 0;
6246515Sraf 		if (priocntl(P_LWPID, P_MYID, PC_DOPRIO, &pcprio) == 0)
6256247Sraf 			priority = pcprio.pc_val;
6266247Sraf 		else
6276247Sraf 			priority = 0;
6286247Sraf 	}
6296247Sraf 
6306247Sraf 	self->ul_cid = pcparm.pc_cid;
6316247Sraf 	self->ul_pri = priority;
632*6812Sraf 	membar_producer();
6336247Sraf 	self->ul_policy = policy;
6346247Sraf 
6356247Sraf 	exit_critical(self);
6366247Sraf }
637