1139825Simp/*- 234925Sdufault * Copyright (c) 1996, 1997, 1998 334925Sdufault * HD Associates, Inc. All rights reserved. 434925Sdufault * 534925Sdufault * Redistribution and use in source and binary forms, with or without 634925Sdufault * modification, are permitted provided that the following conditions 734925Sdufault * are met: 834925Sdufault * 1. Redistributions of source code must retain the above copyright 934925Sdufault * notice, this list of conditions and the following disclaimer. 1034925Sdufault * 2. Redistributions in binary form must reproduce the above copyright 1134925Sdufault * notice, this list of conditions and the following disclaimer in the 1234925Sdufault * documentation and/or other materials provided with the distribution. 1334925Sdufault * 3. All advertising materials mentioning features or use of this software 1434925Sdufault * must display the following acknowledgement: 1534925Sdufault * This product includes software developed by HD Associates, Inc 1634925Sdufault * 4. Neither the name of the author nor the names of any co-contributors 1734925Sdufault * may be used to endorse or promote products derived from this software 1834925Sdufault * without specific prior written permission. 1934925Sdufault * 2034925Sdufault * THIS SOFTWARE IS PROVIDED BY HD ASSOCIATES AND CONTRIBUTORS ``AS IS'' AND 2134925Sdufault * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 2234925Sdufault * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2334925Sdufault * ARE DISCLAIMED. IN NO EVENT SHALL HD ASSOCIATES OR CONTRIBUTORS BE LIABLE 2434925Sdufault * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2534925Sdufault * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2634925Sdufault * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2734925Sdufault * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2834925Sdufault * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2934925Sdufault * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 3034925Sdufault * SUCH DAMAGE. 3134925Sdufault */ 3234925Sdufault 3334925Sdufault/* p1003_1b: Real Time common code. 3434925Sdufault */ 3534925Sdufault 36116192Sobrien#include <sys/cdefs.h> 37116192Sobrien__FBSDID("$FreeBSD$"); 38116192Sobrien 39106969Salfred#include "opt_posix.h" 40106969Salfred 4134925Sdufault#include <sys/param.h> 4234925Sdufault#include <sys/systm.h> 4334925Sdufault#include <sys/kernel.h> 4476166Smarkm#include <sys/lock.h> 4576166Smarkm#include <sys/module.h> 4676166Smarkm#include <sys/mutex.h> 47164033Srwatson#include <sys/priv.h> 4876166Smarkm#include <sys/proc.h> 49164183Strhodes#include <sys/posix4.h> 50144447Sjhb#include <sys/syscallsubr.h> 5176166Smarkm#include <sys/sysctl.h> 5234925Sdufault#include <sys/sysent.h> 5334925Sdufault#include <sys/syslog.h> 5434925Sdufault#include <sys/sysproto.h> 5534925Sdufault 5634925SdufaultMALLOC_DEFINE(M_P31B, "p1003.1b", "Posix 1003.1B"); 5734925Sdufault 58167232Srwatson/* The system calls return ENOSYS if an entry is called that is not run-time 59167232Srwatson * supported. I am also logging since some programs start to use this when 60167232Srwatson * they shouldn't. That will be removed if annoying. 6136155Sdufault */ 6234925Sdufaultint 6383366Sjuliansyscall_not_present(struct thread *td, const char *s, struct nosys_args *uap) 6434925Sdufault{ 6534925Sdufault log(LOG_ERR, "cmd %s pid %d tried to use non-present %s\n", 66173600Sjulian td->td_name, td->td_proc->p_pid, s); 6736155Sdufault 6836155Sdufault /* a " return nosys(p, uap); " here causes a core dump. 6936155Sdufault */ 7036155Sdufault 7136155Sdufault return ENOSYS; 7234925Sdufault} 7334925Sdufault 7434925Sdufault#if !defined(_KPOSIX_PRIORITY_SCHEDULING) 7534925Sdufault 7645739Speter/* Not configured but loadable via a module: 7734925Sdufault */ 7834925Sdufault 79158745Sdavidxustatic int 80158745Sdavidxusched_attach(void) 8134925Sdufault{ 8234925Sdufault return 0; 8334925Sdufault} 8434925Sdufault 8534925SdufaultSYSCALL_NOT_PRESENT_GEN(sched_setparam) 8634925SdufaultSYSCALL_NOT_PRESENT_GEN(sched_getparam) 8734925SdufaultSYSCALL_NOT_PRESENT_GEN(sched_setscheduler) 8834925SdufaultSYSCALL_NOT_PRESENT_GEN(sched_getscheduler) 8934925SdufaultSYSCALL_NOT_PRESENT_GEN(sched_yield) 9034925SdufaultSYSCALL_NOT_PRESENT_GEN(sched_get_priority_max) 9134925SdufaultSYSCALL_NOT_PRESENT_GEN(sched_get_priority_min) 9234925SdufaultSYSCALL_NOT_PRESENT_GEN(sched_rr_get_interval) 9334925Sdufault#else 9434925Sdufault 9534925Sdufault/* Configured in kernel version: 9634925Sdufault */ 9734925Sdufaultstatic struct ksched *ksched; 9834925Sdufault 99158745Sdavidxustatic int 100158745Sdavidxusched_attach(void) 10134925Sdufault{ 10234925Sdufault int ret = ksched_attach(&ksched); 10334925Sdufault 10434925Sdufault if (ret == 0) 105215540Sjhb p31b_setcfg(CTL_P1003_1B_PRIORITY_SCHEDULING, 200112L); 10634925Sdufault 10734925Sdufault return ret; 10834925Sdufault} 10934925Sdufault 110158745Sdavidxuint 111225617Skmacysys_sched_setparam(struct thread *td, struct sched_setparam_args *uap) 11234925Sdufault{ 11383366Sjulian struct thread *targettd; 11479004Srwatson struct proc *targetp; 11534925Sdufault int e; 11682701Sdillon struct sched_param sched_param; 11734925Sdufault 11878943Srwatson e = copyin(uap->param, &sched_param, sizeof(sched_param)); 11978943Srwatson if (e) 12078943Srwatson return (e); 12136218Sdufault 12279020Srwatson if (uap->pid == 0) { 12383366Sjulian targetp = td->td_proc; 12483366Sjulian targettd = td; 12579020Srwatson PROC_LOCK(targetp); 126160322Sdavidxu } else { 127160257Sdavidxu targetp = pfind(uap->pid); 128160257Sdavidxu if (targetp == NULL) 129160257Sdavidxu return (ESRCH); 130160257Sdavidxu targettd = FIRST_THREAD_IN_PROC(targetp); 13179020Srwatson } 13279020Srwatson 133293485Sdchagin e = kern_sched_setparam(td, targettd, &sched_param); 134157623Sdavidxu PROC_UNLOCK(targetp); 13578944Srwatson return (e); 13634925Sdufault} 13734925Sdufault 138158745Sdavidxuint 139293485Sdchaginkern_sched_setparam(struct thread *td, struct thread *targettd, 140293485Sdchagin struct sched_param *param) 141293485Sdchagin{ 142293485Sdchagin struct proc *targetp; 143293485Sdchagin int error; 144293485Sdchagin 145293485Sdchagin targetp = targettd->td_proc; 146293485Sdchagin PROC_LOCK_ASSERT(targetp, MA_OWNED); 147293485Sdchagin 148293485Sdchagin error = p_cansched(td, targetp); 149293485Sdchagin if (error == 0) 150293485Sdchagin error = ksched_setparam(ksched, targettd, 151293485Sdchagin (const struct sched_param *)param); 152293485Sdchagin return (error); 153293485Sdchagin} 154293485Sdchagin 155293485Sdchaginint 156225617Skmacysys_sched_getparam(struct thread *td, struct sched_getparam_args *uap) 15734925Sdufault{ 15834925Sdufault int e; 15936218Sdufault struct sched_param sched_param; 16083366Sjulian struct thread *targettd; 16179004Srwatson struct proc *targetp; 16234925Sdufault 16379020Srwatson if (uap->pid == 0) { 16483366Sjulian targetp = td->td_proc; 16583366Sjulian targettd = td; 16679020Srwatson PROC_LOCK(targetp); 167160322Sdavidxu } else { 16879020Srwatson targetp = pfind(uap->pid); 16982701Sdillon if (targetp == NULL) { 170160257Sdavidxu return (ESRCH); 17182701Sdillon } 172177091Sjeff targettd = FIRST_THREAD_IN_PROC(targetp); 17379020Srwatson } 17479020Srwatson 175293485Sdchagin e = kern_sched_getparam(td, targettd, &sched_param); 17679020Srwatson PROC_UNLOCK(targetp); 17782701Sdillon if (e == 0) 17882701Sdillon e = copyout(&sched_param, uap->param, sizeof(sched_param)); 17978944Srwatson return (e); 18034925Sdufault} 18183366Sjulian 182158745Sdavidxuint 183293485Sdchaginkern_sched_getparam(struct thread *td, struct thread *targettd, 184293485Sdchagin struct sched_param *param) 185293485Sdchagin{ 186293485Sdchagin struct proc *targetp; 187293485Sdchagin int error; 188293485Sdchagin 189293485Sdchagin targetp = targettd->td_proc; 190293485Sdchagin PROC_LOCK_ASSERT(targetp, MA_OWNED); 191293485Sdchagin 192293485Sdchagin error = p_cansee(td, targetp); 193293485Sdchagin if (error == 0) 194293485Sdchagin error = ksched_getparam(ksched, targettd, param); 195293485Sdchagin return (error); 196293485Sdchagin} 197293485Sdchagin 198293485Sdchaginint 199225617Skmacysys_sched_setscheduler(struct thread *td, struct sched_setscheduler_args *uap) 20034925Sdufault{ 20134925Sdufault int e; 20279004Srwatson struct sched_param sched_param; 20383366Sjulian struct thread *targettd; 20479004Srwatson struct proc *targetp; 20536218Sdufault 20678943Srwatson e = copyin(uap->param, &sched_param, sizeof(sched_param)); 20778943Srwatson if (e) 20878943Srwatson return (e); 20936218Sdufault 21079020Srwatson if (uap->pid == 0) { 21183366Sjulian targetp = td->td_proc; 21283366Sjulian targettd = td; 21379020Srwatson PROC_LOCK(targetp); 214160322Sdavidxu } else { 215160257Sdavidxu targetp = pfind(uap->pid); 216160257Sdavidxu if (targetp == NULL) 217160257Sdavidxu return (ESRCH); 218160257Sdavidxu targettd = FIRST_THREAD_IN_PROC(targetp); 21979020Srwatson } 22079020Srwatson 221293485Sdchagin e = kern_sched_setscheduler(td, targettd, uap->policy, 222293485Sdchagin &sched_param); 223157623Sdavidxu PROC_UNLOCK(targetp); 22478944Srwatson return (e); 22534925Sdufault} 22683366Sjulian 227158745Sdavidxuint 228293485Sdchaginkern_sched_setscheduler(struct thread *td, struct thread *targettd, 229293485Sdchagin int policy, struct sched_param *param) 230293485Sdchagin{ 231293485Sdchagin struct proc *targetp; 232293485Sdchagin int error; 233293485Sdchagin 234293485Sdchagin targetp = targettd->td_proc; 235293485Sdchagin PROC_LOCK_ASSERT(targetp, MA_OWNED); 236293485Sdchagin 237293485Sdchagin /* Don't allow non root user to set a scheduler policy. */ 238293485Sdchagin error = priv_check(td, PRIV_SCHED_SET); 239293485Sdchagin if (error) 240293485Sdchagin return (error); 241293485Sdchagin 242293485Sdchagin error = p_cansched(td, targetp); 243293485Sdchagin if (error == 0) 244293485Sdchagin error = ksched_setscheduler(ksched, targettd, policy, 245293485Sdchagin (const struct sched_param *)param); 246293485Sdchagin return (error); 247293485Sdchagin} 248293485Sdchagin 249293485Sdchaginint 250225617Skmacysys_sched_getscheduler(struct thread *td, struct sched_getscheduler_args *uap) 25134925Sdufault{ 252160257Sdavidxu int e, policy; 25383366Sjulian struct thread *targettd; 25479004Srwatson struct proc *targetp; 25534925Sdufault 25679020Srwatson if (uap->pid == 0) { 25783366Sjulian targetp = td->td_proc; 25883366Sjulian targettd = td; 25979020Srwatson PROC_LOCK(targetp); 260160322Sdavidxu } else { 26179020Srwatson targetp = pfind(uap->pid); 262213258Sdavidxu if (targetp == NULL) 263213258Sdavidxu return (ESRCH); 264177091Sjeff targettd = FIRST_THREAD_IN_PROC(targetp); 26579020Srwatson } 26679020Srwatson 267293485Sdchagin e = kern_sched_getscheduler(td, targettd, &policy); 268293485Sdchagin PROC_UNLOCK(targetp); 269293485Sdchagin if (e == 0) 270160257Sdavidxu td->td_retval[0] = policy; 27179020Srwatson 27278944Srwatson return (e); 27334925Sdufault} 27483366Sjulian 275158745Sdavidxuint 276293485Sdchaginkern_sched_getscheduler(struct thread *td, struct thread *targettd, 277293485Sdchagin int *policy) 278293485Sdchagin{ 279293485Sdchagin struct proc *targetp; 280293485Sdchagin int error; 281293485Sdchagin 282293485Sdchagin targetp = targettd->td_proc; 283293485Sdchagin PROC_LOCK_ASSERT(targetp, MA_OWNED); 284293485Sdchagin 285293485Sdchagin error = p_cansee(td, targetp); 286293485Sdchagin if (error == 0) 287293485Sdchagin error = ksched_getscheduler(ksched, targettd, policy); 288293485Sdchagin return (error); 289293485Sdchagin} 290293485Sdchagin 291293485Sdchaginint 292225617Skmacysys_sched_yield(struct thread *td, struct sched_yield_args *uap) 29334925Sdufault{ 29482701Sdillon 295172483Sjeff sched_relinquish(curthread); 296172483Sjeff return 0; 29734925Sdufault} 29883366Sjulian 299158745Sdavidxuint 300225617Skmacysys_sched_get_priority_max(struct thread *td, 301158745Sdavidxu struct sched_get_priority_max_args *uap) 30234925Sdufault{ 303160257Sdavidxu int error, prio; 30482701Sdillon 305160257Sdavidxu error = ksched_get_priority_max(ksched, uap->policy, &prio); 306160257Sdavidxu td->td_retval[0] = prio; 30782701Sdillon return (error); 30834925Sdufault} 30983366Sjulian 310158745Sdavidxuint 311225617Skmacysys_sched_get_priority_min(struct thread *td, 312158745Sdavidxu struct sched_get_priority_min_args *uap) 31334925Sdufault{ 314160257Sdavidxu int error, prio; 31583366Sjulian 316160257Sdavidxu error = ksched_get_priority_min(ksched, uap->policy, &prio); 317160257Sdavidxu td->td_retval[0] = prio; 31882701Sdillon return (error); 31934925Sdufault} 32083366Sjulian 321158745Sdavidxuint 322225617Skmacysys_sched_rr_get_interval(struct thread *td, 323158745Sdavidxu struct sched_rr_get_interval_args *uap) 32434925Sdufault{ 325144447Sjhb struct timespec timespec; 326144447Sjhb int error; 327144447Sjhb 328144447Sjhb error = kern_sched_rr_get_interval(td, uap->pid, ×pec); 329144447Sjhb if (error == 0) 330144447Sjhb error = copyout(×pec, uap->interval, sizeof(timespec)); 331144447Sjhb return (error); 332144447Sjhb} 333144447Sjhb 334158745Sdavidxuint 335158745Sdavidxukern_sched_rr_get_interval(struct thread *td, pid_t pid, 336144447Sjhb struct timespec *ts) 337144447Sjhb{ 33834925Sdufault int e; 33983366Sjulian struct thread *targettd; 34079004Srwatson struct proc *targetp; 34134925Sdufault 342144447Sjhb if (pid == 0) { 34383366Sjulian targettd = td; 34483366Sjulian targetp = td->td_proc; 34579020Srwatson PROC_LOCK(targetp); 346160257Sdavidxu } else { 347213258Sdavidxu targetp = pfind(pid); 348213258Sdavidxu if (targetp == NULL) 349160257Sdavidxu return (ESRCH); 350213258Sdavidxu targettd = FIRST_THREAD_IN_PROC(targetp); 35179020Srwatson } 35279020Srwatson 353293482Sdchagin e = kern_sched_rr_get_interval_td(td, targettd, ts); 35479020Srwatson PROC_UNLOCK(targetp); 35578944Srwatson return (e); 35634925Sdufault} 35734925Sdufault 358293482Sdchaginint 359293482Sdchaginkern_sched_rr_get_interval_td(struct thread *td, struct thread *targettd, 360293482Sdchagin struct timespec *ts) 361293482Sdchagin{ 362293482Sdchagin struct proc *p; 363293482Sdchagin int error; 364293482Sdchagin 365293482Sdchagin p = targettd->td_proc; 366293482Sdchagin PROC_LOCK_ASSERT(p, MA_OWNED); 367293482Sdchagin 368293482Sdchagin error = p_cansee(td, p); 369293482Sdchagin if (error == 0) 370293482Sdchagin error = ksched_rr_get_interval(ksched, targettd, ts); 371293482Sdchagin return (error); 372293482Sdchagin} 37334925Sdufault#endif 37434925Sdufault 375158745Sdavidxustatic void 376158745Sdavidxup31binit(void *notused) 37734925Sdufault{ 37834925Sdufault (void) sched_attach(); 37936578Sdufault p31b_setcfg(CTL_P1003_1B_PAGESIZE, PAGE_SIZE); 38034925Sdufault} 38134925Sdufault 38234925SdufaultSYSINIT(p31b, SI_SUB_P1003_1B, SI_ORDER_FIRST, p31binit, NULL); 383