eventfd(2)
Create a kernel-backed 64-bit counter fd for wakeups between threads or processes.
- Since
- Linux 2.6.22check your kernel →
- glibc
- glibc 2.8
- System
- Linux
- Man page
- eventfd(2)
Synopsis
#include <sys/eventfd.h>
int eventfd(unsigned int initval, int flags);Rod's take
eventfd is a counter with a file descriptor bolted on, and that's the entire API. write() adds, read() drains, and the fd is readable whenever the count is nonzero. That makes it the cheapest way to poke an epoll loop from another thread without dragging a pipe into it. EFD_SEMAPHORE switches reads to one token at a time when several readers compete. Reads and writes are eight bytes; anything shorter gets EINVAL. Small, boring, correct. I have no complaints, and frankly that bothers me.
Flags and arguments that matter
| Name | What it does |
|---|---|
| initval | Initial value of the counter. |
| EFD_CLOEXECLinux 2.6.27 | Set close-on-exec on the new descriptor. |
| EFD_NONBLOCKLinux 2.6.27 | Set O_NONBLOCK; read on zero or write past the max returns EAGAIN. |
| EFD_SEMAPHORELinux 2.6.30 | read(2) returns 1 and decrements by 1 instead of returning and resetting the whole count. |
Errors you will actually hit
| errno | Meaning |
|---|---|
| EINVAL | An unsupported value was specified in flags. |
| EMFILE | Per-process open file descriptor limit reached. |
| ENFILE | System-wide open file limit reached. |
| ENOMEM | Insufficient memory to create a new eventfd. |
| ENODEV | Could not mount (internal) anonymous inode device. |
Example
int efd = eventfd(0, EFD_NONBLOCK | EFD_CLOEXEC);
if (efd < 0)
err(1, "eventfd");
/* producer thread: wake the loop */
uint64_t one = 1;
if (write(efd, &one, sizeof(one)) != sizeof(one))
err(1, "write eventfd");
/* event loop, after epoll reports EPOLLIN: */
uint64_t count;
if (read(efd, &count, sizeof(count)) == sizeof(count))
drain_work_queue(count);Trimmed from the full walkthrough in timerfd, signalfd, eventfd: every event source is a file descriptor now.
BSD equivalent
FreeBSD: eventfd(2) (FreeBSD 13.0). OpenBSD: closest is EVFILT_USER in kqueue(2).
The long version, from the console
Sources
Version numbers are read off the cited man pages, not memory. Spot one that's wrong? Tell Rod.
