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.

Reply via email to