1 /* The kernel call implemented in this file: 2 * m_type: SYS_RUNCTL 3 * 4 * The parameters for this kernel call are: 5 * m1_i1: RC_ENDPT process number to control 6 * m1_i2: RC_ACTION stop or resume the process 7 * m1_i3: RC_FLAGS request flags 8 */ 9 10 #include "kernel/system.h" 11 #include <assert.h> 12 13 #if USE_RUNCTL 14 15 /*===========================================================================* 16 * do_runctl * 17 *===========================================================================*/ 18 int do_runctl(struct proc * caller, message * m_ptr) 19 { 20 /* Control a process's RTS_PROC_STOP flag. Used for process management. 21 * If the process is queued sending a message or stopped for system call 22 * tracing, and the RC_DELAY request flag is given, set MF_SIG_DELAY instead 23 * of RTS_PROC_STOP, and send a SIGSNDELAY signal later when the process is done 24 * sending (ending the delay). Used by PM for safe signal delivery. 25 */ 26 int proc_nr, action, flags; 27 register struct proc *rp; 28 29 /* Extract the message parameters and do sanity checking. */ 30 if (!isokendpt(m_ptr->RC_ENDPT, &proc_nr)) return(EINVAL); 31 if (iskerneln(proc_nr)) return(EPERM); 32 rp = proc_addr(proc_nr); 33 34 action = m_ptr->RC_ACTION; 35 flags = m_ptr->RC_FLAGS; 36 37 /* Is the target sending or syscall-traced? Then set MF_SIG_DELAY instead. 38 * Do this only when the RC_DELAY flag is set in the request flags field. 39 * The process will not become runnable before PM has called SYS_ENDKSIG. 40 * Note that asynchronous messages are not covered: a process using SENDA 41 * should not also install signal handlers *and* expect POSIX compliance. 42 */ 43 44 if (action == RC_STOP && (flags & RC_DELAY)) { 45 if (RTS_ISSET(rp, RTS_SENDING) || (rp->p_misc_flags & MF_SC_DEFER)) 46 rp->p_misc_flags |= MF_SIG_DELAY; 47 48 if (rp->p_misc_flags & MF_SIG_DELAY) 49 return (EBUSY); 50 } 51 52 /* Either set or clear the stop flag. */ 53 switch (action) { 54 case RC_STOP: 55 #if CONFIG_SMP 56 /* check if we must stop a process on a different CPU */ 57 if (rp->p_cpu != cpuid) { 58 smp_schedule_stop_proc(rp); 59 break; 60 } 61 #endif 62 RTS_SET(rp, RTS_PROC_STOP); 63 break; 64 case RC_RESUME: 65 assert(RTS_ISSET(rp, RTS_PROC_STOP)); 66 RTS_UNSET(rp, RTS_PROC_STOP); 67 break; 68 default: 69 return(EINVAL); 70 } 71 72 return(OK); 73 } 74 75 #endif /* USE_RUNCTL */ 76 77