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