Adaptation/GUID-12EFB295-C527-5F96-81F1-6021D335D865.dita
author Graeme Price <GRAEME.PRICE@NOKIA.COM>
Fri, 15 Oct 2010 14:32:18 +0100
changeset 15 307f4279f433
permissions -rw-r--r--
Initial contribution of the Adaptation Documentation.

<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (c) 2007-2010 Nokia Corporation and/or its subsidiary(-ies) All rights reserved. -->
<!-- This component and the accompanying materials are made available under the terms of the License 
"Eclipse Public License v1.0" which accompanies this distribution, 
and is available at the URL "http://www.eclipse.org/legal/epl-v10.html". -->
<!-- Initial Contributors:
    Nokia Corporation - initial contribution.
Contributors: 
-->
<!DOCTYPE concept
  PUBLIC "-//OASIS//DTD DITA Concept//EN" "concept.dtd">
<concept id="GUID-12EFB295-C527-5F96-81F1-6021D335D865" xml:lang="en"><title>Thread
Termination</title><shortdesc>This topic describes how and in what conditions to kill a kernel
side thread. </shortdesc><prolog><metadata><keywords/></metadata></prolog><conbody>
<p>The only way to kill a kernel side thread is for code running in that thread
to call <xref href="GUID-C6946ECB-775F-3EC2-A56F-78F25B9FBE3D.dita#GUID-C6946ECB-775F-3EC2-A56F-78F25B9FBE3D/GUID-808B3622-BDC4-376D-96E9-16281BA28AF8"><apiname>Kern::Exit()</apiname></xref>. </p>
<p>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 <i>can</i> kill a user side thread. </p>
<p>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. </p>
<section id="GUID-A5B308C7-21CE-437E-A033-A373E1E2FE78"><title>How to kill a thread running queued DFCs</title> <p>In principle
the only way to kill a thread that runs queued DFCs is to schedule a DFC that
simply calls <xref href="GUID-C6946ECB-775F-3EC2-A56F-78F25B9FBE3D.dita#GUID-C6946ECB-775F-3EC2-A56F-78F25B9FBE3D/GUID-808B3622-BDC4-376D-96E9-16281BA28AF8"><apiname>Kern::Exit()</apiname></xref>. The DFC should have priority
0 (the lowest). We refer to this as a 'kill' DFC. </p> <p>In practice you
create a 'kill' DFC by creating a <xref href="GUID-A14562A5-3E91-3113-AB3C-71DBEA9D58EB.dita"><apiname>TDfc</apiname></xref> object, and then
make the DFC's callback function include a call to <xref href="GUID-C6946ECB-775F-3EC2-A56F-78F25B9FBE3D.dita#GUID-C6946ECB-775F-3EC2-A56F-78F25B9FBE3D/GUID-808B3622-BDC4-376D-96E9-16281BA28AF8"><apiname>Kern::Exit()</apiname></xref>.
You then queue the DFC onto the DFC queue, a <xref href="GUID-24B2FEDB-9273-351F-A1C6-6F5F91BF83B7.dita"><apiname>TDfcQue</apiname></xref> object,
from the destructor of the logical device driver's factory class, i.e. the
destructor of the class derived from <xref href="GUID-7616AA05-83E6-3989-AB9D-11AE01245BEB.dita"><apiname>DLogicalDevice</apiname></xref>. </p> </section>
<section id="GUID-3DB34648-94EC-4AF4-9550-EF7753FC18BE"><title>Issues to be aware of</title> <ol id="GUID-6335774D-CEDB-52AE-BBED-AFA7CB55DFF5">
<li id="GUID-0573932A-B43C-50B0-9458-B213A6C4346F"><p>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. </p> <p>Perform cleanup by calling <codeph>Cancel()</codeph> (i.e. <xref href="GUID-A14562A5-3E91-3113-AB3C-71DBEA9D58EB.dita#GUID-A14562A5-3E91-3113-AB3C-71DBEA9D58EB/GUID-9851B90B-8D05-3C86-B083-44C4564AC140"><apiname>TDfc::Cancel()</apiname></xref>)
on all queued DFCs. </p> </li>
<li id="GUID-F9D0239F-9174-54B5-B39B-5D1E54FF6EF5"><p>You need to make sure
that the DFC queue object, i.e. the <xref href="GUID-24B2FEDB-9273-351F-A1C6-6F5F91BF83B7.dita"><apiname>TDfcQue</apiname></xref> object, and
the 'kill' DFC object, i.e. the <xref href="GUID-A14562A5-3E91-3113-AB3C-71DBEA9D58EB.dita"><apiname>TDfc</apiname></xref> object, are not destroyed
before the 'kill' DFC has a chance to run. </p> <p>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. </p> </li>
<li id="GUID-29195090-756E-5FB7-BF78-0F6C6C5A7983"><p>You need to make sure
that any code queued to run on your DFC thread never hangs. </p> <p>The important
point is that <xref href="GUID-C6946ECB-775F-3EC2-A56F-78F25B9FBE3D.dita#GUID-C6946ECB-775F-3EC2-A56F-78F25B9FBE3D/GUID-808B3622-BDC4-376D-96E9-16281BA28AF8"><apiname>Kern::Exit()</apiname></xref> 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. </p> <p>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. </p> </li>
</ol> </section>
</conbody></concept>