From 2517c38a8c265bf80a3befbb9bb18863ba453504 Mon Sep 17 00:00:00 2001 From: rsc Date: Sun, 29 Feb 2004 22:53:51 +0000 Subject: Add fdwait routines. --- src/libthread/fdwait.c | 250 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 250 insertions(+) create mode 100644 src/libthread/fdwait.c (limited to 'src/libthread') diff --git a/src/libthread/fdwait.c b/src/libthread/fdwait.c new file mode 100644 index 00000000..2f8581f1 --- /dev/null +++ b/src/libthread/fdwait.c @@ -0,0 +1,250 @@ +#define NOPLAN9DEFINES +#include +#include +#include + +#include +#include +#include +#include + +/* + * Poll file descriptors in an idle loop. + */ + +typedef struct Poll Poll; + +struct Poll +{ + Channel *c; /* for sending back */ +}; + +static Channel *sleepchan[64]; +static int sleeptime[64]; +static int nsleep; + +static struct pollfd pfd[64]; +static struct Poll polls[64]; +static int npoll; + +static void +pollidle(void *v) +{ + int i, n, t; + uint now; + + for(;; yield()){ + //fprint(2, "poll %d:", npoll); + for(i=0; i= nelem(polls)){ + fprint(2, "Too many polled fds.\n"); + abort(); + } + npoll++; + } + + pfd[i].fd = fd; + pfd[i].events = rw=='r' ? POLLIN : POLLOUT; + polls[i].c = &s.c; + //threadstate("fdwait %d %d", f->fd, e); + recvul(&s.c); +} + +void +threadsleep(int ms) +{ + struct { + Channel c; + ulong x; + } s; + + threadfdwaitsetup(); + chaninit(&s.c, sizeof(ulong), 1); + + sleepchan[nsleep] = &s.c; + sleeptime[nsleep++] = p9nsec()/1000000+ms; + recvul(&s.c); +} + +void +threadfdnoblock(int fd) +{ + fcntl(fd, F_SETFL, fcntl(fd, F_GETFL, 0)|O_NONBLOCK); +} + +long +threadread(int fd, void *a, long n) +{ + int nn; + + threadfdnoblock(fd); +again: + nn = read(fd, a, n); + if(nn < 0){ + if(errno == EINTR) + goto again; + if(errno == EAGAIN || errno == EWOULDBLOCK){ + threadfdwait(fd, 'r'); + goto again; + } + } + return nn; +} + +int +threadrecvfd(int fd) +{ + int nn; + + threadfdnoblock(fd); +again: + nn = recvfd(fd); + if(nn < 0){ + if(errno == EINTR) + goto again; + if(errno == EAGAIN || errno == EWOULDBLOCK){ + threadfdwait(fd, 'r'); + goto again; + } + } + return nn; +} + +int +threadsendfd(int fd, int sfd) +{ + int nn; + + threadfdnoblock(fd); +again: + nn = sendfd(fd, sfd); + if(nn < 0){ + if(errno == EINTR) + goto again; + if(errno == EAGAIN || errno == EWOULDBLOCK){ + threadfdwait(fd, 'w'); + goto again; + } + } + return nn; +} + +long +threadreadn(int fd, void *a, long n) +{ + int tot, nn; + + for(tot = 0; tot