Skip to content

Day86 - epoll Internals

Today's Goal

Understand why epoll scales better than poll, how the kernel manages ready file descriptors, and how device drivers continue to implement only the standard .poll callback.

What I Learned

Today I implemented a simplified Linux-style epoll infrastructure from scratch.

Unlike poll(), which scans every registered file descriptor on each call, epoll separates monitored file descriptors from ready file descriptors using two internal lists:

  • Interest List
  • Ready List

Each monitored file descriptor is represented by an epitem. The eventpoll object owns all registered epitem objects and manages both lists.

I also learned that the device driver is completely unaware of epoll. The driver only implements the standard .poll() callback and reports its current readiness. The epoll subsystem is responsible for managing the interest list, rebuilding the ready list, and implementing different notification policies such as Level Trigger and Edge Trigger.

A key realization was that the Ready List is not the source of truth. It is only a temporary notification queue. The actual readiness always comes from the driver's current state.

Implemented Components

  • Linux-style eventpoll
  • epitem
  • Interest List
  • Ready List
  • epoll_ctl_add()
  • epoll_ctl_mod()
  • epoll_ctl_del()
  • epoll_wait_sim()
  • epoll_poll_once_sim()
  • Driver .poll() callback registration
  • Blocking wait support
  • Level Trigger (LT)
  • Edge Trigger (ET)

Labs Completed

Lab1

Implemented basic epoll_ctl() operations.

Topics:

  • Interest List
  • Add
  • Modify
  • Delete

Lab2

Implemented Ready List management.

Topics:

  • epoll_mark_ready()
  • Ready List insertion
  • Duplicate ready prevention

Lab3

Implemented event consumption.

Topics:

  • epoll_wait_sim()
  • maxevents
  • Ready List consumption

Lab4

Implemented blocking event notification.

Topics:

  • Producer / Consumer
  • wake_up()
  • Blocking epoll_wait_sim()

Lab5

Implemented driver readiness recheck.

Topics:

  • Driver .poll() callback
  • Device state
  • Level Trigger model

Lab6

Verified Level Trigger behavior.

Topics:

  • Readiness persists while data remains available
  • Reading clears readiness

Lab7

Implemented Edge Trigger behavior.

Topics:

  • Rising-edge notification
  • EPOLL_ET
  • New readiness transition detection

Key Takeaways

  • epoll scales better because it does not repeatedly scan every file descriptor from userspace.
  • Device drivers never implement epoll-specific callbacks.
  • The driver's .poll() callback remains the single source of readiness information.
  • Interest List stores monitored file descriptors.
  • Ready List temporarily stores file descriptors that should be returned to userspace.
  • Level Trigger repeatedly reports readiness while the device remains ready.
  • Edge Trigger reports only readiness transitions from not-ready to ready.

Next Step

Continue studying Linux asynchronous I/O by exploring fasync and SIGIO, and compare signal-driven notification with poll() and epoll.