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> 47fb919e4dSMark Murray #include <sys/proc.h> 48fe24ab5fSJohn Baldwin #include <sys/syscallsubr.h> 498a6472b7SPeter Dufault #include <sys/sysctl.h> 50fb919e4dSMark Murray #include <sys/sysent.h> 51fb919e4dSMark Murray #include <sys/syslog.h> 52fb919e4dSMark Murray #include <sys/sysproto.h> 538a6472b7SPeter Dufault 548a6472b7SPeter Dufault #include <posix4/posix4.h> 558a6472b7SPeter Dufault 568a6472b7SPeter Dufault MALLOC_DEFINE(M_P31B, "p1003.1b", "Posix 1003.1B"); 578a6472b7SPeter Dufault 582a61a110SPeter Dufault /* The system calls return ENOSYS if an entry is called that is 592a61a110SPeter Dufault * not run-time supported. I am also logging since some programs 602a61a110SPeter Dufault * start to use this when 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", 66b40ce416SJulian Elischer td->td_proc->p_comm, 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 948a6472b7SPeter Dufault #else 958a6472b7SPeter Dufault 968a6472b7SPeter Dufault /* Configured in kernel version: 978a6472b7SPeter Dufault */ 988a6472b7SPeter Dufault static struct ksched *ksched; 998a6472b7SPeter Dufault 100f6c040a2SDavid Xu static int 101f6c040a2SDavid Xu sched_attach(void) 1028a6472b7SPeter Dufault { 1038a6472b7SPeter Dufault int ret = ksched_attach(&ksched); 1048a6472b7SPeter Dufault 1058a6472b7SPeter Dufault if (ret == 0) 1068a6472b7SPeter Dufault p31b_setcfg(CTL_P1003_1B_PRIORITY_SCHEDULING, 1); 1078a6472b7SPeter Dufault 1088a6472b7SPeter Dufault return ret; 1098a6472b7SPeter Dufault } 1108a6472b7SPeter Dufault 1112afac34dSMatthew Dillon /* 1122afac34dSMatthew Dillon * MPSAFE 1132afac34dSMatthew Dillon */ 114f6c040a2SDavid Xu int 115f6c040a2SDavid Xu sched_setparam(struct thread *td, struct sched_setparam_args *uap) 1168a6472b7SPeter Dufault { 117b40ce416SJulian Elischer struct thread *targettd; 1181af55356SRobert Watson struct proc *targetp; 1198a6472b7SPeter Dufault int e; 120aebde782SPeter Dufault struct sched_param sched_param; 1212afac34dSMatthew Dillon 122e8f7a952SRobert Watson e = copyin(uap->param, &sched_param, sizeof(sched_param)); 123e8f7a952SRobert Watson if (e) 124e8f7a952SRobert Watson return (e); 125aebde782SPeter Dufault 126e84b7987SRobert Watson if (uap->pid == 0) { 127b40ce416SJulian Elischer targetp = td->td_proc; 128b40ce416SJulian Elischer targettd = td; 129e84b7987SRobert Watson PROC_LOCK(targetp); 130e84b7987SRobert Watson } else { 131e84b7987SRobert Watson targetp = pfind(uap->pid); 1322afac34dSMatthew Dillon if (targetp == NULL) { 1332afac34dSMatthew Dillon e = ESRCH; 1342afac34dSMatthew Dillon goto done2; 1352afac34dSMatthew Dillon } 136079b7badSJulian Elischer targettd = FIRST_THREAD_IN_PROC(targetp); /* XXXKSE */ 137e84b7987SRobert Watson } 138e84b7987SRobert Watson 139f44d9e24SJohn Baldwin e = p_cansched(td, targetp); 1402afac34dSMatthew Dillon if (e == 0) { 141b40ce416SJulian Elischer e = ksched_setparam(&td->td_retval[0], ksched, targettd, 14264e55bf4SRobert Watson (const struct sched_param *)&sched_param); 1432afac34dSMatthew Dillon } 144e631cff3SDavid Xu PROC_UNLOCK(targetp); 1452afac34dSMatthew Dillon done2: 14664e55bf4SRobert Watson return (e); 1478a6472b7SPeter Dufault } 1488a6472b7SPeter Dufault 1492afac34dSMatthew Dillon /* 1502afac34dSMatthew Dillon * MPSAFE 1512afac34dSMatthew Dillon */ 152f6c040a2SDavid Xu int 153f6c040a2SDavid Xu sched_getparam(struct thread *td, struct sched_getparam_args *uap) 1548a6472b7SPeter Dufault { 1558a6472b7SPeter Dufault int e; 156aebde782SPeter Dufault struct sched_param sched_param; 157b40ce416SJulian Elischer struct thread *targettd; 1581af55356SRobert Watson struct proc *targetp; 1598a6472b7SPeter Dufault 160e84b7987SRobert Watson if (uap->pid == 0) { 161b40ce416SJulian Elischer targetp = td->td_proc; 162b40ce416SJulian Elischer targettd = td; 163e84b7987SRobert Watson PROC_LOCK(targetp); 164e84b7987SRobert Watson } else { 165e84b7987SRobert Watson targetp = pfind(uap->pid); 1662afac34dSMatthew Dillon if (targetp == NULL) { 1672afac34dSMatthew Dillon e = ESRCH; 1682afac34dSMatthew Dillon goto done2; 1692afac34dSMatthew Dillon } 170079b7badSJulian Elischer targettd = FIRST_THREAD_IN_PROC(targetp); /* XXXKSE */ 171e84b7987SRobert Watson } 172e84b7987SRobert Watson 173f44d9e24SJohn Baldwin e = p_cansee(td, targetp); 174e631cff3SDavid Xu if (e == 0) { 175e631cff3SDavid Xu e = ksched_getparam(&td->td_retval[0], ksched, targettd, 176e631cff3SDavid Xu &sched_param); 177e631cff3SDavid Xu } 178e84b7987SRobert Watson PROC_UNLOCK(targetp); 1792afac34dSMatthew Dillon if (e == 0) 18064e55bf4SRobert Watson e = copyout(&sched_param, uap->param, sizeof(sched_param)); 1812afac34dSMatthew Dillon done2: 18264e55bf4SRobert Watson return (e); 1838a6472b7SPeter Dufault } 184b40ce416SJulian Elischer 1852afac34dSMatthew Dillon /* 1862afac34dSMatthew Dillon * MPSAFE 1872afac34dSMatthew Dillon */ 188f6c040a2SDavid Xu int 189f6c040a2SDavid Xu sched_setscheduler(struct thread *td, struct sched_setscheduler_args *uap) 1908a6472b7SPeter Dufault { 1918a6472b7SPeter Dufault int e; 192aebde782SPeter Dufault struct sched_param sched_param; 193b40ce416SJulian Elischer struct thread *targettd; 1941af55356SRobert Watson struct proc *targetp; 1951af55356SRobert Watson 196e8f7a952SRobert Watson e = copyin(uap->param, &sched_param, sizeof(sched_param)); 197e8f7a952SRobert Watson if (e) 198e8f7a952SRobert Watson return (e); 199aebde782SPeter Dufault 200e84b7987SRobert Watson if (uap->pid == 0) { 201b40ce416SJulian Elischer targetp = td->td_proc; 202b40ce416SJulian Elischer targettd = td; 203e84b7987SRobert Watson PROC_LOCK(targetp); 204e84b7987SRobert Watson } else { 205e84b7987SRobert Watson targetp = pfind(uap->pid); 2062afac34dSMatthew Dillon if (targetp == NULL) { 2072afac34dSMatthew Dillon e = ESRCH; 2082afac34dSMatthew Dillon goto done2; 2092afac34dSMatthew Dillon } 210079b7badSJulian Elischer targettd = FIRST_THREAD_IN_PROC(targetp); /* XXXKSE */ 211e84b7987SRobert Watson } 212e84b7987SRobert Watson 213f44d9e24SJohn Baldwin e = p_cansched(td, targetp); 2142afac34dSMatthew Dillon if (e == 0) { 215b40ce416SJulian Elischer e = ksched_setscheduler(&td->td_retval[0], ksched, targettd, 216b40ce416SJulian Elischer uap->policy, (const struct sched_param *)&sched_param); 2172afac34dSMatthew Dillon } 218e631cff3SDavid Xu PROC_UNLOCK(targetp); 2192afac34dSMatthew Dillon done2: 22064e55bf4SRobert Watson return (e); 2218a6472b7SPeter Dufault } 222b40ce416SJulian Elischer 2232afac34dSMatthew Dillon /* 2242afac34dSMatthew Dillon * MPSAFE 2252afac34dSMatthew Dillon */ 226f6c040a2SDavid Xu int 227f6c040a2SDavid Xu sched_getscheduler(struct thread *td, struct sched_getscheduler_args *uap) 2288a6472b7SPeter Dufault { 2298a6472b7SPeter Dufault int e; 230b40ce416SJulian Elischer struct thread *targettd; 2311af55356SRobert Watson struct proc *targetp; 2328a6472b7SPeter Dufault 233e84b7987SRobert Watson if (uap->pid == 0) { 234b40ce416SJulian Elischer targetp = td->td_proc; 235b40ce416SJulian Elischer targettd = td; 236e84b7987SRobert Watson PROC_LOCK(targetp); 237e84b7987SRobert Watson } else { 238e84b7987SRobert Watson targetp = pfind(uap->pid); 2392afac34dSMatthew Dillon if (targetp == NULL) { 2402afac34dSMatthew Dillon e = ESRCH; 2412afac34dSMatthew Dillon goto done2; 2422afac34dSMatthew Dillon } 243079b7badSJulian Elischer targettd = FIRST_THREAD_IN_PROC(targetp); /* XXXKSE */ 244e84b7987SRobert Watson } 245e84b7987SRobert Watson 246f44d9e24SJohn Baldwin e = p_cansee(td, targetp); 2472afac34dSMatthew Dillon if (e == 0) 248b40ce416SJulian Elischer e = ksched_getscheduler(&td->td_retval[0], ksched, targettd); 249e631cff3SDavid Xu PROC_UNLOCK(targetp); 25064e55bf4SRobert Watson 2512afac34dSMatthew Dillon done2: 25264e55bf4SRobert Watson return (e); 2538a6472b7SPeter Dufault } 254b40ce416SJulian Elischer 2552afac34dSMatthew Dillon /* 2562afac34dSMatthew Dillon * MPSAFE 2572afac34dSMatthew Dillon */ 258f6c040a2SDavid Xu int 259f6c040a2SDavid Xu sched_yield(struct thread *td, struct sched_yield_args *uap) 2608a6472b7SPeter Dufault { 2612afac34dSMatthew Dillon int error; 2622afac34dSMatthew Dillon 263b40ce416SJulian Elischer error = ksched_yield(&td->td_retval[0], ksched); 2642afac34dSMatthew Dillon return (error); 2658a6472b7SPeter Dufault } 266b40ce416SJulian Elischer 2672afac34dSMatthew Dillon /* 2682afac34dSMatthew Dillon * MPSAFE 2692afac34dSMatthew Dillon */ 270f6c040a2SDavid Xu int 271f6c040a2SDavid Xu sched_get_priority_max(struct thread *td, 2728a6472b7SPeter Dufault struct sched_get_priority_max_args *uap) 2738a6472b7SPeter Dufault { 2742afac34dSMatthew Dillon int error; 2752afac34dSMatthew Dillon 276b40ce416SJulian Elischer error = ksched_get_priority_max(&td->td_retval[0], ksched, uap->policy); 2772afac34dSMatthew Dillon return (error); 2788a6472b7SPeter Dufault } 279b40ce416SJulian Elischer 2802afac34dSMatthew Dillon /* 2812afac34dSMatthew Dillon * MPSAFE 2822afac34dSMatthew Dillon */ 283f6c040a2SDavid Xu int 284f6c040a2SDavid Xu sched_get_priority_min(struct thread *td, 2858a6472b7SPeter Dufault struct sched_get_priority_min_args *uap) 2868a6472b7SPeter Dufault { 2872afac34dSMatthew Dillon int error; 288b40ce416SJulian Elischer 289b40ce416SJulian Elischer error = ksched_get_priority_min(&td->td_retval[0], ksched, uap->policy); 2902afac34dSMatthew Dillon return (error); 2918a6472b7SPeter Dufault } 292b40ce416SJulian Elischer 2932afac34dSMatthew Dillon /* 2942afac34dSMatthew Dillon * MPSAFE 2952afac34dSMatthew Dillon */ 296f6c040a2SDavid Xu int 297f6c040a2SDavid Xu sched_rr_get_interval(struct thread *td, 2988a6472b7SPeter Dufault struct sched_rr_get_interval_args *uap) 2998a6472b7SPeter Dufault { 300fe24ab5fSJohn Baldwin struct timespec timespec; 301fe24ab5fSJohn Baldwin int error; 302fe24ab5fSJohn Baldwin 303fe24ab5fSJohn Baldwin error = kern_sched_rr_get_interval(td, uap->pid, ×pec); 304fe24ab5fSJohn Baldwin if (error == 0) 305fe24ab5fSJohn Baldwin error = copyout(×pec, uap->interval, sizeof(timespec)); 306fe24ab5fSJohn Baldwin return (error); 307fe24ab5fSJohn Baldwin } 308fe24ab5fSJohn Baldwin 309f6c040a2SDavid Xu int 310f6c040a2SDavid Xu kern_sched_rr_get_interval(struct thread *td, pid_t pid, 311fe24ab5fSJohn Baldwin struct timespec *ts) 312fe24ab5fSJohn Baldwin { 3138a6472b7SPeter Dufault int e; 314b40ce416SJulian Elischer struct thread *targettd; 3151af55356SRobert Watson struct proc *targetp; 3168a6472b7SPeter Dufault 317fe24ab5fSJohn Baldwin if (pid == 0) { 318b40ce416SJulian Elischer targettd = td; 319b40ce416SJulian Elischer targetp = td->td_proc; 320e84b7987SRobert Watson PROC_LOCK(targetp); 321e84b7987SRobert Watson } else { 322fe24ab5fSJohn Baldwin targetp = pfind(pid); 323e631cff3SDavid Xu if (targetp == NULL) 324fe24ab5fSJohn Baldwin return (ESRCH); 325e631cff3SDavid Xu 326079b7badSJulian Elischer targettd = FIRST_THREAD_IN_PROC(targetp); /* XXXKSE */ 327e84b7987SRobert Watson } 328e84b7987SRobert Watson 329f44d9e24SJohn Baldwin e = p_cansee(td, targetp); 330a11acc6fSAlfred Perlstein if (e == 0) 331fe24ab5fSJohn Baldwin e = ksched_rr_get_interval(&td->td_retval[0], ksched, targettd, 332fe24ab5fSJohn Baldwin ts); 333fe24ab5fSJohn Baldwin PROC_UNLOCK(targetp); 33464e55bf4SRobert Watson return (e); 3358a6472b7SPeter Dufault } 3368a6472b7SPeter Dufault 3378a6472b7SPeter Dufault #endif 3388a6472b7SPeter Dufault 339f6c040a2SDavid Xu static void 340f6c040a2SDavid Xu p31binit(void *notused) 3418a6472b7SPeter Dufault { 3428a6472b7SPeter Dufault (void) sched_attach(); 343ce47711dSPeter Dufault p31b_setcfg(CTL_P1003_1B_PAGESIZE, PAGE_SIZE); 3448a6472b7SPeter Dufault } 3458a6472b7SPeter Dufault 3468a6472b7SPeter Dufault SYSINIT(p31b, SI_SUB_P1003_1B, SI_ORDER_FIRST, p31binit, NULL); 347