diff options
-rw-r--r-- | lib/libc_r/uthread/Makefile.inc | 5 | ||||
-rw-r--r-- | lib/libc_r/uthread/pthread_private.h | 9 | ||||
-rw-r--r-- | lib/libc_r/uthread/uthread_poll.c | 140 | ||||
-rw-r--r-- | lib/libpthread/uthread/Makefile.inc | 5 | ||||
-rw-r--r-- | lib/libpthread/uthread/pthread_private.h | 9 | ||||
-rw-r--r-- | lib/libpthread/uthread/uthread_poll.c | 140 |
6 files changed, 300 insertions, 8 deletions
diff --git a/lib/libc_r/uthread/Makefile.inc b/lib/libc_r/uthread/Makefile.inc index 62b4c96a931..4b4ad139bf8 100644 --- a/lib/libc_r/uthread/Makefile.inc +++ b/lib/libc_r/uthread/Makefile.inc @@ -1,5 +1,5 @@ -# $Id: Makefile.inc,v 1.3 1998/12/10 00:33:54 d Exp $ -# $OpenBSD: Makefile.inc,v 1.3 1998/12/10 00:33:54 d Exp $ +# $Id: Makefile.inc,v 1.4 1999/01/08 04:59:49 d Exp $ +# $OpenBSD: Makefile.inc,v 1.4 1999/01/08 04:59:49 d Exp $ # uthread sources .PATH: ${.CURDIR}/uthread @@ -65,6 +65,7 @@ SRCS+= \ uthread_once.c \ uthread_open.c \ uthread_pipe.c \ + uthread_poll.c \ uthread_queue.c \ uthread_read.c \ uthread_readv.c \ diff --git a/lib/libc_r/uthread/pthread_private.h b/lib/libc_r/uthread/pthread_private.h index fb6cc7a1076..9772235728e 100644 --- a/lib/libc_r/uthread/pthread_private.h +++ b/lib/libc_r/uthread/pthread_private.h @@ -31,7 +31,7 @@ * * Private thread definitions for the uthread kernel. * - * $OpenBSD: pthread_private.h,v 1.6 1998/12/23 22:49:46 d Exp $ + * $OpenBSD: pthread_private.h,v 1.7 1999/01/08 04:59:50 d Exp $ * */ @@ -461,7 +461,7 @@ struct pthread { */ /* Kernel thread structure used when there are no running threads: */ -extern struct pthread _thread_kern_thread; +extern struct pthread * volatile _thread_kern_thread; /* Ptr to the thread structure for the running thread: */ extern struct pthread * volatile _thread_run; @@ -753,6 +753,11 @@ pid_t _thread_sys_wait3(int *, int, struct rusage *); pid_t _thread_sys_wait4(pid_t, int *, int, struct rusage *); #endif +/* #include <sys/poll.h> */ +#ifdef _SYS_POLL_H_ +int _thread_sys_poll(struct pollfd[], int, int); +#endif + __END_DECLS #endif /* !_PTHREAD_PRIVATE_H */ diff --git a/lib/libc_r/uthread/uthread_poll.c b/lib/libc_r/uthread/uthread_poll.c new file mode 100644 index 00000000000..583f0631610 --- /dev/null +++ b/lib/libc_r/uthread/uthread_poll.c @@ -0,0 +1,140 @@ +/* + * David Leonard <d@openbsd.org>, 1999. Public Domain. + * + */ +#include <unistd.h> +#include <errno.h> +#include <string.h> +#include <sys/types.h> +#include <sys/time.h> +#include <poll.h> +#include <stdlib.h> +#ifdef _THREAD_SAFE +#include <pthread.h> +#include "pthread_private.h" + +static void +poll_helper(nfds, fds, data) + int nfds; + struct pollfd *fds; + struct pthread_select_data *data; +{ + int maxfd; + int i; + int event; + int fd; + + FD_ZERO(&data->readfds); + FD_ZERO(&data->writefds); + FD_ZERO(&data->exceptfds); + + maxfd = -1; + for (i = 0; i < nfds; i++) { + event = fds[i].events; + fd = fds[i].fd; + + if (event & POLLIN) + FD_SET(fd, &data->readfds); + if (event & POLLOUT) + FD_SET(fd, &data->writefds); + if (fd > maxfd) + maxfd = fd; + } + data->nfds = maxfd + 1; +} + +int +poll(fds, nfds, timeout) + struct pollfd fds[]; + int nfds; + int timeout; +{ + fd_set rfds, wfds, rwfds; + int i; + struct timespec ts; + int fd, event; + struct pthread_select_data data; + struct timeval zero_timeout = { 0, 0 }; + int ret; + + if (timeout < 0) { + /* Wait forever: */ + _thread_kern_set_timeout(NULL); + } else { + ts.tv_sec = timeout / 1000; + ts.tv_nsec = (timeout % 1000) * 1000000L; + _thread_kern_set_timeout(&ts); + } + + /* Obtain locks needed: */ + ret = 0; + FD_ZERO(&rfds); + FD_ZERO(&wfds); + FD_ZERO(&rwfds); + for (i = 0; i < nfds; i++) { + event = fds[i].events; + fd = fds[i].fd; + + if (event & (POLLIN|POLLOUT)) + if (!FD_ISSET(fd, &rwfds) && !FD_ISSET(fd, &rfds) && + !FD_ISSET(fd, &wfds)) { + if ((ret = _FD_LOCK(fd, FD_RDWR, NULL)) != 0) + break; + FD_SET(fd, &rwfds); + continue; + } + + if (event & POLLIN) + if (!FD_ISSET(fd, &rwfds) && !FD_ISSET(fd, &rfds)) { + if ((ret = _FD_LOCK(fd, FD_READ, NULL)) != 0) + break; + FD_SET(fd, &rfds); + } + + if (event & POLLOUT) + if (!FD_ISSET(fd, &rwfds) && !FD_ISSET(fd, &wfds)) { + if ((ret = _FD_LOCK(fd, FD_WRITE, NULL)) != 0) + break; + FD_SET(fd, &wfds); + } + } + + if (ret == 0) { + poll_helper(nfds, fds, &data); + ret = _thread_sys_select(data.nfds, &data.readfds, + &data.writefds, NULL, &zero_timeout); + if (ret == 0) { + poll_helper(nfds, fds, &data); + _thread_run->data.select_data = &data; + _thread_run->interrupted = 0; + _thread_kern_sched_state(PS_SELECT_WAIT, __FILE__, __LINE__); + if (_thread_run->interrupted) { + errno = EINTR; + ret = -1; + } + } + + if (ret >= 0) + ret = _thread_sys_poll(fds, nfds, 0); + } + + /* Clean up the locks: */ + for (i = 0; i < nfds; i++) { + fd = fds[i].fd; + if (FD_ISSET(fd, &rwfds)) { + _FD_UNLOCK(fd, FD_RDWR); + FD_CLR(fd, &rwfds); + } + if (FD_ISSET(fd, &rfds)) { + _FD_UNLOCK(fd, FD_READ); + FD_CLR(fd, &rfds); + } + if (FD_ISSET(fd, &wfds)) { + _FD_UNLOCK(fd, FD_WRITE); + FD_CLR(fd, &wfds); + } + } + + return (ret); +} +#endif diff --git a/lib/libpthread/uthread/Makefile.inc b/lib/libpthread/uthread/Makefile.inc index 62b4c96a931..4b4ad139bf8 100644 --- a/lib/libpthread/uthread/Makefile.inc +++ b/lib/libpthread/uthread/Makefile.inc @@ -1,5 +1,5 @@ -# $Id: Makefile.inc,v 1.3 1998/12/10 00:33:54 d Exp $ -# $OpenBSD: Makefile.inc,v 1.3 1998/12/10 00:33:54 d Exp $ +# $Id: Makefile.inc,v 1.4 1999/01/08 04:59:49 d Exp $ +# $OpenBSD: Makefile.inc,v 1.4 1999/01/08 04:59:49 d Exp $ # uthread sources .PATH: ${.CURDIR}/uthread @@ -65,6 +65,7 @@ SRCS+= \ uthread_once.c \ uthread_open.c \ uthread_pipe.c \ + uthread_poll.c \ uthread_queue.c \ uthread_read.c \ uthread_readv.c \ diff --git a/lib/libpthread/uthread/pthread_private.h b/lib/libpthread/uthread/pthread_private.h index fb6cc7a1076..9772235728e 100644 --- a/lib/libpthread/uthread/pthread_private.h +++ b/lib/libpthread/uthread/pthread_private.h @@ -31,7 +31,7 @@ * * Private thread definitions for the uthread kernel. * - * $OpenBSD: pthread_private.h,v 1.6 1998/12/23 22:49:46 d Exp $ + * $OpenBSD: pthread_private.h,v 1.7 1999/01/08 04:59:50 d Exp $ * */ @@ -461,7 +461,7 @@ struct pthread { */ /* Kernel thread structure used when there are no running threads: */ -extern struct pthread _thread_kern_thread; +extern struct pthread * volatile _thread_kern_thread; /* Ptr to the thread structure for the running thread: */ extern struct pthread * volatile _thread_run; @@ -753,6 +753,11 @@ pid_t _thread_sys_wait3(int *, int, struct rusage *); pid_t _thread_sys_wait4(pid_t, int *, int, struct rusage *); #endif +/* #include <sys/poll.h> */ +#ifdef _SYS_POLL_H_ +int _thread_sys_poll(struct pollfd[], int, int); +#endif + __END_DECLS #endif /* !_PTHREAD_PRIVATE_H */ diff --git a/lib/libpthread/uthread/uthread_poll.c b/lib/libpthread/uthread/uthread_poll.c new file mode 100644 index 00000000000..583f0631610 --- /dev/null +++ b/lib/libpthread/uthread/uthread_poll.c @@ -0,0 +1,140 @@ +/* + * David Leonard <d@openbsd.org>, 1999. Public Domain. + * + */ +#include <unistd.h> +#include <errno.h> +#include <string.h> +#include <sys/types.h> +#include <sys/time.h> +#include <poll.h> +#include <stdlib.h> +#ifdef _THREAD_SAFE +#include <pthread.h> +#include "pthread_private.h" + +static void +poll_helper(nfds, fds, data) + int nfds; + struct pollfd *fds; + struct pthread_select_data *data; +{ + int maxfd; + int i; + int event; + int fd; + + FD_ZERO(&data->readfds); + FD_ZERO(&data->writefds); + FD_ZERO(&data->exceptfds); + + maxfd = -1; + for (i = 0; i < nfds; i++) { + event = fds[i].events; + fd = fds[i].fd; + + if (event & POLLIN) + FD_SET(fd, &data->readfds); + if (event & POLLOUT) + FD_SET(fd, &data->writefds); + if (fd > maxfd) + maxfd = fd; + } + data->nfds = maxfd + 1; +} + +int +poll(fds, nfds, timeout) + struct pollfd fds[]; + int nfds; + int timeout; +{ + fd_set rfds, wfds, rwfds; + int i; + struct timespec ts; + int fd, event; + struct pthread_select_data data; + struct timeval zero_timeout = { 0, 0 }; + int ret; + + if (timeout < 0) { + /* Wait forever: */ + _thread_kern_set_timeout(NULL); + } else { + ts.tv_sec = timeout / 1000; + ts.tv_nsec = (timeout % 1000) * 1000000L; + _thread_kern_set_timeout(&ts); + } + + /* Obtain locks needed: */ + ret = 0; + FD_ZERO(&rfds); + FD_ZERO(&wfds); + FD_ZERO(&rwfds); + for (i = 0; i < nfds; i++) { + event = fds[i].events; + fd = fds[i].fd; + + if (event & (POLLIN|POLLOUT)) + if (!FD_ISSET(fd, &rwfds) && !FD_ISSET(fd, &rfds) && + !FD_ISSET(fd, &wfds)) { + if ((ret = _FD_LOCK(fd, FD_RDWR, NULL)) != 0) + break; + FD_SET(fd, &rwfds); + continue; + } + + if (event & POLLIN) + if (!FD_ISSET(fd, &rwfds) && !FD_ISSET(fd, &rfds)) { + if ((ret = _FD_LOCK(fd, FD_READ, NULL)) != 0) + break; + FD_SET(fd, &rfds); + } + + if (event & POLLOUT) + if (!FD_ISSET(fd, &rwfds) && !FD_ISSET(fd, &wfds)) { + if ((ret = _FD_LOCK(fd, FD_WRITE, NULL)) != 0) + break; + FD_SET(fd, &wfds); + } + } + + if (ret == 0) { + poll_helper(nfds, fds, &data); + ret = _thread_sys_select(data.nfds, &data.readfds, + &data.writefds, NULL, &zero_timeout); + if (ret == 0) { + poll_helper(nfds, fds, &data); + _thread_run->data.select_data = &data; + _thread_run->interrupted = 0; + _thread_kern_sched_state(PS_SELECT_WAIT, __FILE__, __LINE__); + if (_thread_run->interrupted) { + errno = EINTR; + ret = -1; + } + } + + if (ret >= 0) + ret = _thread_sys_poll(fds, nfds, 0); + } + + /* Clean up the locks: */ + for (i = 0; i < nfds; i++) { + fd = fds[i].fd; + if (FD_ISSET(fd, &rwfds)) { + _FD_UNLOCK(fd, FD_RDWR); + FD_CLR(fd, &rwfds); + } + if (FD_ISSET(fd, &rfds)) { + _FD_UNLOCK(fd, FD_READ); + FD_CLR(fd, &rfds); + } + if (FD_ISSET(fd, &wfds)) { + _FD_UNLOCK(fd, FD_WRITE); + FD_CLR(fd, &wfds); + } + } + + return (ret); +} +#endif |