$RodHat_
Syscall reference · Events

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

NameWhat it does
initvalInitial value of the counter.
EFD_CLOEXECLinux 2.6.27Set close-on-exec on the new descriptor.
EFD_NONBLOCKLinux 2.6.27Set O_NONBLOCK; read on zero or write past the max returns EAGAIN.
EFD_SEMAPHORELinux 2.6.30read(2) returns 1 and decrements by 1 instead of returning and resetting the whole count.

Errors you will actually hit

errnoMeaning
EINVALAn unsupported value was specified in flags.
EMFILEPer-process open file descriptor limit reached.
ENFILESystem-wide open file limit reached.
ENOMEMInsufficient memory to create a new eventfd.
ENODEVCould 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

  1. eventfd(2), man7.org
  2. eventfd(2), FreeBSD
  3. kqueue(2), OpenBSD

Version numbers are read off the cited man pages, not memory. Spot one that's wrong? Tell Rod.