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

Slides:



Advertisements
Similar presentations
An introduction to pointers in c
Advertisements

Dynamic Memory Allocation in C.  What is Memory What is Memory  Memory Allocation in C Memory Allocation in C  Difference b\w static memory allocation.
R4 Dynamically loading processes. Overview R4 is closely related to R3, much of what you have written for R3 applies to R4 In R3, we executed procedures.
Programming and Data Structure
Programming Languages and Paradigms The C Programming Language.
Unions The storage referenced by a union variable can hold data of different types subject to the restriction that at any one time, the storage holds data.
What is a pointer? First of all, it is a variable, just like other variables you studied So it has type, storage etc. Difference: it can only store the.
Module R2 CS450. Next Week R1 is due next Friday ▫Bring manuals in a binder - make sure to have a cover page with group number, module, and date. You.
CS 6560 Operating System Design Lecture 7: Kernel Synchronization Kernel Time Management.
Another device-driver? Getting ready to program the network interface.
I/O Multiplexing The role of the ‘poll()’ method in Linux device-driver operations.
1 Pointers A pointer variable holds an address We may add or subtract an integer to get a different address. Adding an integer k to a pointer p with base.
6/10/2015C++ for Java Programmers1 Pointers and References Timothy Budd.
Timeout for some demos An instructive look at how the Linux Operating System sets up system data-structures.
A ‘ringbuffer’ application Introduction to process ‘blocking’ and the Linux kernel’s support for ‘sleeping’ and ‘waking’
Linux kernel timers How can a module cause a function to be invoked at some future moment in time?
CS 635 Advanced Systems Programming Spring 2003 Professor Allan B. Cruse University of San Francisco.
How to make a pseudo-file As a follow-up to our first lab, we examine the steps needed to create our own ‘/proc’ file.
Applying kernel timers Could we prevent a device-driver from consuming an excessive amount of processor time?
Home: Phones OFF Please Unix Kernel Parminder Singh Kang Home:
The kernel’s task list Introduction to process descriptors and their related data-structures for Linux kernel version
Kernel timing issues An introduction to the use of kernel timers and work queues.
Kernel timing issues An introduction to the use of kernel timers and work queues By Allan Cruise modified by sdc.
Guide To UNIX Using Linux Third Edition
A. Frank - P. Weisberg Operating Systems Introduction to Cooperating Processes.
Pointers Applications
FreeRTOS.
Data Types in the Kernel Sarah Diesburg COP 5641.
Operating System Program 5 I/O System DMA Device Driver.
System Calls 1.
C++ Programming: Program Design Including Data Structures, Fourth Edition Chapter 13: Pointers, Classes, Virtual Functions, and Abstract Classes.
C++ Programming: From Problem Analysis to Program Design, Fourth Edition Chapter 14: Pointers, Classes, Virtual Functions, and Abstract Classes.
Data Types in the Kernel Ted Baker  Andy Wang CIS 4930 / COP 5641.
CS591 (Spring 2001) The Linux Kernel: Debugging. CS591 (Spring 2001) Accessing the “Black Box” n Kernel code: n Not always executed in context of a process.
Sogang University Advanced Operating Systems (Linux Module Programming) Sang Gue Oh, Ph.D.
CS 11 java track: lecture 1 Administrivia need a CS cluster account cgi-bin/sysadmin/account_request.cgi need to know UNIX
Chapter 1 Process and Thread. 1.2 process The address space of a program – Text – Code – Stack – Heap A set of registers – PC – SP Other resources – Files.
Silberschatz, Galvin and Gagne  Operating System Concepts Chapter 3: Operating-System Structures System Components Operating System Services.
CE Operating Systems Lecture 3 Overview of OS functions and structure.
Multiprogramming. Readings r Silberschatz, Galvin, Gagne, “Operating System Concepts”, 8 th edition: Chapter 3.1, 3.2.
CPS120: Introduction to Computer Science Functions.
C++ Data Types Structured array struct union class Address pointer reference Simple IntegralFloating char short int long enum float double long double.
An Object-Oriented Approach to Programming Logic and Design Chapter 3 Using Methods and Parameters.
Pointers: Basics. 2 What is a pointer? First of all, it is a variable, just like other variables you studied  So it has type, storage etc. Difference:
Copyright 2005, The Ohio State University 1 Pointers, Dynamic Data, and Reference Types Review on Pointers Reference Variables Dynamic Memory Allocation.
 2007 Pearson Education, Inc. All rights reserved C Structures, Unions, Bit Manipulations and Enumerations.
Java Thread and Memory Model
LOGO System Call. Introduction System call is the mechanism used by an application program to request service from the OS. Users use it to communicate.
Review 1 List Data Structure List operations List Implementation Array Linked List.
Preemptive Context Switching
12/22/ Thread Model for Realizing Concurrency B. Ramamurthy.
1 Process Description and Control Chapter 3. 2 Process A program in execution An instance of a program running on a computer The entity that can be assigned.
1 Chapter 15-1 Pointers, Dynamic Data, and Reference Types Dale/Weems.
CCSA 221 Programming in C CHAPTER 11 POINTERS ALHANOUF ALAMR 1.
Copyright © Curt Hill More on Operating Systems Continuation of Introduction.
Ch6. Flow of Time Ch7. Getting Hold of Memory 홍원의.
Embedded Real-Time Systems Processing interrupts Lecturer Department University.
Timers and Time Management Ok-Kyun Ha
Lesson #8 Structures Linked Lists Command Line Arguments.
Processes and threads.
VBA - Excel VBA is Visual Basic for Applications
Chapter 13: Pointers, Classes, Virtual Functions, and Abstract Classes
Objectives Identify the built-in data types in C++
An introduction to the use of kernel timers and work queues
Pointers and References
C Structures, Unions, Bit Manipulations and Enumerations
Chapter 15 Pointers, Dynamic Data, and Reference Types
Object Oriented Programming in java
Process Description and Control
Overloading functions
Presentation transcript:

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

Kernel timers Linux offers a facility that 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 re-start)

jiffies unsigned long volatile jiffies; global kernel variable (used by scheduler) initialized to zero when system reboots gets incremented during a timer interrupt so it counts ‘clock-ticks’ since cpu restart ‘tick-frequency’ is a ‘configuration’ option On our machines: HZ=250 (in ‘.config’)

jiffies overflow Won’t overflow for at least 16 months Linux kernel got modified to ‘fix’ overflow Now the declaration is in ‘linux/jiffies.h’: unsigned long longjiffies_64; and a new instruction in ‘do_timer()’ (*(u64*)&jiffies_64)++; which compiles to assembly language as add$1, jiffies+0 adc$0, jiffies+4

Kernel timer 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);

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

‘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’

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’

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 );

‘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)

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)

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 a high percentage 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

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

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’

Deferring work Linux supports a ‘workqueue’ mechanism which allows the kernel to defer specified work until some later point in time This mechanism has been ‘reworked’ in a major way since our texts were published So any device-driver has to be modified if it made any use of a kernel ‘workqueue’ Changes require grasp of some ‘macros’

‘sizeof’ and ‘offsetof’ Our GNU compilers permit use of these C/C++ operators on object types The ‘sizeof’ operator returns the number of bytes of memory the compiler allocated for storing the specified object The ‘offsetof’ operator returns the number of bytes in a structure which precede the specified structure-member

A ‘struct’ example struct mystruct{ charw; shortx; longy; long longz; } my_instance; You can use the ‘sizeof’ operator to find out how much memory gets allocated to any ‘struct mystruct’ object, like this: intnbytes = sizeof( my_instance ); You can use the ‘offsetof’’ operator to find out where within a given structure a particular field occurs, like this: intoffset_z = offsetof( struct mystruct, z );

The ‘container_of()’ macro Recent versions of the Linux kernel have introduced a further operator on ‘structs’ container_of( ptr, type, member ); When given a pointer to a field within a structure-object, and the type-name for that that structure-object, and the field- name for that structure’s field-member, then it returns the structure’s address

Using ‘container_of()’ struct mystruct{ charw; shortx; longy; long longz; } my_instance = { 1, 2, 3, 4 }; If you have a pointer to one of the fields in some instance of a this kind of ‘struct’ object, then you could use the ‘container_of()’ macro to get a pointer to that ‘struct’ object itself, like this: long *ptr = &my_instance.y; struct mystruct *p = container_of( ptr, struct mystruct, y ); This would be useful if you now wanted to access other members: printk( “w=%d x=%d y=%d z=%d \n”, p->w, p->x, p->y, p->z );

#include void dowork( struct work_struct *data ); DECLARE_DELAYED_WORK( mywork, dowork ); struct workqueue_struct *myqueue; myqueue = create_singlethread_workqueue( “mywork” );

‘workqueue’ syntax #include struct workqueue_struct *myqueue;// pointer to your workqueue void dowork( struct work_struct *data );// your function’s prototype DECLARE_DELAYED_WORK( mywork, dowork ); int init_module( void ) { myqueue = create_singlethread_workqueue( “mywork” ); if ( !queue_delayed_work( myqueue, &mywork, HZ*5 ) ) return –EBUSY; return0; // SUCCESS } void cleanup_module( void ) { destroy_workqueue( myqueue ); }

‘tryworkq.c’ void dowork( struct work_struct *data ) { printk( “\n\n I am doing the delayed work right now \n” ); } In this example the delayed work consists of simply printing a message to the kernel’s logfile -- you can view by typing the ‘dmesg’ command Notice that the ‘action’ function in this example ignores its ‘data’ argument

An improved example Our ‘announce.c’ module shows how an LKM could display its messages within a window on the Linux graphical desktop It uses the ‘tty_struct’ object which exists in the process-descriptor for the ‘insmod’ task which you launch to install the LKM We shall see how this same idea can be used in a waitqueue’s ‘action’ functions

‘timer’ verses ‘workqueue’ Any kernel-timer’s action-function will be executed in ‘atomic’ context – just like an interrupt service routine: it cannot ‘sleep’, and it cannot access any user-space data But any workqueue’s action-function will be executed by a kernel-thread – and thus it possesses a ‘process’ context, so it can be ‘scheduled’ and ‘sleep’ if necessary – though it, too, cannot access user-space

If ‘dowork()’ needs data… // data items needed by your ‘dowork’ function are packaged in a ‘struct’ struct mydata{ char*msg; struct tty_struct*tty; } my_data = { “\nHello\n”, NULL }; // your module-initialization function sets up your ‘struct delayed_work’ object // and it can also finish initializing your ‘my_data’ object’s member-fields myqueue = create_singlethread_workqueue( “mywork” ); INIT_DELAYED_WORK( &mywork, dowork ); my_data.tty = current->signal->tty; // then your action-function can access members of your ‘my_data’ object like this void dowork( struct work_struct *data ) { struct mydata *dp = container_of( &my_data.msg, struct mydata, msg ); struct tty_struct*tty = dp->tty; tty->driver->write( tty, dp->msg, strlen( dp->msg ) ); }

‘defermsg.c’ This LKM will display a message within a desktop window after a 10-second delay It illustrates a use of the ‘container_of()’ macro (as is needed by the reworked API for the Linux kernel’s workqueues) Our course-website has a link to an online article by author Jonathan Corbet giving details of ongoing kernel changes in 2.6

Summary of tonight’s demos ‘foo.c’ and ‘watchfoo.cpp’ ‘announce.c’ ‘trytimer.c’ ‘trymacro.c’ ‘tryworkq.c’ ‘defermsg.c’ EXERCISE: Modify the ‘foo.c’ device-driver to use a kernel timer in it’s ‘read()’ method