Thread Termination

This topic describes how and in what conditions to kill a kernel side thread.

The only way to kill a kernel side thread is for code running in that thread to call Kern::Exit().

A kernel side thread can kill itself, but cannot kill any other kernel side thread. This avoids the overhead of critical sections. Remember that a kernel side thread can kill a user side thread.

In practice, device drivers will create threads that can run queued DFCs (Deferred Function Calls) only if they choose not to use the two supplied DFC threads, known as DFC thread 0 and DFC thread 1.

How to kill a thread running queued DFCs

In principle the only way to kill a thread that runs queued DFCs is to schedule a DFC that simply calls Kern::Exit(). The DFC should have priority 0 (the lowest). We refer to this as a 'kill' DFC.

In practice you create a 'kill' DFC by creating a TDfc object, and then make the DFC's callback function include a call to Kern::Exit(). You then queue the DFC onto the DFC queue, a TDfcQue object, from the destructor of the logical device driver's factory class, i.e. the destructor of the class derived from DLogicalDevice.

Issues to be aware of

  1. You need to make sure that no other DFCs are on that DFC queue at the time that the 'kill' DFC runs as there is no automatic cleanup.

    Perform cleanup by calling Cancel() (i.e. TDfc::Cancel()) on all queued DFCs.

  2. You need to make sure that the DFC queue object, i.e. the TDfcQue object, and the 'kill' DFC object, i.e. the TDfc object, are not destroyed before the 'kill' DFC has a chance to run.

    You can do this by making both the DFC queue object and the 'kill' DFC object static objects within the driver. The device driver will only be unloaded from RAM by the null thread. By queuing the 'kill' DFC on the DFC thread, you mark it ready-to-run, which means that your 'kill' DFC will run before the driver is unloaded and before the DFC queue object and the 'kill' DFC object vanish.

  3. You need to make sure that any code queued to run on your DFC thread never hangs.

    The important point is that Kern::Exit() can only be used by the thread itself, but if the thread hangs, then it can execute nothing. This means that kernel side threads must be written very carefully so they cannot hang. Any defect in kernel side code is likely to be fatal.

    It may be that you have to consider writing defensive style code; for example, if your thread is waiting for an event, you could consider using a timer to wake it up in case the expected event never happens. Alternatively, you could consider moving some processing to the user side.