diff options
author | Kurt Miller <kurt@cvs.openbsd.org> | 2009-03-24 13:49:39 +0000 |
---|---|---|
committer | Kurt Miller <kurt@cvs.openbsd.org> | 2009-03-24 13:49:39 +0000 |
commit | 357c94f187ffcf56d0506c1f4373ce80a642ac5d (patch) | |
tree | 16b1fb9d86dfe438a6a7ef6781be26d42570d50f | |
parent | 54172b1e5b0d3690847aae62b3d74ae0316ea1a0 (diff) |
Only copy out the revents field, not the whole pollfd structure. This
allows threaded programs to concurrently update the events field while
a thread is blocked in poll(2).
okay deraadt@ millert@
-rw-r--r-- | sys/kern/sys_generic.c | 26 |
1 files changed, 23 insertions, 3 deletions
diff --git a/sys/kern/sys_generic.c b/sys/kern/sys_generic.c index ac9d89dd38d..01eab771b5a 100644 --- a/sys/kern/sys_generic.c +++ b/sys/kern/sys_generic.c @@ -1,4 +1,4 @@ -/* $OpenBSD: sys_generic.c,v 1.59 2008/12/16 07:57:28 guenther Exp $ */ +/* $OpenBSD: sys_generic.c,v 1.60 2009/03/24 13:49:38 kurt Exp $ */ /* $NetBSD: sys_generic.c,v 1.24 1996/03/29 00:25:32 cgd Exp $ */ /* @@ -65,6 +65,7 @@ int selscan(struct proc *, fd_set *, fd_set *, int, int, register_t *); int seltrue(dev_t, int, struct proc *); void pollscan(struct proc *, struct pollfd *, u_int, register_t *); +int pollout(struct pollfd *, struct pollfd *, u_int); /* * Read system call. @@ -853,6 +854,25 @@ pollscan(struct proc *p, struct pollfd *pl, u_int nfd, register_t *retval) } /* + * Only copyout the revents field. + */ +int +pollout(struct pollfd *pl, struct pollfd *upl, u_int nfds) +{ + int error = 0; + u_int i = 0; + + while (!error && i++ < nfds) { + error = copyout(&pl->revents, &upl->revents, + sizeof(upl->revents)); + pl++; + upl++; + } + + return (error); +} + +/* * We are using the same mechanism as select only we encode/decode args * differently. */ @@ -938,13 +958,13 @@ done: */ switch (error) { case ERESTART: - error = copyout(pl, SCARG(uap, fds), sz); + error = pollout(pl, SCARG(uap, fds), nfds); if (error == 0) error = EINTR; break; case EWOULDBLOCK: case 0: - error = copyout(pl, SCARG(uap, fds), sz); + error = pollout(pl, SCARG(uap, fds), nfds); break; } bad: |