From 49808dcf779f6a14e623b6edb1c7d1c7fd29d273 Mon Sep 17 00:00:00 2001 From: David van Moolenbroek Date: Thu, 1 Oct 2009 10:36:09 +0000 Subject: [PATCH] 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 --- include/minix/com.h | 4 +++- include/minix/syslib.h | 7 ++++--- include/signal.h | 2 +- kernel/system.c | 4 ++-- kernel/system/do_runctl.c | 12 ++++++++---- lib/syslib/sys_runctl.c | 3 ++- servers/pm/forkexit.c | 4 +++- servers/pm/signal.c | 21 +++++++++++---------- 8 files changed, 34 insertions(+), 23 deletions(-) diff --git a/include/minix/com.h b/include/minix/com.h index 9b5c76572..50c30b77b 100755 --- a/include/minix/com.h +++ b/include/minix/com.h @@ -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 * diff --git a/include/minix/syslib.h b/include/minix/syslib.h index b3f6d0cad..b879a1c96 100755 --- a/include/minix/syslib.h +++ b/include/minix/syslib.h @@ -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)); diff --git a/include/signal.h b/include/signal.h index 2b47fc269..72ae00494 100755 --- a/include/signal.h +++ b/include/signal.h @@ -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 diff --git a/kernel/system.c b/kernel/system.c index 3e7fff8e9..888170093 100755 --- a/kernel/system.c +++ b/kernel/system.c @@ -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 diff --git a/kernel/system/do_runctl.c b/kernel/system/do_runctl.c index 5b24e259e..466b0ce44 100644 --- a/kernel/system/do_runctl.c +++ b/kernel/system/do_runctl.c @@ -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)) diff --git a/lib/syslib/sys_runctl.c b/lib/syslib/sys_runctl.c index 7c31eef4b..fb2afc7d0 100644 --- a/lib/syslib/sys_runctl.c +++ b/lib/syslib/sys_runctl.c @@ -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)); } diff --git a/servers/pm/forkexit.c b/servers/pm/forkexit.c index 30b58fd31..72266c745 100644 --- a/servers/pm/forkexit.c +++ b/servers/pm/forkexit.c @@ -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); } diff --git a/servers/pm/signal.c b/servers/pm/signal.c index 47bbedb5e..7a234c050 100644 --- a/servers/pm/signal.c +++ b/servers/pm/signal.c @@ -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);