Adaptation/GUID-B97BAC2E-04E3-4979-BACE-9C46BADE912E.dita
changeset 15 307f4279f433
equal deleted inserted replaced
14:578be2adaf3e 15:307f4279f433
       
     1 <?xml version="1.0" encoding="utf-8"?>
       
     2 <!-- Copyright (c) 2007-2010 Nokia Corporation and/or its subsidiary(-ies) All rights reserved. -->
       
     3 <!-- This component and the accompanying materials are made available under the terms of the License 
       
     4 "Eclipse Public License v1.0" which accompanies this distribution, 
       
     5 and is available at the URL "http://www.eclipse.org/legal/epl-v10.html". -->
       
     6 <!-- Initial Contributors:
       
     7     Nokia Corporation - initial contribution.
       
     8 Contributors: 
       
     9 -->
       
    10 <!DOCTYPE concept
       
    11   PUBLIC "-//OASIS//DTD DITA Concept//EN" "concept.dtd">
       
    12 <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
       
    13 used to implement asynchronous requests.</shortdesc><prolog><metadata><keywords/></metadata></prolog><conbody>
       
    14 <section id="GUID-1F20014A-5F1E-48B3-AEB8-ED1922452A84"><title>Deferred
       
    15 function calls</title> <p>Asynchronous request processing is normally
       
    16 done in a Deferred Function Call (DFC). The second stage of interrupt
       
    17 handling is deferred to run as a DFC, which runs in a non-critical
       
    18 context. </p> <p>Different asynchronous requests can be handled using
       
    19 a single or multiple DFCs. The number of DFCs to be created must be
       
    20 decided when the driver is designed. For example, a driver that handles
       
    21 at the same time an asynchronous receive request and a transmit request
       
    22 would create two DFCs, one each for receive and transmit. </p><p>There
       
    23 are two main types of deferred function call:<ul>
       
    24 <li><p>standard Deferred Function Call (DFC)</p></li>
       
    25 <li><p>Immediate Deferred Function Call (IDFC).</p></li>
       
    26 </ul></p><p>A DFC is a kernel object that specifies a function to
       
    27 be run in a thread, which is processing a DFC queue. A DFC is added
       
    28 to a DFC queue that is associated with a given thread, where it is
       
    29 cooperatively scheduled with other DFCs on that queue.  Queued DFCs
       
    30 are run in order of their priority, followed by the order they where
       
    31 queued.  When the DFC gets to run, the function is run kernel side,
       
    32 and no other DFC in this queue will get to run until it completes.
       
    33 A DFC can be queued from any context.</p><p>An IDFC is run as soon
       
    34 as the scheduler is next run, which is:</p><table id="GUID-CCA45A6C-BB16-41D1-B16C-E3491BEF8B7B">
       
    35 <tgroup cols="2"><colspec colname="col1"/><colspec colname="col2"/>
       
    36 <thead>
       
    37 <row>
       
    38 <entry align="center" valign="top">Scheduler</entry>
       
    39 <entry align="center" valign="top">IDFC runs</entry>
       
    40 </row>
       
    41 </thead>
       
    42 <tbody>
       
    43 <row>
       
    44 <entry>queued from an Interrupt Service Routine (ISR)</entry>
       
    45 <entry>during the IRQ postamble.</entry>
       
    46 </row>
       
    47 <row>
       
    48 <entry>queued from an IDFC</entry>
       
    49 <entry>when the currently-running IDFC completes.</entry>
       
    50 </row>
       
    51 <row>
       
    52 <entry>queued from thread context</entry>
       
    53 <entry>when the kernel is next unlocked.</entry>
       
    54 </row>
       
    55 </tbody>
       
    56 </tgroup>
       
    57 </table><p>Unlike a DFC, the IDFC is not run from a thread context,
       
    58 and its execution time must be much smaller.  For these reasons, IDFCs
       
    59 are rarely used directly, but are used for implementation of the kernel
       
    60 and RTOS personality layers.  An important use of IDFCs is in the
       
    61 implementation of queuing DFCs from an ISR context.  IDFCs are run
       
    62 with interrupts enabled but the kernel locked.</p></section>
       
    63 <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
       
    64 an object to be passed to the callback function, and a priority. It
       
    65 can also provide the DFC queue to be used by this DFC at the time
       
    66 of construction. </p> <codeblock id="GUID-B3918CAB-F168-5992-BFA9-868648D07083" xml:space="preserve">TDfc iRxDfc;
       
    67 /* RxDataDfc is a function pointer to a static function, "this" is passed as a parameter */
       
    68 iRxDfc(RxDataDfc,this,1); // This implements an DFC using the standard queue and priority 1.
       
    69 iRxDfc(RxDataDfc,this,iDfcQ,1); // This implements an DFC on a user-specified queue with a priority of 1.
       
    70 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
       
    71 error. IDFCs are created by not specifying a priority. </note></section>
       
    72 <section id="GUID-886457DF-0DB5-4447-BC9B-EB43060A5C6B"><title>Queuing</title> <p>To initiate the process of DFC functionality, the DFC object
       
    73 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
       
    74 associated with the queue (<xref href="GUID-24B2FEDB-9273-351F-A1C6-6F5F91BF83B7.dita"><apiname>TDfcQue</apiname></xref>) object. This
       
    75 can be either done at the time of construction, or can be set later,
       
    76 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">...
       
    77 // Associate the Tx and Rx DFCs with the same queue set to receive 
       
    78 // the client messages for this driver. SetDfcQ() sets up the DFC 
       
    79 // queue for the DFCs constructed for Tx and Rx
       
    80 //
       
    81 iRxDfc.SetDfcQ(iDfcQ);
       
    82 ...</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 
       
    83 // is the only way to queue an IDFC and is the only way to queue a 
       
    84 // DFC from an ISR. To queue a DFC from an IDFC or a thread either 
       
    85 // TDfc::Enque() or TDfc::DoEnque() should be used. This function 
       
    86 // does nothing if the IDFC/DFC is already queued.
       
    87 //
       
    88 iRxDfc.Add();
       
    89 </codeblock></section>
       
    90 <section id="GUID-E0B9073A-1554-4085-BE24-E27633B7EDF2"><title>Callback
       
    91 function</title> <p>The DFC callback function is a static function
       
    92 called when a DFC is executed. A pointer to this function is provided
       
    93 at the time of DFC object creation. This function implements the deferred
       
    94 functionality of an asynchronous request, such as reading or writing
       
    95 data from or to an I/O peripheral. It would then either complete the
       
    96 request or start another operation. </p> <codeblock id="GUID-5682EDE1-8397-592D-82CE-78DF11487512" xml:space="preserve">static void RxDataDfc(TAny* aPtr);</codeblock></section>
       
    97 <section id="GUID-A57C3C99-3032-48CD-A800-E9EE7DCDF4E3"><title>Cancellation</title> <p>A DFC function must be cancelled while cleaning up resources,
       
    98 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
       
    99 is not queued. It must be called to avoid orphaned DFCs. </p> <codeblock id="GUID-CD926E3D-13E8-51C4-B224-8150FD4D70DB" xml:space="preserve">...
       
   100 // If it is a Transmit request, cancel the Transmit DFC. 
       
   101 // TDfc::Cancel() cancels the DFC if it is already queued. It 
       
   102 // does nothing if DFC is not queued.
       
   103 //
       
   104 iTxDfc.Cancel();
       
   105 ...</codeblock></section>
       
   106 </conbody></concept>