Allow non-blocking listens
authorBarret Rhoden <brho@cs.berkeley.edu>
Mon, 20 Jul 2015 11:36:13 +0000 (07:36 -0400)
committerBarret Rhoden <brho@cs.berkeley.edu>
Fri, 24 Jul 2015 07:05:14 +0000 (03:05 -0400)
Plan 9 listens (accept() in the sockets world) can now be set to
non-blocking.

I didn't build in suport for accept4()-type SOCK_NONBLOCK, which sets
the *new* conversation/socket to non-blocking, saving a syscall.  Our
accept()s and listen()s are already super slow, and we will need a
faster interface.  We already use seven syscalls for the accept() shim,
and a normal Plan 9 listen takes three or four (depending on whether or
not you keep the ctlfd around).  That's way too much.  We can build
something like accept4() natively (still going through #I, but not using
open(), or at least not the traditional open().

kern/src/net/devip.c

index 4ac2c6d..88f46c3 100644 (file)
@@ -497,7 +497,13 @@ static struct chan *ipopen(struct chan *c, int omode)
                                        qunlock(&cv->listenq);
                                        nexterror();
                                }
-
+                               /* we can peek at incall without grabbing the cv qlock.  if
+                                * anything is there, it'll remain there until we dequeue it.
+                                * no one else can, since we hold the listenq lock */
+                               if (cv->nonblock && !cv->incall) {
+                                       set_errno(EAGAIN);
+                                       error("listen queue empty");
+                               }
                                /* wait for a connect */
                                rendez_sleep(&cv->listenr, should_wake, cv);
 
@@ -509,6 +515,9 @@ static struct chan *ipopen(struct chan *c, int omode)
                                        cv->incall = nc->next;
                                        mkqid(&c->qid, QID(PROTO(c->qid), nc->x, Qctl), 0, QTFILE);
                                        kstrdup(&cv->owner, ATTACHER(c));
+                                       /* TODO: If we want to support something like accept4(),
+                                        * where the new conversations are nonblocking right away,
+                                        * we can do so here. */
                                }
                                qunlock(&cv->qlock);