X-Git-Url: http://dolda2000.com/gitweb/?a=blobdiff_plain;f=lib%2Fmtio-select.c;h=e0a41773ea7e9e410b19a170af1de14288e59486;hb=4b70e201af5bcc4926ab9b877592ba210b32ccdc;hp=6536c95a1599cd5c6a80422b30bea4556679ed23;hpb=ae13a8b18216c45b0e75060a4df65659e572822a;p=ashd.git diff --git a/lib/mtio-select.c b/lib/mtio-select.c index 6536c95..e0a4177 100644 --- a/lib/mtio-select.c +++ b/lib/mtio-select.c @@ -32,56 +32,103 @@ #include static struct blocker *blockers; +static int exitstatus; struct blocker { struct blocker *n, *p; + struct iterator *it; int fd; - int ev; + int ev, rev, id; time_t to; struct muth *th; }; -int block(int fd, int ev, time_t to) -{ +struct iterator { 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; +}; + +static void addblock(struct blocker *bl) +{ 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); + if(bl->it) { + if((bl->it->bl = bl->n) != NULL) + bl->it->bl->it = bl->it; + bl->it = NULL; + } +} + +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); } -void ioloop(void) +int ioloop(void) { int ret; fd_set rfds, wfds, efds; - struct blocker *bl, *nbl; + struct blocker *bl; + struct iterator it; struct timeval toval; time_t now, timeout; int maxfd; int ev; + exitstatus = 0; while(blockers != NULL) { FD_ZERO(&rfds); FD_ZERO(&wfds); @@ -100,6 +147,8 @@ void ioloop(void) if((bl->to != 0) && ((timeout == 0) || (timeout > bl->to))) timeout = bl->to; } + if(exitstatus) + return(exitstatus); toval.tv_sec = timeout - now; toval.tv_usec = 0; ret = select(maxfd + 1, &rfds, &wfds, &efds, timeout?(&toval):NULL); @@ -110,21 +159,42 @@ void ioloop(void) * probably is. */ sleep(1); } - } - now = time(NULL); - for(bl = blockers; bl; bl = nbl) { - nbl = bl->n; - ev = 0; - if(FD_ISSET(bl->fd, &rfds)) - ev |= EV_READ; - if(FD_ISSET(bl->fd, &wfds)) - 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); + } else { + now = time(NULL); + for(bl = it.bl = blockers; bl; bl = it.bl) { + if((it.bl = bl->n) != NULL) + it.bl->it = ⁢ + ev = 0; + if(FD_ISSET(bl->fd, &rfds)) + ev |= EV_READ; + if(FD_ISSET(bl->fd, &wfds)) + ev |= EV_WRITE; + if(FD_ISSET(bl->fd, &efds)) + ev = -1; + 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); + } + } + if(it.bl) + it.bl->it = NULL; + } } } + return(0); +} + +void exitioloop(int status) +{ + exitstatus = status; }