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:
		
							parent
							
								
									f11f597777
								
							
						
					
					
						commit
						49808dcf77
					
				@ -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 		     *
 | 
			
		||||
 | 
			
		||||
@ -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));
 | 
			
		||||
 | 
			
		||||
@ -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
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -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
 | 
			
		||||
 | 
			
		||||
@ -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))
 | 
			
		||||
 | 
			
		||||
@ -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));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -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);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
@ -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);
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user