Sync char protocol: add nonblocking transfer flag
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
This commit is contained in:
parent
a75c47e5ac
commit
97172a1db0
7 changed files with 85 additions and 75 deletions
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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. */
|
||||
|
|
Loading…
Reference in a new issue