[Return to Library] [Contents] [Previous Chapter] [Next Section] [Next Chapter] [Index] [Help]


6    Device Drivers and Multithreaded Programming

This chapter discusses topics associated with kernel threads with an emphasis on when and why you would use them in device drivers. Before writing device drivers that make use of kernel threads, you should understand:

The following sections briefly describe each of these topics.


[Return to Library] [Contents] [Previous Chapter] [Next Section] [Next Chapter] [Index] [Help]


6.1    Advantages of Using Kernel Threads in Device Drivers

A thread is a single, sequential flow of control within a program. Within a single thread, there is a single point of execution. Application programs use threads to improve their performance (throughput, computational speed, responsiveness or some combination). To start, terminate, delete, and perform other operations on threads, the application programmer calls the interfaces (routines) that the DECthreads product provides.

The term kernel thread distinguishes between the threads that application programs use. A kernel thread is a single sequential flow of control within a device driver or other systems-based program. The device driver or other systems-based program makes use of the kernel interfaces (instead of a threads library package such as DECthreads) to start, terminate, delete, and perform other kernel threads-related operations.

Kernel threads execute within (and share) a single address space. Therefore, kernel threads read and write the same memory locations.

You use kernel threads to improve the performance (throughput, computational speed, responsiveness or some combination) of a device driver. Multiple kernel threads are useful in a multiprocessor environment where kernel threads run concurrently on separate CPUs. However, multiple kernel threads also improve device driver performance on single processor systems by permitting the overlap of input, output, or other slow operations with computational operations.

Kernel threads allow device drivers to perform other useful work while waiting for a device to produce its next event (such as the completion of a disk transfer or the receipt of a packet from the network).

Typically, you make use of kernel threads in device drivers when:

Figure 6-1 shows one example of the previously described situations. As the figure shows, a device driver must check a number of device state changes. One of these device state changes checks for an adapter fatal error condition. If the fatal error condition occurs, the driver must reset the adapter. The code that resets the adapter must block to accomplish the adapter reset operation. Furthermore, the only time this error can occur is during a device interrupt. It is not legal to block in an interrupt service interface. Therefore, the figure shows that the interrupt service interface for the driver calls an xxstate interface that handles all of the state changes. This interface creates a kernel thread called xxerr that starts up when the adapter becomes operational. The job of this kernel thread is to reset the adapter when a fatal error occurs. Note that it is legal for this kernel thread to perform blocking operations.

Figure 6-1: Example Use of Kernel Threads in a Device Driver


[Return to Library] [Contents] [Previous Chapter] [Previous Section] [Next Section] [Next Chapter] [Index] [Help]


6.2    Kernel Threads Execution

You can view multiple kernel threads in a program as executing simultaneously. However, you cannot make any assumptions about the relative start or finish times of kernel threads or the sequence in which they execute. You can influence the scheduling of kernel threads by setting scheduling and policy priority.

Each kernel thread has its own thread indentifier, which allows it to be uniquely identified. This thread identifier is a pointer to the thread structure associated with the kernel thread. The kernel threads creation interfaces return this thread structure pointer to the driver after they successfully create and start the kernel thread. Device drivers use this pointer as a handle to a specific kernel thread in calls to other kernel threads-related interfaces.

A kernel thread changes states during the course of its execution and is always in one of the following states:


[Return to Library] [Contents] [Previous Chapter] [Previous Section] [Next Section] [Next Chapter] [Index] [Help]


6.3    Issues Related to Using Kernel Threads

When you design and code a device driver that uses the kernel thread-related interfaces, consider the following issues:


[Return to Library] [Contents] [Previous Chapter] [Previous Section] [Next Chapter] [Index] [Help]


6.4    Kernel Threads Operations

Table 6-1 lists the kernel interfaces associated with kernel threads and describes the operations they perform. Chapter 7 discusses how to use these interfaces to implement kernel threads in a device driver.

Table 6-1: Summary of Operations That Kernel Threads-Related Interfaces Perform

Kernel Interfaces Description
Creating kernel threads  
kernel_isrthread Starts a fixed priority kernel thread dedicated to interrupt service.
kernel_thread_w_arg Starts a kernel thread with a calling argument passed in.
Blocking kernel threads  
assert_wait_mesg Asserts that the current kernel thread is about to block (sleep).
thread_block Blocks (puts to sleep) the current kernel thread.
Unblocking kernel threads  
thread_wakeup Wakes up all kernel threads waiting for the specified event.
thread_wakeup_one Wakes up the first kernel thread waiting on a channel.
Terminating kernel threads  
thread_terminate Prepares to stop or stops execution of the specified kernel thread.
thread_halt_self Handles asynchronous traps for self-terminating kernel threads.
Miscellaneous  
current_task Returns a pointer to the task structure associated with the currently running kernel thread.
thread_set_timeout Sets a timer for the current kernel thread.