diff -r 578be2adaf3e -r 307f4279f433 Adaptation/GUID-2648B61C-6EBD-4668-AACD-EA4B2C435BB2.dita --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Adaptation/GUID-2648B61C-6EBD-4668-AACD-EA4B2C435BB2.dita Fri Oct 15 14:32:18 2010 +0100 @@ -0,0 +1,90 @@ + + + + + +Message +HandlingThis document describes message queues and message handling. +
Message queues

The +request handling kernel side DFC is managed by a message queue object of the TMessageQueue type. +The message queue consists of a DFC and a doubly linked list of received messages. +The messages are represented by TThreadMessage objects +and are owned by each user thread. Requests are queued as message objects +on the message queue.

The driver framework requires that the driver +sets a DFC queue to use with the message queue. This is done by calling DLogicalChannel::SetDfcQ(). +The message queue must also be enabled to receive incoming messages by calling TMessageQue::Receive().

// Logical Channel Second stage constructor +TInt DExDriverLogicalChannel::DoCreate(TInt /*aUnit*/, const TDesC8* + /*anInfo*/, const TVersion& aVer) + { + ... + // Set up the DFC queue for this driver. Here, the DFC + // queue is created by the PDD dedicated for this driver. + SetDfcQ(Pdd()->DfcQ()); + + // Start receiving the incoming requests on the message queue + iMsgQ.Receive(); + ... + }

The Kernel provides a standard DFC queue, which runs +on a dedicated kernel thread called DFCThread0, for general +use by drivers. However, it is recommended that the driver creates its own +DFC thread to process its requests. The following example shows how a PDD +can implement the DfcQ() function to return a newly created +DFC thread:

// DfcQ - Creates a DFC queue dedicated for the tutorial driver +TDynamicDfcQue* DExUartPhysicalChannelH4::DfcQ() + { + // Create a DFC queue dedicated to the driver with a specified + // priority + TInt r = Kern::DynamicDfcQCreate(pDfcQ,KExUartDfcPriority, + KExUartDfcName); + if (r!=KErrNone) + { + // DfcQ failed, return NULL + return NULL; + } + return iDfcQueue; + }

The DFC thread that is created for the driver must be +destroyed after use. To do this, the driver can create an Exit or Kill DFC +request and queue it to the thread to be destroyed in the logical channel +destructor. This exit DFC function cancels any other requests pending using TDfc::Cancel() and +calls Kern::Exit() to terminate the thread.

The TDynamicDfcQue has +a destroy method that can be run on the channel destructor. The destroy method +destroys the DFC queue, kills the DFC thread and deletes the TDynamicDfcQue object +itself. This avoids the possibilities of memory leaks in the DFC.

+
Message handling

All +synchronous and asynchronous requests are passed to the HandleMsg() function +by the framework, with the message as an argument. A driver should implement +the function to identify the message type and handle the messages accordingly.

The +client thread is blocked until the message is completed, as the request uses +the thread's message object. If the client thread was left free, it would +corrupt the message if another request was issued.

When the driver +has completed handling the message, it notifies the framework by calling TThreadMessage::Complete(). +The client thread is then unblocked, and can either block on the thread semaphore +or issue further requests before blocking.

For synchronous requests, +the message is not completed until the request itself is complete, and the +driver calls the TThreadMessage::Complete() function after +the actual completion of the request. However, for asynchronous requests, +the message is completed after the driver has accepted the request, but not +necessarily after the actual completion of the request, which can happen later. +This means that the driver calls TThreadMessage::Complete() as +soon as it has received the message and initiated the required processing +to complete the request.

void DExDriverLogicalChannel::HandleMsg(TMessageBase* aMsg) + { + TThreadMessage& m = *(TThreadMessage*)aMsg; + // obtain the function id value to determine the request nature + TInt id = m.iValue; + ... + if (id>=0) // Synchronous messages + { + // call synchronous message handler function, DoControl() + TInt r = DoControl(id,m.Ptr0(),m.Ptr1()); + m.Complete(r,ETrue); + return; + } + }
+
\ No newline at end of file