ksched.c revision 72376
1/* 2 * Copyright (c) 1996, 1997 3 * HD Associates, Inc. All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 3. All advertising materials mentioning features or use of this software 14 * must display the following acknowledgement: 15 * This product includes software developed by HD Associates, Inc 16 * 4. Neither the name of the author nor the names of any co-contributors 17 * may be used to endorse or promote products derived from this software 18 * without specific prior written permission. 19 * 20 * THIS SOFTWARE IS PROVIDED BY HD ASSOCIATES AND CONTRIBUTORS ``AS IS'' AND 21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23 * ARE DISCLAIMED. IN NO EVENT SHALL HD ASSOCIATES OR CONTRIBUTORS BE LIABLE 24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 30 * SUCH DAMAGE. 31 * 32 * $FreeBSD: head/sys/kern/ksched.c 72376 2001-02-12 00:20:08Z jake $ 33 */ 34 35/* ksched: Soft real time scheduling based on "rtprio". 36 */ 37 38#include <sys/param.h> 39#include <sys/systm.h> 40#include <sys/proc.h> 41#include <sys/resource.h> 42#include <machine/cpu.h> /* For need_resched */ 43#include <machine/ipl.h> /* For need_resched */ 44 45#include <posix4/posix4.h> 46 47/* ksched: Real-time extension to support POSIX priority scheduling. 48 */ 49 50struct ksched { 51 struct timespec rr_interval; 52}; 53 54int ksched_attach(struct ksched **p) 55{ 56 struct ksched *ksched= p31b_malloc(sizeof(*ksched)); 57 58 ksched->rr_interval.tv_sec = 0; 59 ksched->rr_interval.tv_nsec = 1000000000L / roundrobin_interval(); 60 61 *p = ksched; 62 return 0; 63} 64 65int ksched_detach(struct ksched *p) 66{ 67 p31b_free(p); 68 69 return 0; 70} 71 72/* 73 * XXX About priorities 74 * 75 * POSIX 1003.1b requires that numerically higher priorities be of 76 * higher priority. It also permits sched_setparam to be 77 * implementation defined for SCHED_OTHER. I don't like 78 * the notion of inverted priorites for normal processes when 79 * you can use "setpriority" for that. 80 * 81 * I'm rejecting sched_setparam for SCHED_OTHER with EINVAL. 82 */ 83 84/* Macros to convert between the unix (lower numerically is higher priority) 85 * and POSIX 1003.1b (higher numerically is higher priority) 86 */ 87 88#define p4prio_to_rtpprio(P) (RTP_PRIO_MAX - (P)) 89#define rtpprio_to_p4prio(P) (RTP_PRIO_MAX - (P)) 90 91/* These improve readability a bit for me: 92 */ 93#define P1B_PRIO_MIN rtpprio_to_p4prio(RTP_PRIO_MAX) 94#define P1B_PRIO_MAX rtpprio_to_p4prio(RTP_PRIO_MIN) 95 96static __inline int 97getscheduler(register_t *ret, struct ksched *ksched, struct proc *p) 98{ 99 struct rtprio rtp; 100 int e = 0; 101 102 pri_to_rtp(&p->p_pri, &rtp); 103 switch (rtp.type) 104 { 105 case RTP_PRIO_FIFO: 106 *ret = SCHED_FIFO; 107 break; 108 109 case RTP_PRIO_REALTIME: 110 *ret = SCHED_RR; 111 break; 112 113 default: 114 *ret = SCHED_OTHER; 115 break; 116 } 117 118 return e; 119} 120 121int ksched_setparam(register_t *ret, struct ksched *ksched, 122 struct proc *p, const struct sched_param *param) 123{ 124 register_t policy; 125 int e; 126 127 e = getscheduler(&policy, ksched, p); 128 129 if (e == 0) 130 { 131 if (policy == SCHED_OTHER) 132 e = EINVAL; 133 else 134 e = ksched_setscheduler(ret, ksched, p, policy, param); 135 } 136 137 return e; 138} 139 140int ksched_getparam(register_t *ret, struct ksched *ksched, 141 struct proc *p, struct sched_param *param) 142{ 143 struct rtprio rtp; 144 145 pri_to_rtp(&p->p_pri, &rtp); 146 if (RTP_PRIO_IS_REALTIME(rtp.type)) 147 param->sched_priority = rtpprio_to_p4prio(rtp.prio); 148 149 return 0; 150} 151 152/* 153 * XXX The priority and scheduler modifications should 154 * be moved into published interfaces in kern/kern_sync. 155 * 156 * The permissions to modify process p were checked in "p31b_proc()". 157 * 158 */ 159int ksched_setscheduler(register_t *ret, struct ksched *ksched, 160 struct proc *p, int policy, const struct sched_param *param) 161{ 162 int e = 0; 163 struct rtprio rtp; 164 165 switch(policy) 166 { 167 case SCHED_RR: 168 case SCHED_FIFO: 169 170 if (param->sched_priority >= P1B_PRIO_MIN && 171 param->sched_priority <= P1B_PRIO_MAX) 172 { 173 rtp.prio = p4prio_to_rtpprio(param->sched_priority); 174 rtp.type = (policy == SCHED_FIFO) 175 ? RTP_PRIO_FIFO : RTP_PRIO_REALTIME; 176 177 rtp_to_pri(&rtp, &p->p_pri); 178 need_resched(); 179 } 180 else 181 e = EPERM; 182 183 184 break; 185 186 case SCHED_OTHER: 187 { 188 rtp.type = RTP_PRIO_NORMAL; 189 rtp.prio = p4prio_to_rtpprio(param->sched_priority); 190 rtp_to_pri(&rtp, &p->p_pri); 191 192 /* XXX Simply revert to whatever we had for last 193 * normal scheduler priorities. 194 * This puts a requirement 195 * on the scheduling code: You must leave the 196 * scheduling info alone. 197 */ 198 need_resched(); 199 } 200 break; 201 } 202 203 return e; 204} 205 206int ksched_getscheduler(register_t *ret, struct ksched *ksched, struct proc *p) 207{ 208 return getscheduler(ret, ksched, p); 209} 210 211/* ksched_yield: Yield the CPU. 212 */ 213int ksched_yield(register_t *ret, struct ksched *ksched) 214{ 215 need_resched(); 216 return 0; 217} 218 219int ksched_get_priority_max(register_t*ret, struct ksched *ksched, int policy) 220{ 221 int e = 0; 222 223 switch (policy) 224 { 225 case SCHED_FIFO: 226 case SCHED_RR: 227 *ret = RTP_PRIO_MAX; 228 break; 229 230 case SCHED_OTHER: 231 *ret = PRIO_MAX; 232 break; 233 234 default: 235 e = EINVAL; 236 } 237 238 return e; 239} 240 241int ksched_get_priority_min(register_t *ret, struct ksched *ksched, int policy) 242{ 243 int e = 0; 244 245 switch (policy) 246 { 247 case SCHED_FIFO: 248 case SCHED_RR: 249 *ret = P1B_PRIO_MIN; 250 break; 251 252 case SCHED_OTHER: 253 *ret = PRIO_MIN; 254 break; 255 256 default: 257 e = EINVAL; 258 } 259 260 return e; 261} 262 263int ksched_rr_get_interval(register_t *ret, struct ksched *ksched, 264 struct proc *p, struct timespec *timespec) 265{ 266 *timespec = ksched->rr_interval; 267 268 return 0; 269} 270