mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-08-26 19:00:25 +00:00
![Davide Libenzi](/assets/img/avatar_default.png)
People started using eventfd in a semaphore-like way where before they were using pipes. That is, counter-based resource access. Where a "wait()" returns immediately by decrementing the counter by one, if counter is greater than zero. Otherwise will wait. And where a "post(count)" will add count to the counter releasing the appropriate amount of waiters. If eventfd the "post" (write) part is fine, while the "wait" (read) does not dequeue 1, but the whole counter value. The problem with eventfd is that a read() on the fd returns and wipes the whole counter, making the use of it as semaphore a little bit more cumbersome. You can do a read() followed by a write() of COUNTER-1, but IMO it's pretty easy and cheap to make this work w/out extra steps. This patch introduces a new eventfd flag that tells eventfd to only dequeue 1 from the counter, allowing simple read/write to make it behave like a semaphore. Simple test here: http://www.xmailserver.org/eventfd-sem.c To be back-compatible with earlier kernels, userspace applications should probe for the availability of this feature via #ifdef EFD_SEMAPHORE fd = eventfd2 (CNT, EFD_SEMAPHORE); if (fd == -1 && errno == EINVAL) <fallback> #else <fallback> #endif Signed-off-by: Davide Libenzi <davidel@xmailserver.org> Cc: <linux-api@vger.kernel.org> Tested-by: Michael Kerrisk <mtk.manpages@gmail.com> Cc: Ulrich Drepper <drepper@redhat.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
42 lines
1,012 B
C
42 lines
1,012 B
C
/*
|
|
* include/linux/eventfd.h
|
|
*
|
|
* Copyright (C) 2007 Davide Libenzi <davidel@xmailserver.org>
|
|
*
|
|
*/
|
|
|
|
#ifndef _LINUX_EVENTFD_H
|
|
#define _LINUX_EVENTFD_H
|
|
|
|
#ifdef CONFIG_EVENTFD
|
|
|
|
/* For O_CLOEXEC and O_NONBLOCK */
|
|
#include <linux/fcntl.h>
|
|
|
|
/*
|
|
* CAREFUL: Check include/asm-generic/fcntl.h when defining
|
|
* new flags, since they might collide with O_* ones. We want
|
|
* to re-use O_* flags that couldn't possibly have a meaning
|
|
* from eventfd, in order to leave a free define-space for
|
|
* shared O_* flags.
|
|
*/
|
|
#define EFD_SEMAPHORE (1 << 0)
|
|
#define EFD_CLOEXEC O_CLOEXEC
|
|
#define EFD_NONBLOCK O_NONBLOCK
|
|
|
|
#define EFD_SHARED_FCNTL_FLAGS (O_CLOEXEC | O_NONBLOCK)
|
|
#define EFD_FLAGS_SET (EFD_SHARED_FCNTL_FLAGS | EFD_SEMAPHORE)
|
|
|
|
struct file *eventfd_fget(int fd);
|
|
int eventfd_signal(struct file *file, int n);
|
|
|
|
#else /* CONFIG_EVENTFD */
|
|
|
|
#define eventfd_fget(fd) ERR_PTR(-ENOSYS)
|
|
static inline int eventfd_signal(struct file *file, int n)
|
|
{ return 0; }
|
|
|
|
#endif /* CONFIG_EVENTFD */
|
|
|
|
#endif /* _LINUX_EVENTFD_H */
|
|
|