1f841f6adSraf /* 2f841f6adSraf * CDDL HEADER START 3f841f6adSraf * 4f841f6adSraf * The contents of this file are subject to the terms of the 5f841f6adSraf * Common Development and Distribution License (the "License"). 6f841f6adSraf * You may not use this file except in compliance with the License. 7f841f6adSraf * 8f841f6adSraf * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9f841f6adSraf * or http://www.opensolaris.org/os/licensing. 10f841f6adSraf * See the License for the specific language governing permissions 11f841f6adSraf * and limitations under the License. 12f841f6adSraf * 13f841f6adSraf * When distributing Covered Code, include this CDDL HEADER in each 14f841f6adSraf * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15f841f6adSraf * If applicable, add the following below this CDDL HEADER, with the 16f841f6adSraf * fields enclosed by brackets "[]" replaced with your own identifying 17f841f6adSraf * information: Portions Copyright [yyyy] [name of copyright owner] 18f841f6adSraf * 19f841f6adSraf * CDDL HEADER END 20f841f6adSraf */ 21f841f6adSraf 22f841f6adSraf /* 23d4204c85Sraf * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 24f841f6adSraf * Use is subject to license terms. 25f841f6adSraf */ 26f841f6adSraf 27f841f6adSraf #pragma ident "%Z%%M% %I% %E% SMI" 28f841f6adSraf 29*7257d1b4Sraf #include "lint.h" 30d4204c85Sraf #include "thr_uberdata.h" 31f841f6adSraf #include <sched.h> 32f841f6adSraf #include <sys/tspriocntl.h> 33d4204c85Sraf #include <sys/rtpriocntl.h> 34d4204c85Sraf #include <sys/fxpriocntl.h> 35f841f6adSraf 36f841f6adSraf /* 37d4204c85Sraf * The following array is used for caching information 38f841f6adSraf * for priocntl scheduling classes. 39f841f6adSraf */ 40d4204c85Sraf static pcclass_t sched_class[] = { 41d4204c85Sraf {0, SCHED_OTHER, 0, 0, {-1, "TS", 0}}, 42d4204c85Sraf {0, SCHED_FIFO, 0, 0, {-1, "RT", 0}}, 43d4204c85Sraf {0, SCHED_RR, 0, 0, {-1, "RT", 0}}, 44d4204c85Sraf {0, SCHED_SYS, 0, 0, {0, "SYS", 0}}, 45d4204c85Sraf {0, SCHED_IA, 0, 0, {-1, "IA", 0}}, 46d4204c85Sraf {0, SCHED_FSS, 0, 0, {-1, "FSS", 0}}, 47d4204c85Sraf {0, SCHED_FX, 0, 0, {-1, "FX", 0}}, 48d4204c85Sraf /* 49d4204c85Sraf * Allow unknown (to us) scheduling classes. 50d4204c85Sraf * The kernel allows space for exactly 10 scheduling classes 51d4204c85Sraf * (see the definitions of 'sclass' and 'nclass' in the kernel). 52d4204c85Sraf * We need that number of available slots here. 53d4204c85Sraf * If the kernel space is changed, this has to change too. 54d4204c85Sraf */ 55d4204c85Sraf {0, -1, 0, 0, {-1, "", 0}}, 56d4204c85Sraf {0, -1, 0, 0, {-1, "", 0}}, 57d4204c85Sraf {0, -1, 0, 0, {-1, "", 0}}, 58d4204c85Sraf {0, -1, 0, 0, {-1, "", 0}}, 59d4204c85Sraf {0, -1, 0, 0, {-1, "", 0}}, 60d4204c85Sraf {0, -1, 0, 0, {-1, "", 0}}, 61d4204c85Sraf {0, -1, 0, 0, {-1, "", 0}}, 62d4204c85Sraf {0, -1, 0, 0, {-1, "", 0}}, 63d4204c85Sraf {0, -1, 0, 0, {-1, "", 0}}, 64d4204c85Sraf {0, -1, 0, 0, {-1, "", 0}}, 65d4204c85Sraf }; 66f841f6adSraf 67d4204c85Sraf #define NPOLICY (sizeof (sched_class) / sizeof (pcclass_t)) 68f841f6adSraf 69d4204c85Sraf #if _SCHED_NEXT != SCHED_FX + 1 70d4204c85Sraf #error "fatal: _SCHED_NEXT != SCHED_FX + 1" 71d4204c85Sraf #endif 72f841f6adSraf 73d4204c85Sraf static mutex_t class_lock = DEFAULTMUTEX; /* protects sched_class[] */ 74f841f6adSraf 75f841f6adSraf /* 76d4204c85Sraf * Helper function for get_info_by_policy(), below. 77d4204c85Sraf * Don't let a manufactured policy number duplicate 78d4204c85Sraf * the class of one of our base policy numbers. 79f841f6adSraf */ 80d4204c85Sraf static int 81d4204c85Sraf is_base_class(const char *clname) 82d4204c85Sraf { 83d4204c85Sraf const pcclass_t *pccp; 84d4204c85Sraf int policy; 85d4204c85Sraf 86d4204c85Sraf for (policy = 0, pccp = sched_class; 87d4204c85Sraf policy < _SCHED_NEXT; 88d4204c85Sraf policy++, pccp++) { 89d4204c85Sraf if (strcmp(clname, pccp->pcc_info.pc_clname) == 0) 90d4204c85Sraf return (1); 91d4204c85Sraf } 92d4204c85Sraf return (0); 93d4204c85Sraf } 94d4204c85Sraf 95d4204c85Sraf /* 96d4204c85Sraf * Cache priocntl information on scheduling class by policy. 97d4204c85Sraf */ 98d4204c85Sraf const pcclass_t * 99f841f6adSraf get_info_by_policy(int policy) 100f841f6adSraf { 101d4204c85Sraf pcclass_t *pccp = &sched_class[policy]; 102d4204c85Sraf pcpri_t pcpri; 103d4204c85Sraf pri_t prio; 104d4204c85Sraf int base = 0; 105f841f6adSraf 106d4204c85Sraf if ((uint_t)policy >= NPOLICY || pccp->pcc_state < 0) { 107d4204c85Sraf errno = EINVAL; 108d4204c85Sraf return (NULL); 109d4204c85Sraf } 110d4204c85Sraf 111d4204c85Sraf if (pccp->pcc_state > 0) 112d4204c85Sraf return (pccp); 113d4204c85Sraf 114d4204c85Sraf lmutex_lock(&class_lock); 115d4204c85Sraf 116d4204c85Sraf /* get class info (the system class is known to have class-id == 0) */ 117d4204c85Sraf if (pccp->pcc_policy == -1) { 118d4204c85Sraf /* policy number not defined in <sched.h> */ 119d4204c85Sraf ASSERT(policy >= _SCHED_NEXT); 120d4204c85Sraf pccp->pcc_info.pc_cid = policy - _SCHED_NEXT; 1218cd45542Sraf if (priocntl(0, 0, PC_GETCLINFO, &pccp->pcc_info) == -1 || 122d4204c85Sraf (base = is_base_class(pccp->pcc_info.pc_clname)) != 0) { 123d4204c85Sraf pccp->pcc_info.pc_clname[0] = '\0'; 124d4204c85Sraf pccp->pcc_info.pc_cid = -1; 125d4204c85Sraf /* 126d4204c85Sraf * If we duplicated a base class, permanently 127d4204c85Sraf * disable this policy entry. Else allow for 128d4204c85Sraf * dynamic loading of scheduling classes. 129d4204c85Sraf */ 130d4204c85Sraf if (base) { 131*7257d1b4Sraf membar_producer(); 132d4204c85Sraf pccp->pcc_state = -1; 133d4204c85Sraf } 134d4204c85Sraf errno = EINVAL; 135d4204c85Sraf lmutex_unlock(&class_lock); 136d4204c85Sraf return (NULL); 137d4204c85Sraf } 138d4204c85Sraf pccp->pcc_policy = policy; 139d4204c85Sraf } else if (policy != SCHED_SYS && 1408cd45542Sraf priocntl(0, 0, PC_GETCID, &pccp->pcc_info) == -1) { 141*7257d1b4Sraf membar_producer(); 142d4204c85Sraf pccp->pcc_state = -1; 143d4204c85Sraf errno = EINVAL; 144d4204c85Sraf lmutex_unlock(&class_lock); 145d4204c85Sraf return (NULL); 146d4204c85Sraf } 147d4204c85Sraf 148d4204c85Sraf switch (policy) { 149d4204c85Sraf case SCHED_OTHER: 150d4204c85Sraf prio = ((tsinfo_t *)pccp->pcc_info.pc_clinfo)->ts_maxupri; 151d4204c85Sraf pccp->pcc_primin = -prio; 152d4204c85Sraf pccp->pcc_primax = prio; 153d4204c85Sraf break; 154d4204c85Sraf case SCHED_FIFO: 155d4204c85Sraf case SCHED_RR: 156d4204c85Sraf prio = ((rtinfo_t *)pccp->pcc_info.pc_clinfo)->rt_maxpri; 157d4204c85Sraf pccp->pcc_primin = 0; 158d4204c85Sraf pccp->pcc_primax = prio; 159d4204c85Sraf break; 160d4204c85Sraf default: 161d4204c85Sraf /* 162d4204c85Sraf * All other policy numbers, including policy numbers 163d4204c85Sraf * not defined in <sched.h>. 164d4204c85Sraf */ 165d4204c85Sraf pcpri.pc_cid = pccp->pcc_info.pc_cid; 1668cd45542Sraf if (priocntl(0, 0, PC_GETPRIRANGE, &pcpri) == 0) { 167d4204c85Sraf pccp->pcc_primin = pcpri.pc_clpmin; 168d4204c85Sraf pccp->pcc_primax = pcpri.pc_clpmax; 169d4204c85Sraf } 170d4204c85Sraf break; 171d4204c85Sraf } 172d4204c85Sraf 173*7257d1b4Sraf membar_producer(); 174d4204c85Sraf pccp->pcc_state = 1; 175d4204c85Sraf lmutex_unlock(&class_lock); 176d4204c85Sraf return (pccp); 177d4204c85Sraf } 178d4204c85Sraf 179d4204c85Sraf const pcclass_t * 180d4204c85Sraf get_info_by_class(id_t classid) 181d4204c85Sraf { 182d4204c85Sraf pcinfo_t pcinfo; 183d4204c85Sraf pcclass_t *pccp; 184d4204c85Sraf int policy; 185d4204c85Sraf 186d4204c85Sraf if (classid < 0) { 187d4204c85Sraf errno = EINVAL; 188d4204c85Sraf return (NULL); 189d4204c85Sraf } 190d4204c85Sraf 191d4204c85Sraf /* determine if we already know this classid */ 192d4204c85Sraf for (policy = 0, pccp = sched_class; 193d4204c85Sraf policy < NPOLICY; 194d4204c85Sraf policy++, pccp++) { 195d4204c85Sraf if (pccp->pcc_state > 0 && pccp->pcc_info.pc_cid == classid) 196d4204c85Sraf return (pccp); 197d4204c85Sraf } 198d4204c85Sraf 199d4204c85Sraf pcinfo.pc_cid = classid; 2008cd45542Sraf if (priocntl(0, 0, PC_GETCLINFO, &pcinfo) == -1) { 201d4204c85Sraf if (classid == 0) /* no kernel info for sys class */ 202d4204c85Sraf return (get_info_by_policy(SCHED_SYS)); 203d4204c85Sraf return (NULL); 204d4204c85Sraf } 205d4204c85Sraf 206d4204c85Sraf for (policy = 0, pccp = sched_class; 207d4204c85Sraf policy < NPOLICY; 208d4204c85Sraf policy++, pccp++) { 209d4204c85Sraf if (pccp->pcc_state == 0 && 210d4204c85Sraf strcmp(pcinfo.pc_clname, pccp->pcc_info.pc_clname) == 0) 211d4204c85Sraf return (get_info_by_policy(pccp->pcc_policy)); 212d4204c85Sraf } 213d4204c85Sraf 214d4204c85Sraf /* 215d4204c85Sraf * We have encountered an unknown (to us) scheduling class. 216d4204c85Sraf * Manufacture a policy number for it. Hopefully we still 217d4204c85Sraf * have room in the sched_class[] table. 218d4204c85Sraf */ 219d4204c85Sraf policy = _SCHED_NEXT + classid; 220d4204c85Sraf if (policy >= NPOLICY) { 221d4204c85Sraf errno = EINVAL; 222d4204c85Sraf return (NULL); 223d4204c85Sraf } 224d4204c85Sraf lmutex_lock(&class_lock); 225d4204c85Sraf pccp = &sched_class[policy]; 226d4204c85Sraf pccp->pcc_policy = policy; 227d4204c85Sraf (void) strlcpy(pccp->pcc_info.pc_clname, pcinfo.pc_clname, PC_CLNMSZ); 228d4204c85Sraf lmutex_unlock(&class_lock); 229d4204c85Sraf return (get_info_by_policy(pccp->pcc_policy)); 230d4204c85Sraf } 231d4204c85Sraf 232d4204c85Sraf /* 233d4204c85Sraf * Helper function: get process or lwp current scheduling policy. 234d4204c85Sraf */ 235d4204c85Sraf static const pcclass_t * 236d4204c85Sraf get_parms(idtype_t idtype, id_t id, pcparms_t *pcparmp) 237d4204c85Sraf { 238d4204c85Sraf pcparmp->pc_cid = PC_CLNULL; 2398cd45542Sraf if (priocntl(idtype, id, PC_GETPARMS, pcparmp) == -1) 240d4204c85Sraf return (NULL); 241d4204c85Sraf return (get_info_by_class(pcparmp->pc_cid)); 242d4204c85Sraf } 243d4204c85Sraf 244d4204c85Sraf /* 245d4204c85Sraf * Helper function for setprio() and setparam(), below. 246d4204c85Sraf */ 247d4204c85Sraf static int 248d4204c85Sraf set_priority(idtype_t idtype, id_t id, int policy, int prio, 249d4204c85Sraf pcparms_t *pcparmp, int settq) 250d4204c85Sraf { 251d4204c85Sraf int rv; 252d4204c85Sraf 253d4204c85Sraf switch (policy) { 254d4204c85Sraf case SCHED_OTHER: 255d4204c85Sraf { 256d4204c85Sraf tsparms_t *tsp = (tsparms_t *)pcparmp->pc_clparms; 257d4204c85Sraf tsp->ts_uprilim = prio; 258d4204c85Sraf tsp->ts_upri = prio; 259d4204c85Sraf break; 260d4204c85Sraf } 261d4204c85Sraf case SCHED_FIFO: 262d4204c85Sraf case SCHED_RR: 263d4204c85Sraf { 264d4204c85Sraf rtparms_t *rtp = (rtparms_t *)pcparmp->pc_clparms; 265d4204c85Sraf rtp->rt_tqnsecs = settq? 266d4204c85Sraf (policy == SCHED_FIFO? RT_TQINF : RT_TQDEF) : 267d4204c85Sraf RT_NOCHANGE; 268d4204c85Sraf rtp->rt_pri = prio; 269d4204c85Sraf break; 270d4204c85Sraf } 271d4204c85Sraf default: 272d4204c85Sraf { 273d4204c85Sraf /* 274d4204c85Sraf * Class-independent method for setting the priority. 275d4204c85Sraf */ 276d4204c85Sraf pcprio_t pcprio; 277d4204c85Sraf 278d4204c85Sraf pcprio.pc_op = PC_SETPRIO; 279d4204c85Sraf pcprio.pc_cid = pcparmp->pc_cid; 280d4204c85Sraf pcprio.pc_val = prio; 281d4204c85Sraf do { 2828cd45542Sraf rv = priocntl(idtype, id, PC_DOPRIO, &pcprio); 283d4204c85Sraf } while (rv == -1 && errno == ENOMEM); 284d4204c85Sraf return (rv); 285d4204c85Sraf } 286d4204c85Sraf } 287d4204c85Sraf 288d4204c85Sraf do { 2898cd45542Sraf rv = priocntl(idtype, id, PC_SETPARMS, pcparmp); 290d4204c85Sraf } while (rv == -1 && errno == ENOMEM); 291d4204c85Sraf return (rv); 292d4204c85Sraf } 293d4204c85Sraf 294d4204c85Sraf /* 295d4204c85Sraf * Utility function, private to libc, used by sched_setparam() 296d4204c85Sraf * and posix_spawn(). Because it is called by the vfork() child of 297d4204c85Sraf * posix_spawn(), we must not call any functions exported from libc. 298d4204c85Sraf */ 299d4204c85Sraf id_t 300d4204c85Sraf setprio(idtype_t idtype, id_t id, int prio, int *policyp) 301d4204c85Sraf { 302d4204c85Sraf pcparms_t pcparm; 303d4204c85Sraf int policy; 304d4204c85Sraf const pcclass_t *pccp; 305d4204c85Sraf 306d4204c85Sraf if ((pccp = get_parms(idtype, id, &pcparm)) == NULL) 307d4204c85Sraf return (-1); 308d4204c85Sraf if (prio < pccp->pcc_primin || prio > pccp->pcc_primax) { 309f841f6adSraf errno = EINVAL; 310f841f6adSraf return (-1); 311f841f6adSraf } 312f841f6adSraf 313d4204c85Sraf policy = pccp->pcc_policy; 314d4204c85Sraf if (policyp != NULL && 315d4204c85Sraf (policy == SCHED_FIFO || policy == SCHED_RR)) { 316d4204c85Sraf rtparms_t *rtp = (rtparms_t *)pcparm.pc_clparms; 317d4204c85Sraf policy = (rtp->rt_tqnsecs == RT_TQINF? SCHED_FIFO : SCHED_RR); 318f841f6adSraf } 319f841f6adSraf 320d4204c85Sraf if (set_priority(idtype, id, policy, prio, &pcparm, 0) == -1) 321f841f6adSraf return (-1); 322d4204c85Sraf if (policyp != NULL) 323d4204c85Sraf *policyp = policy; 324d4204c85Sraf return (pccp->pcc_info.pc_cid); 325f841f6adSraf } 326f841f6adSraf 327f841f6adSraf int 328f841f6adSraf sched_setparam(pid_t pid, const struct sched_param *param) 329f841f6adSraf { 330f841f6adSraf if (pid < 0) { 331f841f6adSraf errno = ESRCH; 332f841f6adSraf return (-1); 333f841f6adSraf } 334f841f6adSraf if (pid == 0) 335f841f6adSraf pid = P_MYID; 336f841f6adSraf 337d4204c85Sraf if (setprio(P_PID, pid, param->sched_priority, NULL) == -1) 338f841f6adSraf return (-1); 339d4204c85Sraf return (0); 340d4204c85Sraf } 341d4204c85Sraf 342d4204c85Sraf id_t 343d4204c85Sraf getparam(idtype_t idtype, id_t id, int *policyp, struct sched_param *param) 344d4204c85Sraf { 345d4204c85Sraf pcparms_t pcparm; 346d4204c85Sraf const pcclass_t *pccp; 347d4204c85Sraf int policy; 348d4204c85Sraf int priority; 349d4204c85Sraf 350d4204c85Sraf if ((pccp = get_parms(idtype, id, &pcparm)) == NULL) 351f841f6adSraf return (-1); 352f841f6adSraf 353d4204c85Sraf switch (policy = pccp->pcc_policy) { 354d4204c85Sraf case SCHED_OTHER: 355d4204c85Sraf { 356d4204c85Sraf tsparms_t *tsp = (tsparms_t *)pcparm.pc_clparms; 357d4204c85Sraf priority = tsp->ts_upri; 358d4204c85Sraf break; 359f841f6adSraf } 360d4204c85Sraf case SCHED_FIFO: 361d4204c85Sraf case SCHED_RR: 362d4204c85Sraf { 363d4204c85Sraf rtparms_t *rtp = (rtparms_t *)pcparm.pc_clparms; 364d4204c85Sraf priority = rtp->rt_pri; 365d4204c85Sraf policy = (rtp->rt_tqnsecs == RT_TQINF? SCHED_FIFO : SCHED_RR); 366d4204c85Sraf break; 367d4204c85Sraf } 368d4204c85Sraf default: 369d4204c85Sraf { 370f841f6adSraf /* 371d4204c85Sraf * Class-independent method for getting the priority. 372f841f6adSraf */ 373d4204c85Sraf pcprio_t pcprio; 374d4204c85Sraf 375d4204c85Sraf pcprio.pc_op = PC_GETPRIO; 376d4204c85Sraf pcprio.pc_cid = 0; 377d4204c85Sraf pcprio.pc_val = 0; 3788cd45542Sraf if (priocntl(idtype, id, PC_DOPRIO, &pcprio) == 0) 379d4204c85Sraf priority = pcprio.pc_val; 380d4204c85Sraf else 381d4204c85Sraf priority = 0; 382d4204c85Sraf break; 383d4204c85Sraf } 384f841f6adSraf } 385f841f6adSraf 386d4204c85Sraf *policyp = policy; 387d4204c85Sraf (void) memset(param, 0, sizeof (*param)); 388d4204c85Sraf param->sched_priority = priority; 389d4204c85Sraf 390d4204c85Sraf return (pcparm.pc_cid); 391f841f6adSraf } 392f841f6adSraf 393f841f6adSraf int 394f841f6adSraf sched_getparam(pid_t pid, struct sched_param *param) 395f841f6adSraf { 396f841f6adSraf int policy; 397f841f6adSraf 398f841f6adSraf if (pid < 0) { 399f841f6adSraf errno = ESRCH; 400f841f6adSraf return (-1); 401f841f6adSraf } 402f841f6adSraf if (pid == 0) 403f841f6adSraf pid = P_MYID; 404f841f6adSraf 405d4204c85Sraf if (getparam(P_PID, pid, &policy, param) == -1) 406f841f6adSraf return (-1); 407d4204c85Sraf return (0); 408d4204c85Sraf } 409d4204c85Sraf 410d4204c85Sraf /* 411d4204c85Sraf * Utility function, private to libc, used by sched_setscheduler() 412d4204c85Sraf * and posix_spawn(). Because it is called by the vfork() child of 413d4204c85Sraf * posix_spawn(), we must not call any functions exported from libc. 414d4204c85Sraf */ 415d4204c85Sraf id_t 416d4204c85Sraf setparam(idtype_t idtype, id_t id, int policy, int prio) 417d4204c85Sraf { 418d4204c85Sraf pcparms_t pcparm; 419d4204c85Sraf const pcclass_t *pccp; 420d4204c85Sraf 421d4204c85Sraf if (policy == SCHED_SYS || 422d4204c85Sraf (pccp = get_info_by_policy(policy)) == NULL || 423d4204c85Sraf prio < pccp->pcc_primin || prio > pccp->pcc_primax) { 424d4204c85Sraf errno = EINVAL; 425d4204c85Sraf return (-1); 426d4204c85Sraf } 427d4204c85Sraf 428d4204c85Sraf pcparm.pc_cid = pccp->pcc_info.pc_cid; 429d4204c85Sraf if (set_priority(idtype, id, policy, prio, &pcparm, 1) == -1) 430d4204c85Sraf return (-1); 431d4204c85Sraf return (pccp->pcc_info.pc_cid); 432d4204c85Sraf } 433d4204c85Sraf 434d4204c85Sraf int 435d4204c85Sraf sched_setscheduler(pid_t pid, int policy, const struct sched_param *param) 436d4204c85Sraf { 437d4204c85Sraf pri_t prio = param->sched_priority; 438d4204c85Sraf int oldpolicy; 439d4204c85Sraf 440d4204c85Sraf if ((oldpolicy = sched_getscheduler(pid)) < 0) 441f841f6adSraf return (-1); 442f841f6adSraf 443d4204c85Sraf if (pid == 0) 444d4204c85Sraf pid = P_MYID; 445d4204c85Sraf 446d4204c85Sraf if (setparam(P_PID, pid, policy, prio) == -1) 447d4204c85Sraf return (-1); 448d4204c85Sraf 449d4204c85Sraf return (oldpolicy); 450d4204c85Sraf } 451d4204c85Sraf 452d4204c85Sraf int 453d4204c85Sraf sched_getscheduler(pid_t pid) 454d4204c85Sraf { 455d4204c85Sraf pcparms_t pcparm; 456d4204c85Sraf const pcclass_t *pccp; 457d4204c85Sraf int policy; 458d4204c85Sraf 459d4204c85Sraf if (pid < 0) { 460d4204c85Sraf errno = ESRCH; 461d4204c85Sraf return (-1); 462d4204c85Sraf } 463d4204c85Sraf if (pid == 0) 464d4204c85Sraf pid = P_MYID; 465d4204c85Sraf 466d4204c85Sraf if ((pccp = get_parms(P_PID, pid, &pcparm)) == NULL) 467d4204c85Sraf return (-1); 468d4204c85Sraf 469d4204c85Sraf if ((policy = pccp->pcc_policy) == SCHED_FIFO || policy == SCHED_RR) { 470d4204c85Sraf policy = 471d4204c85Sraf (((rtparms_t *)pcparm.pc_clparms)->rt_tqnsecs == RT_TQINF? 472d4204c85Sraf SCHED_FIFO : SCHED_RR); 473f841f6adSraf } 474f841f6adSraf 475f841f6adSraf return (policy); 476f841f6adSraf } 477f841f6adSraf 478f841f6adSraf int 479f841f6adSraf sched_yield(void) 480f841f6adSraf { 4818cd45542Sraf yield(); 482f841f6adSraf return (0); 483f841f6adSraf } 484f841f6adSraf 485f841f6adSraf int 486f841f6adSraf sched_get_priority_max(int policy) 487f841f6adSraf { 488d4204c85Sraf const pcclass_t *pccp; 489f841f6adSraf 490d4204c85Sraf if ((pccp = get_info_by_policy(policy)) != NULL) 491d4204c85Sraf return (pccp->pcc_primax); 492f841f6adSraf errno = EINVAL; 493f841f6adSraf return (-1); 494f841f6adSraf } 495f841f6adSraf 496f841f6adSraf int 497f841f6adSraf sched_get_priority_min(int policy) 498f841f6adSraf { 499d4204c85Sraf const pcclass_t *pccp; 500f841f6adSraf 501d4204c85Sraf if ((pccp = get_info_by_policy(policy)) != NULL) 502d4204c85Sraf return (pccp->pcc_primin); 503f841f6adSraf errno = EINVAL; 504f841f6adSraf return (-1); 505f841f6adSraf } 506f841f6adSraf 507f841f6adSraf int 508f841f6adSraf sched_rr_get_interval(pid_t pid, timespec_t *interval) 509f841f6adSraf { 510f841f6adSraf pcparms_t pcparm; 511d4204c85Sraf const pcclass_t *pccp; 512f841f6adSraf 513f841f6adSraf if (pid < 0) { 514f841f6adSraf errno = ESRCH; 515f841f6adSraf return (-1); 516f841f6adSraf } 517f841f6adSraf if (pid == 0) 518f841f6adSraf pid = P_MYID; 519f841f6adSraf 520d4204c85Sraf if ((pccp = get_parms(P_PID, pid, &pcparm)) == NULL) 521f841f6adSraf return (-1); 522f841f6adSraf 523d4204c85Sraf /* 524d4204c85Sraf * At the moment, we have no class-independent method to fetch 525d4204c85Sraf * the process/lwp time quantum. Since SUSv3 does not restrict 526d4204c85Sraf * this operation to the real-time class, we return an indefinite 527d4204c85Sraf * quantum (tv_sec == 0 and tv_nsec == 0) for scheduling policies 528d4204c85Sraf * for which this information isn't available. 529d4204c85Sraf */ 530d4204c85Sraf interval->tv_sec = 0; 531d4204c85Sraf interval->tv_nsec = 0; 532f841f6adSraf 533d4204c85Sraf switch (pccp->pcc_policy) { 534d4204c85Sraf case SCHED_FIFO: 535d4204c85Sraf case SCHED_RR: 536d4204c85Sraf { 537d4204c85Sraf rtparms_t *rtp = (rtparms_t *)pcparm.pc_clparms; 538d4204c85Sraf if (rtp->rt_tqnsecs != RT_TQINF) { 539d4204c85Sraf interval->tv_sec = rtp->rt_tqsecs; 540d4204c85Sraf interval->tv_nsec = rtp->rt_tqnsecs; 541d4204c85Sraf } 542d4204c85Sraf } 543d4204c85Sraf break; 544d4204c85Sraf case SCHED_FX: 545d4204c85Sraf { 546d4204c85Sraf fxparms_t *fxp = (fxparms_t *)pcparm.pc_clparms; 547d4204c85Sraf if (fxp->fx_tqnsecs != FX_TQINF) { 548d4204c85Sraf interval->tv_sec = fxp->fx_tqsecs; 549d4204c85Sraf interval->tv_nsec = fxp->fx_tqnsecs; 550d4204c85Sraf } 551d4204c85Sraf } 552d4204c85Sraf break; 553d4204c85Sraf } 554d4204c85Sraf 555f841f6adSraf return (0); 556f841f6adSraf } 557f841f6adSraf 558d4204c85Sraf /* 559d4204c85Sraf * Initialize or update ul_policy, ul_cid, and ul_pri. 560d4204c85Sraf */ 561d4204c85Sraf void 562d4204c85Sraf update_sched(ulwp_t *self) 563d4204c85Sraf { 564d4204c85Sraf volatile sc_shared_t *scp; 565d4204c85Sraf pcparms_t pcparm; 566d4204c85Sraf pcprio_t pcprio; 567d4204c85Sraf const pcclass_t *pccp; 568d4204c85Sraf int priority; 569d4204c85Sraf int policy; 570d4204c85Sraf 571d4204c85Sraf ASSERT(self == curthread); 572d4204c85Sraf 573d4204c85Sraf enter_critical(self); 574d4204c85Sraf 575d4204c85Sraf if ((scp = self->ul_schedctl) == NULL && 576d4204c85Sraf (scp = setup_schedctl()) == NULL) { /* can't happen? */ 577d4204c85Sraf if (self->ul_policy < 0) { 578d4204c85Sraf self->ul_cid = 0; 579d4204c85Sraf self->ul_pri = 0; 580*7257d1b4Sraf membar_producer(); 581d4204c85Sraf self->ul_policy = SCHED_OTHER; 582d4204c85Sraf } 583d4204c85Sraf exit_critical(self); 584d4204c85Sraf return; 585d4204c85Sraf } 586d4204c85Sraf 587d4204c85Sraf if (self->ul_policy >= 0 && 588d4204c85Sraf self->ul_cid == scp->sc_cid && 589d4204c85Sraf (self->ul_pri == scp->sc_cpri || 590d4204c85Sraf (self->ul_epri > 0 && self->ul_epri == scp->sc_cpri))) { 591d4204c85Sraf exit_critical(self); 592d4204c85Sraf return; 593d4204c85Sraf } 594d4204c85Sraf 595d4204c85Sraf pccp = get_parms(P_LWPID, P_MYID, &pcparm); 596d4204c85Sraf if (pccp == NULL) { /* can't happen? */ 597d4204c85Sraf self->ul_cid = scp->sc_cid; 598d4204c85Sraf self->ul_pri = scp->sc_cpri; 599*7257d1b4Sraf membar_producer(); 600d4204c85Sraf self->ul_policy = SCHED_OTHER; 601d4204c85Sraf exit_critical(self); 602d4204c85Sraf return; 603d4204c85Sraf } 604d4204c85Sraf 605d4204c85Sraf switch (policy = pccp->pcc_policy) { 606d4204c85Sraf case SCHED_OTHER: 607d4204c85Sraf priority = ((tsparms_t *)pcparm.pc_clparms)->ts_upri; 608d4204c85Sraf break; 609d4204c85Sraf case SCHED_FIFO: 610d4204c85Sraf case SCHED_RR: 611e84487aeSraf self->ul_rtclassid = pccp->pcc_info.pc_cid; 612d4204c85Sraf priority = ((rtparms_t *)pcparm.pc_clparms)->rt_pri; 613d4204c85Sraf policy = 614d4204c85Sraf ((rtparms_t *)pcparm.pc_clparms)->rt_tqnsecs == RT_TQINF? 615d4204c85Sraf SCHED_FIFO : SCHED_RR; 616d4204c85Sraf break; 617d4204c85Sraf default: 618d4204c85Sraf /* 619d4204c85Sraf * Class-independent method for getting the priority. 620d4204c85Sraf */ 621d4204c85Sraf pcprio.pc_op = PC_GETPRIO; 622d4204c85Sraf pcprio.pc_cid = 0; 623d4204c85Sraf pcprio.pc_val = 0; 6248cd45542Sraf if (priocntl(P_LWPID, P_MYID, PC_DOPRIO, &pcprio) == 0) 625d4204c85Sraf priority = pcprio.pc_val; 626d4204c85Sraf else 627d4204c85Sraf priority = 0; 628d4204c85Sraf } 629d4204c85Sraf 630d4204c85Sraf self->ul_cid = pcparm.pc_cid; 631d4204c85Sraf self->ul_pri = priority; 632*7257d1b4Sraf membar_producer(); 633d4204c85Sraf self->ul_policy = policy; 634d4204c85Sraf 635d4204c85Sraf exit_critical(self); 636f841f6adSraf } 637