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