]> Zhao Yanbai Git Server - minix.git/commitdiff
Support for suspending on character device open and on drivers that need to
authorPhilip Homburg <philip@cs.vu.nl>
Fri, 22 Feb 2008 14:47:40 +0000 (14:47 +0000)
committerPhilip Homburg <philip@cs.vu.nl>
Fri, 22 Feb 2008 14:47:40 +0000 (14:47 +0000)
be restarted.

servers/vfs/pipe.c

index d89948497d49d16670ba46c4c5e83f5eb996353d..407b9d5a5a00d07bd500cdd046124bf1b53d6659 100644 (file)
@@ -245,11 +245,14 @@ int task;                 /* who is proc waiting for? (PIPE = pipe) */
 
   if (task == XPOPEN) susp_count++;/* #procs susp'ed on pipe*/
   fp->fp_suspended = SUSPENDED;
-  assert(!GRANT_VALID(fp->fp_grant));
+  assert(fp->fp_grant == GRANT_INVALID || !GRANT_VALID(fp->fp_grant));
   fp->fp_fd = m_in.fd << 8 | call_nr;
   if(task == NONE)
        panic(__FILE__,"suspend on NONE",NO_NUM);
   fp->fp_task = -task;
+  fp->fp_flags &= ~SUSP_REOPEN;                        /* Clear this flag. The caller
+                                                * can set it when needed.
+                                                */
   if (task == XLOCK) {
        fp->fp_buffer = (char *) m_in.name1;    /* third arg to fcntl() */
        fp->fp_nbytes = m_in.request;           /* second arg to fcntl() */
@@ -371,10 +374,10 @@ int returned;                     /* if hanging on task, how many bytes read */
 /* Revive a previously blocked process. When a process hangs on tty, this
  * is the way it is eventually released.
  */
-
   register struct fproc *rfp;
   register int task;
-  int proc_nr;
+  int fd_nr, proc_nr;
+  struct filp *fil_ptr;
 
   if(isokendpt(proc_nr_e, &proc_nr) != OK)
        return;
@@ -392,13 +395,37 @@ int returned;                     /* if hanging on task, how many bytes read */
        /* Revive a process suspended on a pipe or lock. */
        rfp->fp_revived = REVIVING;
        reviving++;             /* process was waiting on pipe or lock */
-  } else {
+  }
+  else if (task == XDOPEN)
+  {
+       rfp->fp_suspended = NOT_SUSPENDED;
+       fd_nr= rfp->fp_fd>>8;
+       if (returned < 0)
+       {
+               fil_ptr= rfp->fp_filp[fd_nr];
+               rfp->fp_filp[fd_nr] = NIL_FILP;
+               FD_CLR(fd_nr, &rfp->fp_filp_inuse);
+               if (fil_ptr->filp_count != 1)
+               {
+                       panic(__FILE__, "revive: bad count in filp",
+                               fil_ptr->filp_count);
+               }
+               fil_ptr->filp_count= 0;
+               put_vnode(fil_ptr->filp_vno);     
+               fil_ptr->filp_vno = NIL_VNODE;
+               reply(proc_nr_e, returned);
+       }
+       else
+               reply(proc_nr_e, fd_nr);
+  }
+  else {
        rfp->fp_suspended = NOT_SUSPENDED;
        if (task == XPOPEN) /* process blocked in open or create */
                reply(proc_nr_e, rfp->fp_fd>>8);
        else if (task == XSELECT) {
                reply(proc_nr_e, returned);
-       } else {
+       }
+       else {
                /* Revive a process suspended on TTY or other device. 
                 * Pretend it wants only what there is.
                 */
@@ -419,25 +446,10 @@ int returned;                     /* if hanging on task, how many bytes read */
 }
 
 
-/*===========================================================================*
- *                             do_unpause                                   *
- *===========================================================================*/
-PUBLIC int do_unpause()
-{
-/* A signal has been sent to a user who is paused on the file system.
- * Abort the system call with the EINTR error message.
- */
-  int proc_nr_e;
-
-  if (who_e != PM_PROC_NR) return(EPERM);
-  proc_nr_e = m_in.ENDPT;
-  return unpause(proc_nr_e);
-}
-
 /*===========================================================================*
  *                             unpause                                      *
  *===========================================================================*/
-PUBLIC int unpause(proc_nr_e)
+PUBLIC void unpause(proc_nr_e)
 int proc_nr_e;
 {
 /* A signal has been sent to a user who is paused on the file system.
@@ -452,7 +464,8 @@ int proc_nr_e;
 
   okendpt(proc_nr_e, &proc_nr_p);
   rfp = &fproc[proc_nr_p];
-  if (rfp->fp_suspended == NOT_SUSPENDED) return(OK);
+  if (rfp->fp_suspended == NOT_SUSPENDED)
+       return;
   task = -rfp->fp_task;
 
   if (rfp->fp_revived == REVIVING)
@@ -475,7 +488,21 @@ int proc_nr_e;
        case XPOPEN:            /* process trying to open a fifo */
                break;
 
+       case XDOPEN:            /* process trying to open a device */
+               /* Don't cancel OPEN. Just wait until the open completes. */
+               return; 
+
        default:                /* process trying to do device I/O (e.g. tty)*/
+               if (rfp->fp_flags & SUSP_REOPEN)
+               {
+                       /* Process is suspended while waiting for a reopen.
+                        * Just reply EINTR.
+                        */
+                       rfp->fp_flags &= ~SUSP_REOPEN;
+                       status= EINTR;
+                       break;
+               }
+               
                fild = (rfp->fp_fd >> 8) & BYTE;/* extract file descriptor */
                if (fild < 0 || fild >= OPEN_MAX)
                        panic(__FILE__,"unpause err 2",NO_NUM);
@@ -491,6 +518,11 @@ int proc_nr_e;
                fp = rfp;       /* hack - ctty_io uses fp */
                (*dmap[(dev >> MAJOR) & BYTE].dmap_io)(task, &mess);
                status = mess.REP_STATUS;
+               if (status == SUSPEND)
+                       return;         /* Process will be revived at a
+                                        * later time.
+                                        */
+
                if(status == EAGAIN) status = EINTR;
                if(GRANT_VALID(rfp->fp_grant)) {
                        if(cpf_revoke(rfp->fp_grant)) {
@@ -503,7 +535,6 @@ int proc_nr_e;
 
   rfp->fp_suspended = NOT_SUSPENDED;
   reply(proc_nr_e, status);    /* signal interrupted call */
-  return(OK);
 }