diff options
author | Matthew Dempsky <matthew@cvs.openbsd.org> | 2013-04-29 17:06:21 +0000 |
---|---|---|
committer | Matthew Dempsky <matthew@cvs.openbsd.org> | 2013-04-29 17:06:21 +0000 |
commit | f906bc6b3feaa6746a37164ed4affdc64958e7eb (patch) | |
tree | b093f798926d62fa1734fe7ab04fc8464b8ed624 /lib | |
parent | ab57702df769d8c244d528d09917f03ba5ca0e38 (diff) |
Extend P_SIGSUSPEND handling in userret() to properly restore the
sigmask even if there are no pending signals under the temporary
sigmask.
Refactor existing select() and poll() system calls to introduce the
pselect() and ppoll() system calls.
Add rthread wrappers for pselect() and ppoll(). While there, update
cancellation point comments to reflect recent fdatasync() addition.
Minor bumps for libc and librthread due to new symbols.
ok guenther, millert, deraadt, jmc
Diffstat (limited to 'lib')
-rw-r--r-- | lib/libc/shlib_version | 2 | ||||
-rw-r--r-- | lib/libc/sys/Makefile.inc | 6 | ||||
-rw-r--r-- | lib/libc/sys/poll.2 | 65 | ||||
-rw-r--r-- | lib/libc/sys/select.2 | 64 | ||||
-rw-r--r-- | lib/librthread/rthread_cancel.c | 50 | ||||
-rw-r--r-- | lib/librthread/shlib_version | 2 |
6 files changed, 152 insertions, 37 deletions
diff --git a/lib/libc/shlib_version b/lib/libc/shlib_version index bf8551aca93..b52840ac023 100644 --- a/lib/libc/shlib_version +++ b/lib/libc/shlib_version @@ -1,4 +1,4 @@ major=68 -minor=0 +minor=1 # note: If changes were made to include/thread_private.h or if system # calls were added/changed then librthread/shlib_version also be updated. diff --git a/lib/libc/sys/Makefile.inc b/lib/libc/sys/Makefile.inc index a22d4bf77e6..57f76b8fb16 100644 --- a/lib/libc/sys/Makefile.inc +++ b/lib/libc/sys/Makefile.inc @@ -1,4 +1,4 @@ -# $OpenBSD: Makefile.inc,v 1.110 2013/04/15 16:38:21 matthew Exp $ +# $OpenBSD: Makefile.inc,v 1.111 2013/04/29 17:06:20 matthew Exp $ # $NetBSD: Makefile.inc,v 1.35 1995/10/16 23:49:07 jtc Exp $ # @(#)Makefile.inc 8.1 (Berkeley) 6/17/93 @@ -45,7 +45,7 @@ ASM= __get_tcb.o __getcwd.o __semctl.o __set_tcb.o __syscall.o \ mknod.o mknodat.o mlock.o mlockall.o mount.o mprotect.o \ msgctl.o msgget.o msgrcv.o msgsnd.o msync.o munlock.o \ munlockall.o munmap.o nanosleep.o nfssvc.o \ - open.o openat.o pathconf.o pipe.o poll.o profil.o \ + open.o openat.o pathconf.o pipe.o poll.o ppoll.o profil.o pselect.o \ quotactl.o read.o readlink.o readlinkat.o readv.o reboot.o \ recvfrom.o recvmsg.o rename.o renameat.o revoke.o rmdir.o \ sched_yield.o select.o semget.o semop.o sendmsg.o sendto.o \ @@ -239,10 +239,12 @@ MLINKS+=mlockall.2 munlockall.2 MLINKS+=mount.2 unmount.2 MLINKS+=open.2 openat.2 MLINKS+=pathconf.2 fpathconf.2 +MLINKS+=poll.2 ppoll.2 MLINKS+=read.2 readv.2 read.2 pread.2 read.2 preadv.2 MLINKS+=readlink.2 readlinkat.2 MLINKS+=recv.2 recvfrom.2 recv.2 recvmsg.2 MLINKS+=rename.2 renameat.2 +MLINKS+=select.2 pselect.2 MLINKS+=select.2 FD_ISSET.3 select.2 FD_ZERO.3 MLINKS+=select.2 FD_SET.3 select.2 FD_CLR.3 MLINKS+=send.2 sendmsg.2 send.2 sendto.2 diff --git a/lib/libc/sys/poll.2 b/lib/libc/sys/poll.2 index adfb20831c1..7ceaffb33fa 100644 --- a/lib/libc/sys/poll.2 +++ b/lib/libc/sys/poll.2 @@ -1,4 +1,4 @@ -.\" $OpenBSD: poll.2,v 1.21 2007/07/11 08:12:15 jmc Exp $ +.\" $OpenBSD: poll.2,v 1.22 2013/04/29 17:06:20 matthew Exp $ .\" .\" Copyright (c) 1994 Jason R. Thorpe .\" All rights reserved. @@ -28,16 +28,19 @@ .\" OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" -.Dd $Mdocdate: July 11 2007 $ +.Dd $Mdocdate: April 29 2013 $ .Dt POLL 2 .Os .Sh NAME -.Nm poll +.Nm poll , +.Nm ppoll .Nd synchronous I/O multiplexing .Sh SYNOPSIS .Fd #include <poll.h> .Ft int .Fn poll "struct pollfd *fds" "nfds_t nfds" "int timeout" +.Ft int +.Fn ppoll "struct pollfd *fds" "nfds_t nfds" "const struct timespec *timeout" "const sigset_t *mask" .Sh DESCRIPTION .Fn poll provides a mechanism for multiplexing I/O across a set of file @@ -176,18 +179,39 @@ In addition to I/O multiplexing, can be used to generate simple timeouts. This functionality may be achieved by passing a null pointer for .Fa fds . +.Pp +The +.Fn ppoll +function is similar to +.Fn poll +except that it specifies the timeout using a timespec structure, +and a null pointer is used to specify an indefinite timeout +instead of +.Dv INFTIM . +Also, if +.Fa mask +is a non-null pointer, +.Fn ppoll +atomically sets the calling thread's signal mask to the signal set +pointed to by +.Fa mask +for the duration of the function call. +In this case, the original signal mask will be restored before +.Fn ppoll +returns. .Sh RETURN VALUES Upon error, .Fn poll -returns \-1 and sets the global variable +and +.Fn ppoll +return \-1 and set the global variable .Va errno to indicate the error. If the timeout interval was reached before any events occurred, -.Fn poll -returns 0. -Otherwise, -.Fn poll -returns the number of file descriptors for which +they return 0. +Otherwise, they return the number of +.Fa pollfd +structures for which .Fa revents is non-zero. .Sh EXAMPLES @@ -215,22 +239,22 @@ if (read(STDIN_FILENO, buf, sizeof(buf)) == -1) .Ed .Sh ERRORS .Fn poll +and +.Fn ppoll will fail if: -.Bl -tag -width "EINVAL " +.Bl -tag -width Er .It Bq Er EFAULT .Fa fds points outside the process's allocated address space. .It Bq Er EINTR -.Fn poll -caught a signal during the polling process. +A signal was caught before any polled events occurred +and before the timeout elapsed. .It Bq Er EINVAL .Fa nfds was greater than the number of available file descriptors. .It Bq Er EINVAL -The timeout passed to -.Fn poll -was too large. +The timeout passed was invalid. .El .Sh SEE ALSO .Xr getrlimit 2 , @@ -243,11 +267,18 @@ The function is compliant with the .St -xpg4.3 specification. +The +.Fn ppoll +function is a Linux extension. .Sh HISTORY A .Fn poll system call appeared in .At V.3 . +The +.Fn ppoll +function appeared in +.Ox 5.4 . .Sh BUGS The .Dv POLLERR @@ -273,4 +304,6 @@ flags are equivalent. .Pp Internally to the kernel, .Fn poll -works poorly if multiple processes wait on the same file descriptor. +and +.Fn ppoll +work poorly if multiple processes wait on the same file descriptor. diff --git a/lib/libc/sys/select.2 b/lib/libc/sys/select.2 index c521598f672..1cd5bee23ca 100644 --- a/lib/libc/sys/select.2 +++ b/lib/libc/sys/select.2 @@ -1,4 +1,4 @@ -.\" $OpenBSD: select.2,v 1.28 2007/05/31 19:19:33 jmc Exp $ +.\" $OpenBSD: select.2,v 1.29 2013/04/29 17:06:20 matthew Exp $ .\" $NetBSD: select.2,v 1.5 1995/06/27 22:32:28 cgd Exp $ .\" .\" Copyright (c) 1983, 1991, 1993 @@ -30,11 +30,12 @@ .\" .\" @(#)select.2 8.2 (Berkeley) 3/25/94 .\" -.Dd $Mdocdate: May 31 2007 $ +.Dd $Mdocdate: April 29 2013 $ .Dt SELECT 2 .Os .Sh NAME -.Nm select +.Nm select , +.Nm pselect .Nd synchronous I/O multiplexing .Sh SYNOPSIS .Fd #include <sys/types.h> @@ -43,6 +44,8 @@ .Fd #include <unistd.h> .Ft int .Fn select "int nfds" "fd_set *readfds" "fd_set *writefds" "fd_set *exceptfds" "struct timeval *timeout" +.Ft int +.Fn pselect "int nfds" "fd_set *readfds" "fd_set *writefds" "fd_set *exceptfds" "const struct timespec *timeout" "const sigset_t *mask" .Fn FD_SET fd &fdset .Fn FD_CLR fd &fdset .Fn FD_ISSET fd &fdset @@ -122,20 +125,47 @@ Any of and .Fa exceptfds may be given as null pointers if no descriptors are of interest. -.Sh RETURN VALUES +.Pp +The +.Fn pselect +function is similar to .Fn select -returns the number of ready descriptors that are contained in -the descriptor sets, or \-1 if an error occurred. -If the time limit expires, +except that it specifies the timeout using a timespec structure. +Also, if +.Fa mask +is a non-null pointer, +.Fn pselect +atomically sets the calling thread's signal mask to the signal set +pointed to by +.Fa mask +for the duration of the function call. +In this case, the original signal mask will be restored before +.Fn pselect +returns. +.Sh RETURN VALUES +If successful, .Fn select -returns 0. -If +and +.Fn pselect +return the number of ready descriptors that are contained in +the descriptor sets. +If a descriptor is included in multiple descriptor sets, +each inclusion is counted separately. +If the time limit expires before any descriptors become ready, +they return 0. +.Pp +Otherwise, if .Fn select -returns with an error, including one due to an interrupted call, -the descriptor sets will be unmodified. +or +.Fn pselect +return with an error, including one due to an interrupted call, +they return \-1, +and the descriptor sets will be unmodified. .Sh ERRORS An error return from .Fn select +or +.Fn pselect indicates: .Bl -tag -width Er .It Bq Er EFAULT @@ -149,7 +179,7 @@ points outside the process's allocated address space. One of the descriptor sets specified an invalid descriptor. .It Bq Er EINTR A signal was delivered before the time limit expired and -before any of the selected events occurred. +before any of the selected descriptors became ready. .It Bq Er EINVAL The specified time limit is invalid. One of its components is negative or too large. @@ -167,8 +197,12 @@ One of its components is negative or too large. .Sh HISTORY The .Fn select -function call appeared in +function appeared in .Bx 4.2 . +The +.Fn pselect +function appeared in +.Ox 5.4 . .Sh BUGS Although the provision of .Xr getdtablesize 3 @@ -250,7 +284,9 @@ and using .Pp Internally to the kernel, .Fn select -works poorly if multiple processes wait on the same file descriptor. +and +.Fn pselect +work poorly if multiple processes wait on the same file descriptor. Given that, it is rather surprising to see that many daemons are written that way (i.e., .Xr httpd 8 ) . diff --git a/lib/librthread/rthread_cancel.c b/lib/librthread/rthread_cancel.c index a1ccd9f0669..0004eb74f47 100644 --- a/lib/librthread/rthread_cancel.c +++ b/lib/librthread/rthread_cancel.c @@ -1,4 +1,4 @@ -/* $OpenBSD: rthread_cancel.c,v 1.6 2012/04/17 15:10:11 miod Exp $ */ +/* $OpenBSD: rthread_cancel.c,v 1.7 2013/04/29 17:06:20 matthew Exp $ */ /* $snafu: libc_tag.c,v 1.4 2004/11/30 07:00:06 marc Exp $ */ /* PUBLIC DOMAIN: No Rights Reserved. Marco S Hyman <marc@snafu.org> */ @@ -40,8 +40,12 @@ int _thread_sys_nanosleep(const struct timespec *, struct timespec *); int _thread_sys_open(const char *, int, ...); int _thread_sys_openat(int, const char *, int, ...); int _thread_sys_poll(struct pollfd *, nfds_t, int); +int _thread_sys_ppoll(struct pollfd *, nfds_t, const struct timespec *, + const sigset_t *); ssize_t _thread_sys_pread(int, void *, size_t, off_t); ssize_t _thread_sys_preadv(int, const struct iovec *, int, off_t); +int _thread_sys_pselect(int, fd_set *, fd_set *, fd_set *, + const struct timespec *, const sigset_t *); ssize_t _thread_sys_pwrite(int, const void *, size_t, off_t); ssize_t _thread_sys_pwritev(int, const struct iovec *, int, off_t); ssize_t _thread_sys_read(int, void *, size_t); @@ -203,7 +207,7 @@ fcntl(int fd, int cmd, ...) } #if 0 -fdatasync() /* don't have yet */ +fdatasync() /* built on fsync() */ #endif int @@ -333,6 +337,26 @@ poll(struct pollfd *fds, nfds_t nfds, int timeout) return (rv); } +int +ppoll(struct pollfd *fds, nfds_t nfds, const struct timespec *timeout, + const sigset_t *sigmask) +{ + pthread_t self = pthread_self(); + sigset_t set; + int rv; + + if (sigmask != NULL && sigismember(sigmask, SIGTHR)) { + set = *sigmask; + sigdelset(&set, SIGTHR); + sigmask = &set; + } + + _enter_cancel(self); + rv = _thread_sys_ppoll(fds, nfds, timeout, sigmask); + _leave_cancel(self); + return (rv); +} + ssize_t pread(int fd, void *buf, size_t nbytes, off_t offset) { @@ -357,8 +381,28 @@ preadv(int fd, const struct iovec *iov, int iovcnt, off_t offset) return (rv); } +int +pselect(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, + const struct timespec *timeout, const sigset_t *sigmask) +{ + pthread_t self = pthread_self(); + sigset_t set; + int rv; + + if (sigmask != NULL && sigismember(sigmask, SIGTHR)) { + set = *sigmask; + sigdelset(&set, SIGTHR); + sigmask = &set; + } + + _enter_cancel(self); + rv = _thread_sys_pselect(nfds, readfds, writefds, exceptfds, timeout, + sigmask); + _leave_cancel(self); + return (rv); +} + #if 0 -pselect() /* don't have yet */ putmsg() /* don't have: dumb STREAMS stuff */ putpmsg() /* don't have: dumb STREAMS stuff */ #endif diff --git a/lib/librthread/shlib_version b/lib/librthread/shlib_version index ffdd3d2d569..730231c38d0 100644 --- a/lib/librthread/shlib_version +++ b/lib/librthread/shlib_version @@ -1,2 +1,2 @@ major=17 -minor=0 +minor=1 |