drm/linux: Add list_for_each_entry_continue_reverse()
[dragonfly.git] / sys / kern / kern_p1003_1b.c
CommitLineData
984263bc
MD
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: src/sys/posix4/p1003_1b.c,v 1.5.2.2 2003/03/25 06:13:35 rwatson Exp $
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/sysent.h>
3eb2971d 42#include <sys/posix4.h>
984263bc
MD
43#include <sys/proc.h>
44#include <sys/syslog.h>
45#include <sys/module.h>
46#include <sys/sysproto.h>
47#include <sys/sysctl.h>
1973ed78 48#include <sys/unistd.h>
984263bc 49
984263bc
MD
50MALLOC_DEFINE(M_P31B, "p1003.1b", "Posix 1003.1B");
51
e9b43d11
MD
52/*
53 * p31b_proc: Return a proc struct corresponding to a pid to operate on.
984263bc
MD
54 *
55 * Enforce permission policy.
56 *
57 * The policy is the same as for sending signals except there
58 * is no notion of process groups.
59 *
60 * pid == 0 means my process.
61 *
62 * This is disabled until I've got a permission gate in again:
63 * only root can do this.
64 */
65
66#if 0
67/*
68 * This is stolen from CANSIGNAL in kern_sig:
69 *
70 * Can process p, with pcred pc, do "write flavor" operations to process q?
71 */
41c20dac
MD
72#define CAN_AFFECT(p, cr, q) \
73 ((cr)->cr_uid == 0 || \
74 (cr)->cr_ruid == (q)->p_ucred->cr_ruid || \
75 (cr)->cr_uid == (q)->p_ucred->cr_ruid || \
76 (cr)->cr_ruid == (q)->p_ucred->cr_uid || \
77 (cr)->cr_uid == (q)->p_ucred->cr_uid)
984263bc 78#else
41c20dac 79#define CAN_AFFECT(p, cr, q) ((cr)->cr_uid == 0)
984263bc
MD
80#endif
81
a18cc93b
SW
82#if !defined(_KPOSIX_PRIORITY_SCHEDULING)
83
84int syscall_not_present(const char *s);
85
86/* The system calls return ENOSYS if an entry is called that is
87 * not run-time supported. I am also logging since some programs
88 * start to use this when they shouldn't. That will be removed if annoying.
89 */
90int syscall_not_present(const char *s)
91{
92 struct proc *p = curproc;
93 log(LOG_ERR, "cmd %s pid %d tried to use non-present %s\n",
94 p->p_comm, p->p_pid, s);
95
96 /* a " return nosys(p, uap); " here causes a core dump.
97 */
98
99 return ENOSYS;
100}
101
102/* Not configured but loadable via a module:
103 */
104
105static int sched_attach(void)
106{
107 return 0;
108}
109
110#define SYSCALL_NOT_PRESENT_GEN(SC) \
111int sys_##SC (struct SC##_args *uap) \
112{ \
113 return syscall_not_present(#SC); \
114}
115
116SYSCALL_NOT_PRESENT_GEN(sched_setparam)
117SYSCALL_NOT_PRESENT_GEN(sched_getparam)
118SYSCALL_NOT_PRESENT_GEN(sched_setscheduler)
119SYSCALL_NOT_PRESENT_GEN(sched_getscheduler)
120SYSCALL_NOT_PRESENT_GEN(sched_yield)
121SYSCALL_NOT_PRESENT_GEN(sched_get_priority_max)
122SYSCALL_NOT_PRESENT_GEN(sched_get_priority_min)
123SYSCALL_NOT_PRESENT_GEN(sched_rr_get_interval)
124
125#else
126
984263bc
MD
127/*
128 * p31b_proc: Look up a proc from a PID. If proc is 0 it is
129 * my own proc.
e9b43d11
MD
130 *
131 * Returns a held process in *pp.
984263bc 132 */
e9b43d11
MD
133static
134int
135p31b_proc(pid_t pid, struct proc **pp)
984263bc
MD
136{
137 int ret = 0;
e9b43d11
MD
138 struct proc *p = curproc;
139 struct proc *other_proc;
984263bc 140
58c2553a 141 if (pid == 0) {
984263bc 142 other_proc = p;
58c2553a
MD
143 if (other_proc)
144 PHOLD(other_proc);
145 } else {
984263bc 146 other_proc = pfind(pid);
58c2553a
MD
147 /* ref from pfind() */
148 }
984263bc 149
58c2553a 150 if (other_proc) {
984263bc
MD
151 /* Enforce permission policy.
152 */
e9b43d11 153 if (CAN_AFFECT(p, p->p_ucred, other_proc)) {
984263bc 154 *pp = other_proc;
e9b43d11
MD
155 lwkt_gettoken(&other_proc->p_token);
156 } else {
157 *pp = NULL;
984263bc 158 ret = EPERM;
e9b43d11
MD
159 PRELE(other_proc);
160 }
58c2553a 161 } else {
e9b43d11 162 *pp = NULL;
984263bc 163 ret = ESRCH;
58c2553a 164 }
984263bc
MD
165 return ret;
166}
167
e9b43d11
MD
168static
169void
170p31b_proc_done(struct proc *other_proc)
171{
172 if (other_proc) {
173 lwkt_reltoken(&other_proc->p_token);
174 PRELE(other_proc);
175 }
176}
177
984263bc
MD
178/* Configured in kernel version:
179 */
180static struct ksched *ksched;
181
182static int sched_attach(void)
183{
184 int ret = ksched_attach(&ksched);
185
186 if (ret == 0)
187 p31b_setcfg(CTL_P1003_1B_PRIORITY_SCHEDULING, 1);
188
189 return ret;
190}
191
41c20dac 192int
753fd850 193sys_sched_setparam(struct sched_setparam_args *uap)
984263bc 194{
e9b43d11 195 struct proc *p;
08f2f1bb 196 struct lwp *lp;
984263bc 197 struct sched_param sched_param;
e9b43d11 198 int e;
3919ced0 199
984263bc
MD
200 copyin(uap->param, &sched_param, sizeof(sched_param));
201
e9b43d11 202 if ((e = p31b_proc(uap->pid, &p)) == 0) {
08f2f1bb 203 lp = FIRST_LWP_IN_PROC(p); /* XXX lwp */
e9b43d11
MD
204 if (lp) {
205 LWPHOLD(lp);
206 lwkt_gettoken(&lp->lwp_token);
207 e = ksched_setparam(&uap->sysmsg_reg, ksched, lp,
3919ced0 208 (const struct sched_param *)&sched_param);
e9b43d11
MD
209 lwkt_reltoken(&lp->lwp_token);
210 LWPRELE(lp);
211 } else {
212 e = ESRCH;
213 }
214 p31b_proc_done(p);
41c20dac 215 }
984263bc
MD
216 return e;
217}
218
41c20dac 219int
753fd850 220sys_sched_getparam(struct sched_getparam_args *uap)
984263bc
MD
221{
222 struct proc *targetp;
08f2f1bb 223 struct lwp *lp;
984263bc
MD
224 struct sched_param sched_param;
225 int e;
226
e9b43d11
MD
227 if ((e = p31b_proc(uap->pid, &targetp)) == 0) {
228 lp = FIRST_LWP_IN_PROC(targetp); /* XXX lwp */
229 if (lp) {
230 LWPHOLD(lp);
231 lwkt_gettoken(&lp->lwp_token);
232 e = ksched_getparam(&uap->sysmsg_reg, ksched,
233 lp, &sched_param);
234 lwkt_reltoken(&lp->lwp_token);
235 LWPRELE(lp);
236 } else {
237 e = ESRCH;
238 }
239 p31b_proc_done(targetp);
41c20dac 240 }
3919ced0 241 if (e == 0)
984263bc 242 copyout(&sched_param, uap->param, sizeof(sched_param));
984263bc
MD
243 return e;
244}
41c20dac
MD
245
246int
753fd850 247sys_sched_setscheduler(struct sched_setscheduler_args *uap)
984263bc 248{
e9b43d11 249 struct proc *p;
08f2f1bb 250 struct lwp *lp;
984263bc 251 int e;
984263bc 252 struct sched_param sched_param;
3919ced0 253
984263bc
MD
254 copyin(uap->param, &sched_param, sizeof(sched_param));
255
e9b43d11 256 if ((e = p31b_proc(uap->pid, &p)) == 0) {
08f2f1bb 257 lp = FIRST_LWP_IN_PROC(p); /* XXX lwp */
e9b43d11
MD
258 if (lp) {
259 LWPHOLD(lp);
260 lwkt_gettoken(&lp->lwp_token);
261 e = ksched_setscheduler(&uap->sysmsg_reg, ksched,
262 lp, uap->policy,
3919ced0 263 (const struct sched_param *)&sched_param);
e9b43d11
MD
264 lwkt_reltoken(&lp->lwp_token);
265 LWPRELE(lp);
266 } else {
267 e = ESRCH;
268 }
269 p31b_proc_done(p);
41c20dac 270 }
984263bc
MD
271 return e;
272}
41c20dac
MD
273
274int
753fd850 275sys_sched_getscheduler(struct sched_getscheduler_args *uap)
984263bc
MD
276{
277 struct proc *targetp;
08f2f1bb 278 struct lwp *lp;
984263bc
MD
279 int e;
280
e9b43d11
MD
281 if ((e = p31b_proc(uap->pid, &targetp)) == 0) {
282 lp = FIRST_LWP_IN_PROC(targetp); /* XXX lwp */
283 if (lp) {
284 LWPHOLD(lp);
285 lwkt_gettoken(&lp->lwp_token);
286 e = ksched_getscheduler(&uap->sysmsg_reg, ksched, lp);
287 lwkt_reltoken(&lp->lwp_token);
288 LWPRELE(lp);
289 } else {
290 e = ESRCH;
291 }
292 p31b_proc_done(targetp);
41c20dac 293 }
984263bc
MD
294 return e;
295}
41c20dac 296
3919ced0
MD
297/*
298 * MPSAFE
299 */
41c20dac 300int
753fd850 301sys_sched_yield(struct sched_yield_args *uap)
984263bc 302{
bfc09ba0 303 return ksched_yield(&uap->sysmsg_reg, ksched);
984263bc 304}
41c20dac 305
3919ced0
MD
306/*
307 * MPSAFE
308 */
41c20dac 309int
753fd850 310sys_sched_get_priority_max(struct sched_get_priority_max_args *uap)
984263bc 311{
bfc09ba0 312 return ksched_get_priority_max(&uap->sysmsg_reg, ksched, uap->policy);
984263bc 313}
41c20dac 314
3919ced0
MD
315/*
316 * MPSAFE
317 */
41c20dac 318int
753fd850 319sys_sched_get_priority_min(struct sched_get_priority_min_args *uap)
984263bc 320{
bfc09ba0 321 return ksched_get_priority_min(&uap->sysmsg_reg, ksched, uap->policy);
984263bc 322}
41c20dac
MD
323
324int
753fd850 325sys_sched_rr_get_interval(struct sched_rr_get_interval_args *uap)
984263bc
MD
326{
327 int e;
e9b43d11
MD
328 struct proc *p;
329 struct lwp *lp;
e31a849e 330 struct timespec ts;
984263bc 331
e9b43d11
MD
332 if ((e = p31b_proc(uap->pid, &p)) == 0) {
333 lp = FIRST_LWP_IN_PROC(p); /* XXX lwp */
334 if (lp) {
335 LWPHOLD(lp);
336 lwkt_gettoken(&lp->lwp_token);
337 e = ksched_rr_get_interval(&uap->sysmsg_reg, ksched,
338 lp, &ts);
339 if (e == 0)
340 e = copyout(&ts, uap->interval, sizeof(ts));
341 lwkt_reltoken(&lp->lwp_token);
342 LWPRELE(lp);
343 } else {
344 e = ESRCH;
345 }
346 p31b_proc_done(p);
41c20dac 347 }
984263bc
MD
348 return e;
349}
350
351#endif
352
3919ced0
MD
353static void
354p31binit(void *notused)
984263bc 355{
2c9600ce 356 sched_attach();
08fc2af9 357 p31b_setcfg(CTL_P1003_1B_ASYNCHRONOUS_IO, -1);
12346ef9
SW
358 p31b_setcfg(CTL_P1003_1B_FSYNC, _POSIX_FSYNC);
359 p31b_setcfg(CTL_P1003_1B_MAPPED_FILES, _POSIX_MAPPED_FILES);
1973ed78 360 p31b_setcfg(CTL_P1003_1B_MESSAGE_PASSING, _POSIX_MESSAGE_PASSING);
2c9600ce 361 p31b_setcfg(CTL_P1003_1B_PAGESIZE, PAGE_SIZE);
12346ef9
SW
362 p31b_setcfg(CTL_P1003_1B_SEMAPHORES, _POSIX_SEMAPHORES);
363 p31b_setcfg(CTL_P1003_1B_SEM_NSEMS_MAX, 256);
2c9600ce
SW
364 p31b_setcfg(CTL_P1003_1B_SHARED_MEMORY_OBJECTS,
365 _POSIX_SHARED_MEMORY_OBJECTS);
12346ef9
SW
366
367#if 0 /* XXX missing */
368 p31b_setcfg(CTL_P1003_1B_ASYNCHRONOUS_IO, _POSIX_ASYNCHRONOUS_IO);
369 p31b_setcfg(CTL_P1003_1B_AIO_PRIO_DELTA_MAX, 0);
370 p31b_setcfg(CTL_P1003_1B_AIO_MAX, 0);
371 p31b_setcfg(CTL_P1003_1B_AIO_LISTIO_MAX, 0);
372 p31b_setcfg(CTL_P1003_1B_DELAYTIMER_MAX, 0);
373 p31b_setcfg(CTL_P1003_1B_MEMLOCK, 0);
374 p31b_setcfg(CTL_P1003_1B_MEMLOCK_RANGE, 0);
375 p31b_setcfg(CTL_P1003_1B_MEMORY_PROTECTION, 0);
376 p31b_setcfg(CTL_P1003_1B_PRIORITIZED_IO, _POSIX_PRIORITIZED_IO);
377 p31b_setcfg(CTL_P1003_1B_REALTIME_SIGNALS, _POSIX_REALTIME_SIGNALS);
378 p31b_setcfg(CTL_P1003_1B_RTSIG_MAX, SIGRTMAX - SIGRTMIN + 1);
379 p31b_setcfg(CTL_P1003_1B_SIGQUEUE_MAX, 0);
380 p31b_setcfg(CTL_P1003_1B_SYNCHRONIZED_IO, _POSIX_SYNCHRONIZED_IO);
381 p31b_setcfg(CTL_P1003_1B_TIMERS, _POSIX_TIMERS);
382 p31b_setcfg(CTL_P1003_1B_TIMER_MAX, 0);
383#endif
984263bc
MD
384}
385
386SYSINIT(p31b, SI_SUB_P1003_1B, SI_ORDER_FIRST, p31binit, NULL);