p1003_1b.c revision 157623
1132451Sroberto/*- 2132451Sroberto * Copyright (c) 1996, 1997, 1998 354359Sroberto * HD Associates, Inc. All rights reserved. 4132451Sroberto * 582498Sroberto * Redistribution and use in source and binary forms, with or without 654359Sroberto * modification, are permitted provided that the following conditions 754359Sroberto * are met: 854359Sroberto * 1. Redistributions of source code must retain the above copyright 954359Sroberto * notice, this list of conditions and the following disclaimer. 1054359Sroberto * 2. Redistributions in binary form must reproduce the above copyright 1154359Sroberto * notice, this list of conditions and the following disclaimer in the 1254359Sroberto * documentation and/or other materials provided with the distribution. 1354359Sroberto * 3. All advertising materials mentioning features or use of this software 1454359Sroberto * must display the following acknowledgement: 15106163Sroberto * This product includes software developed by HD Associates, Inc 16106163Sroberto * 4. Neither the name of the author nor the names of any co-contributors 1754359Sroberto * may be used to endorse or promote products derived from this software 1854359Sroberto * without specific prior written permission. 1954359Sroberto * 2054359Sroberto * THIS SOFTWARE IS PROVIDED BY HD ASSOCIATES AND CONTRIBUTORS ``AS IS'' AND 2154359Sroberto * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 2254359Sroberto * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2354359Sroberto * ARE DISCLAIMED. IN NO EVENT SHALL HD ASSOCIATES OR CONTRIBUTORS BE LIABLE 2454359Sroberto * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25132451Sroberto * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2654359Sroberto * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 27132451Sroberto * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 28132451Sroberto * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 29132451Sroberto * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 3082498Sroberto * SUCH DAMAGE. 31132451Sroberto */ 3254359Sroberto 3354359Sroberto/* p1003_1b: Real Time common code. 3454359Sroberto */ 3554359Sroberto 3654359Sroberto#include <sys/cdefs.h> 3754359Sroberto__FBSDID("$FreeBSD: head/sys/kern/p1003_1b.c 157623 2006-04-10 04:55:59Z davidxu $"); 3854359Sroberto 3954359Sroberto#include "opt_posix.h" 4054359Sroberto 41132451Sroberto#include <sys/param.h> 42132451Sroberto#include <sys/systm.h> 43132451Sroberto#include <sys/kernel.h> 4454359Sroberto#include <sys/lock.h> 45132451Sroberto#include <sys/module.h> 46132451Sroberto#include <sys/mutex.h> 47132451Sroberto#include <sys/proc.h> 48132451Sroberto#include <sys/syscallsubr.h> 4954359Sroberto#include <sys/sysctl.h> 5054359Sroberto#include <sys/sysent.h> 51132451Sroberto#include <sys/syslog.h> 5254359Sroberto#include <sys/sysproto.h> 5354359Sroberto 5454359Sroberto#include <posix4/posix4.h> 5554359Sroberto 56132451SrobertoMALLOC_DEFINE(M_P31B, "p1003.1b", "Posix 1003.1B"); 57132451Sroberto 5854359Sroberto/* The system calls return ENOSYS if an entry is called that is 59132451Sroberto * not run-time supported. I am also logging since some programs 6056746Sroberto * start to use this when they shouldn't. That will be removed if annoying. 61132451Sroberto */ 62132451Srobertoint 63132451Srobertosyscall_not_present(struct thread *td, const char *s, struct nosys_args *uap) 6482498Sroberto{ 6582498Sroberto log(LOG_ERR, "cmd %s pid %d tried to use non-present %s\n", 66132451Sroberto td->td_proc->p_comm, td->td_proc->p_pid, s); 67106163Sroberto 68132451Sroberto /* a " return nosys(p, uap); " here causes a core dump. 69132451Sroberto */ 70132451Sroberto 7182498Sroberto return ENOSYS; 72132451Sroberto} 7354359Sroberto 74132451Sroberto#if !defined(_KPOSIX_PRIORITY_SCHEDULING) 7554359Sroberto 76132451Sroberto/* Not configured but loadable via a module: 7754359Sroberto */ 78132451Sroberto 79132451Srobertostatic int sched_attach(void) 8054359Sroberto{ 8154359Sroberto return 0; 82132451Sroberto} 8354359Sroberto 8454359SrobertoSYSCALL_NOT_PRESENT_GEN(sched_setparam) 85132451SrobertoSYSCALL_NOT_PRESENT_GEN(sched_getparam) 8654359SrobertoSYSCALL_NOT_PRESENT_GEN(sched_setscheduler) 87132451SrobertoSYSCALL_NOT_PRESENT_GEN(sched_getscheduler) 8854359SrobertoSYSCALL_NOT_PRESENT_GEN(sched_yield) 89132451SrobertoSYSCALL_NOT_PRESENT_GEN(sched_get_priority_max) 9054359SrobertoSYSCALL_NOT_PRESENT_GEN(sched_get_priority_min) 9182498SrobertoSYSCALL_NOT_PRESENT_GEN(sched_rr_get_interval) 92106163Sroberto 9382498Sroberto#else 9482498Sroberto 9582498Sroberto/* Configured in kernel version: 9654359Sroberto */ 97132451Srobertostatic struct ksched *ksched; 98132451Sroberto 99132451Srobertostatic int sched_attach(void) 100132451Sroberto{ 101132451Sroberto int ret = ksched_attach(&ksched); 10282498Sroberto 103132451Sroberto if (ret == 0) 10454359Sroberto p31b_setcfg(CTL_P1003_1B_PRIORITY_SCHEDULING, 1); 10554359Sroberto 10654359Sroberto return ret; 107132451Sroberto} 108132451Sroberto 109132451Sroberto/* 110132451Sroberto * MPSAFE 11154359Sroberto */ 11254359Srobertoint sched_setparam(struct thread *td, 11354359Sroberto struct sched_setparam_args *uap) 114132451Sroberto{ 115132451Sroberto struct thread *targettd; 116132451Sroberto struct proc *targetp; 117132451Sroberto int e; 118132451Sroberto struct sched_param sched_param; 119106163Sroberto 120132451Sroberto e = copyin(uap->param, &sched_param, sizeof(sched_param)); 121106163Sroberto if (e) 122132451Sroberto return (e); 123132451Sroberto 124132451Sroberto if (uap->pid == 0) { 125132451Sroberto targetp = td->td_proc; 126132451Sroberto targettd = td; 127132451Sroberto PROC_LOCK(targetp); 128132451Sroberto } else { 129132451Sroberto targetp = pfind(uap->pid); 130132451Sroberto if (targetp == NULL) { 131132451Sroberto e = ESRCH; 132132451Sroberto goto done2; 133132451Sroberto } 134132451Sroberto targettd = FIRST_THREAD_IN_PROC(targetp); /* XXXKSE */ 135132451Sroberto } 136132451Sroberto 13756746Sroberto e = p_cansched(td, targetp); 138132451Sroberto if (e == 0) { 139132451Sroberto e = ksched_setparam(&td->td_retval[0], ksched, targettd, 140132451Sroberto (const struct sched_param *)&sched_param); 141132451Sroberto } 142132451Sroberto PROC_UNLOCK(targetp); 143132451Srobertodone2: 144132451Sroberto return (e); 145132451Sroberto} 146132451Sroberto 147132451Sroberto/* 148132451Sroberto * MPSAFE 149132451Sroberto */ 150132451Srobertoint sched_getparam(struct thread *td, 151132451Sroberto struct sched_getparam_args *uap) 152132451Sroberto{ 153132451Sroberto int e; 15454359Sroberto struct sched_param sched_param; 155132451Sroberto struct thread *targettd; 15654359Sroberto struct proc *targetp; 157132451Sroberto 158132451Sroberto if (uap->pid == 0) { 159132451Sroberto targetp = td->td_proc; 160132451Sroberto targettd = td; 161132451Sroberto PROC_LOCK(targetp); 162132451Sroberto } else { 16382498Sroberto targetp = pfind(uap->pid); 16482498Sroberto if (targetp == NULL) { 16582498Sroberto e = ESRCH; 16682498Sroberto goto done2; 16782498Sroberto } 168132451Sroberto targettd = FIRST_THREAD_IN_PROC(targetp); /* XXXKSE */ 169132451Sroberto } 170132451Sroberto 171132451Sroberto e = p_cansee(td, targetp); 17254359Sroberto if (e == 0) { 17354359Sroberto e = ksched_getparam(&td->td_retval[0], ksched, targettd, 17454359Sroberto &sched_param); 17554359Sroberto } 17654359Sroberto PROC_UNLOCK(targetp); 177132451Sroberto if (e == 0) 17854359Sroberto e = copyout(&sched_param, uap->param, sizeof(sched_param)); 179132451Srobertodone2: 180106163Sroberto return (e); 181132451Sroberto} 182132451Sroberto 183132451Sroberto/* 18482498Sroberto * MPSAFE 185132451Sroberto */ 186106163Srobertoint sched_setscheduler(struct thread *td, 187132451Sroberto struct sched_setscheduler_args *uap) 188106163Sroberto{ 189106163Sroberto int e; 190106163Sroberto struct sched_param sched_param; 191106163Sroberto struct thread *targettd; 192106163Sroberto struct proc *targetp; 193106163Sroberto 194106163Sroberto e = copyin(uap->param, &sched_param, sizeof(sched_param)); 195106163Sroberto if (e) 196106163Sroberto return (e); 197106163Sroberto 198106163Sroberto if (uap->pid == 0) { 199106424Sroberto targetp = td->td_proc; 20054359Sroberto targettd = td; 20154359Sroberto PROC_LOCK(targetp); 202132451Sroberto } else { 20354359Sroberto targetp = pfind(uap->pid); 20482498Sroberto if (targetp == NULL) { 20582498Sroberto e = ESRCH; 206132451Sroberto goto done2; 207132451Sroberto } 208132451Sroberto targettd = FIRST_THREAD_IN_PROC(targetp); /* XXXKSE */ 209132451Sroberto } 210132451Sroberto 211132451Sroberto e = p_cansched(td, targetp); 212132451Sroberto if (e == 0) { 213132451Sroberto e = ksched_setscheduler(&td->td_retval[0], ksched, targettd, 214132451Sroberto uap->policy, (const struct sched_param *)&sched_param); 215132451Sroberto } 216132451Sroberto PROC_UNLOCK(targetp); 217132451Srobertodone2: 218132451Sroberto return (e); 219132451Sroberto} 220132451Sroberto 221132451Sroberto/* 222132451Sroberto * MPSAFE 223132451Sroberto */ 224132451Srobertoint sched_getscheduler(struct thread *td, 225132451Sroberto struct sched_getscheduler_args *uap) 226132451Sroberto{ 227132451Sroberto int e; 228132451Sroberto struct thread *targettd; 229132451Sroberto struct proc *targetp; 230132451Sroberto 231132451Sroberto if (uap->pid == 0) { 232132451Sroberto targetp = td->td_proc; 233132451Sroberto targettd = td; 234132451Sroberto PROC_LOCK(targetp); 235132451Sroberto } else { 236132451Sroberto targetp = pfind(uap->pid); 237132451Sroberto if (targetp == NULL) { 238132451Sroberto e = ESRCH; 239132451Sroberto goto done2; 240132451Sroberto } 241132451Sroberto targettd = FIRST_THREAD_IN_PROC(targetp); /* XXXKSE */ 24282498Sroberto } 24382498Sroberto 24454359Sroberto e = p_cansee(td, targetp); 24554359Sroberto if (e == 0) 24682498Sroberto e = ksched_getscheduler(&td->td_retval[0], ksched, targettd); 247132451Sroberto PROC_UNLOCK(targetp); 248132451Sroberto 249106163Srobertodone2: 250132451Sroberto return (e); 251132451Sroberto} 25282498Sroberto 253132451Sroberto/* 254106163Sroberto * MPSAFE 255132451Sroberto */ 256132451Srobertoint sched_yield(struct thread *td, 257132451Sroberto struct sched_yield_args *uap) 258132451Sroberto{ 259132451Sroberto int error; 260132451Sroberto 261132451Sroberto error = ksched_yield(&td->td_retval[0], ksched); 262132451Sroberto return (error); 263106163Sroberto} 264106163Sroberto 265106163Sroberto/* 266132451Sroberto * MPSAFE 267132451Sroberto */ 268132451Srobertoint sched_get_priority_max(struct thread *td, 269132451Sroberto struct sched_get_priority_max_args *uap) 270132451Sroberto{ 271132451Sroberto int error; 272132451Sroberto 273132451Sroberto error = ksched_get_priority_max(&td->td_retval[0], ksched, uap->policy); 274132451Sroberto return (error); 275132451Sroberto} 276132451Sroberto 277132451Sroberto/* 278132451Sroberto * MPSAFE 279132451Sroberto */ 280132451Srobertoint sched_get_priority_min(struct thread *td, 281132451Sroberto struct sched_get_priority_min_args *uap) 282132451Sroberto{ 283132451Sroberto int error; 284132451Sroberto 285132451Sroberto error = ksched_get_priority_min(&td->td_retval[0], ksched, uap->policy); 286132451Sroberto return (error); 287132451Sroberto} 288132451Sroberto 289132451Sroberto/* 290132451Sroberto * MPSAFE 291132451Sroberto */ 292132451Srobertoint sched_rr_get_interval(struct thread *td, 293132451Sroberto struct sched_rr_get_interval_args *uap) 294132451Sroberto{ 295132451Sroberto struct timespec timespec; 296132451Sroberto int error; 297132451Sroberto 298132451Sroberto error = kern_sched_rr_get_interval(td, uap->pid, ×pec); 299132451Sroberto if (error == 0) 300132451Sroberto error = copyout(×pec, uap->interval, sizeof(timespec)); 301132451Sroberto return (error); 302132451Sroberto} 303132451Sroberto 304132451Srobertoint kern_sched_rr_get_interval(struct thread *td, pid_t pid, 305132451Sroberto struct timespec *ts) 306132451Sroberto{ 307132451Sroberto int e; 308132451Sroberto struct thread *targettd; 309132451Sroberto struct proc *targetp; 310132451Sroberto 311132451Sroberto if (pid == 0) { 312132451Sroberto targettd = td; 313132451Sroberto targetp = td->td_proc; 314132451Sroberto PROC_LOCK(targetp); 315132451Sroberto } else { 316132451Sroberto targetp = pfind(pid); 317132451Sroberto if (targetp == NULL) 318132451Sroberto return (ESRCH); 319132451Sroberto 320132451Sroberto targettd = FIRST_THREAD_IN_PROC(targetp); /* XXXKSE */ 321132451Sroberto } 322132451Sroberto 323132451Sroberto e = p_cansee(td, targetp); 324132451Sroberto if (e == 0) 325132451Sroberto e = ksched_rr_get_interval(&td->td_retval[0], ksched, targettd, 326132451Sroberto ts); 327132451Sroberto PROC_UNLOCK(targetp); 328132451Sroberto return (e); 329132451Sroberto} 330132451Sroberto 331106163Sroberto#endif 332106163Sroberto 33354359Srobertostatic void p31binit(void *notused) 33454359Sroberto{ 335132451Sroberto (void) sched_attach(); 336132451Sroberto p31b_setcfg(CTL_P1003_1B_PAGESIZE, PAGE_SIZE); 337132451Sroberto} 338132451Sroberto 33954359SrobertoSYSINIT(p31b, SI_SUB_P1003_1B, SI_ORDER_FIRST, p31binit, NULL); 34082498Sroberto