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. */
#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 *

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));
/* 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));

View file

@ -66,7 +66,7 @@ typedef unsigned long sigset_t;
*/
#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

View file

@ -374,13 +374,13 @@ PUBLIC void sig_delay_done(rp)
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

View file

@ -4,6 +4,7 @@
* 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"
@ -18,10 +19,11 @@ PUBLIC int do_runctl(message *m_ptr)
{
/* 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. */
@ -30,13 +32,15 @@ PUBLIC int do_runctl(message *m_ptr)
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))

View file

@ -3,12 +3,13 @@
/*===========================================================================*
* 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));
}

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
* 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);
}

View file

@ -298,14 +298,14 @@ sigset_t sig_map;
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))
@ -377,7 +377,7 @@ int trace; /* pass signal to tracer first? */
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);
@ -555,6 +555,7 @@ struct mproc *rmp;
{
/* FS has replied to a request from us; do signal-related work.
*/
int r;
if (rmp->mp_flags & (FS_CALL | EXITING)) return;
@ -575,7 +576,8 @@ struct mproc *rmp;
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);
}
}
}
@ -601,9 +603,7 @@ struct mproc *rmp; /* which process */
/* 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);
@ -616,10 +616,10 @@ struct mproc *rmp; /* which process */
/* 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) {
@ -703,7 +703,8 @@ int signo; /* signal to send to process (1 to _NSIG-1) */
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);