This extends 9p to have bits for readable and writable, in the O_NONBLOCK sense. This is required for select().
Pipes and #ip use qio helpers to set the bit. Other devices will need to do something similar, if they use queues. If not, they'll have to do something else. Signed-off-by: Barret Rhoden <[email protected]> --- kern/drivers/dev/pipe.c | 13 +++++++++---- kern/include/ns.h | 4 ++++ kern/src/net/devip.c | 14 +++++++++++--- kern/src/ns/qio.c | 12 ++++++++++++ 4 files changed, 36 insertions(+), 7 deletions(-) diff --git a/kern/drivers/dev/pipe.c b/kern/drivers/dev/pipe.c index fad7b228ba39..3707768c37c9 100644 --- a/kern/drivers/dev/pipe.c +++ b/kern/drivers/dev/pipe.c @@ -219,6 +219,7 @@ static int pipestat(struct chan *c, uint8_t * db, int n) Pipe *p; struct dir dir; struct dirtab *tab; + int perm; p = c->aux; tab = p->pipedir; @@ -228,12 +229,16 @@ static int pipestat(struct chan *c, uint8_t * db, int n) devdir(c, c->qid, ".", 0, eve, DMDIR | 0555, &dir); break; case Qdata0: - devdir(c, c->qid, tab[1].name, qlen(p->q[0]), eve, tab[1].perm, - &dir); + perm = tab[1].perm; + perm |= qreadable(p->q[0]) ? DMREADABLE : 0; + perm |= qwritable(p->q[0]) ? DMWRITABLE : 0; + devdir(c, c->qid, tab[1].name, qlen(p->q[0]), eve, perm, &dir); break; case Qdata1: - devdir(c, c->qid, tab[2].name, qlen(p->q[1]), eve, tab[2].perm, - &dir); + perm = tab[2].perm; + perm |= qreadable(p->q[1]) ? DMREADABLE : 0; + perm |= qwritable(p->q[1]) ? DMWRITABLE : 0; + devdir(c, c->qid, tab[2].name, qlen(p->q[1]), eve, perm, &dir); break; default: panic("pipestat"); diff --git a/kern/include/ns.h b/kern/include/ns.h index 4f072a5974d6..126f335992d8 100644 --- a/kern/include/ns.h +++ b/kern/include/ns.h @@ -120,6 +120,8 @@ extern int parseether(uint8_t * unused_uint8_p_t, char *unused_char_p_t); #define DMAPPEND 0x40000000 /* mode bit for append only files */ #define DMEXCL 0x20000000 /* mode bit for exclusive use files */ #define DMMOUNT 0x10000000 /* mode bit for mounted channel */ +#define DMWRITABLE 0x08000000 /* non-standard, for select() */ +#define DMREADABLE 0x04000000 /* non-standard, for select() */ #define DMSYMLINK 0x02000000 /* symlink -- from 9p2000.u */ #define DMREAD 0x4 /* mode bit for read permission */ #define DMWRITE 0x2 /* mode bit for write permission */ @@ -844,6 +846,8 @@ ssize_t qwrite(struct queue *, void *, int); ssize_t qwrite_nonblock(struct queue *, void *, int); typedef void (*qio_wake_cb_t)(struct queue *q, void *data, int filter); void qio_set_wake_cb(struct queue *q, qio_wake_cb_t func, void *data); +bool qreadable(struct queue *q); +bool qwritable(struct queue *q); void *realloc(void *, uint32_t); int readmem(unsigned long offset, char *buf, unsigned long n, diff --git a/kern/src/net/devip.c b/kern/src/net/devip.c index 39430a38e6f6..2bc6160d5f20 100644 --- a/kern/src/net/devip.c +++ b/kern/src/net/devip.c @@ -128,6 +128,7 @@ static int ip3gen(struct chan *c, int i, struct dir *dp) struct qid q; struct conv *cv; char *p; + int perm; cv = chan2conv(c); if (cv->owner == NULL) @@ -141,11 +142,16 @@ static int ip3gen(struct chan *c, int i, struct dir *dp) return founddevdir(c, q, "ctl", 0, cv->owner, cv->perm, dp); case Qdata: + perm = cv->perm; + perm |= qreadable(cv->rq) ? DMREADABLE : 0; + perm |= qwritable(cv->wq) ? DMWRITABLE : 0; return founddevdir(c, q, "data", qlen(cv->rq), - cv->owner, cv->perm, dp); + cv->owner, perm, dp); case Qerr: + perm = cv->perm; + perm |= qreadable(cv->eq) ? DMREADABLE : 0; return founddevdir(c, q, "err", qlen(cv->eq), - cv->owner, cv->perm, dp); + cv->owner, perm, dp); case Qlisten: return founddevdir(c, q, "listen", 0, cv->owner, cv->perm, dp); case Qlocal: @@ -157,8 +163,10 @@ static int ip3gen(struct chan *c, int i, struct dir *dp) case Qsnoop: if (strcmp(cv->p->name, "ipifc") != 0) return -1; + perm = 0400; + perm |= qreadable(cv->sq) ? DMREADABLE : 0; return founddevdir(c, q, "snoop", qlen(cv->sq), - cv->owner, 0400, dp); + cv->owner, perm, dp); case Qstatus: p = "status"; break; diff --git a/kern/src/ns/qio.c b/kern/src/ns/qio.c index dcfd935ce68b..69f4f5e26ae5 100644 --- a/kern/src/ns/qio.c +++ b/kern/src/ns/qio.c @@ -1859,3 +1859,15 @@ void qio_set_wake_cb(struct queue *q, qio_wake_cb_t func, void *data) wmb(); /* if we see func, we'll also see the data for it */ q->wake_cb = func; } + +/* Helper for detecting whether we'll block on a read at this instant. */ +bool qreadable(struct queue *q) +{ + return qlen(q) > 0; +} + +/* Helper for detecting whether we'll block on a write at this instant. */ +bool qwritable(struct queue *q) +{ + return qwindow(q) > 0; +} -- 2.8.0.rc3.226.g39d4020 -- You received this message because you are subscribed to the Google Groups "Akaros" group. To unsubscribe from this group and stop receiving emails from it, send an email to [email protected]. To post to this group, send email to [email protected]. For more options, visit https://groups.google.com/d/optout.
