1 /* $NetBSD: linux_sched.c,v 1.18 2004/09/10 22:22:20 wiz Exp $ */
2
3 /*-
4 * Copyright (c) 1999 The NetBSD Foundation, Inc.
5 * All rights reserved.
6 *
7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility,
9 * NASA Ames Research Center; by Matthias Scheler.
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions and the following disclaimer.
16 * 2. Redistributions in binary form must reproduce the above copyright
17 * notice, this list of conditions and the following disclaimer in the
18 * documentation and/or other materials provided with the distribution.
19 * 3. All advertising materials mentioning features or use of this software
20 * must display the following acknowledgement:
21 * This product includes software developed by the NetBSD
22 * Foundation, Inc. and its contributors.
23 * 4. Neither the name of The NetBSD Foundation nor the names of its
24 * contributors may be used to endorse or promote products derived
25 * from this software without specific prior written permission.
26 *
27 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
28 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
29 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
30 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
31 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
32 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
33 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
34 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
35 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
36 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
37 * POSSIBILITY OF SUCH DAMAGE.
38 */
39
40 /*
41 * Linux compatibility module. Try to deal with scheduler related syscalls.
42 */
43
44 #include <sys/cdefs.h>
45 __KERNEL_RCSID(0, "$NetBSD: linux_sched.c,v 1.18 2004/09/10 22:22:20 wiz Exp $");
46
47 #include <sys/param.h>
48 #include <sys/mount.h>
49 #include <sys/proc.h>
50 #include <sys/systm.h>
51 #include <sys/sa.h>
52 #include <sys/syscallargs.h>
53 #include <sys/wait.h>
54
55 #include <machine/cpu.h>
56
57 #include <compat/linux/common/linux_types.h>
58 #include <compat/linux/common/linux_signal.h>
59
60 #include <compat/linux/linux_syscallargs.h>
61
62 #include <compat/linux/common/linux_sched.h>
63
64 int
65 linux_sys_clone(l, v, retval)
66 struct lwp *l;
67 void *v;
68 register_t *retval;
69 {
70 struct linux_sys_clone_args /* {
71 syscallarg(int) flags;
72 syscallarg(void *) stack;
73 } */ *uap = v;
74 int flags, sig;
75
76 /*
77 * We don't support the Linux CLONE_PID or CLONE_PTRACE flags.
78 */
79 if (SCARG(uap, flags) & (LINUX_CLONE_PID|LINUX_CLONE_PTRACE))
80 return (EINVAL);
81
82 /*
83 * Thread group implies shared signals. Shared signals
84 * imply shared VM. This matches what Linux kernel does.
85 */
86 if (SCARG(uap, flags) & LINUX_CLONE_THREAD
87 && (SCARG(uap, flags) & LINUX_CLONE_SIGHAND) == 0)
88 return (EINVAL);
89 if (SCARG(uap, flags) & LINUX_CLONE_SIGHAND
90 && (SCARG(uap, flags) & LINUX_CLONE_VM) == 0)
91 return (EINVAL);
92
93 flags = 0;
94
95 if (SCARG(uap, flags) & LINUX_CLONE_VM)
96 flags |= FORK_SHAREVM;
97 if (SCARG(uap, flags) & LINUX_CLONE_FS)
98 flags |= FORK_SHARECWD;
99 if (SCARG(uap, flags) & LINUX_CLONE_FILES)
100 flags |= FORK_SHAREFILES;
101 if (SCARG(uap, flags) & LINUX_CLONE_SIGHAND)
102 flags |= FORK_SHARESIGS;
103 if (SCARG(uap, flags) & LINUX_CLONE_VFORK)
104 flags |= FORK_PPWAIT;
105
106 sig = SCARG(uap, flags) & LINUX_CLONE_CSIGNAL;
107 if (sig < 0 || sig >= LINUX__NSIG)
108 return (EINVAL);
109 sig = linux_to_native_signo[sig];
110
111 /*
112 * Note that Linux does not provide a portable way of specifying
113 * the stack area; the caller must know if the stack grows up
114 * or down. So, we pass a stack size of 0, so that the code
115 * that makes this adjustment is a noop.
116 */
117 return (fork1(l, flags, sig, SCARG(uap, stack), 0,
118 NULL, NULL, retval, NULL));
119 }
120
121 int
122 linux_sys_sched_setparam(cl, v, retval)
123 struct lwp *cl;
124 void *v;
125 register_t *retval;
126 {
127 struct linux_sys_sched_setparam_args /* {
128 syscallarg(linux_pid_t) pid;
129 syscallarg(const struct linux_sched_param *) sp;
130 } */ *uap = v;
131 struct proc *cp = cl->l_proc;
132 int error;
133 struct linux_sched_param lp;
134 struct proc *p;
135
136 /*
137 * We only check for valid parameters and return afterwards.
138 */
139
140 if (SCARG(uap, pid) < 0 || SCARG(uap, sp) == NULL)
141 return EINVAL;
142
143 error = copyin(SCARG(uap, sp), &lp, sizeof(lp));
144 if (error)
145 return error;
146
147 if (SCARG(uap, pid) != 0) {
148 struct pcred *pc = cp->p_cred;
149
150 if ((p = pfind(SCARG(uap, pid))) == NULL)
151 return ESRCH;
152 if (!(cp == p ||
153 pc->pc_ucred->cr_uid == 0 ||
154 pc->p_ruid == p->p_cred->p_ruid ||
155 pc->pc_ucred->cr_uid == p->p_cred->p_ruid ||
156 pc->p_ruid == p->p_ucred->cr_uid ||
157 pc->pc_ucred->cr_uid == p->p_ucred->cr_uid))
158 return EPERM;
159 }
160
161 return 0;
162 }
163
164 int
165 linux_sys_sched_getparam(cl, v, retval)
166 struct lwp *cl;
167 void *v;
168 register_t *retval;
169 {
170 struct linux_sys_sched_getparam_args /* {
171 syscallarg(linux_pid_t) pid;
172 syscallarg(struct linux_sched_param *) sp;
173 } */ *uap = v;
174 struct proc *cp = cl->l_proc;
175 struct proc *p;
176 struct linux_sched_param lp;
177
178 /*
179 * We only check for valid parameters and return a dummy priority afterwards.
180 */
181 if (SCARG(uap, pid) < 0 || SCARG(uap, sp) == NULL)
182 return EINVAL;
183
184 if (SCARG(uap, pid) != 0) {
185 struct pcred *pc = cp->p_cred;
186
187 if ((p = pfind(SCARG(uap, pid))) == NULL)
188 return ESRCH;
189 if (!(cp == p ||
190 pc->pc_ucred->cr_uid == 0 ||
191 pc->p_ruid == p->p_cred->p_ruid ||
192 pc->pc_ucred->cr_uid == p->p_cred->p_ruid ||
193 pc->p_ruid == p->p_ucred->cr_uid ||
194 pc->pc_ucred->cr_uid == p->p_ucred->cr_uid))
195 return EPERM;
196 }
197
198 lp.sched_priority = 0;
199 return copyout(&lp, SCARG(uap, sp), sizeof(lp));
200 }
201
202 int
203 linux_sys_sched_setscheduler(cl, v, retval)
204 struct lwp *cl;
205 void *v;
206 register_t *retval;
207 {
208 struct linux_sys_sched_setscheduler_args /* {
209 syscallarg(linux_pid_t) pid;
210 syscallarg(int) policy;
211 syscallarg(cont struct linux_sched_scheduler *) sp;
212 } */ *uap = v;
213 struct proc *cp = cl->l_proc;
214 int error;
215 struct linux_sched_param lp;
216 struct proc *p;
217
218 /*
219 * We only check for valid parameters and return afterwards.
220 */
221
222 if (SCARG(uap, pid) < 0 || SCARG(uap, sp) == NULL)
223 return EINVAL;
224
225 error = copyin(SCARG(uap, sp), &lp, sizeof(lp));
226 if (error)
227 return error;
228
229 if (SCARG(uap, pid) != 0) {
230 struct pcred *pc = cp->p_cred;
231
232 if ((p = pfind(SCARG(uap, pid))) == NULL)
233 return ESRCH;
234 if (!(cp == p ||
235 pc->pc_ucred->cr_uid == 0 ||
236 pc->p_ruid == p->p_cred->p_ruid ||
237 pc->pc_ucred->cr_uid == p->p_cred->p_ruid ||
238 pc->p_ruid == p->p_ucred->cr_uid ||
239 pc->pc_ucred->cr_uid == p->p_ucred->cr_uid))
240 return EPERM;
241 }
242
243 /*
244 * We can't emulate anything put the default scheduling policy.
245 */
246 if (SCARG(uap, policy) != LINUX_SCHED_OTHER || lp.sched_priority != 0)
247 return EINVAL;
248
249 return 0;
250 }
251
252 int
253 linux_sys_sched_getscheduler(cl, v, retval)
254 struct lwp *cl;
255 void *v;
256 register_t *retval;
257 {
258 struct linux_sys_sched_getscheduler_args /* {
259 syscallarg(linux_pid_t) pid;
260 } */ *uap = v;
261 struct proc *cp = cl->l_proc;
262 struct proc *p;
263
264 *retval = -1;
265 /*
266 * We only check for valid parameters and return afterwards.
267 */
268
269 if (SCARG(uap, pid) != 0) {
270 struct pcred *pc = cp->p_cred;
271
272 if ((p = pfind(SCARG(uap, pid))) == NULL)
273 return ESRCH;
274 if (!(cp == p ||
275 pc->pc_ucred->cr_uid == 0 ||
276 pc->p_ruid == p->p_cred->p_ruid ||
277 pc->pc_ucred->cr_uid == p->p_cred->p_ruid ||
278 pc->p_ruid == p->p_ucred->cr_uid ||
279 pc->pc_ucred->cr_uid == p->p_ucred->cr_uid))
280 return EPERM;
281 }
282
283 /*
284 * We can't emulate anything put the default scheduling policy.
285 */
286 *retval = LINUX_SCHED_OTHER;
287 return 0;
288 }
289
290 int
291 linux_sys_sched_yield(cl, v, retval)
292 struct lwp *cl;
293 void *v;
294 register_t *retval;
295 {
296
297 yield();
298 return 0;
299 }
300
301 int
302 linux_sys_sched_get_priority_max(cl, v, retval)
303 struct lwp *cl;
304 void *v;
305 register_t *retval;
306 {
307 struct linux_sys_sched_get_priority_max_args /* {
308 syscallarg(int) policy;
309 } */ *uap = v;
310
311 /*
312 * We can't emulate anything put the default scheduling policy.
313 */
314 if (SCARG(uap, policy) != LINUX_SCHED_OTHER) {
315 *retval = -1;
316 return EINVAL;
317 }
318
319 *retval = 0;
320 return 0;
321 }
322
323 int
324 linux_sys_sched_get_priority_min(cl, v, retval)
325 struct lwp *cl;
326 void *v;
327 register_t *retval;
328 {
329 struct linux_sys_sched_get_priority_min_args /* {
330 syscallarg(int) policy;
331 } */ *uap = v;
332
333 /*
334 * We can't emulate anything put the default scheduling policy.
335 */
336 if (SCARG(uap, policy) != LINUX_SCHED_OTHER) {
337 *retval = -1;
338 return EINVAL;
339 }
340
341 *retval = 0;
342 return 0;
343 }
344
345 #ifndef __m68k__
346 /* Present on everything but m68k */
347 int
348 linux_sys_exit_group(l, v, retval)
349 struct lwp *l;
350 void *v;
351 register_t *retval;
352 {
353 struct linux_sys_exit_group_args /* {
354 syscallarg(int) error_code;
355 } */ *uap = v;
356
357 /*
358 * XXX The calling thread is supposed to kill all threads
359 * in the same thread group (i.e. all threads created
360 * via clone(2) with CLONE_THREAD flag set). This appears
361 * to not be used yet, so the thread group handling
362 * is currently not implemented.
363 */
364
365 exit1(l, W_EXITCODE(SCARG(uap, error_code), 0));
366 /* NOTREACHED */
367 return 0;
368 }
369 #endif /* !__m68k__ */
Cache object: b405e6793d21f1ed8789f82cc828b32d
|