PM delay call infrastructure improvements

- allow PM to tell sys_runctl() whether to use delay call feature
- only use this feature in PM for delivering signals - not for exits
- do better error checking in PM on sys_runctl() calls
- rename SIGKREADY to SIGNDELAY
This commit is contained in:
David van Moolenbroek 2009-10-01 10:36:09 +00:00
parent f11f597777
commit 49808dcf77
8 changed files with 34 additions and 23 deletions

View file

@ -639,8 +639,10 @@
/* Field names for SYS_RUNCTL. */ /* Field names for SYS_RUNCTL. */
#define RC_ENDPT m1_i1 /* which process to stop or resume */ #define RC_ENDPT m1_i1 /* which process to stop or resume */
#define RC_ACTION m1_i2 /* set or clear stop flag */ #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_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 * * Messages for the Reincarnation Server *

View file

@ -41,9 +41,10 @@ _PROTOTYPE( int sys_exit, (endpoint_t proc_ep));
_PROTOTYPE( int sys_trace, (int req, endpoint_t proc_ep, long addr, long *data_p)); _PROTOTYPE( int sys_trace, (int req, endpoint_t proc_ep, long addr, long *data_p));
/* Shorthands for sys_runctl() system call. */ /* Shorthands for sys_runctl() system call. */
#define sys_stop(proc_ep) sys_runctl(proc_ep, RC_STOP) #define sys_stop(proc_ep) sys_runctl(proc_ep, RC_STOP, 0)
#define sys_resume(proc_ep) sys_runctl(proc_ep, RC_RESUME) #define sys_delay_stop(proc_ep) sys_runctl(proc_ep, RC_STOP, RC_DELAY)
_PROTOTYPE( int sys_runctl, (endpoint_t proc_ep, int action)); #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_privctl, (endpoint_t proc_ep, int req, void *p));
_PROTOTYPE( int sys_setgrant, (cp_grant_t *grants, int ngrants)); _PROTOTYPE( int sys_setgrant, (cp_grant_t *grants, int ngrants));

View file

@ -66,7 +66,7 @@ typedef unsigned long sigset_t;
*/ */
#define SIGKMESS 29 /* new kernel message */ #define SIGKMESS 29 /* new kernel message */
#define SIGKSIG 30 /* kernel signal pending */ #define SIGKSIG 30 /* kernel signal pending */
#define SIGKREADY 31 /* ready for signal delivery */ #define SIGNDELAY 31 /* end of delay for signal delivery */
#endif #endif

View file

@ -374,13 +374,13 @@ PUBLIC void sig_delay_done(rp)
struct proc *rp; struct proc *rp;
{ {
/* A process is now known not to send any direct messages. /* 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. * Used for actual signal delivery.
*/ */
rp->p_misc_flags &= ~MF_SIG_DELAY; rp->p_misc_flags &= ~MF_SIG_DELAY;
cause_sig(proc_nr(rp), SIGKREADY); cause_sig(proc_nr(rp), SIGNDELAY);
} }
#if _MINIX_CHIP == _CHIP_INTEL #if _MINIX_CHIP == _CHIP_INTEL

View file

@ -4,6 +4,7 @@
* The parameters for this kernel call are: * The parameters for this kernel call are:
* m1_i1: RC_ENDPT process number to control * m1_i1: RC_ENDPT process number to control
* m1_i2: RC_ACTION stop or resume the process * m1_i2: RC_ACTION stop or resume the process
* m1_i3: RC_FLAGS request flags
*/ */
#include "../system.h" #include "../system.h"
@ -18,10 +19,11 @@ PUBLIC int do_runctl(message *m_ptr)
{ {
/* Control a process's PROC_STOP flag. Used for process management. /* Control a process's PROC_STOP flag. Used for process management.
* If the process is queued sending a message or stopped for system call * 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 * tracing, and the RC_DELAY request flag is given, set MF_SIG_DELAY instead
* later when the process is done sending. Used by PM for safe signal delivery. * 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; register struct proc *rp;
/* Extract the message parameters and do sanity checking. */ /* Extract the message parameters and do sanity checking. */
@ -30,13 +32,15 @@ PUBLIC int do_runctl(message *m_ptr)
rp = proc_addr(proc_nr); rp = proc_addr(proc_nr);
action = m_ptr->RC_ACTION; action = m_ptr->RC_ACTION;
flags = m_ptr->RC_FLAGS;
/* Is the target sending or syscall-traced? Then set MF_SIG_DELAY instead. /* 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. * The process will not become runnable before PM has called SYS_ENDKSIG.
* Note that asynchronous messages are not covered: a process using SENDA * Note that asynchronous messages are not covered: a process using SENDA
* should not also install signal handlers *and* expect POSIX compliance. * 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); RTS_LOCK_SET(rp, SYS_LOCK);
if (RTS_ISSET(rp, SENDING) || (rp->p_misc_flags & MF_SC_DEFER)) if (RTS_ISSET(rp, SENDING) || (rp->p_misc_flags & MF_SC_DEFER))

View file

@ -3,12 +3,13 @@
/*===========================================================================* /*===========================================================================*
* sys_runctl * * 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; message m;
m.RC_ENDPT = proc_ep; m.RC_ENDPT = proc_ep;
m.RC_ACTION = action; m.RC_ACTION = action;
m.RC_FLAGS = flags;
return(_taskcall(SYSTASK, SYS_RUNCTL, &m)); return(_taskcall(SYSTASK, SYS_RUNCTL, &m));
} }

View file

@ -273,7 +273,9 @@ int dump_core; /* flag indicating whether to dump core */
* This order is important so that FS can tell drivers to cancel requests * 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. * 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) { if((r=vm_willexit(proc_nr_e)) != OK) {
panic(__FILE__, "exit_proc: vm_willexit failed", r); panic(__FILE__, "exit_proc: vm_willexit failed", r);
} }

View file

@ -298,14 +298,14 @@ sigset_t sig_map;
check_sig(id, i); 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 * 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 * 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 * 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 * 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. * 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; rmp->mp_flags &= ~DELAY_CALL;
if (rmp->mp_flags & (FS_CALL | PM_SIG_PENDING)) if (rmp->mp_flags & (FS_CALL | PM_SIG_PENDING))
@ -377,7 +377,7 @@ int trace; /* pass signal to tracer first? */
sigaddset(&rmp->mp_sigpending, signo); sigaddset(&rmp->mp_sigpending, signo);
if (!(rmp->mp_flags & PM_SIG_PENDING)) { 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) if ((r = sys_stop(rmp->mp_endpoint)) != OK)
panic(__FILE__, "sys_stop failed", r); panic(__FILE__, "sys_stop failed", r);
@ -555,6 +555,7 @@ struct mproc *rmp;
{ {
/* FS has replied to a request from us; do signal-related work. /* 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 | EXITING)) return;
@ -575,7 +576,8 @@ struct mproc *rmp;
if (!(rmp->mp_flags & FS_CALL)) { if (!(rmp->mp_flags & FS_CALL)) {
rmp->mp_flags &= ~(PM_SIG_PENDING | UNPAUSED); 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);
} }
} }
} }
@ -601,9 +603,7 @@ struct mproc *rmp; /* which process */
/* Check to see if process is hanging on a PAUSE, WAIT or SIGSUSPEND call. */ /* Check to see if process is hanging on a PAUSE, WAIT or SIGSUSPEND call. */
if (rmp->mp_flags & (PAUSED | WAITING | SIGSUSPENDED)) { if (rmp->mp_flags & (PAUSED | WAITING | SIGSUSPENDED)) {
/* Stop process from running. /* Stop process from running. No delay calls: it called us. */
* This stop request must never result in EBUSY here!
*/
if ((r = sys_stop(rmp->mp_endpoint)) != OK) if ((r = sys_stop(rmp->mp_endpoint)) != OK)
panic(__FILE__, "sys_stop failed", r); panic(__FILE__, "sys_stop failed", r);
@ -616,10 +616,10 @@ struct mproc *rmp; /* which process */
/* Not paused in PM. Let FS try to unpause the process. */ /* Not paused in PM. Let FS try to unpause the process. */
if (!(rmp->mp_flags & PM_SIG_PENDING)) { if (!(rmp->mp_flags & PM_SIG_PENDING)) {
/* Stop process from running. */ /* 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 /* 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. * is done.
*/ */
if (r == EBUSY) { if (r == EBUSY) {
@ -703,7 +703,8 @@ int signo; /* signal to send to process (1 to _NSIG-1) */
if ((rmp->mp_flags & (PM_SIG_PENDING | UNPAUSED)) == UNPAUSED) { if ((rmp->mp_flags & (PM_SIG_PENDING | UNPAUSED)) == UNPAUSED) {
rmp->mp_flags &= ~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); return(TRUE);