Adaptation/GUID-2648B61C-6EBD-4668-AACD-EA4B2C435BB2.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-2648B61C-6EBD-4668-AACD-EA4B2C435BB2" xml:lang="en"><title>Message
       
    13 Handling</title><shortdesc>This document describes message queues and message handling.</shortdesc><prolog><metadata><keywords/></metadata></prolog><conbody>
       
    14 <section id="GUID-AE9A6778-85AE-4D1D-BF61-EE06339549D9"><title>Message queues</title> <p>The
       
    15 request handling kernel side DFC is managed by a message queue object of the <xref href="GUID-F10B7D2F-D546-3997-A020-37A0D894F1CD.dita"><apiname>TMessageQueue</apiname></xref> type.
       
    16 The message queue consists of a DFC and a doubly linked list of received messages.
       
    17 The messages are represented by <xref href="GUID-D43CB8FA-C212-3B56-AD16-9F1D69DA7551.dita"><apiname>TThreadMessage</apiname></xref> objects
       
    18 and are owned by each user thread. Requests are queued as message objects
       
    19 on the message queue. </p> <p>The driver framework requires that the driver
       
    20 sets a DFC queue to use with the message queue. This is done by calling <xref href="GUID-A3CC1D95-4681-3349-A67C-F113A614041D.dita#GUID-A3CC1D95-4681-3349-A67C-F113A614041D/GUID-EB160A2E-39A9-3739-ABDE-C91E2A28D26D"><apiname>DLogicalChannel::SetDfcQ()</apiname></xref>.
       
    21 The message queue must also be enabled to receive incoming messages by calling <xref href="GUID-382DD935-E9D7-3E00-88B2-B28A89CAD4FB.dita#GUID-382DD935-E9D7-3E00-88B2-B28A89CAD4FB/GUID-EF06556E-9EC6-3D1C-AEE9-0CDDF6B42A24"><apiname>TMessageQue::Receive()</apiname></xref>. </p> <codeblock id="GUID-A995A927-113D-5CB6-B813-DF88DC02D0C1" xml:space="preserve">// Logical Channel Second stage constructor
       
    22 TInt DExDriverLogicalChannel::DoCreate(TInt /*aUnit*/, const TDesC8*
       
    23         /*anInfo*/, const TVersion&amp; aVer)
       
    24     {
       
    25     ...
       
    26     // Set up the DFC queue for this driver. Here, the DFC 
       
    27     // queue is created by the PDD dedicated for this driver.
       
    28     SetDfcQ(Pdd()-&gt;DfcQ());
       
    29 
       
    30     // Start receiving the incoming requests on the message queue
       
    31     iMsgQ.Receive();
       
    32     ...
       
    33     }</codeblock> <p>The Kernel provides a standard DFC queue, which runs
       
    34 on a dedicated kernel thread called <codeph>DFCThread0</codeph>, for general
       
    35 use by drivers. However, it is recommended that the driver creates its own
       
    36 DFC thread to process its requests. The following example shows how a PDD
       
    37 can implement the <codeph>DfcQ()</codeph> function to return a newly created
       
    38 DFC thread: </p> <codeblock id="GUID-4753E5B1-8B8F-5589-8547-C94B48B7D66A" xml:space="preserve">// DfcQ - Creates a DFC queue dedicated for the tutorial driver
       
    39 TDynamicDfcQue* DExUartPhysicalChannelH4::DfcQ()
       
    40     {
       
    41     // Create a DFC queue dedicated to the driver with a specified 
       
    42     // priority
       
    43     TInt r = Kern::DynamicDfcQCreate(pDfcQ,KExUartDfcPriority,
       
    44     KExUartDfcName);
       
    45     if (r!=KErrNone)
       
    46         {
       
    47         // DfcQ failed, return NULL
       
    48         return NULL;
       
    49         }
       
    50     return iDfcQueue;
       
    51     }</codeblock> <p>The DFC thread that is created for the driver must be
       
    52 destroyed after use. To do this, the driver can create an Exit or Kill DFC
       
    53 request and queue it to the thread to be destroyed in the logical channel
       
    54 destructor. This exit DFC function cancels any other requests pending using <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> and
       
    55 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> to terminate the thread. </p> <p>The <xref href="GUID-D9111A26-FAA3-3D8E-AB41-5B1263FABB6A.dita"><apiname>TDynamicDfcQue</apiname></xref> has
       
    56 a destroy method that can be run on the channel destructor. The destroy method
       
    57 destroys the DFC queue, kills the DFC thread and deletes the <xref href="GUID-D9111A26-FAA3-3D8E-AB41-5B1263FABB6A.dita"><apiname>TDynamicDfcQue</apiname></xref> object
       
    58 itself. This avoids the possibilities of memory leaks in the DFC. </p></section>
       
    59 <section id="GUID-2463763E-1838-4D7D-80F2-D77420B49D09"><title>Message handling</title> <p>All
       
    60 synchronous and asynchronous requests are passed to the <xref href="GUID-621F4531-996F-33BB-8081-4B2067CC262A.dita"><apiname>HandleMsg()</apiname></xref> function
       
    61 by the framework, with the message as an argument. A driver should implement
       
    62 the function to identify the message type and handle the messages accordingly. </p> <p>The
       
    63 client thread is blocked until the message is completed, as the request uses
       
    64 the thread's message object. If the client thread was left free, it would
       
    65 corrupt the message if another request was issued. </p> <p>When the driver
       
    66 has completed handling the message, it notifies the framework by calling <xref href="GUID-D43CB8FA-C212-3B56-AD16-9F1D69DA7551.dita#GUID-D43CB8FA-C212-3B56-AD16-9F1D69DA7551/GUID-20CFC972-7C07-36D8-BAC8-BB63AA4612B6"><apiname>TThreadMessage::Complete()</apiname></xref>.
       
    67 The client thread is then unblocked, and can either block on the thread semaphore
       
    68 or issue further requests before blocking. </p> <p>For synchronous requests,
       
    69 the message is not completed until the request itself is complete, and the
       
    70 driver calls the <codeph>TThreadMessage::Complete()</codeph> function after
       
    71 the actual completion of the request. However, for asynchronous requests,
       
    72 the message is completed after the driver has accepted the request, but not
       
    73 necessarily after the actual completion of the request, which can happen later.
       
    74 This means that the driver calls <codeph>TThreadMessage::Complete()</codeph> as
       
    75 soon as it has received the message and initiated the required processing
       
    76 to complete the request. </p> <codeblock id="GUID-C178DFFA-2321-5396-AED6-5244BBF98388" xml:space="preserve">void DExDriverLogicalChannel::HandleMsg(TMessageBase* aMsg)
       
    77     {            
       
    78     TThreadMessage&amp; m = *(TThreadMessage*)aMsg;        
       
    79     // obtain the function id value to determine the request nature
       
    80     TInt id = m.iValue;        
       
    81     ...
       
    82     if (id&gt;=0)    // Synchronous messages
       
    83         {
       
    84         // call synchronous message handler function, DoControl()    
       
    85         TInt r = DoControl(id,m.Ptr0(),m.Ptr1());
       
    86         m.Complete(r,ETrue);
       
    87         return;
       
    88         }    
       
    89     }</codeblock></section>
       
    90 </conbody></concept>