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, &timespec);
329144447Sjhb	if (error == 0)
330144447Sjhb		error = copyout(&timespec, 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