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, &timespec);
299132451Sroberto	if (error == 0)
300132451Sroberto		error = copyout(&timespec, 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