p1003_1b.c revision 83366
1/*
2 * Copyright (c) 1996, 1997, 1998
3 *	HD Associates, Inc.  All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 *    notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 *    notice, this list of conditions and the following disclaimer in the
12 *    documentation and/or other materials provided with the distribution.
13 * 3. All advertising materials mentioning features or use of this software
14 *    must display the following acknowledgement:
15 *	This product includes software developed by HD Associates, Inc
16 * 4. Neither the name of the author nor the names of any co-contributors
17 *    may be used to endorse or promote products derived from this software
18 *    without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY HD ASSOCIATES AND CONTRIBUTORS ``AS IS'' AND
21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 * ARE DISCLAIMED.  IN NO EVENT SHALL HD ASSOCIATES OR CONTRIBUTORS BE LIABLE
24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30 * SUCH DAMAGE.
31 *
32 * $FreeBSD: head/sys/kern/p1003_1b.c 83366 2001-09-12 08:38:13Z julian $
33 */
34
35/* p1003_1b: Real Time common code.
36 */
37
38#include <sys/param.h>
39#include <sys/systm.h>
40#include <sys/kernel.h>
41#include <sys/lock.h>
42#include <sys/module.h>
43#include <sys/mutex.h>
44#include <sys/proc.h>
45#include <sys/sysctl.h>
46#include <sys/sysent.h>
47#include <sys/syslog.h>
48#include <sys/sysproto.h>
49
50#include <posix4/posix4.h>
51
52MALLOC_DEFINE(M_P31B, "p1003.1b", "Posix 1003.1B");
53
54/* The system calls return ENOSYS if an entry is called that is
55 * not run-time supported.  I am also logging since some programs
56 * start to use this when they shouldn't.  That will be removed if annoying.
57 */
58int
59syscall_not_present(struct thread *td, const char *s, struct nosys_args *uap)
60{
61	log(LOG_ERR, "cmd %s pid %d tried to use non-present %s\n",
62			td->td_proc->p_comm, td->td_proc->p_pid, s);
63
64	/* a " return nosys(p, uap); " here causes a core dump.
65	 */
66
67	return ENOSYS;
68}
69
70#if !defined(_KPOSIX_PRIORITY_SCHEDULING)
71
72/* Not configured but loadable via a module:
73 */
74
75static int sched_attach(void)
76{
77	return 0;
78}
79
80SYSCALL_NOT_PRESENT_GEN(sched_setparam)
81SYSCALL_NOT_PRESENT_GEN(sched_getparam)
82SYSCALL_NOT_PRESENT_GEN(sched_setscheduler)
83SYSCALL_NOT_PRESENT_GEN(sched_getscheduler)
84SYSCALL_NOT_PRESENT_GEN(sched_yield)
85SYSCALL_NOT_PRESENT_GEN(sched_get_priority_max)
86SYSCALL_NOT_PRESENT_GEN(sched_get_priority_min)
87SYSCALL_NOT_PRESENT_GEN(sched_rr_get_interval)
88
89#else
90
91/* Configured in kernel version:
92 */
93static struct ksched *ksched;
94
95static int sched_attach(void)
96{
97	int ret = ksched_attach(&ksched);
98
99	if (ret == 0)
100		p31b_setcfg(CTL_P1003_1B_PRIORITY_SCHEDULING, 1);
101
102	return ret;
103}
104
105/*
106 * MPSAFE
107 */
108int sched_setparam(struct thread *td,
109	struct sched_setparam_args *uap)
110{
111	struct thread *targettd;
112	struct proc *targetp;
113	int e;
114	struct sched_param sched_param;
115
116	e = copyin(uap->param, &sched_param, sizeof(sched_param));
117	if (e)
118		return (e);
119
120	mtx_lock(&Giant);
121	if (uap->pid == 0) {
122		targetp = td->td_proc;
123		targettd = td;
124		PROC_LOCK(targetp);
125	} else {
126		targetp = pfind(uap->pid);
127		if (targetp == NULL) {
128			e = ESRCH;
129			goto done2;
130		}
131		targettd = &targetp->p_thread; /* XXXKSE */
132	}
133
134	e = p_cansched(td->td_proc, targetp);
135	PROC_UNLOCK(targetp);
136	if (e == 0) {
137		e = ksched_setparam(&td->td_retval[0], ksched, targettd,
138			(const struct sched_param *)&sched_param);
139	}
140done2:
141	mtx_unlock(&Giant);
142	return (e);
143}
144
145/*
146 * MPSAFE
147 */
148int sched_getparam(struct thread *td,
149	struct sched_getparam_args *uap)
150{
151	int e;
152	struct sched_param sched_param;
153	struct thread *targettd;
154	struct proc *targetp;
155
156	mtx_lock(&Giant);
157	if (uap->pid == 0) {
158		targetp = td->td_proc;
159		targettd = td;
160		PROC_LOCK(targetp);
161	} else {
162		targetp = pfind(uap->pid);
163		if (targetp == NULL) {
164			e = ESRCH;
165			goto done2;
166		}
167		targettd = &targetp->p_thread; /* XXXKSE */
168	}
169
170	e = p_cansee(td->td_proc, targetp);
171	PROC_UNLOCK(targetp);
172	if (e)
173		goto done2;
174
175	e = ksched_getparam(&td->td_retval[0], ksched, targettd, &sched_param);
176	if (e == 0)
177		e = copyout(&sched_param, uap->param, sizeof(sched_param));
178done2:
179	mtx_unlock(&Giant);
180	return (e);
181}
182
183/*
184 * MPSAFE
185 */
186int sched_setscheduler(struct thread *td,
187	struct sched_setscheduler_args *uap)
188{
189	int e;
190	struct sched_param sched_param;
191	struct thread *targettd;
192	struct proc *targetp;
193
194	e = copyin(uap->param, &sched_param, sizeof(sched_param));
195	if (e)
196		return (e);
197
198	mtx_lock(&Giant);
199	if (uap->pid == 0) {
200		targetp = td->td_proc;
201		targettd = td;
202		PROC_LOCK(targetp);
203	} else {
204		targetp = pfind(uap->pid);
205		if (targetp == NULL) {
206			e = ESRCH;
207			goto done2;
208		}
209		targettd = &targetp->p_thread; /* XXXKSE */
210	}
211
212	e = p_cansched(td->td_proc, targetp);
213	PROC_UNLOCK(targetp);
214	if (e == 0) {
215		e = ksched_setscheduler(&td->td_retval[0], ksched, targettd,
216			uap->policy, (const struct sched_param *)&sched_param);
217	}
218done2:
219	mtx_unlock(&Giant);
220	return (e);
221}
222
223/*
224 * MPSAFE
225 */
226int sched_getscheduler(struct thread *td,
227	struct sched_getscheduler_args *uap)
228{
229	int e;
230	struct thread *targettd;
231	struct proc *targetp;
232
233	mtx_lock(&Giant);
234	if (uap->pid == 0) {
235		targetp = td->td_proc;
236		targettd = td;
237		PROC_LOCK(targetp);
238	} else {
239		targetp = pfind(uap->pid);
240		if (targetp == NULL) {
241			e = ESRCH;
242			goto done2;
243		}
244		targettd = &targetp->p_thread; /* XXXKSE */
245	}
246
247	e = p_cansee(td->td_proc, targetp);
248	PROC_UNLOCK(targetp);
249	if (e == 0)
250		e = ksched_getscheduler(&td->td_retval[0], ksched, targettd);
251
252done2:
253	mtx_unlock(&Giant);
254	return (e);
255}
256
257/*
258 * MPSAFE
259 */
260int sched_yield(struct thread *td,
261	struct sched_yield_args *uap)
262{
263	int error;
264
265	mtx_lock(&Giant);
266	error = ksched_yield(&td->td_retval[0], ksched);
267	mtx_unlock(&Giant);
268	return (error);
269}
270
271/*
272 * MPSAFE
273 */
274int sched_get_priority_max(struct thread *td,
275	struct sched_get_priority_max_args *uap)
276{
277	int error;
278
279	mtx_lock(&Giant);
280	error = ksched_get_priority_max(&td->td_retval[0], ksched, uap->policy);
281	mtx_unlock(&Giant);
282	return (error);
283}
284
285/*
286 * MPSAFE
287 */
288int sched_get_priority_min(struct thread *td,
289	struct sched_get_priority_min_args *uap)
290{
291	int error;
292
293	mtx_lock(&Giant);
294	error = ksched_get_priority_min(&td->td_retval[0], ksched, uap->policy);
295	mtx_unlock(&Giant);
296	return (error);
297}
298
299/*
300 * MPSAFE
301 */
302int sched_rr_get_interval(struct thread *td,
303	struct sched_rr_get_interval_args *uap)
304{
305	int e;
306	struct thread *targettd;
307	struct proc *targetp;
308
309	mtx_lock(&Giant);
310	if (uap->pid == 0) {
311		targettd = td;
312		targetp = td->td_proc;
313		PROC_LOCK(targetp);
314	} else {
315		targetp = pfind(uap->pid);
316		if (targetp == NULL) {
317			e = ESRCH;
318			goto done2;
319		}
320		targettd = &targetp->p_thread; /* XXXKSE */
321	}
322
323	e = p_cansee(td->td_proc, targetp);
324	PROC_UNLOCK(targetp);
325	if (e == 0) {
326		e = ksched_rr_get_interval(&td->td_retval[0], ksched, targettd,
327			uap->interval);
328	}
329done2:
330	mtx_unlock(&Giant);
331	return (e);
332}
333
334#endif
335
336static void p31binit(void *notused)
337{
338	(void) sched_attach();
339	p31b_setcfg(CTL_P1003_1B_PAGESIZE, PAGE_SIZE);
340}
341
342SYSINIT(p31b, SI_SUB_P1003_1B, SI_ORDER_FIRST, p31binit, NULL);
343