$NetBSD: patch-ac,v 1.4 2002/11/26 21:42:49 skrll Exp $ --- pth_high.c.orig Sun Jan 27 13:14:36 2002 +++ pth_high.c @@ -35,6 +35,42 @@ #include "pth_p.h" +/* Pth variant of nanosleep(2) */ +int pth_nanosleep(const struct timespec *rqtp, struct timespec *rmtp) +{ + pth_time_t until; + pth_time_t offset; + pth_time_t now; + pth_event_t ev; + static pth_key_t ev_key = PTH_KEY_INIT; + + if (rqtp == NULL) { + return_errno(-1, EFAULT); + } + + /* short-circuit */ + if (rqtp->tv_sec == 0 && rqtp->tv_nsec == 0) + return 0; + + /* calculate asleep time */ + offset = pth_time((long)rqtp->tv_sec, (long)(rqtp->tv_nsec / 1000)); + pth_time_set(&until, PTH_TIME_NOW); + pth_time_add(&until, &offset); + + /* and let thread sleep until this time is elapsed */ + ev = pth_event(PTH_EVENT_TIME|PTH_MODE_STATIC, &ev_key, until); + pth_wait(ev); + + if (rmtp != NULL) { + pth_time_set(&now, PTH_TIME_NOW); + pth_time_sub(&until, &now); + rmtp->tv_sec = until.tv_sec; + rmtp->tv_nsec = until.tv_usec * 1000; + } + + return 0; +} + /* Pth variant of usleep(3) */ int pth_usleep(unsigned int usec) { @@ -141,8 +177,43 @@ int pth_sigwait_ev(const sigset_t *set, return 0; } +#ifdef HAVE_SYS_RESOURCE_H +/* Pth variant of wait4(2) */ +pid_t pth_wait4(pid_t wpid, int *status, int options, struct rusage *rusage) +{ + pth_event_t ev; + static pth_key_t ev_key = PTH_KEY_INIT; + pid_t pid; + + pth_debug2("pth_wait4: called from thread \"%s\"", pth_current->name); + + for (;;) { + /* do a non-blocking poll for the pid */ + while ( (pid = pth_sc(wait4)(wpid, status, options|WNOHANG, rusage)) < 0 + && errno == EINTR) ; + + /* if pid was found or caller requested a polling return immediately */ + if (pid == -1 || pid > 0 || (pid == 0 && (options & WNOHANG))) + break; + + /* else wait a little bit */ + ev = pth_event(PTH_EVENT_TIME|PTH_MODE_STATIC, &ev_key, pth_timeout(0,250000)); + pth_wait(ev); + } + + pth_debug2("pth_wait4: leave to thread \"%s\"", pth_current->name); + return pid; +} + /* Pth variant of waitpid(2) */ -pid_t pth_waitpid(pid_t wpid, int *status, int options) +pid_t pth_waitpid(pid_t wpid, int *status, int options) +{ + return pth_wait4(wpid, status, options, 0); +} + +#else +/* Pth variant of wait4(2) */ +pid_t pth_waitpid(pid_t wpid, int *status, int options) { pth_event_t ev; static pth_key_t ev_key = PTH_KEY_INIT; @@ -167,6 +238,8 @@ pid_t pth_waitpid(pid_t wpid, int *statu pth_debug2("pth_waitpid: leave to thread \"%s\"", pth_current->name); return pid; } +#endif + /* Pth variant of system(3) */ int pth_system(const char *cmd) @@ -195,7 +268,7 @@ int pth_system(const char *cmd) /* block SIGCHLD signal */ sigemptyset(&ss_block); sigaddset(&ss_block, SIGCHLD); - sigprocmask(SIG_BLOCK, &ss_block, &ss_old); + pth_sc(sigprocmask)(SIG_BLOCK, &ss_block, &ss_old); /* fork the current process */ pstat = -1; @@ -207,7 +280,7 @@ int pth_system(const char *cmd) /* restore original signal dispositions and execute the command */ sigaction(SIGINT, &sa_int, NULL); sigaction(SIGQUIT, &sa_quit, NULL); - sigprocmask(SIG_SETMASK, &ss_old, NULL); + pth_sc(sigprocmask)(SIG_SETMASK, &ss_old, NULL); /* stop the Pth scheduling */ pth_scheduler_kill(); @@ -227,7 +300,7 @@ int pth_system(const char *cmd) /* restore original signal dispositions and execute the command */ sigaction(SIGINT, &sa_int, NULL); sigaction(SIGQUIT, &sa_quit, NULL); - sigprocmask(SIG_SETMASK, &ss_old, NULL); + pth_sc(sigprocmask)(SIG_SETMASK, &ss_old, NULL); /* return error or child process result code */ return (pid == -1 ? -1 : pstat); @@ -258,6 +331,9 @@ int pth_select_ev(int nfd, fd_set *rfds, pth_implicit_init(); pth_debug2("pth_select_ev: called from thread \"%s\"", pth_current->name); + if (nfd < 0 || nfd > FD_SETSIZE) + return_errno(-1, EINVAL); + /* first deal with the special situation of a plain microsecond delay */ if (nfd == 0 && rfds == NULL && wfds == NULL && efds == NULL && timeout != NULL) { if (timeout->tv_sec < 0 || timeout->tv_usec < 0) @@ -280,10 +356,11 @@ int pth_select_ev(int nfd, fd_set *rfds, return_errno(-1, EINTR); } } + /* POSIX compliance */ - if (rfds != NULL) FD_ZERO(rfds); - if (wfds != NULL) FD_ZERO(wfds); - if (efds != NULL) FD_ZERO(efds); + if (rfds != NULL) pth_util_fd_zero(nfd, rfds); + if (wfds != NULL) pth_util_fd_zero(nfd, wfds); + if (efds != NULL) pth_util_fd_zero(nfd, efds); return 0; } @@ -295,36 +372,42 @@ int pth_select_ev(int nfd, fd_set *rfds, delay.tv_sec = 0; delay.tv_usec = 0; rtmp = NULL; + if (rfds != NULL) { - rspare = *rfds; + pth_util_fd_copy(nfd, &rspare, rfds); rtmp = &rspare; } wtmp = NULL; if (wfds != NULL) { - wspare = *wfds; + pth_util_fd_copy(nfd, &wspare, wfds); wtmp = &wspare; } etmp = NULL; if (efds != NULL) { - espare = *efds; + pth_util_fd_copy(nfd, &espare, efds); etmp = &espare; } while ((rc = pth_sc(select)(nfd, rtmp, wtmp, etmp, &delay)) < 0 && errno == EINTR) ; + if (rc < 0) + return_errno(-1, errno); if (rc > 0) { - if (rfds != NULL) - *rfds = rspare; - if (wfds != NULL) - *wfds = wspare; - if (efds != NULL) - *efds = espare; + if (rfds != NULL) { + pth_util_fd_copy(nfd, rfds, &rspare); + } + if (wfds != NULL) { + pth_util_fd_copy(nfd, wfds, &wspare); + } + if (efds != NULL) { + pth_util_fd_copy(nfd, efds, &espare); + } return rc; } if (rc == 0 && timeout != NULL) { if (pth_time_cmp(timeout, PTH_TIME_ZERO) == 0) { /* POSIX compliance */ - if (rfds != NULL) FD_ZERO(rfds); - if (wfds != NULL) FD_ZERO(wfds); - if (efds != NULL) FD_ZERO(efds); + if (rfds != NULL) pth_util_fd_zero(nfd, rfds); + if (wfds != NULL) pth_util_fd_zero(nfd, wfds); + if (efds != NULL) pth_util_fd_zero(nfd, efds); return 0; } } @@ -350,10 +433,9 @@ int pth_select_ev(int nfd, fd_set *rfds, pth_event_isolate(ev_timeout); if (pth_event_occurred(ev_timeout)) { selected = TRUE; - /* POSIX compliance */ - if (rfds != NULL) FD_ZERO(rfds); - if (wfds != NULL) FD_ZERO(wfds); - if (efds != NULL) FD_ZERO(efds); + if (rfds != NULL) pth_util_fd_zero(nfd, rfds); + if (wfds != NULL) pth_util_fd_zero(nfd, wfds); + if (efds != NULL) pth_util_fd_zero(nfd, efds); rc = 0; } } @@ -362,7 +444,7 @@ int pth_select_ev(int nfd, fd_set *rfds, return rc; } -/* Pth variant of select(2) */ +/* Pth variant of poll(2) */ int pth_poll(struct pollfd *pfd, nfds_t nfd, int timeout) { return pth_poll_ev(pfd, nfd, timeout, NULL); @@ -373,7 +455,7 @@ int pth_poll(struct pollfd *pfd, nfds_t INTERNALLY THE SCHEDULER IS ONLY select(2) BASED!! */ int pth_poll_ev(struct pollfd *pfd, nfds_t nfd, int timeout, pth_event_t ev_extra) { - fd_set rfds, wfds, efds; + fd_set rfds, wfds, efds, cfds; struct timeval tv, *ptv; int maxfd, rc, ok; unsigned int i; @@ -410,58 +492,64 @@ int pth_poll_ev(struct pollfd *pfd, nfds FD_ZERO(&rfds); FD_ZERO(&wfds); FD_ZERO(&efds); + FD_ZERO(&cfds); for(i = 0; i < nfd; i++) { - if (!pth_util_fd_valid(pfd[i].fd)) - return_errno(-1, EBADF); - if (pfd[i].events & POLLIN) - FD_SET(pfd[i].fd, &rfds); - if (pfd[i].events & POLLOUT) - FD_SET(pfd[i].fd, &wfds); - if (pfd[i].events & POLLPRI) - FD_SET(pfd[i].fd, &efds); - if (pfd[i].fd >= maxfd && (pfd[i].events & (POLLIN|POLLOUT|POLLPRI))) - maxfd = pfd[i].fd; + if (fcntl(pfd[i].fd, F_GETFL) == -1 && errno == EBADF) { + FD_SET(pfd[i].fd, &cfds); + } else { + if (pfd[i].events & POLLIN) + FD_SET(pfd[i].fd, &rfds); + if (pfd[i].events & POLLOUT) + FD_SET(pfd[i].fd, &wfds); + if (pfd[i].events & POLLPRI) + FD_SET(pfd[i].fd, &efds); + if (pfd[i].fd >= maxfd && (pfd[i].events & (POLLIN|POLLOUT|POLLPRI))) + maxfd = pfd[i].fd; + } + } + if (maxfd != -1) { + /* examine fd sets */ + rc = pth_select_ev(maxfd+1, &rfds, &wfds, &efds, ptv, ev_extra); + if (rc < 0) + return rc; } - if (maxfd == -1) - return_errno(-1, EINVAL); - - /* examine fd sets */ - rc = pth_select_ev(maxfd+1, &rfds, &wfds, &efds, ptv, ev_extra); /* establish results */ - if (rc > 0) { - rc = 0; - for (i = 0; i < nfd; i++) { - ok = 0; - pfd[i].revents = 0; - if (pfd[i].fd < 0) { - pfd[i].revents |= POLLNVAL; - continue; - } - if (FD_ISSET(pfd[i].fd, &rfds)) { - pfd[i].revents |= POLLIN; - ok++; - /* support for POLLHUP */ - if (recv(pfd[i].fd, data, 64, MSG_PEEK) == -1) { - if ( errno == ESHUTDOWN || errno == ECONNRESET - || errno == ECONNABORTED || errno == ENETRESET) { - pfd[i].revents &= ~(POLLIN); - pfd[i].revents |= POLLHUP; - ok--; - } + rc = 0; + for (i = 0; i < nfd; i++) { + ok = 0; + pfd[i].revents = 0; + if (FD_ISSET(pfd[i].fd, &cfds)) { + pfd[i].revents |= POLLNVAL; + if (pfd[i].fd >= 0) + rc++; + continue; + } + if (maxfd == -1) + continue; + if (FD_ISSET(pfd[i].fd, &rfds)) { + pfd[i].revents |= POLLIN; + ok++; + /* support for POLLHUP */ + if (recv(pfd[i].fd, data, 64, MSG_PEEK) == -1) { + if ( errno == ESHUTDOWN || errno == ECONNRESET + || errno == ECONNABORTED || errno == ENETRESET) { + pfd[i].revents &= ~(POLLIN); + pfd[i].revents |= POLLHUP; + ok--; } } - if (FD_ISSET(pfd[i].fd, &wfds)) { - pfd[i].revents |= POLLOUT; - ok++; - } - if (FD_ISSET(pfd[i].fd, &efds)) { - pfd[i].revents |= POLLPRI; - ok++; - } - if (ok) - rc++; } + if (FD_ISSET(pfd[i].fd, &wfds)) { + pfd[i].revents |= POLLOUT; + ok++; + } + if (FD_ISSET(pfd[i].fd, &efds)) { + pfd[i].revents |= POLLPRI; + ok++; + } + if (ok) + rc++; } return rc; } @@ -485,7 +573,8 @@ int pth_connect_ev(int s, const struct s pth_debug2("pth_connect_ev: enter from thread \"%s\"", pth_current->name); /* force filedescriptor into non-blocking mode */ - fdmode = pth_fdmode(s, PTH_FDMODE_NONBLOCK); + if ((fdmode = pth_fdmode(s, PTH_FDMODE_NONBLOCK)) == PTH_FDMODE_ERROR) + return_errno(-1, EBADF); /* try to connect */ while ( (rv = pth_sc(connect)(s, (struct sockaddr *)addr, addrlen)) == -1 @@ -498,6 +587,13 @@ int pth_connect_ev(int s, const struct s /* if it is still on progress wait until socket is really writeable */ if (rv == -1 && errno == EINPROGRESS && fdmode != PTH_FDMODE_NONBLOCK) { ev = pth_event(PTH_EVENT_FD|PTH_UNTIL_FD_WRITEABLE|PTH_MODE_STATIC, &ev_key, s); + /* + * This will fail if the fd is > FD_SETSIZE so pass the error back to the + * caller. + */ + if (ev == NULL) { + return_errno(-1, errno); + } if (ev_extra != NULL) pth_event_concat(ev, ev_extra, NULL); pth_wait(ev); @@ -536,7 +632,8 @@ int pth_accept_ev(int s, struct sockaddr pth_debug2("pth_accept_ev: enter from thread \"%s\"", pth_current->name); /* force filedescriptor into non-blocking mode */ - fdmode = pth_fdmode(s, PTH_FDMODE_NONBLOCK); + if ((fdmode = pth_fdmode(s, PTH_FDMODE_NONBLOCK)) == PTH_FDMODE_ERROR) + return_errno(-1, EBADF); /* poll socket via accept */ ev = NULL; @@ -585,6 +682,7 @@ ssize_t pth_read_ev(int fd, void *buf, s pth_event_t ev; static pth_key_t ev_key = PTH_KEY_INIT; fd_set fds; + int fdmode; int n; pth_implicit_init(); @@ -594,8 +692,12 @@ ssize_t pth_read_ev(int fd, void *buf, s if (nbytes == 0) return 0; + /* check mode of filedescriptor */ + if ((fdmode = pth_fdmode(fd, PTH_FDMODE_POLL)) == PTH_FDMODE_ERROR) + return_errno(-1, EBADF); + /* poll filedescriptor if not already in non-blocking operation */ - if (pth_fdmode(fd, PTH_FDMODE_POLL) == PTH_FDMODE_BLOCK) { + if (fdmode == PTH_FDMODE_BLOCK) { /* now directly poll filedescriptor for readability to avoid unneccessary (and resource consuming because of context @@ -662,7 +764,8 @@ ssize_t pth_write_ev(int fd, const void return 0; /* force filedescriptor into non-blocking mode */ - fdmode = pth_fdmode(fd, PTH_FDMODE_NONBLOCK); + if ((fdmode = pth_fdmode(fd, PTH_FDMODE_NONBLOCK)) == PTH_FDMODE_ERROR) + return_errno(-1, EBADF); /* poll filedescriptor if not already in non-blocking operation */ if (fdmode != PTH_FDMODE_NONBLOCK) { @@ -749,6 +852,7 @@ ssize_t pth_readv_ev(int fd, const struc pth_event_t ev; static pth_key_t ev_key = PTH_KEY_INIT; fd_set fds; + int fdmode; int n; pth_implicit_init(); @@ -758,8 +862,12 @@ ssize_t pth_readv_ev(int fd, const struc if (iovcnt <= 0 || iovcnt > UIO_MAXIOV) return_errno(-1, EINVAL); + /* check mode of filedescriptor */ + if ((fdmode = pth_fdmode(fd, PTH_FDMODE_POLL)) == PTH_FDMODE_ERROR) + return_errno(-1, EBADF); + /* poll filedescriptor if not already in non-blocking operation */ - if (pth_fdmode(fd, PTH_FDMODE_POLL) == PTH_FDMODE_BLOCK) { + if (fdmode == PTH_FDMODE_BLOCK) { /* first directly poll filedescriptor for readability to avoid unneccessary (and resource consuming because of context @@ -881,7 +989,8 @@ ssize_t pth_writev_ev(int fd, const stru return_errno(-1, EINVAL); /* force filedescriptor into non-blocking mode */ - fdmode = pth_fdmode(fd, PTH_FDMODE_NONBLOCK); + if ((fdmode = pth_fdmode(fd, PTH_FDMODE_NONBLOCK)) == PTH_FDMODE_ERROR) + return_errno(-1, EBADF); /* poll filedescriptor if not already in non-blocking operation */ if (fdmode != PTH_FDMODE_NONBLOCK) { @@ -1176,6 +1285,7 @@ ssize_t pth_recvfrom_ev(int fd, void *bu pth_event_t ev; static pth_key_t ev_key = PTH_KEY_INIT; fd_set fds; + int fdmode; int n; pth_implicit_init(); @@ -1185,8 +1295,12 @@ ssize_t pth_recvfrom_ev(int fd, void *bu if (nbytes == 0) return 0; + /* check mode of filedescriptor */ + if ((fdmode = pth_fdmode(fd, PTH_FDMODE_POLL)) == PTH_FDMODE_ERROR) + return_errno(-1, EBADF); + /* poll filedescriptor if not already in non-blocking operation */ - if (pth_fdmode(fd, PTH_FDMODE_POLL) == PTH_FDMODE_BLOCK) { + if (fdmode == PTH_FDMODE_BLOCK) { /* now directly poll filedescriptor for readability to avoid unneccessary (and resource consuming because of context @@ -1265,7 +1379,8 @@ ssize_t pth_sendto_ev(int fd, const void return 0; /* force filedescriptor into non-blocking mode */ - fdmode = pth_fdmode(fd, PTH_FDMODE_NONBLOCK); + if ((fdmode = pth_fdmode(fd, PTH_FDMODE_NONBLOCK)) == PTH_FDMODE_ERROR) + return_errno(-1, EBADF); /* poll filedescriptor if not already in non-blocking operation */ if (fdmode != PTH_FDMODE_NONBLOCK) {