]> Zhao Yanbai Git Server - minix.git/commitdiff
Sync char protocol: add nonblocking transfer flag 44/944/2
authorDavid van Moolenbroek <david@minix3.org>
Fri, 30 Aug 2013 08:48:34 +0000 (10:48 +0200)
committerLionel Sambuc <lionel@minix3.org>
Tue, 18 Feb 2014 10:25:02 +0000 (11:25 +0100)
The async char protocol already has this, so this patch closes the
gap between the two protocols a bit. Support for this flag has been
added to all sync char drivers that support CANCEL at all.

The LOG driver was already using the asynchronous protocol, but it
did not support the nonblocking transfer flag. This has been fixed
as well.

Change-Id: Ia55432c9f102765b59ad3feb45a8bd47a782c93f

drivers/log/log.c
drivers/printer/printer.c
drivers/tty/arch/i386/keyboard.c
drivers/tty/pty.c
drivers/tty/tty.c
servers/inet/sr.c
servers/vfs/device.c

index 5de3d89df7e03b5af805caf648a9c5429155038d..756d5908884a093d9c8f70e66f83e11cc42b2a9a 100644 (file)
@@ -282,7 +282,7 @@ static int log_transfer(
   iovec_t *iov,                        /* pointer to read or write request vector */
   unsigned int nr_req,         /* length of request vector */
   endpoint_t user_endpt,       /* endpoint of user process */
-  unsigned int UNUSED(flags)
+  unsigned int flags
 )
 {
 /* Read or write one the driver's minor devices. */
@@ -317,6 +317,8 @@ static int log_transfer(
                if (!log->log_size) {
                        if(accumulated_read)
                                return OK;
+                       if (flags & FLG_OP_NONBLOCK)
+                               return EAGAIN;
                        /* No data available; let caller block. */
                        log->log_source = endpt;
                        log->log_iosize = count;
index 5ab2a9491c46c84a6bcafea41c6c80800d7f9d69..a0059f91bcf0cac206084f73e3a33c350902ca28 100644 (file)
@@ -220,8 +220,9 @@ register message *m_ptr;    /* pointer to the newly arrived message */
     /* Reject command if last write is not yet finished, the count is not
      * positive, or the user address is bad.
      */
-    if (writing)                       r = EIO;
-    else if (m_ptr->COUNT <= 0)        r = EINVAL;
+    if (writing)                               r = EIO;
+    else if (m_ptr->COUNT <= 0)                r = EINVAL;
+    else if (m_ptr->FLAGS & FLG_OP_NONBLOCK)   r = EAGAIN; /* not supported */
 
     /* Reply to FS, no matter what happened, possible SUSPEND caller. */
     reply(TASK_REPLY, m_ptr->m_source, m_ptr->USER_ENDPT, r);
index fb02ce2a8c122f17e3d1ce77ce56d12a6c1e298f..20d0dfc1da34e361b2929fb1e0335f9a3a803524 100644 (file)
@@ -246,6 +246,10 @@ message *m;
                }
                if (kbdp->avail == 0)
                {
+                       if (m->FLAGS & FLG_OP_NONBLOCK) {
+                               r = EAGAIN;
+                               break;
+                       }
                        /* Should record proc */
                        kbdp->req_size= m->COUNT;
                        kbdp->req_proc= m->USER_ENDPT;
index 72e4724eb66df92c8f65a5b5565c1a8254183bd8..f009fa23bf51f75ff2f18656aa23c1c6755c0dd7 100644 (file)
@@ -118,7 +118,11 @@ void do_pty(tty_t *tp, message *m_ptr)
                return;                 /* already done */
        }
 
-       {
+       if (m_ptr->FLAGS & FLG_OP_NONBLOCK) {
+               r = pp->rdcum > 0 ? pp->rdcum : EAGAIN;
+               pp->rdleft = pp->rdcum = 0;
+               pp->rdgrant = GRANT_INVALID;
+       } else {
                r = SUSPEND;                            /* do suspend */
                pp->rdsendreply = FALSE;
        }
@@ -154,7 +158,12 @@ void do_pty(tty_t *tp, message *m_ptr)
                return;                 /* already done */
        }
 
-       {
+       if (m_ptr->FLAGS & FLG_OP_NONBLOCK) {
+               r = pp->wrcum > 0 ? pp->wrcum : EAGAIN;
+               pp->wrleft = pp->wrcum = 0;
+               pp->wrgrant = GRANT_INVALID;
+               r = EAGAIN;
+       } else {
                pp->wrsendreply = FALSE;                        /* do suspend */
                r = SUSPEND;
        }
index bc532cc04757e97ed9595ea722aeed9e38469bfe..894571d84883b76d75de051386278dcacca1aef9 100644 (file)
@@ -309,6 +309,7 @@ set_color(tty_t *tp, int color)
 
        buf[0] = '\033';
        snprintf(&buf[1], sizeof(buf) - 1, "[1;%dm", color);
+       memset(&msg, 0, sizeof(msg));
        msg.m_source = KERNEL;
        msg.IO_GRANT = buf;
        msg.COUNT = sizeof(buf);
@@ -324,6 +325,7 @@ reset_color(tty_t *tp)
 #define SGR_COLOR_RESET        39
        buf[0] = '\033';
        snprintf(&buf[1], sizeof(buf) - 1, "[0;%dm", SGR_COLOR_RESET);
+       memset(&msg, 0, sizeof(msg));
        msg.m_source = KERNEL;
        msg.IO_GRANT = buf;
        msg.COUNT = sizeof(buf);
@@ -499,6 +501,7 @@ do_new_kmess(void)
 
                if (kernel_msg_color != 0)
                        set_color(tp, kernel_msg_color);
+               memset(&print_kmsg, 0, sizeof(print_kmsg));
                print_kmsg.m_source = KERNEL;
                print_kmsg.IO_GRANT = kernel_buf_copy;
                print_kmsg.COUNT = bytes;
@@ -685,11 +688,16 @@ register message *m_ptr;  /* pointer to message sent to the task */
                return;                 /* already done */
        }
 
-       /* There were no bytes in the input queue available, so suspend
-        * the caller.
-        */
-       r = SUSPEND;                            /* suspend the caller */
-       tp->tty_inrepcode = TTY_REVIVE;
+       /* There were no bytes in the input queue available. */
+       if (m_ptr->FLAGS & FLG_OP_NONBLOCK) {
+               tty_icancel(tp);
+               r = tp->tty_incum > 0 ? tp->tty_incum : EAGAIN;
+               tp->tty_inleft = tp->tty_incum = tp->tty_inrevived = 0;
+               tp->tty_ingrant = GRANT_INVALID;
+       } else {
+               r = SUSPEND;                    /* suspend the caller */
+               tp->tty_inrepcode = TTY_REVIVE;
+       }
   }
   tty_reply(TASK_REPLY, m_ptr->m_source, m_ptr->USER_ENDPT, r);
   if (tp->tty_select_ops)
@@ -728,11 +736,15 @@ register message *m_ptr;  /* pointer to message sent to the task */
        if (tp->tty_outleft == 0)
                return; /* already done */
 
-       /* None or not all the bytes could be written, so suspend the
-        * caller.
-        */
-       r = SUSPEND;                            /* suspend the caller */
-       tp->tty_outrepcode = TTY_REVIVE;
+       /* None or not all the bytes could be written. */
+       if (m_ptr->FLAGS & FLG_OP_NONBLOCK) {
+               r = tp->tty_outcum > 0 ? tp->tty_outcum : EAGAIN;
+               tp->tty_outleft = tp->tty_outcum = tp->tty_outrevived = 0;
+               tp->tty_outgrant = GRANT_INVALID;
+       } else {
+               r = SUSPEND;                    /* suspend the caller */
+               tp->tty_outrepcode = TTY_REVIVE;
+       }
   }
   tty_reply(TASK_REPLY, m_ptr->m_source, m_ptr->USER_ENDPT, r);
 }
@@ -800,12 +812,16 @@ message *m_ptr;                   /* pointer to message sent to task */
     case TCSETSF:
     case TCDRAIN:
        if (tp->tty_outleft > 0) {
-               /* Wait for all ongoing output processing to finish. */
-               tp->tty_iocaller = m_ptr->m_source;
-               tp->tty_ioproc = m_ptr->USER_ENDPT;
-               tp->tty_ioreq = m_ptr->REQUEST;
-               tp->tty_iogrant = (cp_grant_id_t) m_ptr->IO_GRANT;
-               r = SUSPEND;
+               if (m_ptr->FLAGS & FLG_OP_NONBLOCK) {
+                       r = EAGAIN;
+               } else {
+                       /* Wait for all ongoing output processing to finish. */
+                       tp->tty_iocaller = m_ptr->m_source;
+                       tp->tty_ioproc = m_ptr->USER_ENDPT;
+                       tp->tty_ioreq = m_ptr->REQUEST;
+                       tp->tty_iogrant = (cp_grant_id_t) m_ptr->IO_GRANT;
+                       r = SUSPEND;
+               }
                break;
        }
        if (m_ptr->TTY_REQUEST == TCDRAIN) break;
index a84792c45ec98a14e35a6fc96447e69c2269380c..201bdd4672a644570a9b9040494b7cda65210519 100644 (file)
@@ -156,9 +156,10 @@ mq_t *m;
        case DEV_WRITE_S:
        case DEV_IOCTL_S:
                result= sr_rwio(m);
-               assert(result == OK || result == SUSPEND);
-               send_reply= (result == SUSPEND);
-               free_mess= 0;
+               assert(result == OK || result == EAGAIN || result == EINTR ||
+                       result == SUSPEND);
+               send_reply= (result == EAGAIN || result == SUSPEND);
+               free_mess= (result == EAGAIN);
                break;
        case CANCEL:
                result= sr_cancel(&m->mq_mess);
@@ -323,6 +324,9 @@ mq_t *m;
                assert(sr_fd->srf_flags & susp_flag);
                assert(*q_head_ptr);
 
+               if (m->mq_mess.FLAGS & FLG_OP_NONBLOCK)
+                       return EAGAIN;
+
                (*q_tail_ptr)->mq_next= m;
                *q_tail_ptr= m;
                return SUSPEND;
@@ -368,9 +372,14 @@ mq_t *m;
 
        assert(r == OK || r == SUSPEND || 
                (printf("r= %d\n", r), 0));
-       if (r == SUSPEND)
+       if (r == SUSPEND) {
                sr_fd->srf_flags |= susp_flag;
-       else
+               if (m->mq_mess.FLAGS & FLG_OP_NONBLOCK) {
+                       r= sr_cancel(&m->mq_mess);
+                       assert(r == OK); /* must have been head of queue */
+                       return EINTR;
+               }
+       } else
                mq_free(m);
        return r;
 }
index 4d0ce596d6b523d71f0731af251fce84050edac5..a4a7d5d8c32bd70b60fcc3cb93a830ea30d53259 100644 (file)
@@ -361,32 +361,6 @@ u32_t *pos_lo;
   return(0);
 }
 
-static int cancel_nblock(struct dmap * dp,
-                       int minor,
-                       int call,
-                       endpoint_t ioproc,
-                       cp_grant_id_t gid)
-{
-  message dev_mess;
-
-  dev_mess.m_type = CANCEL;
-  dev_mess.USER_ENDPT = ioproc;
-  dev_mess.IO_GRANT = (char *) gid;
-
-  /* This R_BIT/W_BIT check taken from suspend()/unpause()
-   * logic. Mode is expected in the COUNT field.
-   */
-  dev_mess.COUNT = 0;
-  if (call == READ)
-         dev_mess.COUNT = R_BIT;
-  else if (call == WRITE)
-         dev_mess.COUNT = W_BIT;
-  dev_mess.DEVICE = minor;
-  (*dp->dmap_io)(dp->dmap_driver, &dev_mess);
-  
-  return dev_mess.REP_STATUS;
-}
-
 /*===========================================================================*
  *                             dev_io                                       *
  *===========================================================================*/
@@ -480,33 +454,28 @@ int dev_io(
 
   ret = dev_mess.REP_STATUS;
 
+  /* Legacy support: translate EINTR to EAGAIN for nonblocking calls. */
+  if (ret == EINTR && (flags & O_NONBLOCK))
+       ret = EAGAIN;
+
   /* Task has completed.  See if call completed. */
   if (ret == SUSPEND) {
        if ((flags & O_NONBLOCK) && !is_asyn) {
-               /* Not supposed to block. */
-               ret = cancel_nblock(dp, minor_dev, job_call_nr, ioproc, gid);
-               if (ret == EINTR)
-                       ret = EAGAIN;
-       } else {
-               /* select() will do suspending itself. */
-               if(op != DEV_SELECT) {
-                       /* Suspend user. */
-                       wait_for(dp->dmap_driver);
-               }
-               assert(!GRANT_VALID(fp->fp_grant));
-               fp->fp_grant = gid;     /* revoke this when unsuspended. */
-               fp->fp_ioproc = ioproc;
-
-               if ((flags & O_NONBLOCK) && !is_asyn) {
-                       /* Not supposed to block, send cancel message */
-                       cancel_nblock(dp, minor_dev, job_call_nr, ioproc, gid);
-                       /*
-                        * FIXME Should do something about EINTR -> EAGAIN
-                        * mapping
-                        */
-               }
-               return(SUSPEND);
+               printf("VFS: sync char driver %u sent SUSPEND on NONBLOCK\n",
+                       dp->dmap_driver);
+               /* We'd cancel, but the other side won't play ball anyway.. */
        }
+
+       /* select() will do suspending itself. */
+       if(op != DEV_SELECT) {
+               /* Suspend user. */
+               wait_for(dp->dmap_driver);
+       }
+       assert(!GRANT_VALID(fp->fp_grant));
+       fp->fp_grant = gid;     /* revoke this when unsuspended. */
+       fp->fp_ioproc = ioproc;
+
+       return(SUSPEND);
   }
 
   /* No suspend, or cancelled suspend, so I/O is over and can be cleaned up. */