Day85 - poll() Internals¶
Goal¶
Understand how Linux poll() is built on top of wait queues and how a driver exposes event readiness through its poll callback.
Topics Covered¶
poll()poll_wait()poll_table- Driver
pollcallback - Event mask
POLLIN- Event-driven I/O
- Relationship between
polland wait queues list_headas a shared kernel-style list primitive
Labs Completed¶
Lab1 - Poll Table and Wait Queue Mapping¶
Built a simplified poll table.
Key points:
poll_tablerecords wait queues monitored by one poll operation.poll_table_entrystores a pointer to await_queue_head.poll_wait()registers a wait queue into the poll table.poll_wait()does not sleep.
Lab2 - Driver poll Callback¶
Implemented a simulated driver poll callback.
Flow:
Validation:
- No data returns
0. - Data ready returns
POLLIN.
Lab3 - Userspace poll Flow¶
Implemented a simplified userspace poll() flow.
Flow:
Validation:
- No event prints a waiting message and returns
0. - Ready event returns
POLLIN.
Lab4 - Blocking poll Simulation¶
Implemented a blocking poll simulation with two threads.
Flow:
poll thread
|
+-- user_poll()
|
+-- driver_poll()
|
+-- no event
|
+-- wait_event()
|
+-- wake_up()
|
+-- driver_poll()
|
+-- return POLLIN
|
+-- read()
Producer flow:
Final validation log:
Implementation Notes¶
Shared list utility¶
Added a simplified Linux-style list_head implementation.
Main APIs:
INIT_LIST_HEAD()list_add()list_add_tail()list_del()list_empty()list_entry()list_first_entry()list_for_each()list_for_each_entry()list_for_each_entry_safe()
Key concept:
- Linux
list_headis a circular doubly linked list. - The list head is a sentinel node, not a data node.
list_del()can updatehead->nextorhead->prevautomatically because the head participates in the circular list.
Shared wait queue utility¶
Moved wait queue logic into a reusable utils/waitqueue/ module.
Main concepts:
wait_queue_headwait_queue_entry- task state
prepare_to_wait()finish_wait()wait_event()wake_up()
Important design decision:
wake_up()only wakes waiting entries.finish_wait()restores task state and removes the wait queue entry.- Waiting loops must re-check the condition after wakeup.
Shared poll utility¶
Added a simplified utils/poll/ module.
Main concepts:
poll_tablepoll_table_entrypoll_wait()- event masks
Important design decision:
poll_wait()only registers a wait queue.- It does not sleep.
- The driver
pollcallback decides readiness by returning an event mask.
Key Takeaways¶
poll()is an event readiness mechanism, not a data transfer mechanism.read()consumes data;poll()reports whether data can be read.- Driver
pollcallbacks usually follow this pattern:
poll_wait()connects the current poll operation to the driver's wait queue.- A wakeup only means the condition may have changed.
- The waiting side must always re-check the condition.
Next Step¶
Continue with epoll at a conceptual level and compare it with poll.
Focus areas:
- Why
poll()scales poorly with many file descriptors - How
epollavoids scanning all descriptors every time - Why drivers still only implement the normal
pollcallback