svn commit: r266614 - user/dchagin/lemul/sys/compat/linux
Dmitry Chagin
dchagin at FreeBSD.org
Sat May 24 12:16:34 UTC 2014
Author: dchagin
Date: Sat May 24 12:16:33 2014
New Revision: 266614
URL: http://svnweb.freebsd.org/changeset/base/266614
Log:
Fix some bugs in eventfd:
Do not disable eventfd read and write system call restart
after signal being caught. [1]
Rewrite eventfd_read(). Check predicate again after mtx_sleep()
to prevent spurious wakeups. Avoid using uiomove_nofault() call which
will fail if the destination user buffer is not physically mapped.
Instead, unlock efd->efd_lock and then call uiomove(). [2]
Drop the efd_count overflow check in eventfd_poll() as eventfd_write() can
never overflow it.
Pointed out by Jilles Tjoelker. [1, 2]
Modified:
user/dchagin/lemul/sys/compat/linux/linux_event.c
Modified: user/dchagin/lemul/sys/compat/linux/linux_event.c
==============================================================================
--- user/dchagin/lemul/sys/compat/linux/linux_event.c Sat May 24 11:42:50 2014 (r266613)
+++ user/dchagin/lemul/sys/compat/linux/linux_event.c Sat May 24 12:16:33 2014 (r266614)
@@ -649,14 +649,15 @@ eventfd_read(struct file *fp, struct uio
error = 0;
mtx_lock(&efd->efd_lock);
+retry:
if (efd->efd_count == 0) {
if ((efd->efd_flags & LINUX_O_NONBLOCK) != 0) {
mtx_unlock(&efd->efd_lock);
return (EAGAIN);
}
error = mtx_sleep(&efd->efd_count, &efd->efd_lock, PCATCH, "lefdrd", 0);
- if (error == ERESTART)
- error = EINTR;
+ if (error == 0)
+ goto retry;
}
if (error == 0) {
if ((efd->efd_flags & LINUX_EFD_SEMAPHORE) != 0) {
@@ -666,14 +667,13 @@ eventfd_read(struct file *fp, struct uio
count = efd->efd_count;
efd->efd_count = 0;
}
- error = uiomove_nofault(&count, sizeof(eventfd_t), uio);
- if (error == 0) {
- KNOTE_LOCKED(&efd->efd_sel.si_note, 0);
- selwakeup(&efd->efd_sel);
- wakeup(&efd->efd_count);
- }
- }
- mtx_unlock(&efd->efd_lock);
+ KNOTE_LOCKED(&efd->efd_sel.si_note, 0);
+ selwakeup(&efd->efd_sel);
+ wakeup(&efd->efd_count);
+ mtx_unlock(&efd->efd_lock);
+ error = uiomove(&count, sizeof(eventfd_t), uio);
+ } else
+ mtx_unlock(&efd->efd_lock);
return (error);
}
@@ -708,8 +708,6 @@ retry:
}
error = mtx_sleep(&efd->efd_count, &efd->efd_lock,
PCATCH, "lefdwr", 0);
- if (error == ERESTART)
- error = EINTR;
if (error == 0)
goto retry;
}
@@ -736,8 +734,6 @@ eventfd_poll(struct file *fp, int events
return (POLLERR);
mtx_lock(&efd->efd_lock);
- if (efd->efd_count == UINT64_MAX)
- revents |= events & POLLERR;
if ((events & (POLLIN|POLLRDNORM)) && efd->efd_count > 0)
revents |= events & (POLLIN|POLLRDNORM);
if ((events & (POLLOUT|POLLWRNORM)) && UINT64_MAX - 1 > efd->efd_count)
More information about the svn-src-user
mailing list