100 likes | 111 Views
Learn how modules can cause functions to be invoked at specific future moments in time using Linux kernel timers, including hardware timer-counters and software timers. See examples of hardware timers like Programmable Interval Timer, Real Time Clock, and Pentium's Time Stamp Counter, as well as the usage of software timers for detecting device "lockups" and other purposes. Explore the kernel's dynamic-timer handling and the efficient partitioning structure used for managing multiple timers.
E N D
Linux kernel timers How can a module cause a function to be invoked at some future moment in time?
Hardware timer-counters • IA32 systems: several hardware timers • External devices, or internal to processor • Examples: • 8254 Programmable Interval Timer (IRQ0) • MC146818 Real Time Clock w/CMOS (IRQ8) • Pentium’s 64-bit Time Stamp Counter register • Local APIC’s programmable Counter register • (optional) 8254 Watchdog Timer (NMI) • (optional) Network Interface Card (IRQ varies)
Linux Software Timers • Easy for device-driver programmers to use • Used mainly for detecting device “lockups” • But could also be used for other purposes • The driver-writer merely needs to: 1) define a “customized” timeout-function 2) allocate and initialize a kernel-structure 3) call standard routines for timer-control
Software Timer’s Data-Structure struct timer_list struct list_head list; unsigned long expires; unsigned long data; void (*function)( unsigned long ); Use the ‘init_timer()’ routine to initialize the ‘list’ field
Defining your “timeout” action void my_action( unsigned long dataptr ) { /* …perform your desired actions… */ /* then reschedule timer expiration */ next_timeout = jiffies + 5*HZ; mod_timer( &my_timer, next_timeout ); }
Assigning structure’s attributes struct timer_list my_timer; // declared global int init_module( void ) { init_timer( &my_timer ); // for ‘list’ setup my_timer.data = (unsigned long)&my_data; my_timer.function = my_action; my_timer.expires = jiffies + 5 * HZ; add_timer( &my_timer ); return SUCCESS; }
Removing your timer safely void cleanup_module( void ) { int status = del_timer_sync( &my_timer ); // 1 means ‘my_timer’ was queued // 0 means ‘my_timer’ wasn’t queued }
Kernel’s dynamic-timer handling • Need to deal efficiently with many timers • One big linked list would NOT be efficient • Linux adopts a clever partitioning structure • Uses special structures (called ‘tvec’s) • Timers partitioned by their expiration-times • Result: reduces amount of list-processing
Groups of timer lists Array of ‘tvec’ structures (< 0xFF ) ( < 0x3FFF ) ( < 0xFFFFF ) ( < 0x3FFFFFF ) ( < 0xFFFFFFFF )
In-Class Exercise • Modify the ‘mytimer.c’ demo (on website) • Change expiration-frequency (to 5 secs) • Print timer’s messages on user’s console • (See our ‘announce.c’ demo for how-to)