From: Fredrik Tolf Date: Wed, 18 May 2016 01:02:23 +0000 (+0200) Subject: lib: Added support for blocking on multiple file descriptors. X-Git-Url: http://git.dolda2000.com/gitweb/?a=commitdiff_plain;h=205ee93306ceb8a0f1c000d916bd055d14fa63c1;p=ashd.git lib: Added support for blocking on multiple file descriptors. Lacking support for kqueue for now. --- diff --git a/lib/mtio-epoll.c b/lib/mtio-epoll.c index 72468e0..d9e794e 100644 --- a/lib/mtio-epoll.c +++ b/lib/mtio-epoll.c @@ -37,7 +37,7 @@ static struct blocker *blockers; struct blocker { struct blocker *n, *p, *n2, *p2; int fd, reg; - int ev; + int ev, rev, id; time_t to; struct muth *th; }; @@ -129,34 +129,72 @@ static void remfd(struct blocker *bl) bl->reg = 0; } -int block(int fd, int ev, time_t to) +static int addblock(struct blocker *bl) { - struct blocker *bl; - int rv; - - omalloc(bl); - bl->fd = fd; - bl->ev = ev; - if(to > 0) - bl->to = time(NULL) + to; - bl->th = current; - if((epfd >= 0) && regfd(bl)) { - free(bl); + if((epfd >= 0) && regfd(bl)) return(-1); - } bl->n = blockers; if(blockers) blockers->p = bl; blockers = bl; - rv = yield(); + return(0); +} + +static void remblock(struct blocker *bl) +{ if(bl->n) bl->n->p = bl->p; if(bl->p) bl->p->n = bl->n; - if(bl == blockers) + if(blockers == bl) blockers = bl->n; remfd(bl); - free(bl); +} + +struct selected mblock(time_t to, int n, struct selected *spec) +{ + int i, id; + struct blocker bls[n]; + + to = (to > 0)?(time(NULL) + to):0; + for(i = 0; i < n; i++) { + bls[i] = (struct blocker) { + .fd = spec[i].fd, + .ev = spec[i].ev, + .id = i, + .to = to, + .th = current, + }; + if(addblock(&bls[i])) { + for(i--; i >= 0; i++) + remblock(&bls[i]); + return((struct selected){.fd = -1, .ev = -1}); + } + } + id = yield(); + for(i = 0; i < n; i++) + remblock(&bls[i]); + if(id < 0) + return((struct selected){.fd = -1, .ev = -1}); + return((struct selected){.fd = bls[id].fd, .ev = bls[id].rev}); +} + +int block(int fd, int ev, time_t to) +{ + struct blocker bl; + int rv; + + bl = (struct blocker) { + .fd = fd, + .ev = ev, + .id = -1, + .to = (to > 0)?(time(NULL) + to):0, + .th = current, + }; + if(addblock(&bl)) + return(-1); + rv = yield(); + remblock(&bl); return(rv); } @@ -211,15 +249,27 @@ int ioloop(void) ev = -1; for(bl = fdlist[fd]; bl; bl = nbl) { nbl = bl->n2; - if((ev < 0) || (ev & bl->ev)) - resume(bl->th, ev); + if((ev < 0) || (ev & bl->ev)) { + if(bl->id < 0) { + resume(bl->th, ev); + } else { + bl->rev = ev; + resume(bl->th, bl->id); + } + } } } now = time(NULL); for(bl = blockers; bl; bl = nbl) { nbl = bl->n; - if((bl->to != 0) && (bl->to <= now)) - resume(bl->th, 0); + if((bl->to != 0) && (bl->to <= now)) { + if(bl->id < 0) { + resume(bl->th, 0); + } else { + bl->rev = 0; + resume(bl->th, bl->id); + } + } } } for(bl = blockers; bl; bl = bl->n) diff --git a/lib/mtio-select.c b/lib/mtio-select.c index 26e6785..6e9a767 100644 --- a/lib/mtio-select.c +++ b/lib/mtio-select.c @@ -37,39 +37,73 @@ static int exitstatus; struct blocker { struct blocker *n, *p; int fd; - int ev; + int ev, rev, id; time_t to; struct muth *th; }; -int block(int fd, int ev, time_t to) +static void addblock(struct blocker *bl) { - struct blocker *bl; - int rv; - - if(fd >= FD_SETSIZE) { - flog(LOG_ERR, "tried to use more file descriptors than select() can handle: fd %i", fd); - errno = EMFILE; - return(-1); - } - omalloc(bl); - bl->fd = fd; - bl->ev = ev; - if(to > 0) - bl->to = time(NULL) + to; - bl->th = current; bl->n = blockers; if(blockers) blockers->p = bl; blockers = bl; - rv = yield(); +} + +static void remblock(struct blocker *bl) +{ if(bl->n) bl->n->p = bl->p; if(bl->p) bl->p->n = bl->n; if(bl == blockers) blockers = bl->n; - free(bl); +} + +struct selected mblock(time_t to, int n, struct selected *spec) +{ + int i, id; + struct blocker bls[n]; + + to = (to > 0)?(time(NULL) + to):0; + for(i = 0; i < n; i++) { + bls[i] = (struct blocker){ + .fd = spec[i].fd, + .ev = spec[i].ev, + .id = i, + .to = to, + .th = current, + }; + addblock(&bls[i]); + } + id = yield(); + for(i = 0; i < n; i++) + remblock(&bls[i]); + if(id < 0) + return((struct selected){.fd = -1, .ev = -1}); + return((struct selected){.fd = bls[id].fd, .ev = bls[id].rev}); +} + +int block(int fd, int ev, time_t to) +{ + struct blocker bl; + int rv; + + if(fd >= FD_SETSIZE) { + flog(LOG_ERR, "tried to use more file descriptors than select() can handle: fd %i", fd); + errno = EMFILE; + return(-1); + } + bl = (struct blocker) { + .fd = fd, + .ev = ev, + .id = -1, + .to = (to > 0)?(time(NULL) + to):0, + .th = current, + }; + addblock(&bl); + rv = yield(); + remblock(&bl); return(rv); } @@ -125,10 +159,21 @@ int ioloop(void) ev |= EV_WRITE; if(FD_ISSET(bl->fd, &efds)) ev = -1; - if((ev < 0) || (ev & bl->ev)) - resume(bl->th, ev); - else if((bl->to != 0) && (bl->to <= now)) - resume(bl->th, 0); + if((ev < 0) || (ev & bl->ev)) { + if(bl->id < 0) { + resume(bl->th, ev); + } else { + bl->rev = ev; + resume(bl->th, bl->id); + } + } else if((bl->to != 0) && (bl->to <= now)) { + if(bl->id < 0) { + resume(bl->th, 0); + } else { + bl->rev = 0; + resume(bl->th, bl->id); + } + } } } } diff --git a/lib/mtio.h b/lib/mtio.h index 567c0a6..ffb57da 100644 --- a/lib/mtio.h +++ b/lib/mtio.h @@ -13,6 +13,11 @@ struct stdiofd { int rights, sendrights; }; +struct selected { + int fd, ev; +}; + +struct selected mblock(time_t to, int n, struct selected *spec); int block(int fd, int ev, time_t to); int ioloop(void); void exitioloop(int status);