Symbian3/PDK/Source/GUID-12EFB295-C527-5F96-81F1-6021D335D865.dita
author Dominic Pinkman <Dominic.Pinkman@Nokia.com>
Tue, 30 Mar 2010 11:56:28 +0100
changeset 5 f345bda72bc4
parent 3 46218c8b8afa
child 14 578be2adaf3e
permissions -rw-r--r--
Week 12 contribution of PDK documentation_content. See release notes for details. Fixes Bug 2054, Bug 1583, Bug 381, Bug 390, Bug 463, Bug 1897, Bug 344, Bug 1319, Bug 394, Bug 1520, Bug 1522, Bug 1892"

<?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>