linux_sched.c revision 1.1.2.1 1 /* $NetBSD: linux_sched.c,v 1.1.2.1 1999/12/27 18:34:27 wrstuden 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, retval, NULL));
103 }
104
105 int
106 linux_sys_sched_setparam(cp, v, retval)
107 struct proc *cp;
108 void *v;
109 register_t *retval;
110 {
111 struct linux_sys_sched_setparam_args /* {
112 syscallarg(linux_pid_t) pid;
113 syscallarg(const struct linux_sched_param *) sp;
114 } */ *uap = v;
115 int error;
116 struct linux_sched_param lp;
117 register struct proc *p;
118
119 /*
120 * We only check for valid parameters and return afterwards.
121 */
122
123 if (SCARG(uap, pid) < 0 || SCARG(uap, sp) == NULL)
124 return EINVAL;
125
126 error = copyin(SCARG(uap, sp), &lp, sizeof(lp));
127 if (error)
128 return error;
129
130 if (SCARG(uap, pid) != 0) {
131 register struct pcred *pc = cp->p_cred;
132
133 if ((p = pfind(SCARG(uap, pid))) == NULL)
134 return ESRCH;
135 if (!(cp == p ||
136 pc->pc_ucred->cr_uid == 0 ||
137 pc->p_ruid == p->p_cred->p_ruid ||
138 pc->pc_ucred->cr_uid == p->p_cred->p_ruid ||
139 pc->p_ruid == p->p_ucred->cr_uid ||
140 pc->pc_ucred->cr_uid == p->p_ucred->cr_uid))
141 return EPERM;
142 }
143
144 return 0;
145 }
146
147 int
148 linux_sys_sched_getparam(cp, v, retval)
149 struct proc *cp;
150 void *v;
151 register_t *retval;
152 {
153 struct linux_sys_sched_getparam_args /* {
154 syscallarg(linux_pid_t) pid;
155 syscallarg(struct linux_sched_param *) sp;
156 } */ *uap = v;
157 register struct proc *p;
158 struct linux_sched_param lp;
159
160 /*
161 * We only check for valid parameters and return a dummy priority afterwards.
162 */
163 if (SCARG(uap, pid) < 0 || SCARG(uap, sp) == NULL)
164 return EINVAL;
165
166 if (SCARG(uap, pid) != 0) {
167 register struct pcred *pc = cp->p_cred;
168
169 if ((p = pfind(SCARG(uap, pid))) == NULL)
170 return ESRCH;
171 if (!(cp == p ||
172 pc->pc_ucred->cr_uid == 0 ||
173 pc->p_ruid == p->p_cred->p_ruid ||
174 pc->pc_ucred->cr_uid == p->p_cred->p_ruid ||
175 pc->p_ruid == p->p_ucred->cr_uid ||
176 pc->pc_ucred->cr_uid == p->p_ucred->cr_uid))
177 return EPERM;
178 }
179
180 lp.sched_priority = 0;
181 return copyout(&lp, SCARG(uap, sp), sizeof(lp));
182 }
183
184 int
185 linux_sys_sched_setscheduler(cp, v, retval)
186 struct proc *cp;
187 void *v;
188 register_t *retval;
189 {
190 struct linux_sys_sched_setscheduler_args /* {
191 syscallarg(linux_pid_t) pid;
192 syscallarg(int) policy;
193 syscallarg(cont struct linux_sched_scheduler *) sp;
194 } */ *uap = v;
195 int error;
196 struct linux_sched_param lp;
197 register struct proc *p;
198
199 /*
200 * We only check for valid parameters and return afterwards.
201 */
202
203 if (SCARG(uap, pid) < 0 || SCARG(uap, sp) == NULL)
204 return EINVAL;
205
206 error = copyin(SCARG(uap, sp), &lp, sizeof(lp));
207 if (error)
208 return error;
209
210 if (SCARG(uap, pid) != 0) {
211 register struct pcred *pc = cp->p_cred;
212
213 if ((p = pfind(SCARG(uap, pid))) == NULL)
214 return ESRCH;
215 if (!(cp == p ||
216 pc->pc_ucred->cr_uid == 0 ||
217 pc->p_ruid == p->p_cred->p_ruid ||
218 pc->pc_ucred->cr_uid == p->p_cred->p_ruid ||
219 pc->p_ruid == p->p_ucred->cr_uid ||
220 pc->pc_ucred->cr_uid == p->p_ucred->cr_uid))
221 return EPERM;
222 }
223
224 /*
225 * We can't emulate anything put the default scheduling policy.
226 */
227 if (SCARG(uap, policy) != LINUX_SCHED_OTHER || lp.sched_priority != 0)
228 return EINVAL;
229
230 return 0;
231 }
232
233 int
234 linux_sys_sched_getscheduler(cp, v, retval)
235 struct proc *cp;
236 void *v;
237 register_t *retval;
238 {
239 struct linux_sys_sched_getscheduler_args /* {
240 syscallarg(linux_pid_t) pid;
241 } */ *uap = v;
242 register struct proc *p;
243
244 *retval = -1;
245 /*
246 * We only check for valid parameters and return afterwards.
247 */
248
249 if (SCARG(uap, pid) != 0) {
250 register struct pcred *pc = cp->p_cred;
251
252 if ((p = pfind(SCARG(uap, pid))) == NULL)
253 return ESRCH;
254 if (!(cp == p ||
255 pc->pc_ucred->cr_uid == 0 ||
256 pc->p_ruid == p->p_cred->p_ruid ||
257 pc->pc_ucred->cr_uid == p->p_cred->p_ruid ||
258 pc->p_ruid == p->p_ucred->cr_uid ||
259 pc->pc_ucred->cr_uid == p->p_ucred->cr_uid))
260 return EPERM;
261 }
262
263 /*
264 * We can't emulate anything put the default scheduling policy.
265 */
266 *retval = LINUX_SCHED_OTHER;
267 return 0;
268 }
269
270 int
271 linux_sys_sched_yield(cp, v, retval)
272 struct proc *cp;
273 void *v;
274 register_t *retval;
275 {
276 need_resched();
277 return 0;
278 }
279
280 int
281 linux_sys_sched_get_priority_max(cp, v, retval)
282 struct proc *cp;
283 void *v;
284 register_t *retval;
285 {
286 struct linux_sys_sched_get_priority_max_args /* {
287 syscallarg(int) policy;
288 } */ *uap = v;
289
290 /*
291 * We can't emulate anything put the default scheduling policy.
292 */
293 if (SCARG(uap, policy) != LINUX_SCHED_OTHER) {
294 *retval = -1;
295 return EINVAL;
296 }
297
298 *retval = 0;
299 return 0;
300 }
301
302 int
303 linux_sys_sched_get_priority_min(cp, v, retval)
304 struct proc *cp;
305 void *v;
306 register_t *retval;
307 {
308 struct linux_sys_sched_get_priority_min_args /* {
309 syscallarg(int) policy;
310 } */ *uap = v;
311
312 /*
313 * We can't emulate anything put the default scheduling policy.
314 */
315 if (SCARG(uap, policy) != LINUX_SCHED_OTHER) {
316 *retval = -1;
317 return EINVAL;
318 }
319
320 *retval = 0;
321 return 0;
322 }
323