linux_sched.c revision 1.7.2.2 1 /* $NetBSD: linux_sched.c,v 1.7.2.2 2001/11/14 19:13:13 nathanw 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.7.2.2 2001/11/14 19:13:13 nathanw Exp $");
46
47 #include <sys/types.h>
48 #include <sys/param.h>
49 #include <sys/mount.h>
50 #include <sys/lwp.h>
51 #include <sys/proc.h>
52 #include <sys/systm.h>
53 #include <sys/syscallargs.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 flags = 0;
83
84 if (SCARG(uap, flags) & LINUX_CLONE_VM)
85 flags |= FORK_SHAREVM;
86 if (SCARG(uap, flags) & LINUX_CLONE_FS)
87 flags |= FORK_SHARECWD;
88 if (SCARG(uap, flags) & LINUX_CLONE_FILES)
89 flags |= FORK_SHAREFILES;
90 if (SCARG(uap, flags) & LINUX_CLONE_SIGHAND)
91 flags |= FORK_SHARESIGS;
92 if (SCARG(uap, flags) & LINUX_CLONE_VFORK)
93 flags |= FORK_PPWAIT;
94
95 sig = SCARG(uap, flags) & LINUX_CLONE_CSIGNAL;
96 if (sig < 0 || sig >= LINUX__NSIG)
97 return (EINVAL);
98 sig = linux_to_native_sig[sig];
99
100 /*
101 * Note that Linux does not provide a portable way of specifying
102 * the stack area; the caller must know if the stack grows up
103 * or down. So, we pass a stack size of 0, so that the code
104 * that makes this adjustment is a noop.
105 */
106 return (fork1(l, flags, sig, SCARG(uap, stack), 0,
107 NULL, NULL, retval, NULL));
108 }
109
110 int
111 linux_sys_sched_setparam(cl, v, retval)
112 struct lwp *cl;
113 void *v;
114 register_t *retval;
115 {
116 struct linux_sys_sched_setparam_args /* {
117 syscallarg(linux_pid_t) pid;
118 syscallarg(const struct linux_sched_param *) sp;
119 } */ *uap = v;
120 struct proc *cp = cl->l_proc;
121 int error;
122 struct linux_sched_param lp;
123 struct proc *p;
124
125 /*
126 * We only check for valid parameters and return afterwards.
127 */
128
129 if (SCARG(uap, pid) < 0 || SCARG(uap, sp) == NULL)
130 return EINVAL;
131
132 error = copyin(SCARG(uap, sp), &lp, sizeof(lp));
133 if (error)
134 return error;
135
136 if (SCARG(uap, pid) != 0) {
137 struct pcred *pc = cp->p_cred;
138
139 if ((p = pfind(SCARG(uap, pid))) == NULL)
140 return ESRCH;
141 if (!(cp == p ||
142 pc->pc_ucred->cr_uid == 0 ||
143 pc->p_ruid == p->p_cred->p_ruid ||
144 pc->pc_ucred->cr_uid == p->p_cred->p_ruid ||
145 pc->p_ruid == p->p_ucred->cr_uid ||
146 pc->pc_ucred->cr_uid == p->p_ucred->cr_uid))
147 return EPERM;
148 }
149
150 return 0;
151 }
152
153 int
154 linux_sys_sched_getparam(cl, v, retval)
155 struct lwp *cl;
156 void *v;
157 register_t *retval;
158 {
159 struct linux_sys_sched_getparam_args /* {
160 syscallarg(linux_pid_t) pid;
161 syscallarg(struct linux_sched_param *) sp;
162 } */ *uap = v;
163 struct proc *cp = cl->l_proc;
164 struct proc *p;
165 struct linux_sched_param lp;
166
167 /*
168 * We only check for valid parameters and return a dummy priority afterwards.
169 */
170 if (SCARG(uap, pid) < 0 || SCARG(uap, sp) == NULL)
171 return EINVAL;
172
173 if (SCARG(uap, pid) != 0) {
174 struct pcred *pc = cp->p_cred;
175
176 if ((p = pfind(SCARG(uap, pid))) == NULL)
177 return ESRCH;
178 if (!(cp == p ||
179 pc->pc_ucred->cr_uid == 0 ||
180 pc->p_ruid == p->p_cred->p_ruid ||
181 pc->pc_ucred->cr_uid == p->p_cred->p_ruid ||
182 pc->p_ruid == p->p_ucred->cr_uid ||
183 pc->pc_ucred->cr_uid == p->p_ucred->cr_uid))
184 return EPERM;
185 }
186
187 lp.sched_priority = 0;
188 return copyout(&lp, SCARG(uap, sp), sizeof(lp));
189 }
190
191 int
192 linux_sys_sched_setscheduler(cl, v, retval)
193 struct lwp *cl;
194 void *v;
195 register_t *retval;
196 {
197 struct linux_sys_sched_setscheduler_args /* {
198 syscallarg(linux_pid_t) pid;
199 syscallarg(int) policy;
200 syscallarg(cont struct linux_sched_scheduler *) sp;
201 } */ *uap = v;
202 struct proc *cp = cl->l_proc;
203 int error;
204 struct linux_sched_param lp;
205 struct proc *p;
206
207 /*
208 * We only check for valid parameters and return afterwards.
209 */
210
211 if (SCARG(uap, pid) < 0 || SCARG(uap, sp) == NULL)
212 return EINVAL;
213
214 error = copyin(SCARG(uap, sp), &lp, sizeof(lp));
215 if (error)
216 return error;
217
218 if (SCARG(uap, pid) != 0) {
219 struct pcred *pc = cp->p_cred;
220
221 if ((p = pfind(SCARG(uap, pid))) == NULL)
222 return ESRCH;
223 if (!(cp == p ||
224 pc->pc_ucred->cr_uid == 0 ||
225 pc->p_ruid == p->p_cred->p_ruid ||
226 pc->pc_ucred->cr_uid == p->p_cred->p_ruid ||
227 pc->p_ruid == p->p_ucred->cr_uid ||
228 pc->pc_ucred->cr_uid == p->p_ucred->cr_uid))
229 return EPERM;
230 }
231
232 /*
233 * We can't emulate anything put the default scheduling policy.
234 */
235 if (SCARG(uap, policy) != LINUX_SCHED_OTHER || lp.sched_priority != 0)
236 return EINVAL;
237
238 return 0;
239 }
240
241 int
242 linux_sys_sched_getscheduler(cl, v, retval)
243 struct lwp *cl;
244 void *v;
245 register_t *retval;
246 {
247 struct linux_sys_sched_getscheduler_args /* {
248 syscallarg(linux_pid_t) pid;
249 } */ *uap = v;
250 struct proc *cp = cl->l_proc;
251 struct proc *p;
252
253 *retval = -1;
254 /*
255 * We only check for valid parameters and return afterwards.
256 */
257
258 if (SCARG(uap, pid) != 0) {
259 struct pcred *pc = cp->p_cred;
260
261 if ((p = pfind(SCARG(uap, pid))) == NULL)
262 return ESRCH;
263 if (!(cp == p ||
264 pc->pc_ucred->cr_uid == 0 ||
265 pc->p_ruid == p->p_cred->p_ruid ||
266 pc->pc_ucred->cr_uid == p->p_cred->p_ruid ||
267 pc->p_ruid == p->p_ucred->cr_uid ||
268 pc->pc_ucred->cr_uid == p->p_ucred->cr_uid))
269 return EPERM;
270 }
271
272 /*
273 * We can't emulate anything put the default scheduling policy.
274 */
275 *retval = LINUX_SCHED_OTHER;
276 return 0;
277 }
278
279 int
280 linux_sys_sched_yield(cl, v, retval)
281 struct lwp *cl;
282 void *v;
283 register_t *retval;
284 {
285 need_resched(curcpu());
286 return 0;
287 }
288
289 int
290 linux_sys_sched_get_priority_max(cl, v, retval)
291 struct lwp *cl;
292 void *v;
293 register_t *retval;
294 {
295 struct linux_sys_sched_get_priority_max_args /* {
296 syscallarg(int) policy;
297 } */ *uap = v;
298
299 /*
300 * We can't emulate anything put the default scheduling policy.
301 */
302 if (SCARG(uap, policy) != LINUX_SCHED_OTHER) {
303 *retval = -1;
304 return EINVAL;
305 }
306
307 *retval = 0;
308 return 0;
309 }
310
311 int
312 linux_sys_sched_get_priority_min(cl, v, retval)
313 struct lwp *cl;
314 void *v;
315 register_t *retval;
316 {
317 struct linux_sys_sched_get_priority_min_args /* {
318 syscallarg(int) policy;
319 } */ *uap = v;
320
321 /*
322 * We can't emulate anything put the default scheduling policy.
323 */
324 if (SCARG(uap, policy) != LINUX_SCHED_OTHER) {
325 *retval = -1;
326 return EINVAL;
327 }
328
329 *retval = 0;
330 return 0;
331 }
332