/* Field names for SYS_RUNCTL. */
#define RC_ENDPT m1_i1 /* which process to stop or resume */
#define RC_ACTION m1_i2 /* set or clear stop flag */
-# define RC_STOP 0 /* stop the process, unless delaying */
+# define RC_STOP 0 /* stop the process */
# define RC_RESUME 1 /* clear the stop flag */
+#define RC_FLAGS m1_i3 /* request flags */
+# define RC_DELAY 1 /* delay stop if process is sending */
/*===========================================================================*
* Messages for the Reincarnation Server *
_PROTOTYPE( int sys_trace, (int req, endpoint_t proc_ep, long addr, long *data_p));
/* Shorthands for sys_runctl() system call. */
-#define sys_stop(proc_ep) sys_runctl(proc_ep, RC_STOP)
-#define sys_resume(proc_ep) sys_runctl(proc_ep, RC_RESUME)
-_PROTOTYPE( int sys_runctl, (endpoint_t proc_ep, int action));
+#define sys_stop(proc_ep) sys_runctl(proc_ep, RC_STOP, 0)
+#define sys_delay_stop(proc_ep) sys_runctl(proc_ep, RC_STOP, RC_DELAY)
+#define sys_resume(proc_ep) sys_runctl(proc_ep, RC_RESUME, 0)
+_PROTOTYPE( int sys_runctl, (endpoint_t proc_ep, int action, int flags));
_PROTOTYPE( int sys_privctl, (endpoint_t proc_ep, int req, void *p));
_PROTOTYPE( int sys_setgrant, (cp_grant_t *grants, int ngrants));
*/
#define SIGKMESS 29 /* new kernel message */
#define SIGKSIG 30 /* kernel signal pending */
-#define SIGKREADY 31 /* ready for signal delivery */
+#define SIGNDELAY 31 /* end of delay for signal delivery */
#endif
struct proc *rp;
{
/* A process is now known not to send any direct messages.
- * Tell PM by sending a signal to the process.
+ * Tell PM that the stop delay has ended, by sending a signal to the process.
* Used for actual signal delivery.
*/
rp->p_misc_flags &= ~MF_SIG_DELAY;
- cause_sig(proc_nr(rp), SIGKREADY);
+ cause_sig(proc_nr(rp), SIGNDELAY);
}
#if _MINIX_CHIP == _CHIP_INTEL
* The parameters for this kernel call are:
* m1_i1: RC_ENDPT process number to control
* m1_i2: RC_ACTION stop or resume the process
+ * m1_i3: RC_FLAGS request flags
*/
#include "../system.h"
{
/* Control a process's PROC_STOP flag. Used for process management.
* If the process is queued sending a message or stopped for system call
- * tracing, set MF_SIG_DELAY instead of PROC_STOP, and send a SIGKREADY signal
- * later when the process is done sending. Used by PM for safe signal delivery.
+ * tracing, and the RC_DELAY request flag is given, set MF_SIG_DELAY instead
+ * of PROC_STOP, and send a SIGNDELAY signal later when the process is done
+ * sending (ending the delay). Used by PM for safe signal delivery.
*/
- int proc_nr, action, delayed;
+ int proc_nr, action, flags, delayed;
register struct proc *rp;
/* Extract the message parameters and do sanity checking. */
rp = proc_addr(proc_nr);
action = m_ptr->RC_ACTION;
+ flags = m_ptr->RC_FLAGS;
/* Is the target sending or syscall-traced? Then set MF_SIG_DELAY instead.
+ * Do this only when the RC_DELAY flag is set in the request flags field.
* The process will not become runnable before PM has called SYS_ENDKSIG.
* Note that asynchronous messages are not covered: a process using SENDA
* should not also install signal handlers *and* expect POSIX compliance.
*/
- if (action == RC_STOP) {
+ if (action == RC_STOP && (flags & RC_DELAY)) {
RTS_LOCK_SET(rp, SYS_LOCK);
if (RTS_ISSET(rp, SENDING) || (rp->p_misc_flags & MF_SC_DEFER))
/*===========================================================================*
* sys_runctl *
*===========================================================================*/
-PUBLIC int sys_runctl(endpoint_t proc_ep, int action)
+PUBLIC int sys_runctl(endpoint_t proc_ep, int action, int flags)
{
message m;
m.RC_ENDPT = proc_ep;
m.RC_ACTION = action;
+ m.RC_FLAGS = flags;
return(_taskcall(SYSTASK, SYS_RUNCTL, &m));
}
* This order is important so that FS can tell drivers to cancel requests
* such as copying to/ from the exiting process, before it is gone.
*/
- sys_stop(proc_nr_e); /* stop the process */
+ if ((r = sys_stop(proc_nr_e)) != OK) /* stop the process */
+ panic(__FILE__, "sys_stop failed", r);
+
if((r=vm_willexit(proc_nr_e)) != OK) {
panic(__FILE__, "exit_proc: vm_willexit failed", r);
}
check_sig(id, i);
}
- /* If SIGKREADY is set, an earlier sys_stop() failed because the process was
+ /* If SIGNDELAY is set, an earlier sys_stop() failed because the process was
* still sending, and the kernel hereby tells us that the process is now done
* with that. We can now try to resume what we planned to do in the first
* place: set up a signal handler. However, the process's message may have
* been a call to PM, in which case the process may have changed any of its
* signal settings. The process may also have forked, exited etcetera.
*/
- if (sigismember(&sig_map, SIGKREADY) && (rmp->mp_flags & DELAY_CALL)) {
+ if (sigismember(&sig_map, SIGNDELAY) && (rmp->mp_flags & DELAY_CALL)) {
rmp->mp_flags &= ~DELAY_CALL;
if (rmp->mp_flags & (FS_CALL | PM_SIG_PENDING))
sigaddset(&rmp->mp_sigpending, signo);
if (!(rmp->mp_flags & PM_SIG_PENDING)) {
- /* This stop request must never result in EBUSY here! */
+ /* No delay calls: FS_CALL implies the process called us. */
if ((r = sys_stop(rmp->mp_endpoint)) != OK)
panic(__FILE__, "sys_stop failed", r);
{
/* FS has replied to a request from us; do signal-related work.
*/
+ int r;
if (rmp->mp_flags & (FS_CALL | EXITING)) return;
if (!(rmp->mp_flags & FS_CALL)) {
rmp->mp_flags &= ~(PM_SIG_PENDING | UNPAUSED);
- sys_resume(rmp->mp_endpoint);
+ if ((r = sys_resume(rmp->mp_endpoint)) != OK)
+ panic(__FILE__, "sys_resume failed", r);
}
}
}
/* Check to see if process is hanging on a PAUSE, WAIT or SIGSUSPEND call. */
if (rmp->mp_flags & (PAUSED | WAITING | SIGSUSPENDED)) {
- /* Stop process from running.
- * This stop request must never result in EBUSY here!
- */
+ /* Stop process from running. No delay calls: it called us. */
if ((r = sys_stop(rmp->mp_endpoint)) != OK)
panic(__FILE__, "sys_stop failed", r);
/* Not paused in PM. Let FS try to unpause the process. */
if (!(rmp->mp_flags & PM_SIG_PENDING)) {
/* Stop process from running. */
- r = sys_stop(rmp->mp_endpoint);
+ r = sys_delay_stop(rmp->mp_endpoint);
/* If the process is still busy sending a message, the kernel will give
- * us EBUSY now and send a SIGKREADY to the process as soon as sending
+ * us EBUSY now and send a SIGNDELAY to the process as soon as sending
* is done.
*/
if (r == EBUSY) {
if ((rmp->mp_flags & (PM_SIG_PENDING | UNPAUSED)) == UNPAUSED) {
rmp->mp_flags &= ~UNPAUSED;
- sys_resume(rmp->mp_endpoint);
+ if ((r = sys_resume(rmp->mp_endpoint)) != OK)
+ panic(__FILE__, "sys_resume failed", r);
}
return(TRUE);