Adaptation/GUID-B97BAC2E-04E3-4979-BACE-9C46BADE912E.dita
changeset 15 307f4279f433
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Adaptation/GUID-B97BAC2E-04E3-4979-BACE-9C46BADE912E.dita	Fri Oct 15 14:32:18 2010 +0100
@@ -0,0 +1,106 @@
+<?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-B97BAC2E-04E3-4979-BACE-9C46BADE912E" xml:lang="en"><title>Deferred Function Calls</title><shortdesc>This document describes how Deferred Function Calls are
+used to implement asynchronous requests.</shortdesc><prolog><metadata><keywords/></metadata></prolog><conbody>
+<section id="GUID-1F20014A-5F1E-48B3-AEB8-ED1922452A84"><title>Deferred
+function calls</title> <p>Asynchronous request processing is normally
+done in a Deferred Function Call (DFC). The second stage of interrupt
+handling is deferred to run as a DFC, which runs in a non-critical
+context. </p> <p>Different asynchronous requests can be handled using
+a single or multiple DFCs. The number of DFCs to be created must be
+decided when the driver is designed. For example, a driver that handles
+at the same time an asynchronous receive request and a transmit request
+would create two DFCs, one each for receive and transmit. </p><p>There
+are two main types of deferred function call:<ul>
+<li><p>standard Deferred Function Call (DFC)</p></li>
+<li><p>Immediate Deferred Function Call (IDFC).</p></li>
+</ul></p><p>A DFC is a kernel object that specifies a function to
+be run in a thread, which is processing a DFC queue. A DFC is added
+to a DFC queue that is associated with a given thread, where it is
+cooperatively scheduled with other DFCs on that queue.  Queued DFCs
+are run in order of their priority, followed by the order they where
+queued.  When the DFC gets to run, the function is run kernel side,
+and no other DFC in this queue will get to run until it completes.
+A DFC can be queued from any context.</p><p>An IDFC is run as soon
+as the scheduler is next run, which is:</p><table id="GUID-CCA45A6C-BB16-41D1-B16C-E3491BEF8B7B">
+<tgroup cols="2"><colspec colname="col1"/><colspec colname="col2"/>
+<thead>
+<row>
+<entry align="center" valign="top">Scheduler</entry>
+<entry align="center" valign="top">IDFC runs</entry>
+</row>
+</thead>
+<tbody>
+<row>
+<entry>queued from an Interrupt Service Routine (ISR)</entry>
+<entry>during the IRQ postamble.</entry>
+</row>
+<row>
+<entry>queued from an IDFC</entry>
+<entry>when the currently-running IDFC completes.</entry>
+</row>
+<row>
+<entry>queued from thread context</entry>
+<entry>when the kernel is next unlocked.</entry>
+</row>
+</tbody>
+</tgroup>
+</table><p>Unlike a DFC, the IDFC is not run from a thread context,
+and its execution time must be much smaller.  For these reasons, IDFCs
+are rarely used directly, but are used for implementation of the kernel
+and RTOS personality layers.  An important use of IDFCs is in the
+implementation of queuing DFCs from an ISR context.  IDFCs are run
+with interrupts enabled but the kernel locked.</p></section>
+<section id="GUID-5439E26D-754A-46F3-B607-D229BF5B8A8C"><title>Creation</title> <p>DFCs are created using <xref href="GUID-A14562A5-3E91-3113-AB3C-71DBEA9D58EB.dita"><apiname>TDfc</apiname></xref> objects. </p> <p>The DFC is initialized with a DFC callback function, a pointer to
+an object to be passed to the callback function, and a priority. It
+can also provide the DFC queue to be used by this DFC at the time
+of construction. </p> <codeblock id="GUID-B3918CAB-F168-5992-BFA9-868648D07083" xml:space="preserve">TDfc iRxDfc;
+/* RxDataDfc is a function pointer to a static function, "this" is passed as a parameter */
+iRxDfc(RxDataDfc,this,1); // This implements an DFC using the standard queue and priority 1.
+iRxDfc(RxDataDfc,this,iDfcQ,1); // This implements an DFC on a user-specified queue with a priority of 1.
+iRxDfc(RxDataDfc,this); // This implements an IDFC.</codeblock><note>DFCs are created with a priority which is 0 to (<xref href="GUID-483DF06F-0236-36C0-8F59-475BB38344E5.dita"><apiname>KNumDfcPriorities</apiname></xref>—1), which is typically 0..7. Using a higher priority value is an
+error. IDFCs are created by not specifying a priority. </note></section>
+<section id="GUID-886457DF-0DB5-4447-BC9B-EB43060A5C6B"><title>Queuing</title> <p>To initiate the process of DFC functionality, the DFC object
+must be queued to the DFC queue associated with the Kernel thread. </p> <p>Before adding the DFC to a DFC queue of the thread, it must be
+associated with the queue (<xref href="GUID-24B2FEDB-9273-351F-A1C6-6F5F91BF83B7.dita"><apiname>TDfcQue</apiname></xref>) object. This
+can be either done at the time of construction, or can be set later,
+by calling <xref href="GUID-A14562A5-3E91-3113-AB3C-71DBEA9D58EB.dita#GUID-A14562A5-3E91-3113-AB3C-71DBEA9D58EB/GUID-E3458CD4-7A1C-3FBD-A7FB-488A9C92AE42"><apiname>TDfc::SetDfcQ()</apiname></xref>. </p> <codeblock id="GUID-B57B1C37-A1A5-5C85-AED8-FDD8DBE84280" xml:space="preserve">...
+// Associate the Tx and Rx DFCs with the same queue set to receive 
+// the client messages for this driver. SetDfcQ() sets up the DFC 
+// queue for the DFCs constructed for Tx and Rx
+//
+iRxDfc.SetDfcQ(iDfcQ);
+...</codeblock> <p> <xref href="GUID-A14562A5-3E91-3113-AB3C-71DBEA9D58EB.dita#GUID-A14562A5-3E91-3113-AB3C-71DBEA9D58EB/GUID-18073EBB-D91B-3AC8-87A2-424AEDD4D7A4"><apiname> TDfc::Add()</apiname></xref> or <xref href="GUID-A14562A5-3E91-3113-AB3C-71DBEA9D58EB.dita#GUID-A14562A5-3E91-3113-AB3C-71DBEA9D58EB/GUID-F6F0C858-8EB2-387B-AE1A-F04B51CE4CED"><apiname>TDfc::Enque()</apiname></xref> is used to add the DFC object to the DFC queue. From an ISR, <xref href="GUID-A14562A5-3E91-3113-AB3C-71DBEA9D58EB.dita#GUID-A14562A5-3E91-3113-AB3C-71DBEA9D58EB/GUID-18073EBB-D91B-3AC8-87A2-424AEDD4D7A4"><apiname>TDfc::Add()</apiname></xref> is used. From a thread, <xref href="GUID-A14562A5-3E91-3113-AB3C-71DBEA9D58EB.dita#GUID-A14562A5-3E91-3113-AB3C-71DBEA9D58EB/GUID-F6F0C858-8EB2-387B-AE1A-F04B51CE4CED"><apiname>TDfc::Enque()</apiname></xref> is used. If preemption is disabled, <codeph>TDfc::Add()</codeph> could also be used. </p> <codeblock id="GUID-9FBB6881-4BA9-534E-86C7-3A0167E9159C" xml:space="preserve">// TDfc::Add() will queue an IDFC or a DFC from an ISR. This function 
+// is the only way to queue an IDFC and is the only way to queue a 
+// DFC from an ISR. To queue a DFC from an IDFC or a thread either 
+// TDfc::Enque() or TDfc::DoEnque() should be used. This function 
+// does nothing if the IDFC/DFC is already queued.
+//
+iRxDfc.Add();
+</codeblock></section>
+<section id="GUID-E0B9073A-1554-4085-BE24-E27633B7EDF2"><title>Callback
+function</title> <p>The DFC callback function is a static function
+called when a DFC is executed. A pointer to this function is provided
+at the time of DFC object creation. This function implements the deferred
+functionality of an asynchronous request, such as reading or writing
+data from or to an I/O peripheral. It would then either complete the
+request or start another operation. </p> <codeblock id="GUID-5682EDE1-8397-592D-82CE-78DF11487512" xml:space="preserve">static void RxDataDfc(TAny* aPtr);</codeblock></section>
+<section id="GUID-A57C3C99-3032-48CD-A800-E9EE7DCDF4E3"><title>Cancellation</title> <p>A DFC function must be cancelled while cleaning up resources,
+for example, when closing the channel. The function <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> cancels the DFC if it is already queued. It does nothing if a DFC
+is not queued. It must be called to avoid orphaned DFCs. </p> <codeblock id="GUID-CD926E3D-13E8-51C4-B224-8150FD4D70DB" xml:space="preserve">...
+// If it is a Transmit request, cancel the Transmit DFC. 
+// TDfc::Cancel() cancels the DFC if it is already queued. It 
+// does nothing if DFC is not queued.
+//
+iTxDfc.Cancel();
+...</codeblock></section>
+</conbody></concept>
\ No newline at end of file