160727d8bSWarner Losh /*- 28a6472b7SPeter Dufault * Copyright (c) 1996, 1997, 1998 38a6472b7SPeter Dufault * HD Associates, Inc. All rights reserved. 48a6472b7SPeter Dufault * 58a6472b7SPeter Dufault * Redistribution and use in source and binary forms, with or without 68a6472b7SPeter Dufault * modification, are permitted provided that the following conditions 78a6472b7SPeter Dufault * are met: 88a6472b7SPeter Dufault * 1. Redistributions of source code must retain the above copyright 98a6472b7SPeter Dufault * notice, this list of conditions and the following disclaimer. 108a6472b7SPeter Dufault * 2. Redistributions in binary form must reproduce the above copyright 118a6472b7SPeter Dufault * notice, this list of conditions and the following disclaimer in the 128a6472b7SPeter Dufault * documentation and/or other materials provided with the distribution. 138a6472b7SPeter Dufault * 3. All advertising materials mentioning features or use of this software 148a6472b7SPeter Dufault * must display the following acknowledgement: 158a6472b7SPeter Dufault * This product includes software developed by HD Associates, Inc 168a6472b7SPeter Dufault * 4. Neither the name of the author nor the names of any co-contributors 178a6472b7SPeter Dufault * may be used to endorse or promote products derived from this software 188a6472b7SPeter Dufault * without specific prior written permission. 198a6472b7SPeter Dufault * 208a6472b7SPeter Dufault * THIS SOFTWARE IS PROVIDED BY HD ASSOCIATES AND CONTRIBUTORS ``AS IS'' AND 218a6472b7SPeter Dufault * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 228a6472b7SPeter Dufault * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 238a6472b7SPeter Dufault * ARE DISCLAIMED. IN NO EVENT SHALL HD ASSOCIATES OR CONTRIBUTORS BE LIABLE 248a6472b7SPeter Dufault * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 258a6472b7SPeter Dufault * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 268a6472b7SPeter Dufault * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 278a6472b7SPeter Dufault * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 288a6472b7SPeter Dufault * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 298a6472b7SPeter Dufault * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 308a6472b7SPeter Dufault * SUCH DAMAGE. 318a6472b7SPeter Dufault */ 328a6472b7SPeter Dufault 338a6472b7SPeter Dufault /* p1003_1b: Real Time common code. 348a6472b7SPeter Dufault */ 358a6472b7SPeter Dufault 36f4636c59SDavid E. O'Brien #include <sys/cdefs.h> 37f4636c59SDavid E. O'Brien __FBSDID("$FreeBSD$"); 38f4636c59SDavid E. O'Brien 39b565fb9eSAlfred Perlstein #include "opt_posix.h" 40b565fb9eSAlfred Perlstein 418a6472b7SPeter Dufault #include <sys/param.h> 428a6472b7SPeter Dufault #include <sys/systm.h> 438a6472b7SPeter Dufault #include <sys/kernel.h> 44fb919e4dSMark Murray #include <sys/lock.h> 458a6472b7SPeter Dufault #include <sys/module.h> 46fb919e4dSMark Murray #include <sys/mutex.h> 47acd3428bSRobert Watson #include <sys/priv.h> 48fb919e4dSMark Murray #include <sys/proc.h> 49bdd04ab1STom Rhodes #include <sys/posix4.h> 50fe24ab5fSJohn Baldwin #include <sys/syscallsubr.h> 518a6472b7SPeter Dufault #include <sys/sysctl.h> 52fb919e4dSMark Murray #include <sys/sysent.h> 53fb919e4dSMark Murray #include <sys/syslog.h> 54fb919e4dSMark Murray #include <sys/sysproto.h> 558a6472b7SPeter Dufault 568a6472b7SPeter Dufault MALLOC_DEFINE(M_P31B, "p1003.1b", "Posix 1003.1B"); 578a6472b7SPeter Dufault 58873fbcd7SRobert Watson /* The system calls return ENOSYS if an entry is called that is not run-time 59873fbcd7SRobert Watson * supported. I am also logging since some programs start to use this when 60873fbcd7SRobert Watson * they shouldn't. That will be removed if annoying. 612a61a110SPeter Dufault */ 628a6472b7SPeter Dufault int 63b40ce416SJulian Elischer syscall_not_present(struct thread *td, const char *s, struct nosys_args *uap) 648a6472b7SPeter Dufault { 658a6472b7SPeter Dufault log(LOG_ERR, "cmd %s pid %d tried to use non-present %s\n", 66431f8906SJulian Elischer td->td_name, td->td_proc->p_pid, s); 672a61a110SPeter Dufault 682a61a110SPeter Dufault /* a " return nosys(p, uap); " here causes a core dump. 692a61a110SPeter Dufault */ 702a61a110SPeter Dufault 712a61a110SPeter Dufault return ENOSYS; 728a6472b7SPeter Dufault } 738a6472b7SPeter Dufault 748a6472b7SPeter Dufault #if !defined(_KPOSIX_PRIORITY_SCHEDULING) 758a6472b7SPeter Dufault 76e9189611SPeter Wemm /* Not configured but loadable via a module: 778a6472b7SPeter Dufault */ 788a6472b7SPeter Dufault 79f6c040a2SDavid Xu static int 80f6c040a2SDavid Xu sched_attach(void) 818a6472b7SPeter Dufault { 828a6472b7SPeter Dufault return 0; 838a6472b7SPeter Dufault } 848a6472b7SPeter Dufault 858a6472b7SPeter Dufault SYSCALL_NOT_PRESENT_GEN(sched_setparam) 868a6472b7SPeter Dufault SYSCALL_NOT_PRESENT_GEN(sched_getparam) 878a6472b7SPeter Dufault SYSCALL_NOT_PRESENT_GEN(sched_setscheduler) 888a6472b7SPeter Dufault SYSCALL_NOT_PRESENT_GEN(sched_getscheduler) 898a6472b7SPeter Dufault SYSCALL_NOT_PRESENT_GEN(sched_yield) 908a6472b7SPeter Dufault SYSCALL_NOT_PRESENT_GEN(sched_get_priority_max) 918a6472b7SPeter Dufault SYSCALL_NOT_PRESENT_GEN(sched_get_priority_min) 928a6472b7SPeter Dufault SYSCALL_NOT_PRESENT_GEN(sched_rr_get_interval) 938a6472b7SPeter Dufault #else 948a6472b7SPeter Dufault 958a6472b7SPeter Dufault /* Configured in kernel version: 968a6472b7SPeter Dufault */ 978a6472b7SPeter Dufault static struct ksched *ksched; 988a6472b7SPeter Dufault 99f6c040a2SDavid Xu static int 100f6c040a2SDavid Xu sched_attach(void) 1018a6472b7SPeter Dufault { 1028a6472b7SPeter Dufault int ret = ksched_attach(&ksched); 1038a6472b7SPeter Dufault 1048a6472b7SPeter Dufault if (ret == 0) 10534c1c599SJohn Baldwin p31b_setcfg(CTL_P1003_1B_PRIORITY_SCHEDULING, 200112L); 1068a6472b7SPeter Dufault 1078a6472b7SPeter Dufault return ret; 1088a6472b7SPeter Dufault } 1098a6472b7SPeter Dufault 110f6c040a2SDavid Xu int 111*8451d0ddSKip Macy sys_sched_setparam(struct thread *td, struct sched_setparam_args *uap) 1128a6472b7SPeter Dufault { 113b40ce416SJulian Elischer struct thread *targettd; 1141af55356SRobert Watson struct proc *targetp; 1158a6472b7SPeter Dufault int e; 116aebde782SPeter Dufault struct sched_param sched_param; 1172afac34dSMatthew Dillon 118e8f7a952SRobert Watson e = copyin(uap->param, &sched_param, sizeof(sched_param)); 119e8f7a952SRobert Watson if (e) 120e8f7a952SRobert Watson return (e); 121aebde782SPeter Dufault 122e84b7987SRobert Watson if (uap->pid == 0) { 123b40ce416SJulian Elischer targetp = td->td_proc; 124b40ce416SJulian Elischer targettd = td; 125e84b7987SRobert Watson PROC_LOCK(targetp); 12624af5900SDavid Xu } else { 127e84b7987SRobert Watson targetp = pfind(uap->pid); 12865343c78SDavid Xu if (targetp == NULL) 12965343c78SDavid Xu return (ESRCH); 13065343c78SDavid Xu targettd = FIRST_THREAD_IN_PROC(targetp); 131e84b7987SRobert Watson } 132e84b7987SRobert Watson 133f44d9e24SJohn Baldwin e = p_cansched(td, targetp); 1342afac34dSMatthew Dillon if (e == 0) { 13565343c78SDavid Xu e = ksched_setparam(ksched, targettd, 13664e55bf4SRobert Watson (const struct sched_param *)&sched_param); 1372afac34dSMatthew Dillon } 138e631cff3SDavid Xu PROC_UNLOCK(targetp); 13964e55bf4SRobert Watson return (e); 1408a6472b7SPeter Dufault } 1418a6472b7SPeter Dufault 142f6c040a2SDavid Xu int 143*8451d0ddSKip Macy sys_sched_getparam(struct thread *td, struct sched_getparam_args *uap) 1448a6472b7SPeter Dufault { 1458a6472b7SPeter Dufault int e; 146aebde782SPeter Dufault struct sched_param sched_param; 147b40ce416SJulian Elischer struct thread *targettd; 1481af55356SRobert Watson struct proc *targetp; 1498a6472b7SPeter Dufault 150e84b7987SRobert Watson if (uap->pid == 0) { 151b40ce416SJulian Elischer targetp = td->td_proc; 152b40ce416SJulian Elischer targettd = td; 153e84b7987SRobert Watson PROC_LOCK(targetp); 15424af5900SDavid Xu } else { 155e84b7987SRobert Watson targetp = pfind(uap->pid); 1562afac34dSMatthew Dillon if (targetp == NULL) { 15765343c78SDavid Xu return (ESRCH); 1582afac34dSMatthew Dillon } 1596617724cSJeff Roberson targettd = FIRST_THREAD_IN_PROC(targetp); 160e84b7987SRobert Watson } 161e84b7987SRobert Watson 162f44d9e24SJohn Baldwin e = p_cansee(td, targetp); 163e631cff3SDavid Xu if (e == 0) { 16465343c78SDavid Xu e = ksched_getparam(ksched, targettd, &sched_param); 165e631cff3SDavid Xu } 166e84b7987SRobert Watson PROC_UNLOCK(targetp); 1672afac34dSMatthew Dillon if (e == 0) 16864e55bf4SRobert Watson e = copyout(&sched_param, uap->param, sizeof(sched_param)); 16964e55bf4SRobert Watson return (e); 1708a6472b7SPeter Dufault } 171b40ce416SJulian Elischer 172f6c040a2SDavid Xu int 173*8451d0ddSKip Macy sys_sched_setscheduler(struct thread *td, struct sched_setscheduler_args *uap) 1748a6472b7SPeter Dufault { 1758a6472b7SPeter Dufault int e; 176aebde782SPeter Dufault struct sched_param sched_param; 177b40ce416SJulian Elischer struct thread *targettd; 1781af55356SRobert Watson struct proc *targetp; 1791af55356SRobert Watson 180acd3428bSRobert Watson /* Don't allow non root user to set a scheduler policy. */ 181acd3428bSRobert Watson e = priv_check(td, PRIV_SCHED_SET); 182acd3428bSRobert Watson if (e) 183acd3428bSRobert Watson return (e); 184f705bbe8SDavid Xu 185e8f7a952SRobert Watson e = copyin(uap->param, &sched_param, sizeof(sched_param)); 186e8f7a952SRobert Watson if (e) 187e8f7a952SRobert Watson return (e); 188aebde782SPeter Dufault 189e84b7987SRobert Watson if (uap->pid == 0) { 190b40ce416SJulian Elischer targetp = td->td_proc; 191b40ce416SJulian Elischer targettd = td; 192e84b7987SRobert Watson PROC_LOCK(targetp); 19324af5900SDavid Xu } else { 194e84b7987SRobert Watson targetp = pfind(uap->pid); 19565343c78SDavid Xu if (targetp == NULL) 19665343c78SDavid Xu return (ESRCH); 19765343c78SDavid Xu targettd = FIRST_THREAD_IN_PROC(targetp); 198e84b7987SRobert Watson } 199e84b7987SRobert Watson 200f44d9e24SJohn Baldwin e = p_cansched(td, targetp); 2012afac34dSMatthew Dillon if (e == 0) { 20265343c78SDavid Xu e = ksched_setscheduler(ksched, targettd, 203b40ce416SJulian Elischer uap->policy, (const struct sched_param *)&sched_param); 2042afac34dSMatthew Dillon } 205e631cff3SDavid Xu PROC_UNLOCK(targetp); 20664e55bf4SRobert Watson return (e); 2078a6472b7SPeter Dufault } 208b40ce416SJulian Elischer 209f6c040a2SDavid Xu int 210*8451d0ddSKip Macy sys_sched_getscheduler(struct thread *td, struct sched_getscheduler_args *uap) 2118a6472b7SPeter Dufault { 21265343c78SDavid Xu int e, policy; 213b40ce416SJulian Elischer struct thread *targettd; 2141af55356SRobert Watson struct proc *targetp; 2158a6472b7SPeter Dufault 216e84b7987SRobert Watson if (uap->pid == 0) { 217b40ce416SJulian Elischer targetp = td->td_proc; 218b40ce416SJulian Elischer targettd = td; 219e84b7987SRobert Watson PROC_LOCK(targetp); 22024af5900SDavid Xu } else { 221e84b7987SRobert Watson targetp = pfind(uap->pid); 222931e4573SDavid Xu if (targetp == NULL) 223931e4573SDavid Xu return (ESRCH); 2246617724cSJeff Roberson targettd = FIRST_THREAD_IN_PROC(targetp); 225e84b7987SRobert Watson } 226e84b7987SRobert Watson 227f44d9e24SJohn Baldwin e = p_cansee(td, targetp); 22865343c78SDavid Xu if (e == 0) { 22965343c78SDavid Xu e = ksched_getscheduler(ksched, targettd, &policy); 23065343c78SDavid Xu td->td_retval[0] = policy; 23165343c78SDavid Xu } 232e631cff3SDavid Xu PROC_UNLOCK(targetp); 23364e55bf4SRobert Watson 23464e55bf4SRobert Watson return (e); 2358a6472b7SPeter Dufault } 236b40ce416SJulian Elischer 237f6c040a2SDavid Xu int 238*8451d0ddSKip Macy sys_sched_yield(struct thread *td, struct sched_yield_args *uap) 2398a6472b7SPeter Dufault { 2402afac34dSMatthew Dillon 24105dc0eb2SJeff Roberson sched_relinquish(curthread); 24205dc0eb2SJeff Roberson return 0; 2438a6472b7SPeter Dufault } 244b40ce416SJulian Elischer 245f6c040a2SDavid Xu int 246*8451d0ddSKip Macy sys_sched_get_priority_max(struct thread *td, 2478a6472b7SPeter Dufault struct sched_get_priority_max_args *uap) 2488a6472b7SPeter Dufault { 24965343c78SDavid Xu int error, prio; 2502afac34dSMatthew Dillon 25165343c78SDavid Xu error = ksched_get_priority_max(ksched, uap->policy, &prio); 25265343c78SDavid Xu td->td_retval[0] = prio; 2532afac34dSMatthew Dillon return (error); 2548a6472b7SPeter Dufault } 255b40ce416SJulian Elischer 256f6c040a2SDavid Xu int 257*8451d0ddSKip Macy sys_sched_get_priority_min(struct thread *td, 2588a6472b7SPeter Dufault struct sched_get_priority_min_args *uap) 2598a6472b7SPeter Dufault { 26065343c78SDavid Xu int error, prio; 261b40ce416SJulian Elischer 26265343c78SDavid Xu error = ksched_get_priority_min(ksched, uap->policy, &prio); 26365343c78SDavid Xu td->td_retval[0] = prio; 2642afac34dSMatthew Dillon return (error); 2658a6472b7SPeter Dufault } 266b40ce416SJulian Elischer 267f6c040a2SDavid Xu int 268*8451d0ddSKip Macy sys_sched_rr_get_interval(struct thread *td, 2698a6472b7SPeter Dufault struct sched_rr_get_interval_args *uap) 2708a6472b7SPeter Dufault { 271fe24ab5fSJohn Baldwin struct timespec timespec; 272fe24ab5fSJohn Baldwin int error; 273fe24ab5fSJohn Baldwin 274fe24ab5fSJohn Baldwin error = kern_sched_rr_get_interval(td, uap->pid, ×pec); 275fe24ab5fSJohn Baldwin if (error == 0) 276fe24ab5fSJohn Baldwin error = copyout(×pec, uap->interval, sizeof(timespec)); 277fe24ab5fSJohn Baldwin return (error); 278fe24ab5fSJohn Baldwin } 279fe24ab5fSJohn Baldwin 280f6c040a2SDavid Xu int 281f6c040a2SDavid Xu kern_sched_rr_get_interval(struct thread *td, pid_t pid, 282fe24ab5fSJohn Baldwin struct timespec *ts) 283fe24ab5fSJohn Baldwin { 2848a6472b7SPeter Dufault int e; 285b40ce416SJulian Elischer struct thread *targettd; 2861af55356SRobert Watson struct proc *targetp; 2878a6472b7SPeter Dufault 288fe24ab5fSJohn Baldwin if (pid == 0) { 289b40ce416SJulian Elischer targettd = td; 290b40ce416SJulian Elischer targetp = td->td_proc; 291e84b7987SRobert Watson PROC_LOCK(targetp); 29265343c78SDavid Xu } else { 293931e4573SDavid Xu targetp = pfind(pid); 294931e4573SDavid Xu if (targetp == NULL) 29565343c78SDavid Xu return (ESRCH); 296931e4573SDavid Xu targettd = FIRST_THREAD_IN_PROC(targetp); 297e84b7987SRobert Watson } 298e84b7987SRobert Watson 299f44d9e24SJohn Baldwin e = p_cansee(td, targetp); 300a11acc6fSAlfred Perlstein if (e == 0) 30165343c78SDavid Xu e = ksched_rr_get_interval(ksched, targettd, ts); 302fe24ab5fSJohn Baldwin PROC_UNLOCK(targetp); 30364e55bf4SRobert Watson return (e); 3048a6472b7SPeter Dufault } 3058a6472b7SPeter Dufault 3068a6472b7SPeter Dufault #endif 3078a6472b7SPeter Dufault 308f6c040a2SDavid Xu static void 309f6c040a2SDavid Xu p31binit(void *notused) 3108a6472b7SPeter Dufault { 3118a6472b7SPeter Dufault (void) sched_attach(); 312ce47711dSPeter Dufault p31b_setcfg(CTL_P1003_1B_PAGESIZE, PAGE_SIZE); 3138a6472b7SPeter Dufault } 3148a6472b7SPeter Dufault 3158a6472b7SPeter Dufault SYSINIT(p31b, SI_SUB_P1003_1B, SI_ORDER_FIRST, p31binit, NULL); 316