memory: use sys_safememset() for /dev/zero
[minix.git] / kernel / system.c
blobcb6ef14e8b33ae4e36de5091d286da3ca708c738
1 /* This task handles the interface between the kernel and user-level servers.
2 * System services can be accessed by doing a system call. System calls are
3 * transformed into request messages, which are handled by this task. By
4 * convention, a sys_call() is transformed in a SYS_CALL request message that
5 * is handled in a function named do_call().
7 * A private call vector is used to map all system calls to the functions that
8 * handle them. The actual handler functions are contained in separate files
9 * to keep this file clean. The call vector is used in the system task's main
10 * loop to handle all incoming requests.
12 * In addition to the main sys_task() entry point, which starts the main loop,
13 * there are several other minor entry points:
14 * get_priv: assign privilege structure to user or system process
15 * set_sendto_bit: allow a process to send messages to a new target
16 * unset_sendto_bit: disallow a process from sending messages to a target
17 * fill_sendto_mask: fill the target mask of a given process
18 * send_sig: send a signal directly to a system process
19 * cause_sig: take action to cause a signal to occur via a signal mgr
20 * sig_delay_done: tell PM that a process is not sending
21 * get_randomness: accumulate randomness in a buffer
22 * clear_endpoint: remove a process' ability to send and receive messages
23 * sched_proc: schedule a process
25 * Changes:
26 * Nov 22, 2009 get_priv supports static priv ids (Cristiano Giuffrida)
27 * Aug 04, 2005 check if system call is allowed (Jorrit N. Herder)
28 * Jul 20, 2005 send signal to services with message (Jorrit N. Herder)
29 * Jan 15, 2005 new, generalized virtual copy function (Jorrit N. Herder)
30 * Oct 10, 2004 dispatch system calls from call vector (Jorrit N. Herder)
31 * Sep 30, 2004 source code documentation updated (Jorrit N. Herder)
34 #include "kernel.h"
35 #include "system.h"
36 #include "vm.h"
37 #include "kernel/clock.h"
38 #include <stdlib.h>
39 #include <assert.h>
40 #include <signal.h>
41 #include <unistd.h>
42 #include <minix/endpoint.h>
43 #include <minix/safecopies.h>
45 /* Declaration of the call vector that defines the mapping of system calls
46 * to handler functions. The vector is initialized in sys_init() with map(),
47 * which makes sure the system call numbers are ok. No space is allocated,
48 * because the dummy is declared extern. If an illegal call is given, the
49 * array size will be negative and this won't compile.
51 static int (*call_vec[NR_SYS_CALLS])(struct proc * caller, message *m_ptr);
53 #define map(call_nr, handler) \
54 { int call_index = call_nr-KERNEL_CALL; \
55 assert(call_index >= 0 && call_index < NR_SYS_CALLS); \
56 call_vec[call_index] = (handler) ; }
58 static void kernel_call_finish(struct proc * caller, message *msg, int result)
60 if(result == VMSUSPEND) {
61 /* Special case: message has to be saved for handling
62 * until VM tells us it's allowed. VM has been notified
63 * and we must wait for its reply to restart the call.
65 assert(RTS_ISSET(caller, RTS_VMREQUEST));
66 assert(caller->p_vmrequest.type == VMSTYPE_KERNELCALL);
67 caller->p_vmrequest.saved.reqmsg = *msg;
68 caller->p_misc_flags |= MF_KCALL_RESUME;
69 } else {
71 * call is finished, we could have been suspended because of VM,
72 * remove the request message
74 caller->p_vmrequest.saved.reqmsg.m_source = NONE;
75 if (result != EDONTREPLY) {
76 /* copy the result as a message to the original user buffer */
77 msg->m_source = SYSTEM;
78 msg->m_type = result; /* report status of call */
79 #if DEBUG_IPC_HOOK
80 hook_ipc_msgkresult(msg, caller);
81 #endif
82 if (copy_msg_to_user(msg, (message *)caller->p_delivermsg_vir)) {
83 printf("WARNING wrong user pointer 0x%08x from "
84 "process %s / %d\n",
85 caller->p_delivermsg_vir,
86 caller->p_name,
87 caller->p_endpoint);
88 cause_sig(proc_nr(caller), SIGSEGV);
94 static int kernel_call_dispatch(struct proc * caller, message *msg)
96 int result = OK;
97 int call_nr;
99 #if DEBUG_IPC_HOOK
100 hook_ipc_msgkcall(msg, caller);
101 #endif
102 call_nr = msg->m_type - KERNEL_CALL;
104 /* See if the caller made a valid request and try to handle it. */
105 if (call_nr < 0 || call_nr >= NR_SYS_CALLS) { /* check call number */
106 printf("SYSTEM: illegal request %d from %d.\n",
107 call_nr,msg->m_source);
108 result = EBADREQUEST; /* illegal message type */
110 else if (!GET_BIT(priv(caller)->s_k_call_mask, call_nr)) {
111 printf("SYSTEM: denied request %d from %d.\n",
112 call_nr,msg->m_source);
113 result = ECALLDENIED; /* illegal message type */
114 } else {
115 /* handle the system call */
116 if (call_vec[call_nr])
117 result = (*call_vec[call_nr])(caller, msg);
118 else {
119 printf("Unused kernel call %d from %d\n",
120 call_nr, caller->p_endpoint);
121 result = EBADREQUEST;
125 return result;
128 /*===========================================================================*
129 * kernel_call *
130 *===========================================================================*/
132 * this function checks the basic syscall parameters and if accepted it
133 * dispatches its handling to the right handler
135 void kernel_call(message *m_user, struct proc * caller)
137 int result = OK;
138 message msg;
140 caller->p_delivermsg_vir = (vir_bytes) m_user;
142 * the ldt and cr3 of the caller process is loaded because it just've trapped
143 * into the kernel or was already set in switch_to_user() before we resume
144 * execution of an interrupted kernel call
146 if (copy_msg_from_user(m_user, &msg) == 0) {
147 msg.m_source = caller->p_endpoint;
148 result = kernel_call_dispatch(caller, &msg);
150 else {
151 printf("WARNING wrong user pointer 0x%08x from process %s / %d\n",
152 m_user, caller->p_name, caller->p_endpoint);
153 cause_sig(proc_nr(caller), SIGSEGV);
154 return;
158 /* remember who invoked the kcall so we can bill it its time */
159 kbill_kcall = caller;
161 kernel_call_finish(caller, &msg, result);
164 /*===========================================================================*
165 * initialize *
166 *===========================================================================*/
167 void system_init(void)
169 register struct priv *sp;
170 int i;
172 /* Initialize IRQ handler hooks. Mark all hooks available. */
173 for (i=0; i<NR_IRQ_HOOKS; i++) {
174 irq_hooks[i].proc_nr_e = NONE;
177 /* Initialize all alarm timers for all processes. */
178 for (sp=BEG_PRIV_ADDR; sp < END_PRIV_ADDR; sp++) {
179 tmr_inittimer(&(sp->s_alarm_timer));
182 /* Initialize the call vector to a safe default handler. Some system calls
183 * may be disabled or nonexistant. Then explicitely map known calls to their
184 * handler functions. This is done with a macro that gives a compile error
185 * if an illegal call number is used. The ordering is not important here.
187 for (i=0; i<NR_SYS_CALLS; i++) {
188 call_vec[i] = NULL;
191 /* Process management. */
192 map(SYS_FORK, do_fork); /* a process forked a new process */
193 map(SYS_EXEC, do_exec); /* update process after execute */
194 map(SYS_CLEAR, do_clear); /* clean up after process exit */
195 map(SYS_EXIT, do_exit); /* a system process wants to exit */
196 map(SYS_PRIVCTL, do_privctl); /* system privileges control */
197 map(SYS_TRACE, do_trace); /* request a trace operation */
198 map(SYS_SETGRANT, do_setgrant); /* get/set own parameters */
199 map(SYS_RUNCTL, do_runctl); /* set/clear stop flag of a process */
200 map(SYS_UPDATE, do_update); /* update a process into another */
201 map(SYS_STATECTL, do_statectl); /* let a process control its state */
203 /* Signal handling. */
204 map(SYS_KILL, do_kill); /* cause a process to be signaled */
205 map(SYS_GETKSIG, do_getksig); /* signal manager checks for signals */
206 map(SYS_ENDKSIG, do_endksig); /* signal manager finished signal */
207 map(SYS_SIGSEND, do_sigsend); /* start POSIX-style signal */
208 map(SYS_SIGRETURN, do_sigreturn); /* return from POSIX-style signal */
210 /* Device I/O. */
211 map(SYS_IRQCTL, do_irqctl); /* interrupt control operations */
212 map(SYS_DEVIO, do_devio); /* inb, inw, inl, outb, outw, outl */
213 map(SYS_VDEVIO, do_vdevio); /* vector with devio requests */
215 /* Memory management. */
216 map(SYS_MEMSET, do_memset); /* write char to memory area */
217 map(SYS_VMCTL, do_vmctl); /* various VM process settings */
219 /* Copying. */
220 map(SYS_UMAP, do_umap); /* map virtual to physical address */
221 map(SYS_UMAP_REMOTE, do_umap_remote); /* do_umap for non-caller process */
222 map(SYS_VUMAP, do_vumap); /* vectored virtual to physical map */
223 map(SYS_VIRCOPY, do_vircopy); /* use pure virtual addressing */
224 map(SYS_PHYSCOPY, do_copy); /* use physical addressing */
225 map(SYS_SAFECOPYFROM, do_safecopy_from);/* copy with pre-granted permission */
226 map(SYS_SAFECOPYTO, do_safecopy_to); /* copy with pre-granted permission */
227 map(SYS_VSAFECOPY, do_vsafecopy); /* vectored safecopy */
229 /* safe memset */
230 map(SYS_SAFEMEMSET, do_safememset); /* safememset */
232 /* Mapping. */
233 map(SYS_SAFEMAP, do_safemap); /* map pages from other process */
234 map(SYS_SAFEREVMAP, do_saferevmap); /* grantor revokes the map grant */
235 map(SYS_SAFEUNMAP, do_safeunmap); /* requestor unmaps the mapped pages */
237 /* Clock functionality. */
238 map(SYS_TIMES, do_times); /* get uptime and process times */
239 map(SYS_SETALARM, do_setalarm); /* schedule a synchronous alarm */
240 map(SYS_STIME, do_stime); /* set the boottime */
241 map(SYS_VTIMER, do_vtimer); /* set or retrieve a virtual timer */
243 /* System control. */
244 map(SYS_ABORT, do_abort); /* abort MINIX */
245 map(SYS_GETINFO, do_getinfo); /* request system information */
246 map(SYS_SYSCTL, do_sysctl); /* misc system manipulation */
248 /* Profiling. */
249 map(SYS_SPROF, do_sprofile); /* start/stop statistical profiling */
250 map(SYS_CPROF, do_cprofile); /* get/reset call profiling data */
251 map(SYS_PROFBUF, do_profbuf); /* announce locations to kernel */
253 /* i386-specific. */
254 #if defined(__i386__)
255 map(SYS_READBIOS, do_readbios); /* read from BIOS locations */
256 map(SYS_IOPENABLE, do_iopenable); /* Enable I/O */
257 map(SYS_SDEVIO, do_sdevio); /* phys_insb, _insw, _outsb, _outsw */
259 /* Machine state switching. */
260 map(SYS_SETMCONTEXT, do_setmcontext); /* set machine context */
261 map(SYS_GETMCONTEXT, do_getmcontext); /* get machine context */
262 #endif
264 /* Scheduling */
265 map(SYS_SCHEDULE, do_schedule); /* reschedule a process */
266 map(SYS_SCHEDCTL, do_schedctl); /* change process scheduler */
269 /*===========================================================================*
270 * get_priv *
271 *===========================================================================*/
272 int get_priv(rc, priv_id)
273 register struct proc *rc; /* new (child) process pointer */
274 int priv_id; /* privilege id */
276 /* Allocate a new privilege structure for a system process. Privilege ids
277 * can be assigned either statically or dynamically.
279 register struct priv *sp; /* privilege structure */
281 if(priv_id == NULL_PRIV_ID) { /* allocate slot dynamically */
282 for (sp = BEG_DYN_PRIV_ADDR; sp < END_DYN_PRIV_ADDR; ++sp)
283 if (sp->s_proc_nr == NONE) break;
284 if (sp >= END_DYN_PRIV_ADDR) return(ENOSPC);
286 else { /* allocate slot from id */
287 if(!is_static_priv_id(priv_id)) {
288 return EINVAL; /* invalid static priv id */
290 if(priv[priv_id].s_proc_nr != NONE) {
291 return EBUSY; /* slot already in use */
293 sp = &priv[priv_id];
295 rc->p_priv = sp; /* assign new slot */
296 rc->p_priv->s_proc_nr = proc_nr(rc); /* set association */
298 return(OK);
301 /*===========================================================================*
302 * set_sendto_bit *
303 *===========================================================================*/
304 void set_sendto_bit(const struct proc *rp, int id)
306 /* Allow a process to send messages to the process(es) associated with the
307 * system privilege structure with the given ID.
310 /* Disallow the process from sending to a process privilege structure with no
311 * associated process, and disallow the process from sending to itself.
313 if (id_to_nr(id) == NONE || priv_id(rp) == id) {
314 unset_sys_bit(priv(rp)->s_ipc_to, id);
315 return;
318 set_sys_bit(priv(rp)->s_ipc_to, id);
320 /* The process that this process can now send to, must be able to reply (or
321 * vice versa). Therefore, its send mask should be updated as well. Ignore
322 * receivers that don't support traps other than RECEIVE, they can't reply
323 * or send messages anyway.
325 if (priv_addr(id)->s_trap_mask & ~((1 << RECEIVE)))
326 set_sys_bit(priv_addr(id)->s_ipc_to, priv_id(rp));
329 /*===========================================================================*
330 * unset_sendto_bit *
331 *===========================================================================*/
332 void unset_sendto_bit(const struct proc *rp, int id)
334 /* Prevent a process from sending to another process. Retain the send mask
335 * symmetry by also unsetting the bit for the other direction.
338 unset_sys_bit(priv(rp)->s_ipc_to, id);
340 unset_sys_bit(priv_addr(id)->s_ipc_to, priv_id(rp));
343 /*===========================================================================*
344 * fill_sendto_mask *
345 *===========================================================================*/
346 void fill_sendto_mask(const struct proc *rp, sys_map_t *map)
348 int i;
350 for (i=0; i < NR_SYS_PROCS; i++) {
351 if (get_sys_bit(*map, i))
352 set_sendto_bit(rp, i);
353 else
354 unset_sendto_bit(rp, i);
358 /*===========================================================================*
359 * send_sig *
360 *===========================================================================*/
361 int send_sig(endpoint_t ep, int sig_nr)
363 /* Notify a system process about a signal. This is straightforward. Simply
364 * set the signal that is to be delivered in the pending signals map and
365 * send a notification with source SYSTEM.
367 register struct proc *rp;
368 struct priv *priv;
369 int proc_nr;
371 if(!isokendpt(ep, &proc_nr) || isemptyn(proc_nr))
372 return EINVAL;
374 rp = proc_addr(proc_nr);
375 priv = priv(rp);
376 if(!priv) return ENOENT;
377 sigaddset(&priv->s_sig_pending, sig_nr);
378 mini_notify(proc_addr(SYSTEM), rp->p_endpoint);
380 return OK;
383 /*===========================================================================*
384 * cause_sig *
385 *===========================================================================*/
386 void cause_sig(proc_nr, sig_nr)
387 proc_nr_t proc_nr; /* process to be signalled */
388 int sig_nr; /* signal to be sent */
390 /* A system process wants to send a signal to a process. Examples are:
391 * - HARDWARE wanting to cause a SIGSEGV after a CPU exception
392 * - TTY wanting to cause SIGINT upon getting a DEL
393 * - FS wanting to cause SIGPIPE for a broken pipe
394 * Signals are handled by sending a message to the signal manager assigned to
395 * the process. This function handles the signals and makes sure the signal
396 * manager gets them by sending a notification. The process being signaled
397 * is blocked while the signal manager has not finished all signals for it.
398 * Race conditions between calls to this function and the system calls that
399 * process pending kernel signals cannot exist. Signal related functions are
400 * only called when a user process causes a CPU exception and from the kernel
401 * process level, which runs to completion.
403 register struct proc *rp, *sig_mgr_rp;
404 endpoint_t sig_mgr;
405 int sig_mgr_proc_nr;
407 /* Lookup signal manager. */
408 rp = proc_addr(proc_nr);
409 sig_mgr = priv(rp)->s_sig_mgr;
410 if(sig_mgr == SELF) sig_mgr = rp->p_endpoint;
412 /* If the target is the signal manager of itself, send the signal directly. */
413 if(rp->p_endpoint == sig_mgr) {
414 if(SIGS_IS_LETHAL(sig_nr)) {
415 /* If the signal is lethal, see if a backup signal manager exists. */
416 sig_mgr = priv(rp)->s_bak_sig_mgr;
417 if(sig_mgr != NONE && isokendpt(sig_mgr, &sig_mgr_proc_nr)) {
418 priv(rp)->s_sig_mgr = sig_mgr;
419 priv(rp)->s_bak_sig_mgr = NONE;
420 sig_mgr_rp = proc_addr(sig_mgr_proc_nr);
421 RTS_UNSET(sig_mgr_rp, RTS_NO_PRIV);
422 cause_sig(proc_nr, sig_nr); /* try again with the new sig mgr. */
423 return;
425 /* We are out of luck. Time to panic. */
426 proc_stacktrace(rp);
427 panic("cause_sig: sig manager %d gets lethal signal %d for itself",
428 rp->p_endpoint, sig_nr);
430 sigaddset(&priv(rp)->s_sig_pending, sig_nr);
431 if(OK != send_sig(rp->p_endpoint, SIGKSIGSM))
432 panic("send_sig failed");
433 return;
436 /* Check if the signal is already pending. Process it otherwise. */
437 if (! sigismember(&rp->p_pending, sig_nr)) {
438 sigaddset(&rp->p_pending, sig_nr);
439 if (! (RTS_ISSET(rp, RTS_SIGNALED))) { /* other pending */
440 RTS_SET(rp, RTS_SIGNALED | RTS_SIG_PENDING);
441 if(OK != send_sig(sig_mgr, SIGKSIG))
442 panic("send_sig failed");
447 /*===========================================================================*
448 * sig_delay_done *
449 *===========================================================================*/
450 void sig_delay_done(struct proc *rp)
452 /* A process is now known not to send any direct messages.
453 * Tell PM that the stop delay has ended, by sending a signal to the process.
454 * Used for actual signal delivery.
457 rp->p_misc_flags &= ~MF_SIG_DELAY;
459 cause_sig(proc_nr(rp), SIGSNDELAY);
462 /*===========================================================================*
463 * clear_ipc *
464 *===========================================================================*/
465 static void clear_ipc(
466 register struct proc *rc /* slot of process to clean up */
469 /* Clear IPC data for a given process slot. */
470 struct proc **xpp; /* iterate over caller queue */
472 if (RTS_ISSET(rc, RTS_SENDING)) {
473 int target_proc;
475 okendpt(rc->p_sendto_e, &target_proc);
476 xpp = &proc_addr(target_proc)->p_caller_q; /* destination's queue */
477 while (*xpp) { /* check entire queue */
478 if (*xpp == rc) { /* process is on the queue */
479 *xpp = (*xpp)->p_q_link; /* replace by next process */
480 #if DEBUG_ENABLE_IPC_WARNINGS
481 printf("endpoint %d / %s removed from queue at %d\n",
482 rc->p_endpoint, rc->p_name, rc->p_sendto_e);
483 #endif
484 break; /* can only be queued once */
486 xpp = &(*xpp)->p_q_link; /* proceed to next queued */
488 RTS_UNSET(rc, RTS_SENDING);
490 RTS_UNSET(rc, RTS_RECEIVING);
493 /*===========================================================================*
494 * clear_endpoint *
495 *===========================================================================*/
496 void clear_endpoint(rc)
497 register struct proc *rc; /* slot of process to clean up */
499 if(isemptyp(rc)) panic("clear_proc: empty process: %d", rc->p_endpoint);
502 #if DEBUG_IPC_HOOK
503 hook_ipc_clear(rc);
504 #endif
506 /* Make sure that the exiting process is no longer scheduled. */
507 RTS_SET(rc, RTS_NO_ENDPOINT);
508 if (priv(rc)->s_flags & SYS_PROC)
510 priv(rc)->s_asynsize= 0;
513 /* If the process happens to be queued trying to send a
514 * message, then it must be removed from the message queues.
516 clear_ipc(rc);
518 /* Likewise, if another process was sending or receive a message to or from
519 * the exiting process, it must be alerted that process no longer is alive.
520 * Check all processes.
522 clear_ipc_refs(rc, EDEADSRCDST);
526 /*===========================================================================*
527 * clear_ipc_refs *
528 *===========================================================================*/
529 void clear_ipc_refs(rc, caller_ret)
530 register struct proc *rc; /* slot of process to clean up */
531 int caller_ret; /* code to return on callers */
533 /* Clear IPC references for a given process slot. */
534 struct proc *rp; /* iterate over process table */
535 int src_id;
537 /* Tell processes that sent asynchronous messages to 'rc' they are not
538 * going to be delivered */
539 while ((src_id = has_pending_asend(rc, ANY)) != NULL_PRIV_ID)
540 cancel_async(proc_addr(id_to_nr(src_id)), rc);
542 for (rp = BEG_PROC_ADDR; rp < END_PROC_ADDR; rp++) {
543 if(isemptyp(rp))
544 continue;
546 /* Unset pending notification bits. */
547 unset_sys_bit(priv(rp)->s_notify_pending, priv(rc)->s_id);
549 /* Unset pending asynchronous messages */
550 unset_sys_bit(priv(rp)->s_asyn_pending, priv(rc)->s_id);
552 /* Check if process depends on given process. */
553 if (P_BLOCKEDON(rp) == rc->p_endpoint) {
554 rp->p_reg.retreg = caller_ret; /* return requested code */
555 clear_ipc(rp);
560 /*===========================================================================*
561 * kernel_call_resume *
562 *===========================================================================*/
563 void kernel_call_resume(struct proc *caller)
565 int result;
567 assert(!RTS_ISSET(caller, RTS_SLOT_FREE));
568 assert(!RTS_ISSET(caller, RTS_VMREQUEST));
570 assert(caller->p_vmrequest.saved.reqmsg.m_source == caller->p_endpoint);
573 printf("KERNEL_CALL restart from %s / %d rts 0x%08x misc 0x%08x\n",
574 caller->p_name, caller->p_endpoint,
575 caller->p_rts_flags, caller->p_misc_flags);
578 /* re-execute the kernel call, with MF_KCALL_RESUME still set so
579 * the call knows this is a retry.
581 result = kernel_call_dispatch(caller, &caller->p_vmrequest.saved.reqmsg);
583 * we are resuming the kernel call so we have to remove this flag so it
584 * can be set again
586 caller->p_misc_flags &= ~MF_KCALL_RESUME;
587 kernel_call_finish(caller, &caller->p_vmrequest.saved.reqmsg, result);
590 /*===========================================================================*
591 * sched_proc *
592 *===========================================================================*/
593 int sched_proc(struct proc *p,
594 int priority,
595 int quantum,
596 int cpu)
598 /* Make sure the values given are within the allowed range.*/
599 if ((priority < TASK_Q && priority != -1) || priority > NR_SCHED_QUEUES)
600 return(EINVAL);
602 if (quantum < 1 && quantum != -1)
603 return(EINVAL);
605 #ifdef CONFIG_SMP
606 if ((cpu < 0 && cpu != -1) || (cpu > 0 && (unsigned) cpu >= ncpus))
607 return(EINVAL);
608 if (cpu != -1 && !(cpu_is_ready(cpu)))
609 return EBADCPU;
610 #endif
612 /* In some cases, we might be rescheduling a runnable process. In such
613 * a case (i.e. if we are updating the priority) we set the NO_QUANTUM
614 * flag before the generic unset to dequeue/enqueue the process
617 /* FIXME this preempts the process, do we really want to do that ?*/
619 /* FIXME this is a problem for SMP if the processes currently runs on a
620 * different CPU */
621 if (proc_is_runnable(p)) {
622 #ifdef CONFIG_SMP
623 if (p->p_cpu != cpuid && cpu != -1 && cpu != p->p_cpu) {
624 smp_schedule_migrate_proc(p, cpu);
626 #endif
628 RTS_SET(p, RTS_NO_QUANTUM);
631 if (proc_is_runnable(p))
632 RTS_SET(p, RTS_NO_QUANTUM);
634 if (priority != -1)
635 p->p_priority = priority;
636 if (quantum != -1) {
637 p->p_quantum_size_ms = quantum;
638 p->p_cpu_time_left = ms_2_cpu_time(quantum);
640 #ifdef CONFIG_SMP
641 if (cpu != -1)
642 p->p_cpu = cpu;
643 #endif
645 /* Clear the scheduling bit and enqueue the process */
646 RTS_UNSET(p, RTS_NO_QUANTUM);
648 return OK;