Presentation is loading. Please wait.

Presentation is loading. Please wait.

Kernel timing issues An introduction to the use of kernel timers and work queues.

Similar presentations


Presentation on theme: "Kernel timing issues An introduction to the use of kernel timers and work queues."— Presentation transcript:

1 Kernel timing issues An introduction to the use of kernel timers and work queues

2 Kernel semaphores Our ‘stash.c’ device-driver exhibited some ‘race conditions’ when we used it with two or more ‘reader’ processes (or with two or more ‘writer’ processes) We can eliminate such ‘races’ if our driver enforces a ‘one writer/one reader’ policy This is easy to do by using ‘semaphores’

3 Mutual-exclusion syntax Declare a semaphore: struct semaphore sem; To initialize this semaphore: init_MUTEX( &sem ); To acquire this semaphore: down_interruptible( &sem ); To release this semaphore: up( &sem);

4 ‘open()’ uses file->f_fmode You can implement an ‘open()’ method in your device-driver that lets only one task at a time open your device for reading: { if ( file->f_fmode & FMODE_READ ) down_interruptible( &sem ); return 0;// success }

5 ‘release()’ uses file->f_fmode You can implement a ‘release()’ method in your device-driver that lets a ‘reader’ task release its earlier acquired semaphore: { if ( file->f_fmode & FMODE_READ ) up( &sem ); return 0;// success }

6 struct file_operations struct file_operations my_fops = { owner:THIS_MODULE, read:my_read, write:my_write, open:my_open, release:my_release, };

7 ‘newstash.c’ We wrote a new version of ‘stash.c’ that illustrates the use of two semaphores to restrict device-file access to one ‘writer’ and one ‘reader’ at a time Other tasks that want to ‘read’ or ‘write’ are put to sleep if they try to ‘open’ the device-file, but are woken up when the appropriate semaphore gets ‘released’

8 Kernel timers Another facility Linux offers lets drivers put a process to sleep until a fixed amount of time has elapsed (as measured in jiffies) When the timer expires, a driver-defined action will be performed, which can ‘wake up’ the process that was put to sleep, or could perform some alternative action (for example, the kernel timer could start over)

9 Programming syntax Declare a timer: struct timer_list mytimer; Initialize this timer: init_timer( &mytimer ); mytimer.func = mytimeraction; mytimer.data = (unsigned long)mydata; mytimer.expires = Install this timer: add_timer( &mytimer ); Modify this timer: mod_timer( &mytimer, ); Delete this timer: del_timer( &mytimer ); Delete it safely: del_timer_sync( &mytimer);

10 A kernel-timer caution A kernel timer’s timeout-action cannot do anything that could cause the current task to ‘sleep’ (such as copying data between user-space and kernel-space, or trying to allocate more kernel memory) However, to aid debugging, a timer CAN use ‘printk()’ within its timeout-routine

11 ‘trytimer.c’ We have posted an example that shows how a Linux kernel timer can be used to perform a periodic action (such as using ‘printk()’ to issue a message every time the time expires, then restart the timer Notice that our demo is not able to issue messages directly to the console – its timer-function executes without a ‘tty’

12 Delaying work If a device-driver needs to perform actions that require using process resources (like a tty), or that may possibly ‘sleep’, then it can defer that work – using a ‘workqueue’

13 Programming syntax Declare: struct workqueue_struct *myqueue; struct work_struct thework; Define: void dowork( void *data ) { /* actions */ }; Initialize: myqueue = create_singlethread_workqueue( “mywork” ); INIT_WORK( &thework, dowork, ); Schedule: queue_dalayed_work( myqueue, &thework, ); Cleanup:if ( !cancel_delayed_work( &thework ) ) flush_workqueue( myqueue ); destroy_workqueue( myqueue );

14 ‘tryworkq.c’ and ‘defermsg.c’ We have posted demo-modules that show the use of workqueues to perform actions later, either as soon as a ‘process context’ is available, or after a prescribed time Further details on the options for using an existing kernel workqueue or a workqueue of your own creation may be found in our textbook (Chapter 7 of LDD3)

15 Applying these ideas To demonstrate a programming situation in which using kernel timers is valuable, we created the ‘foo.c’ device-driver, plus an application that uses it (‘watchfoo.cpp’) You can compile and install the module, then execute the application: $ watchfoo But you will notice there are two ‘problems’ (excess cpu usage and loop-termination)

16 Reducing CPU’s usage The ‘watchfoo’ program rereads ‘/dev/foo’ constantly (numerous times per second), much faster than the human eye can see If you run the ‘top’ utility, you will see that up to 99-percent of the available CPU time is being consumed by ‘watchfoo’ You can add a kernel timer to the ‘foo.c’ driver to curtail this excessive reading

17 In-class exercise Modify ‘foo.c’ (call it ‘timedfoo.c’) as follows Create an integer flag-variable (‘ready’) as a global object in your module When your ‘read()’ function gets called, it should sleep until ‘ready’ equals TRUE; it should set ‘ready’ equal to FALSE when it awakens, but should set a timer to expire after 1/10 seconds Your timer’s action-function should set ‘ready’ back to TRUE, then wake up any sleeping tasks

18 Implementation hints You need a wait-queue (so your driver’s ‘reader’ tasks can sleep on it) You need a timer action-function You need to organize your timer-function’s data-items into a single structure (because the timer-function has only one argument) Your timer-function must do two things: –Change ‘ready’ to TRUE –Wake up any ‘sleepers’


Download ppt "Kernel timing issues An introduction to the use of kernel timers and work queues."

Similar presentations


Ads by Google