1917e476dSPeter Dufault /* 2917e476dSPeter Dufault * Copyright (c) 1996, 1997 3917e476dSPeter Dufault * HD Associates, Inc. All rights reserved. 4917e476dSPeter Dufault * 5917e476dSPeter Dufault * Redistribution and use in source and binary forms, with or without 6917e476dSPeter Dufault * modification, are permitted provided that the following conditions 7917e476dSPeter Dufault * are met: 8917e476dSPeter Dufault * 1. Redistributions of source code must retain the above copyright 9917e476dSPeter Dufault * notice, this list of conditions and the following disclaimer. 10917e476dSPeter Dufault * 2. Redistributions in binary form must reproduce the above copyright 11917e476dSPeter Dufault * notice, this list of conditions and the following disclaimer in the 12917e476dSPeter Dufault * documentation and/or other materials provided with the distribution. 13917e476dSPeter Dufault * 3. All advertising materials mentioning features or use of this software 14917e476dSPeter Dufault * must display the following acknowledgement: 15917e476dSPeter Dufault * This product includes software developed by HD Associates, Inc 16917e476dSPeter Dufault * 4. Neither the name of the author nor the names of any co-contributors 17917e476dSPeter Dufault * may be used to endorse or promote products derived from this software 18917e476dSPeter Dufault * without specific prior written permission. 19917e476dSPeter Dufault * 20917e476dSPeter Dufault * THIS SOFTWARE IS PROVIDED BY HD ASSOCIATES AND CONTRIBUTORS ``AS IS'' AND 21917e476dSPeter Dufault * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22917e476dSPeter Dufault * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23917e476dSPeter Dufault * ARE DISCLAIMED. IN NO EVENT SHALL HD ASSOCIATES OR CONTRIBUTORS BE LIABLE 24917e476dSPeter Dufault * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25917e476dSPeter Dufault * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 26917e476dSPeter Dufault * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 27917e476dSPeter Dufault * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 28917e476dSPeter Dufault * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 29917e476dSPeter Dufault * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 30917e476dSPeter Dufault * SUCH DAMAGE. 31917e476dSPeter Dufault * 32917e476dSPeter Dufault */ 33917e476dSPeter Dufault 34917e476dSPeter Dufault /* ksched: Soft real time scheduling based on "rtprio". 35917e476dSPeter Dufault */ 36917e476dSPeter Dufault 37917e476dSPeter Dufault #include <sys/param.h> 38917e476dSPeter Dufault #include <sys/systm.h> 39917e476dSPeter Dufault #include <sys/proc.h> 40917e476dSPeter Dufault #include <sys/kernel.h> 41917e476dSPeter Dufault #include <machine/cpu.h> /* For need_resched */ 42917e476dSPeter Dufault #include <fcntl.h> 43917e476dSPeter Dufault 44917e476dSPeter Dufault #include <sys/posix4.h> 45917e476dSPeter Dufault 46917e476dSPeter Dufault /* ksched: Real-time extension to support POSIX priority scheduling. 47917e476dSPeter Dufault */ 48917e476dSPeter Dufault 49917e476dSPeter Dufault static struct timespec rr_interval; 50917e476dSPeter Dufault 51917e476dSPeter Dufault int ksched_attach(int p4_instance, int fac_code, void **p) 52917e476dSPeter Dufault { 53917e476dSPeter Dufault rr_interval.tv_sec = 0; 54917e476dSPeter Dufault rr_interval.tv_nsec = 1000000000L / roundrobin_interval(); 55917e476dSPeter Dufault 56917e476dSPeter Dufault *p = 0; 57917e476dSPeter Dufault 58917e476dSPeter Dufault return 0; 59917e476dSPeter Dufault } 60917e476dSPeter Dufault 61917e476dSPeter Dufault int ksched_detach(void *p) 62917e476dSPeter Dufault { 63917e476dSPeter Dufault return 0; 64917e476dSPeter Dufault } 65917e476dSPeter Dufault 66917e476dSPeter Dufault /* 67917e476dSPeter Dufault * XXX About priorities 68917e476dSPeter Dufault * 69917e476dSPeter Dufault * POSIX4 requires that numerically higher priorities be of 70917e476dSPeter Dufault * higher priority. It also permits sched_setparam to be 71917e476dSPeter Dufault * implementation defined for SCHED_OTHER. I don't like 72917e476dSPeter Dufault * the notion of inverted priorites for normal processes when 73917e476dSPeter Dufault * you can use "setpriority" for that. 74917e476dSPeter Dufault * 75917e476dSPeter Dufault * I'm rejecting sched_setparam for SCHED_OTHER with EINVAL. 76917e476dSPeter Dufault */ 77917e476dSPeter Dufault 78917e476dSPeter Dufault /* Macros to convert between the unix (lower numerically is higher priority) 79917e476dSPeter Dufault * and POSIX4 (higher numerically is higher priority) 80917e476dSPeter Dufault */ 81917e476dSPeter Dufault 82917e476dSPeter Dufault #define p4prio_to_rtpprio(P) (RTP_PRIO_MAX - (P)) 83917e476dSPeter Dufault #define rtpprio_to_p4prio(P) (RTP_PRIO_MAX - (P)) 84917e476dSPeter Dufault 85917e476dSPeter Dufault static inline int 86917e476dSPeter Dufault getscheduler(int *ret, void *hook, struct proc *p) 87917e476dSPeter Dufault { 88917e476dSPeter Dufault int e = 0; 89917e476dSPeter Dufault 90917e476dSPeter Dufault switch (p->p_rtprio.type) 91917e476dSPeter Dufault { 92917e476dSPeter Dufault case RTP_PRIO_FIFO: 93917e476dSPeter Dufault *ret = SCHED_FIFO; 94917e476dSPeter Dufault break; 95917e476dSPeter Dufault 96917e476dSPeter Dufault case RTP_PRIO_REALTIME: 97917e476dSPeter Dufault *ret = SCHED_RR; 98917e476dSPeter Dufault break; 99917e476dSPeter Dufault 100917e476dSPeter Dufault default: 101917e476dSPeter Dufault *ret = SCHED_OTHER; 102917e476dSPeter Dufault break; 103917e476dSPeter Dufault } 104917e476dSPeter Dufault 105917e476dSPeter Dufault return e; 106917e476dSPeter Dufault } 107917e476dSPeter Dufault 108917e476dSPeter Dufault int ksched_setparam(int *ret, void *hook, 109917e476dSPeter Dufault struct proc *p, const struct sched_param *param) 110917e476dSPeter Dufault { 111917e476dSPeter Dufault int e, policy; 112917e476dSPeter Dufault 113917e476dSPeter Dufault e = getscheduler(&policy, hook, p); 114917e476dSPeter Dufault 115917e476dSPeter Dufault if (e == 0) 116917e476dSPeter Dufault { 117917e476dSPeter Dufault if (policy == SCHED_OTHER) 118917e476dSPeter Dufault e = EINVAL; 119917e476dSPeter Dufault else 120917e476dSPeter Dufault e = ksched_setscheduler(ret, hook, p, policy, param); 121917e476dSPeter Dufault } 122917e476dSPeter Dufault 123917e476dSPeter Dufault return e; 124917e476dSPeter Dufault } 125917e476dSPeter Dufault 126917e476dSPeter Dufault int ksched_getparam(int *ret, void *hook, 127917e476dSPeter Dufault struct proc *p, struct sched_param *param) 128917e476dSPeter Dufault { 129917e476dSPeter Dufault if (RTP_PRIO_IS_REALTIME(p->p_rtprio.type)) 130917e476dSPeter Dufault param->sched_priority = rtpprio_to_p4prio(p->p_rtprio.prio); 131917e476dSPeter Dufault 132917e476dSPeter Dufault return 0; 133917e476dSPeter Dufault } 134917e476dSPeter Dufault 135917e476dSPeter Dufault /* 136917e476dSPeter Dufault * XXX The priority and scheduler modifications should 137917e476dSPeter Dufault * be moved into published interfaces in kern/kern_sync. 138917e476dSPeter Dufault * 139917e476dSPeter Dufault * The permissions to modify process p were checked in "posix4proc()". 140917e476dSPeter Dufault * 141917e476dSPeter Dufault */ 142917e476dSPeter Dufault int ksched_setscheduler(int *ret, void *hook, 143917e476dSPeter Dufault struct proc *p, int policy, const struct sched_param *param) 144917e476dSPeter Dufault { 145917e476dSPeter Dufault int e = 0; 146917e476dSPeter Dufault struct rtprio rtp; 147917e476dSPeter Dufault 148917e476dSPeter Dufault switch(policy) 149917e476dSPeter Dufault { 150917e476dSPeter Dufault case SCHED_RR: 151917e476dSPeter Dufault case SCHED_FIFO: 152917e476dSPeter Dufault 153917e476dSPeter Dufault if (param->sched_priority >= RTP_PRIO_MIN && 154917e476dSPeter Dufault param->sched_priority <= RTP_PRIO_MAX) 155917e476dSPeter Dufault { 156917e476dSPeter Dufault rtp.type = (policy == SCHED_FIFO) 157917e476dSPeter Dufault ? RTP_PRIO_FIFO : RTP_PRIO_REALTIME; 158917e476dSPeter Dufault 159917e476dSPeter Dufault rtp.prio = p4prio_to_rtpprio(RTP_PRIO_MAX); 160917e476dSPeter Dufault p->p_rtprio = rtp; 161917e476dSPeter Dufault (void)resetpriority(p); 162917e476dSPeter Dufault } 163917e476dSPeter Dufault else 164917e476dSPeter Dufault e = EPERM; 165917e476dSPeter Dufault 166917e476dSPeter Dufault 167917e476dSPeter Dufault break; 168917e476dSPeter Dufault 169917e476dSPeter Dufault case SCHED_OTHER: 170917e476dSPeter Dufault { 171917e476dSPeter Dufault rtp.type = RTP_PRIO_NORMAL; 172917e476dSPeter Dufault rtp.prio = p4prio_to_rtpprio(RTP_PRIO_MIN); 173917e476dSPeter Dufault p->p_rtprio = rtp; 174917e476dSPeter Dufault 175917e476dSPeter Dufault /* XXX Simply revert to whatever we had for last 176917e476dSPeter Dufault * normal scheduler priorities. 177917e476dSPeter Dufault * This puts a requirement 178917e476dSPeter Dufault * on the scheduling code: You must leave the 179917e476dSPeter Dufault * scheduling info alone. 180917e476dSPeter Dufault */ 181917e476dSPeter Dufault (void)resetpriority(p); 182917e476dSPeter Dufault } 183917e476dSPeter Dufault break; 184917e476dSPeter Dufault } 185917e476dSPeter Dufault 186917e476dSPeter Dufault return e; 187917e476dSPeter Dufault } 188917e476dSPeter Dufault 189917e476dSPeter Dufault int ksched_getscheduler(int *ret, void *hook, struct proc *p) 190917e476dSPeter Dufault { 191917e476dSPeter Dufault return getscheduler(ret, hook, p); 192917e476dSPeter Dufault } 193917e476dSPeter Dufault 194917e476dSPeter Dufault /* ksched_yield: Yield the CPU. 195917e476dSPeter Dufault */ 196917e476dSPeter Dufault int ksched_yield(int *ret, void *hook) 197917e476dSPeter Dufault { 198917e476dSPeter Dufault need_resched(); 199917e476dSPeter Dufault return 0; 200917e476dSPeter Dufault } 201917e476dSPeter Dufault 202917e476dSPeter Dufault int ksched_get_priority_max(int *ret, void *hook, int policy) 203917e476dSPeter Dufault { 204917e476dSPeter Dufault int e = 0; 205917e476dSPeter Dufault 206917e476dSPeter Dufault switch (policy) 207917e476dSPeter Dufault { 208917e476dSPeter Dufault case SCHED_FIFO: 209917e476dSPeter Dufault case SCHED_RR: 210917e476dSPeter Dufault *ret = RTP_PRIO_MAX; 211917e476dSPeter Dufault break; 212917e476dSPeter Dufault 213917e476dSPeter Dufault case SCHED_OTHER: 214917e476dSPeter Dufault *ret = PRIO_MAX; 215917e476dSPeter Dufault break; 216917e476dSPeter Dufault 217917e476dSPeter Dufault default: 218917e476dSPeter Dufault e = EINVAL; 219917e476dSPeter Dufault } 220917e476dSPeter Dufault 221917e476dSPeter Dufault return e; 222917e476dSPeter Dufault } 223917e476dSPeter Dufault 224917e476dSPeter Dufault int ksched_get_priority_min(int *ret, void *hook, int policy) 225917e476dSPeter Dufault { 226917e476dSPeter Dufault int e = 0; 227917e476dSPeter Dufault 228917e476dSPeter Dufault switch (policy) 229917e476dSPeter Dufault { 230917e476dSPeter Dufault case SCHED_FIFO: 231917e476dSPeter Dufault case SCHED_RR: 232917e476dSPeter Dufault *ret = RTP_PRIO_MIN; 233917e476dSPeter Dufault break; 234917e476dSPeter Dufault 235917e476dSPeter Dufault case SCHED_OTHER: 236917e476dSPeter Dufault *ret = PRIO_MIN; 237917e476dSPeter Dufault break; 238917e476dSPeter Dufault 239917e476dSPeter Dufault default: 240917e476dSPeter Dufault e = EINVAL; 241917e476dSPeter Dufault } 242917e476dSPeter Dufault 243917e476dSPeter Dufault return e; 244917e476dSPeter Dufault } 245917e476dSPeter Dufault 246917e476dSPeter Dufault int ksched_rr_get_interval(int *ret, void *hook, 247917e476dSPeter Dufault struct proc *p, struct timespec *timespec) 248917e476dSPeter Dufault { 249917e476dSPeter Dufault *timespec = rr_interval; 250917e476dSPeter Dufault 251917e476dSPeter Dufault return 0; 252917e476dSPeter Dufault } 253