Skip to content

Day51 - Timer-based Pollable Event Driver

Overview

Day51 extends the Day50 pollable character driver into a timer-driven asynchronous event framework.

New features introduced:

  • delayed_work periodic event source
  • timer start/stop control
  • manual trigger events
  • event source abstraction
  • runtime statistics
  • queue overflow handling
  • sysfs runtime observability
  • epoll integration

The driver architecture evolved from:

userspace-triggered event queue

into:

generic asynchronous event-driven framework

1. Review of Day50 Architecture

Day50 implemented a pollable character driver with:

  • blocking read
  • non-blocking read
  • wait queue
  • .poll() support
  • epoll integration
  • FIFO event queue

Original event flow:

write(/dev/mypoll)
push event into queue
wake_up_interruptible()
poll()/epoll() reports EPOLLIN
read()
pop event from queue

Only userspace write operations could generate events.


2. Internal Timer Event Source

Day51 introduced a driver-internal event source using delayed work.

New event flow:

delayed_work handler
mypoll_generate_event()
queue push
wake_up_interruptible()
epoll()/read()

Userspace write is no longer the only event source.


3. Event Generation Refactor

Event generation logic was refactored into a shared helper:

static int mypoll_generate_event(struct mypoll_dev *mydev,
                                 enum mypoll_event_source source)

This centralizes:

  • sequence generation
  • queue push
  • overflow handling
  • statistics update
  • wait queue wakeup

Benefits:

  • reusable event generation path
  • cleaner architecture
  • easy future extension
  • consistent queue policy

4. delayed_work as Periodic Event Source

The driver uses:

struct delayed_work event_work;

Periodic event generation flow:

schedule_delayed_work()
work handler executes
generate one event
re-schedule delayed_work

Important APIs:

INIT_DELAYED_WORK()
schedule_delayed_work()
cancel_delayed_work_sync()
msecs_to_jiffies()

5. Event Source Abstraction

Multiple event sources were introduced:

enum mypoll_event_source {
    MYPOLL_EVENT_SOURCE_MANUAL = 0,
    MYPOLL_EVENT_SOURCE_TIMER,
};

Each event now contains source information:

struct mypoll_event {
    u32 sequence;
    enum mypoll_event_source source;
};

Userspace output example:

event=35 source=manual
event=36 source=timer

6. Runtime Statistics

Runtime statistics were grouped into:

struct mypoll_stats {
    u32 events_generated;
    u32 events_dropped;
    u32 events_manual;
    u32 events_timer;
};

Driver state also tracks:

u32 event_sequence;

Statistics are updated during event generation.


7. Queue Overflow Handling

Timer-generated events may exceed userspace consumption speed.

Overflow policy:

queue full
drop new event
increment dropped counter

Important design decision:

event sequence increases only when queue push succeeds

This prevents gaps caused by dropped events.

Example:

event_sequence=16
generated=16
dropped=83
queue_depth=16

8. Runtime Observability with sysfs

A read-only sysfs node was added:

/sys/class/mypoll/mypoll/stats

Implementation:

static DEVICE_ATTR_RO(stats);

Example output:

event_sequence=83
generated=83
dropped=174
manual_triggered=1
timer_triggered=82
queue_depth=0
timer_running=0

This separates:

Purpose Interface
Event stream /dev/mypoll
Control commands write()
Runtime state sysfs
Debug logging dev_info()

9. epoll Integration

The timer-generated events fully integrate with epoll.

Event flow:

timer delayed_work
queue push
wake_up_interruptible()
epoll receives EPOLLIN
userspace read()

Userspace asynchronous event handling works without modification.


10. Python Integration Test

A full Python integration test was added.

Covered features:

  • device existence
  • manual trigger event
  • timer event generation
  • timer stop behavior
  • epoll integration
  • queue overflow statistics
  • reset statistics

The test also validates:

  • event source correctness
  • runtime stats behavior
  • queue overflow handling

Key Learning Points

Day51 introduced several important Linux driver concepts:

  • asynchronous event generation
  • periodic delayed work scheduling
  • event source abstraction
  • runtime observability
  • queue overflow/backpressure
  • sysfs runtime status
  • epoll with internal event source