--- a/Symbian3/PDK/Source/GUID-E7C55048-5B7A-5BF2-B7F4-4D731659B88C-GENID-1-7-1-14-1-1-7-1-7-1-11-1-7-1-5-1-9-1.dita Thu Mar 11 15:24:26 2010 +0000
+++ b/Symbian3/PDK/Source/GUID-E7C55048-5B7A-5BF2-B7F4-4D731659B88C-GENID-1-7-1-14-1-1-7-1-7-1-11-1-7-1-5-1-9-1.dita Thu Mar 11 18:02:22 2010 +0000
@@ -1,183 +1,183 @@
-<?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-E7C55048-5B7A-5BF2-B7F4-4D731659B88C-GENID-1-7-1-14-1-1-7-1-7-1-11-1-7-1-5-1-9-1" xml:lang="en"><title>Device
-Driver Writing and Migration Technology Tutorial</title><shortdesc>Explains techniques for writing device drivers on data paged systems
-and migrating device drivers to data paged systems. </shortdesc><prolog><metadata><keywords/></metadata></prolog><conbody>
-<section id="GUID-8629C08B-C1C8-4435-962A-A57F11EB25CF-GENID-1-7-1-14-1-1-7-1-7-1-11-1-7-1-5-1-9-1-3-1"><title>Impact of data paging on kernel APIs</title> <p>The use of
-data paging impacts on the task of writing and migrating device drivers in
-two main ways: the preconditions for kernel API calls and the performance
-of the kernel APIs. </p> <p>Firstly, kernel APIs which access user memory
-may only be called subject to preconditions. The preconditions are that </p> <ul>
-<li id="GUID-81B56316-97C6-5EE8-BD88-D0741F9301F9-GENID-1-7-1-14-1-1-7-1-7-1-11-1-7-1-5-1-9-1-3-1-4-1"><p>no fast mutex may be
-held while calling them, and </p> </li>
-<li id="GUID-507412E1-1CA8-5590-B974-809B51C3D79D-GENID-1-7-1-14-1-1-7-1-7-1-11-1-7-1-5-1-9-1-3-1-4-2"><p>no kernel mutex may
-be held while calling them. </p> </li>
-</ul> <p>The APIs are these: </p> <ul>
-<li id="GUID-7A4E9152-8BFA-515E-A115-265436C843F4-GENID-1-7-1-14-1-1-7-1-7-1-11-1-7-1-5-1-9-1-3-1-6-1"><p> <xref href="GUID-C6946ECB-775F-3EC2-A56F-78F25B9FBE3D.dita#GUID-C6946ECB-775F-3EC2-A56F-78F25B9FBE3D/GUID-C154A151-0DF7-345D-9A10-E9B1CF3400D9"><apiname>Kern::KUDesInfo</apiname></xref> </p> </li>
-<li id="GUID-3C31D5D3-48E9-5D6D-8489-8259D98BF117-GENID-1-7-1-14-1-1-7-1-7-1-11-1-7-1-5-1-9-1-3-1-6-2"><p> <xref href="GUID-C6946ECB-775F-3EC2-A56F-78F25B9FBE3D.dita#GUID-C6946ECB-775F-3EC2-A56F-78F25B9FBE3D/GUID-FAFAA120-AA28-32FD-9202-1534C3148026"><apiname>Kern::InfoCopy</apiname></xref> </p> </li>
-<li id="GUID-FCE0C3D6-EE49-5AC9-856E-9833D22D541A-GENID-1-7-1-14-1-1-7-1-7-1-11-1-7-1-5-1-9-1-3-1-6-3"><p> <xref href="GUID-C6946ECB-775F-3EC2-A56F-78F25B9FBE3D.dita#GUID-C6946ECB-775F-3EC2-A56F-78F25B9FBE3D/GUID-B79007D0-FF1F-30E7-986D-7CEBC5E45102"><apiname>Kern::KUDesGet</apiname></xref> </p> </li>
-<li id="GUID-72D4E609-B189-570A-B4D6-D2F4F1289EC1-GENID-1-7-1-14-1-1-7-1-7-1-11-1-7-1-5-1-9-1-3-1-6-4"><p> <xref href="GUID-C6946ECB-775F-3EC2-A56F-78F25B9FBE3D.dita#GUID-C6946ECB-775F-3EC2-A56F-78F25B9FBE3D/GUID-CDEA7B22-9520-3DB1-AA04-1289C2287936"><apiname>Kern::KUDesPut</apiname></xref> </p> </li>
-<li id="GUID-EE2D8F45-5B12-5D69-A9FD-7ED47A0B5EAD-GENID-1-7-1-14-1-1-7-1-7-1-11-1-7-1-5-1-9-1-3-1-6-5"><p> <xref href="GUID-C6946ECB-775F-3EC2-A56F-78F25B9FBE3D.dita#GUID-C6946ECB-775F-3EC2-A56F-78F25B9FBE3D/GUID-94F2DF65-87A5-32C6-9695-9557E5832ACF"><apiname>Kern::KUDesSetLength</apiname></xref> </p> </li>
-<li id="GUID-46805316-D1D5-5477-8287-FBF43DD8D3C4-GENID-1-7-1-14-1-1-7-1-7-1-11-1-7-1-5-1-9-1-3-1-6-6"><p> <xref href="GUID-EE4CB2B4-EAFC-3721-BF0D-ECDF96C29FBF.dita"><apiname>umemget</apiname></xref>, <xref href="GUID-E569834D-8960-3D4E-8980-64902200D4F8.dita"><apiname>kumemget</apiname></xref>, <xref href="GUID-388FF557-3092-3EA0-BF4A-D73504521CD0.dita"><apiname>umemget32</apiname></xref>, <xref href="GUID-874BB607-F0CA-3123-AB2D-D04F4763B16A.dita"><apiname>kumemget32</apiname></xref> </p> </li>
-<li id="GUID-DB8BF5C7-2444-5B8F-8F66-12383ECB6A81-GENID-1-7-1-14-1-1-7-1-7-1-11-1-7-1-5-1-9-1-3-1-6-7"><p> <xref href="GUID-71B53E34-1F41-3B53-8133-D76D8847D143.dita"><apiname>umemput</apiname></xref>, <xref href="GUID-7B0CC157-0EF6-3CF5-BAF2-D8227F7734A5.dita"><apiname>kumemput</apiname></xref>, <xref href="GUID-A6303814-456F-3583-86B0-A99EA5C3E5A4.dita"><apiname>umemput32</apiname></xref>, <xref href="GUID-B00A6392-9A90-357E-B6A2-D2762800C2C5.dita"><apiname>kumemput32</apiname></xref> </p> </li>
-<li id="GUID-9E6B180A-B360-58A6-B60E-8605E22F2C2E-GENID-1-7-1-14-1-1-7-1-7-1-11-1-7-1-5-1-9-1-3-1-6-8"><p> <xref href="GUID-BBF5941C-3369-3B56-A560-6E80A7CFFE0F.dita"><apiname>umemset</apiname></xref>, <xref href="GUID-08C2BCA6-6842-3D10-AB56-835B618317F9.dita"><apiname>kumemset</apiname></xref>, <xref href="GUID-B48B5214-ACDD-3E9B-AE07-1B40F645D959.dita"><apiname>umemset32</apiname></xref>, <xref href="GUID-5C1EB135-F9A7-37A5-B256-299CB9598DA9.dita"><apiname>kumemset32</apiname></xref> </p> </li>
-<li id="GUID-F307081B-7672-5C3F-869C-9B4B4F55CE62-GENID-1-7-1-14-1-1-7-1-7-1-11-1-7-1-5-1-9-1-3-1-6-9"><p> <xref href="GUID-C6946ECB-775F-3EC2-A56F-78F25B9FBE3D.dita#GUID-C6946ECB-775F-3EC2-A56F-78F25B9FBE3D/GUID-D0FCFD5B-2814-3D81-A54A-9E2FA226019B"><apiname>Kern::RequestComplete</apiname></xref> </p> </li>
-<li id="GUID-647B36DF-2124-5252-824E-E100695624C2-GENID-1-7-1-14-1-1-7-1-7-1-11-1-7-1-5-1-9-1-3-1-6-10"><p> <xref href="GUID-C6946ECB-775F-3EC2-A56F-78F25B9FBE3D.dita#GUID-C6946ECB-775F-3EC2-A56F-78F25B9FBE3D/GUID-589188FC-48E8-3973-B88B-D9E47CFE4403"><apiname>Kern::ThreadRawRead</apiname></xref> </p> </li>
-<li id="GUID-9776CFD1-B061-5FC1-B100-0A55D7E8BFA5-GENID-1-7-1-14-1-1-7-1-7-1-11-1-7-1-5-1-9-1-3-1-6-11"><p> <xref href="GUID-C6946ECB-775F-3EC2-A56F-78F25B9FBE3D.dita#GUID-C6946ECB-775F-3EC2-A56F-78F25B9FBE3D/GUID-68BFCE22-E05E-3710-9014-6E72FDE7891F"><apiname>Kern::ThreadRawWrite</apiname></xref> </p> </li>
-<li id="GUID-21F695FF-8933-5FF4-84DC-1F09056E36A6-GENID-1-7-1-14-1-1-7-1-7-1-11-1-7-1-5-1-9-1-3-1-6-12"><p> <xref href="GUID-C6946ECB-775F-3EC2-A56F-78F25B9FBE3D.dita#GUID-C6946ECB-775F-3EC2-A56F-78F25B9FBE3D/GUID-451FD979-14A8-3301-A389-7B509C969FE9"><apiname>Kern::ThreadDesRead</apiname></xref> </p> </li>
-<li id="GUID-B477D969-B73E-514B-8E40-565EE6C4490E-GENID-1-7-1-14-1-1-7-1-7-1-11-1-7-1-5-1-9-1-3-1-6-13"><p> <xref href="GUID-C6946ECB-775F-3EC2-A56F-78F25B9FBE3D.dita#GUID-C6946ECB-775F-3EC2-A56F-78F25B9FBE3D/GUID-B4A7AF78-179A-378B-9184-CCC2E31830F5"><apiname>Kern::ThreadDesWrite</apiname></xref> </p> </li>
-<li id="GUID-C8080F75-2F3B-5DBE-B0DE-D8518ED49516-GENID-1-7-1-14-1-1-7-1-7-1-11-1-7-1-5-1-9-1-3-1-6-14"><p> <xref href="GUID-C6946ECB-775F-3EC2-A56F-78F25B9FBE3D.dita#GUID-C6946ECB-775F-3EC2-A56F-78F25B9FBE3D/GUID-6668EA8F-AA55-3CB4-ADEA-879579E94729"><apiname>Kern::ThreadGetDesLength</apiname></xref> </p> </li>
-<li id="GUID-8D644BB0-9A01-5248-8DD2-95CDAE058B09-GENID-1-7-1-14-1-1-7-1-7-1-11-1-7-1-5-1-9-1-3-1-6-15"><p> <xref href="GUID-C6946ECB-775F-3EC2-A56F-78F25B9FBE3D.dita#GUID-C6946ECB-775F-3EC2-A56F-78F25B9FBE3D/GUID-53813A59-7CED-39E2-818A-D9E0374D2BFD"><apiname>Kern::ThreadGetDesMaxLength</apiname></xref> </p> </li>
-<li id="GUID-746E54A0-C6D0-5B90-89F3-D197DD04470C-GENID-1-7-1-14-1-1-7-1-7-1-11-1-7-1-5-1-9-1-3-1-6-16"><p> <xref href="GUID-C6946ECB-775F-3EC2-A56F-78F25B9FBE3D.dita#GUID-C6946ECB-775F-3EC2-A56F-78F25B9FBE3D/GUID-60E5E01D-2965-3E33-BC05-052A575303F8"><apiname>Kern::ThreadGetDesInfo</apiname></xref> </p> </li>
-</ul> </section>
-<section id="GUID-8C767668-D568-40E4-82F7-DD6FC6EA8132-GENID-1-7-1-14-1-1-7-1-7-1-11-1-7-1-5-1-9-1-3-2"><title>Impact of data paging on execution</title> <p>Device drivers
-use kernel side APIs to access user memory, and even when they are called
-in accordance with their preconditions they are no longer guaranteed to execute
-in a short and bounded time. This is because they may access paged memory
-and incur page faults which propagate from one thread to another. This document
-discusses how to mitigate the impact of data paging on device drivers. </p> </section>
-<section id="GUID-3903425C-EA48-44D6-B65E-253F583465BF-GENID-1-7-1-14-1-1-7-1-7-1-11-1-7-1-5-1-9-1-3-3"><title>Mitigating data paging: general principles</title> <p>Three
-general principles are involved in mitigating the impact of data paging on
-device drivers. </p> <ul>
-<li id="GUID-955ACDFA-CA71-5489-920F-B2F74039EA37-GENID-1-7-1-14-1-1-7-1-7-1-11-1-7-1-5-1-9-1-3-3-3-1"><p>Device drivers should
-not use shared DFC queues. </p> </li>
-<li id="GUID-3FD4823A-C1A0-53B2-8987-45313BC984C3-GENID-1-7-1-14-1-1-7-1-7-1-11-1-7-1-5-1-9-1-3-3-3-2"><p>Device drivers should,
-as far as possible, not access paged memory. </p> </li>
-<li id="GUID-3557B245-D479-5FA3-B039-092A8F1B7E06-GENID-1-7-1-14-1-1-7-1-7-1-11-1-7-1-5-1-9-1-3-3-3-3"><p>If a device driver needs
-to access paged memory, it should do so in the context of the client thread. </p> </li>
-</ul> </section>
-<section id="GUID-BE00235A-D227-4290-B3FA-93B20966073F-GENID-1-7-1-14-1-1-7-1-7-1-11-1-7-1-5-1-9-1-3-4"><title>Driver frameworks</title> <p>There are three main categories
-of device driver: </p> <ul>
-<li id="GUID-EAD164EF-A615-5AFE-A512-032C1C0CC0AC-GENID-1-7-1-14-1-1-7-1-7-1-11-1-7-1-5-1-9-1-3-4-3-1"><p>boot-loaded non-channel
-drivers, </p> </li>
-<li id="GUID-B82465B7-6306-5AAC-B6B4-FB5A4D07EBB2-GENID-1-7-1-14-1-1-7-1-7-1-11-1-7-1-5-1-9-1-3-4-3-2"><p>media drivers, and </p> </li>
-<li id="GUID-86AB0CC9-B147-5019-837C-B2A6B32A9F6B-GENID-1-7-1-14-1-1-7-1-7-1-11-1-7-1-5-1-9-1-3-4-3-3"><p>dynamically loaded,
-channel-based IO device drivers </p> </li>
-</ul> <p>The document <xref href="GUID-91C11D80-7A62-5135-8EE0-6EC5576D1118.dita">Demand
-Paged Device Drivers Writing Guide</xref> discusses these three frameworks
-and identifies areas where they are vulnerable to the impact of data paging. </p> </section>
-<section id="GUID-6CD39776-B448-4F7D-8EC2-727AF13B575B-GENID-1-7-1-14-1-1-7-1-7-1-11-1-7-1-5-1-9-1-3-5"><title>Mitigation techniques</title> <p>The impact of data paging
-on device drivers is mitigated by the use of various different techniques
-which are the subject of the rest of this document. </p> <p><b>Passing
-data by value</b> </p> <p>Clients should pass data by value not as pointers.
-Return values of calls should be return codes not data. </p> <p><b>Using dedicated DFC queues</b> </p> <p>All drivers which use DFCs should
-use a dedicated DFC queue to service them. You should not use the kernel queues <xref href="GUID-C6946ECB-775F-3EC2-A56F-78F25B9FBE3D.dita#GUID-C6946ECB-775F-3EC2-A56F-78F25B9FBE3D/GUID-96588DB1-6884-300F-A85B-EA14A8A1BFAD"><apiname>Kern::DfcQue0</apiname></xref> and <xref href="GUID-C6946ECB-775F-3EC2-A56F-78F25B9FBE3D.dita#GUID-C6946ECB-775F-3EC2-A56F-78F25B9FBE3D/GUID-7B1F53D8-7EC2-3A05-9F1B-240550A7283B"><apiname>Kern::DfcQue1</apiname></xref> for this purpose. How you create a dedicated DFC queue depends on the nature
-of the driver. </p> <p>To service boot loaded drivers and media drivers, you
-create a DFC queue by calling <xref href="GUID-C6946ECB-775F-3EC2-A56F-78F25B9FBE3D.dita#GUID-C6946ECB-775F-3EC2-A56F-78F25B9FBE3D/GUID-F8D26F25-FBFB-3D89-9A80-95719D165C8E"><apiname>Kern::DfcQueueCreate()</apiname></xref>. </p> <p>To
-service dynamically loaded drivers derived from DLogicalChannelBase you call <xref href="GUID-C6946ECB-775F-3EC2-A56F-78F25B9FBE3D.dita#GUID-C6946ECB-775F-3EC2-A56F-78F25B9FBE3D/GUID-ED1B8C3D-ABFB-37BD-A6E9-4080FCCE115C"><apiname>Kern::DynamicDfcQCreate()</apiname></xref> with
-a <xref href="GUID-D9111A26-FAA3-3D8E-AB41-5B1263FABB6A.dita"><apiname>TDynamicDfcQue</apiname></xref> as argument: </p> <codeblock id="GUID-73C0C08A-6BAC-5526-A987-57079ED762E7-GENID-1-7-1-14-1-1-7-1-7-1-11-1-7-1-5-1-9-1-3-5-9" xml:space="preserve">TInt Kern::DynamicDfcQCreate(TDynamicDfcQue*& aDfcQ, TInt aPriority, const TDesC& aBaseName);</codeblock> <p>To service a dynamically loaded driver derived from <xref href="GUID-A3CC1D95-4681-3349-A67C-F113A614041D.dita"><apiname>DLogicalChannel</apiname></xref>,
-you use the DFC queue supplied with it (the member <xref href="GUID-954F5891-8BF3-33B2-9F40-9D80A6D2A17C.dita"><apiname>iDfc</apiname></xref>,
-accessed by pointer). To use the queue you call the <xref href="GUID-2FC8CE8F-102C-3025-86B6-C903D26CD002.dita"><apiname>SetDfcQ()</apiname></xref> function
-during the second phase construction of the LDD. </p> <p>You destroy queues
-by calling their function <xref href="GUID-38F49D2C-2798-37DB-82CC-A49EAB22B829.dita"><apiname>Destroy()</apiname></xref> which also terminates
-the associated thread. </p> <p><b>Setting
-realtime state</b> </p> <p>The realtime state of a thread determines whether
-it is enabled to access paged memory. If a thread is realtime (its realtime
-state is on) it is guaranteed not to access paged memory, so avoiding unpredictable
-delays. The realtime state of a thread may be set to <xref href="GUID-0AD1C6D1-591E-3ED2-A4AA-2486A37AE5CE.dita"><apiname>ERealtimeStateOn</apiname></xref>, <xref href="GUID-19425C4A-0B5F-3D89-B5C9-C5DB7E984D7F.dita"><apiname>ERealtimeStateOff</apiname></xref> and <xref href="GUID-2AB828E6-39A5-377C-87B1-FA0CB886E2D7.dita"><apiname>ERealtimeStateWarn</apiname></xref> as defined in the enumeration <xref href="GUID-C9606015-7E55-338D-BE81-42AF50980F59.dita"><apiname>TThreadRealtimeState</apiname></xref> and
-set by the kernel function <xref href="GUID-802BE082-128E-3F1E-A8D5-304DCDABFCC8.dita"><apiname>SetRealtimeState</apiname></xref>. </p> <p>If
-a driver uses DFC threads and is subject to performance guarantees, their
-realtime state should be set to on (this is the default when data paging is
-enabled). Otherwise the state should be set to off: the warning state is used
-for debugging. </p> <p><b>Validating
-arguments in client context</b> </p> <p>It is often necessary to validate
-the arguments of a request function. This should be done in the context of
-the client thread as far as possible. </p> <p>When a driver derived from the
-class <xref href="GUID-E7550422-5121-3393-A85E-BB797969CD2A.dita"><apiname>DLogicalChannelBase</apiname></xref> makes a request this happens
-automatically as a call to the <xref href="GUID-92AA62BB-14F1-325D-9A22-9C87AAE0535C.dita"><apiname>Request()</apiname></xref> function takes
-place in the client thread. When the driver is derived from the class <xref href="GUID-A3CC1D95-4681-3349-A67C-F113A614041D.dita"><apiname>DLogicalChannel</apiname></xref> the
-request involves a call to the <xref href="GUID-E31B440A-A98E-30DA-B222-C8BA59A81A0E.dita"><apiname>SendMsg()</apiname></xref> function inherited
-from the base class and it is necessary to override the base implementation
-to force evaluation of the arguments within the client thread. </p> <p><b>Accessing user memory from client context</b> </p> <p>The DFC should access
-user memory as little as possible. Whenever there is a need to access user
-memory and it can be accessed in the context of the client thread, it should
-be. </p> <p>When the driver is derived from the class <xref href="GUID-E7550422-5121-3393-A85E-BB797969CD2A.dita"><apiname>DLogicalChannelBase</apiname></xref>,
-read and write operations on user memory can be performed with calls to the <xref href="GUID-92AA62BB-14F1-325D-9A22-9C87AAE0535C.dita"><apiname>Request()</apiname></xref> function
-and these take place in the context of the client thread. </p> <p>When the
-driver is derived from the class <xref href="GUID-A3CC1D95-4681-3349-A67C-F113A614041D.dita"><apiname>DLogicalChannel</apiname></xref> it is
-possible to read from and write to user memory by overriding the <xref href="GUID-E31B440A-A98E-30DA-B222-C8BA59A81A0E.dita"><apiname>SendMsg()</apiname></xref> function
-before passing the message on to be processed by the DFC thread if necessary.
-If the message is passed on, data must be stored kernel side either on the
-client thread's kernel stack or in the channel object. </p> <p>Message data
-can only be stored on the client thread's kernel stack if the message is synchronous
-and the size of the data is less than 4Kb. Since the stack is local to the
-client it can be used by more than one thread. One way of doing this is to
-implement <xref href="GUID-E31B440A-A98E-30DA-B222-C8BA59A81A0E.dita"><apiname>SendMsg()</apiname></xref> with a call to <xref href="GUID-4DF8919A-CAA2-36D5-B91B-E26D2A32F5F5.dita"><apiname>SendControl()</apiname></xref> which
-is itself implemented to perform the copying in the client thread context
-and independently call the <xref href="GUID-E31B440A-A98E-30DA-B222-C8BA59A81A0E.dita"><apiname>SendMsg()</apiname></xref> function of the parent
-class. </p> <p>Where the message is asynchronous you can use a similar strategy
-for overriding the <xref href="GUID-E31B440A-A98E-30DA-B222-C8BA59A81A0E.dita"><apiname>SendMsg()</apiname></xref> function but this time perform
-the copying to a buffer owned by the channel independently of a call to the <xref href="GUID-E31B440A-A98E-30DA-B222-C8BA59A81A0E.dita"><apiname>SendMsg()</apiname></xref> function
-of the parent class. In this case the size of the data must be small (in the
-region of 4Kb), there must be only one client using the buffer, and data cannot
-be written back to the client. </p> <p><b>Using
-TClientDataRequest</b> </p> <p>An asynchronous request often needs to copy
-a structure of fixed size to its client to complete a request. The <xref href="GUID-918410AB-63D3-3672-82BE-73289F88C03E.dita"><apiname>TClientDataRequest</apiname></xref> object
-exists for this purpose: it writes a fixed size structure to user memory and
-completes the request in the following steps. </p> <ol id="GUID-100FA302-3292-565D-A0BC-A7314C2E2499-GENID-1-7-1-14-1-1-7-1-7-1-11-1-7-1-5-1-9-1-3-5-26">
-<li id="GUID-41BF301F-9FC7-55F8-9346-42262F49B5EE-GENID-1-7-1-14-1-1-7-1-7-1-11-1-7-1-5-1-9-1-3-5-26-1"><p>The driver creates a <xref href="GUID-918410AB-63D3-3672-82BE-73289F88C03E.dita"><apiname>TClientDataRequest</apiname></xref> object
-for each asynchronous client which may be outstanding concurrently: either
-one per client or one per request as appropriate. </p> </li>
-<li id="GUID-D4322A3D-C2F7-52D2-B600-35A65EF460CD-GENID-1-7-1-14-1-1-7-1-7-1-11-1-7-1-5-1-9-1-3-5-26-2"><p>When the client makes
-a request the <xref href="GUID-918410AB-63D3-3672-82BE-73289F88C03E.dita"><apiname>TClientDataRequest</apiname></xref> object is set to contain
-the address of the client's buffer or descriptor and the address of the client's <xref href="GUID-E0B34F3E-D4C4-3232-B8B1-7DB35B454646.dita"><apiname>TRequestStatus</apiname></xref>.
-This takes place in the client context. </p> </li>
-<li id="GUID-6FBED29F-E54D-5C5C-A6E5-8DBA41625338-GENID-1-7-1-14-1-1-7-1-7-1-11-1-7-1-5-1-9-1-3-5-26-3"><p>The data to be written
-is copied into the buffer of the <xref href="GUID-918410AB-63D3-3672-82BE-73289F88C03E.dita"><apiname>TClientDataRequest</apiname></xref> object. </p> </li>
-<li id="GUID-3316EB6E-804D-5CBC-8930-68D8E226C955-GENID-1-7-1-14-1-1-7-1-7-1-11-1-7-1-5-1-9-1-3-5-26-4"><p>A call to <xref href="GUID-C6946ECB-775F-3EC2-A56F-78F25B9FBE3D.dita#GUID-C6946ECB-775F-3EC2-A56F-78F25B9FBE3D/GUID-DE0CF5BD-B166-3C5B-9E27-F95710322F21"><apiname>Kern::QueueRequestComplete()</apiname></xref> passes
-the address of the <xref href="GUID-918410AB-63D3-3672-82BE-73289F88C03E.dita"><apiname>TClientDataRequest</apiname></xref> object. </p> </li>
-<li id="GUID-39DE78F0-D6E0-582B-B3F1-3AEC6D0E12CE-GENID-1-7-1-14-1-1-7-1-7-1-11-1-7-1-5-1-9-1-3-5-26-5"><p>The client is signalled
-immediately. </p> </li>
-<li id="GUID-5FF0CD64-F05D-5DF2-BD96-6B5966119CA8-GENID-1-7-1-14-1-1-7-1-7-1-11-1-7-1-5-1-9-1-3-5-26-6"><p>When the client thread
-next runs, the buffer contents and completion value are written to the client. </p> </li>
-</ol> <p><b>Using
-TClientBufferRequest</b> </p> <p>When it is necessary to access user memory
-from a DFC thread context, that memory must be pinned for the duration of
-the request and unpinned when the request is completed. The pinning must be
-performed in the context of the client thread. The <xref href="GUID-5CD6D111-213B-31A2-AA46-C5598DDB7249.dita"><apiname>TClientBufferRequest</apiname></xref> object
-exists for this purpose.It is used in the following way. </p> <ol id="GUID-3FEB8983-0BF6-578D-856A-09433AD7182E-GENID-1-7-1-14-1-1-7-1-7-1-11-1-7-1-5-1-9-1-3-5-29">
-<li id="GUID-4C3FB914-624A-50FE-94E0-EFF85D6169F8-GENID-1-7-1-14-1-1-7-1-7-1-11-1-7-1-5-1-9-1-3-5-29-1"><p>The driver creates a <xref href="GUID-5CD6D111-213B-31A2-AA46-C5598DDB7249.dita"><apiname>TClientBufferRequest</apiname></xref> object
-for each client request which may be outstanding concurrently: either one
-per client or one per request as appropriate. </p> </li>
-<li id="GUID-CAD03D3A-19E6-5C3D-A203-1726917A50B2-GENID-1-7-1-14-1-1-7-1-7-1-11-1-7-1-5-1-9-1-3-5-29-2"><p>Whe a client makes a
-request, the <xref href="GUID-5CD6D111-213B-31A2-AA46-C5598DDB7249.dita"><apiname>TClientBufferRequest</apiname></xref> object is set to contain
-the address of any buffers used and the address of the client's <xref href="GUID-E0B34F3E-D4C4-3232-B8B1-7DB35B454646.dita"><apiname>TRequestStatus</apiname></xref>.
-Doing so pins the contents of the buffers: they can be specified as descriptors
-or by start address and length. This takes place in the client context. </p> </li>
-<li id="GUID-8493130F-9E96-580F-B509-5EB5B69852A0-GENID-1-7-1-14-1-1-7-1-7-1-11-1-7-1-5-1-9-1-3-5-29-3"><p>The driver calls <xref href="GUID-C6946ECB-775F-3EC2-A56F-78F25B9FBE3D.dita#GUID-C6946ECB-775F-3EC2-A56F-78F25B9FBE3D/GUID-A33C039B-981C-3234-A414-95487D4103A9"><apiname>Kern::ThreadBufRead()</apiname></xref> and <xref href="GUID-C6946ECB-775F-3EC2-A56F-78F25B9FBE3D.dita#GUID-C6946ECB-775F-3EC2-A56F-78F25B9FBE3D/GUID-0C62AA11-87B4-307A-B63E-08A6842C7283"><apiname>Kern::ThreadBufWrite()</apiname></xref> to access the client's buffers. This takes place in the context of the DFC. </p> </li>
-<li id="GUID-5C63E867-025B-5F67-90CE-CE960DC254BB-GENID-1-7-1-14-1-1-7-1-7-1-11-1-7-1-5-1-9-1-3-5-29-4"><p>When the request is
-complete, the driver calls <xref href="GUID-C6946ECB-775F-3EC2-A56F-78F25B9FBE3D.dita#GUID-C6946ECB-775F-3EC2-A56F-78F25B9FBE3D/GUID-ECE11E29-0831-3271-AFAA-88DAE4131BE1"><apiname>Kern::QueueBufferRequestComplete()</apiname></xref> passing
-the <xref href="GUID-5CD6D111-213B-31A2-AA46-C5598DDB7249.dita"><apiname>TClientBufferRequest</apiname></xref> object. This signals the client
-immediately and unpins the buffers. </p> </li>
-<li id="GUID-474B2BBE-F24E-5DB3-B83F-CDA95DDE0C3E-GENID-1-7-1-14-1-1-7-1-7-1-11-1-7-1-5-1-9-1-3-5-29-5"><p>When the client thread
-next runs, the completion value is written back to the client along with the
-updated length of any descriptors. </p> </li>
-</ol> <p><b>Using
-Kern::RequestComplete()</b> </p> <p>The function <xref href="GUID-C6946ECB-775F-3EC2-A56F-78F25B9FBE3D.dita#GUID-C6946ECB-775F-3EC2-A56F-78F25B9FBE3D/GUID-D720BB4C-5E31-3213-BB16-859AA325FE98"><apiname>Kern::RequestComplete()</apiname></xref> exists
-in two versions: </p> <codeblock id="GUID-11FEEAC7-3223-5B27-9FA2-0C71F5F55E8C-GENID-1-7-1-14-1-1-7-1-7-1-11-1-7-1-5-1-9-1-3-5-32" xml:space="preserve">static void Kern::RequestComplete(DThread* aThread, TRequestStatus*& aStatus, TInt aReason);</codeblock> <p>which is now deprecated, and its overloaded replacement </p> <codeblock id="GUID-AAAAF661-3C0F-5048-8AD2-16C085A65387-GENID-1-7-1-14-1-1-7-1-7-1-11-1-7-1-5-1-9-1-3-5-34" xml:space="preserve">static void Kern::RequestComplete(TRequestStatus*& aStatus, TInt aReason);</codeblock> <p>The
-overloaded version should always be used, as it does not take a thread pointer
-argument. </p> <p><b>Using
-shared chunks</b> </p> <p>Shared chunks are a mechanism by which kernel side
-code shares buffers with user side code. As an alternative to pinning memory
-they have the following advantages: </p> <ul>
-<li id="GUID-65C6ECA6-A89B-5303-B674-E90AA805841A-GENID-1-7-1-14-1-1-7-1-7-1-11-1-7-1-5-1-9-1-3-5-38-1"><p>Shared chunks cannot
-be paged and therefore paging faults never arise. </p> </li>
-<li id="GUID-D7B96CD0-725F-5FCB-A30A-6FFF55ADC439-GENID-1-7-1-14-1-1-7-1-7-1-11-1-7-1-5-1-9-1-3-5-38-2"><p>Shared chunks transfer
-data with a minimum number of copying operations and are useful where high
-speeds and large volumes are required. </p> </li>
-</ul> <p>Shared chunks present disadvantages when a driver is being migrated
-rather than written from scratch, as the client API must be rewritten as well
-as the driver code. </p> </section>
-<section id="GUID-143D7A45-D119-4AEF-8941-116C2567514F-GENID-1-7-1-14-1-1-7-1-7-1-11-1-7-1-5-1-9-1-3-6"><title>See Also</title> <p> <xref href="GUID-91C11D80-7A62-5135-8EE0-6EC5576D1118.dita">Demand
-Paged Device Drivers Overview</xref> </p> <p> <xref href="GUID-85C18DAF-DB76-51C6-B38D-A802E314F4D1.dita">Performance
-Guarantee Tutorial</xref> </p> </section>
+<?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-E7C55048-5B7A-5BF2-B7F4-4D731659B88C-GENID-1-7-1-14-1-1-7-1-7-1-11-1-7-1-5-1-9-1" xml:lang="en"><title>Device
+Driver Writing and Migration Technology Tutorial</title><shortdesc>Explains techniques for writing device drivers on data paged systems
+and migrating device drivers to data paged systems. </shortdesc><prolog><metadata><keywords/></metadata></prolog><conbody>
+<section id="GUID-8629C08B-C1C8-4435-962A-A57F11EB25CF-GENID-1-7-1-14-1-1-7-1-7-1-11-1-7-1-5-1-9-1-3-1"><title>Impact of data paging on kernel APIs</title> <p>The use of
+data paging impacts on the task of writing and migrating device drivers in
+two main ways: the preconditions for kernel API calls and the performance
+of the kernel APIs. </p> <p>Firstly, kernel APIs which access user memory
+may only be called subject to preconditions. The preconditions are that </p> <ul>
+<li id="GUID-81B56316-97C6-5EE8-BD88-D0741F9301F9-GENID-1-7-1-14-1-1-7-1-7-1-11-1-7-1-5-1-9-1-3-1-4-1"><p>no fast mutex may be
+held while calling them, and </p> </li>
+<li id="GUID-507412E1-1CA8-5590-B974-809B51C3D79D-GENID-1-7-1-14-1-1-7-1-7-1-11-1-7-1-5-1-9-1-3-1-4-2"><p>no kernel mutex may
+be held while calling them. </p> </li>
+</ul> <p>The APIs are these: </p> <ul>
+<li id="GUID-7A4E9152-8BFA-515E-A115-265436C843F4-GENID-1-7-1-14-1-1-7-1-7-1-11-1-7-1-5-1-9-1-3-1-6-1"><p> <xref href="GUID-C6946ECB-775F-3EC2-A56F-78F25B9FBE3D.dita#GUID-C6946ECB-775F-3EC2-A56F-78F25B9FBE3D/GUID-C154A151-0DF7-345D-9A10-E9B1CF3400D9"><apiname>Kern::KUDesInfo</apiname></xref> </p> </li>
+<li id="GUID-3C31D5D3-48E9-5D6D-8489-8259D98BF117-GENID-1-7-1-14-1-1-7-1-7-1-11-1-7-1-5-1-9-1-3-1-6-2"><p> <xref href="GUID-C6946ECB-775F-3EC2-A56F-78F25B9FBE3D.dita#GUID-C6946ECB-775F-3EC2-A56F-78F25B9FBE3D/GUID-FAFAA120-AA28-32FD-9202-1534C3148026"><apiname>Kern::InfoCopy</apiname></xref> </p> </li>
+<li id="GUID-FCE0C3D6-EE49-5AC9-856E-9833D22D541A-GENID-1-7-1-14-1-1-7-1-7-1-11-1-7-1-5-1-9-1-3-1-6-3"><p> <xref href="GUID-C6946ECB-775F-3EC2-A56F-78F25B9FBE3D.dita#GUID-C6946ECB-775F-3EC2-A56F-78F25B9FBE3D/GUID-B79007D0-FF1F-30E7-986D-7CEBC5E45102"><apiname>Kern::KUDesGet</apiname></xref> </p> </li>
+<li id="GUID-72D4E609-B189-570A-B4D6-D2F4F1289EC1-GENID-1-7-1-14-1-1-7-1-7-1-11-1-7-1-5-1-9-1-3-1-6-4"><p> <xref href="GUID-C6946ECB-775F-3EC2-A56F-78F25B9FBE3D.dita#GUID-C6946ECB-775F-3EC2-A56F-78F25B9FBE3D/GUID-CDEA7B22-9520-3DB1-AA04-1289C2287936"><apiname>Kern::KUDesPut</apiname></xref> </p> </li>
+<li id="GUID-EE2D8F45-5B12-5D69-A9FD-7ED47A0B5EAD-GENID-1-7-1-14-1-1-7-1-7-1-11-1-7-1-5-1-9-1-3-1-6-5"><p> <xref href="GUID-C6946ECB-775F-3EC2-A56F-78F25B9FBE3D.dita#GUID-C6946ECB-775F-3EC2-A56F-78F25B9FBE3D/GUID-94F2DF65-87A5-32C6-9695-9557E5832ACF"><apiname>Kern::KUDesSetLength</apiname></xref> </p> </li>
+<li id="GUID-46805316-D1D5-5477-8287-FBF43DD8D3C4-GENID-1-7-1-14-1-1-7-1-7-1-11-1-7-1-5-1-9-1-3-1-6-6"><p> <xref href="GUID-EE4CB2B4-EAFC-3721-BF0D-ECDF96C29FBF.dita"><apiname>umemget</apiname></xref>, <xref href="GUID-E569834D-8960-3D4E-8980-64902200D4F8.dita"><apiname>kumemget</apiname></xref>, <xref href="GUID-388FF557-3092-3EA0-BF4A-D73504521CD0.dita"><apiname>umemget32</apiname></xref>, <xref href="GUID-874BB607-F0CA-3123-AB2D-D04F4763B16A.dita"><apiname>kumemget32</apiname></xref> </p> </li>
+<li id="GUID-DB8BF5C7-2444-5B8F-8F66-12383ECB6A81-GENID-1-7-1-14-1-1-7-1-7-1-11-1-7-1-5-1-9-1-3-1-6-7"><p> <xref href="GUID-71B53E34-1F41-3B53-8133-D76D8847D143.dita"><apiname>umemput</apiname></xref>, <xref href="GUID-7B0CC157-0EF6-3CF5-BAF2-D8227F7734A5.dita"><apiname>kumemput</apiname></xref>, <xref href="GUID-A6303814-456F-3583-86B0-A99EA5C3E5A4.dita"><apiname>umemput32</apiname></xref>, <xref href="GUID-B00A6392-9A90-357E-B6A2-D2762800C2C5.dita"><apiname>kumemput32</apiname></xref> </p> </li>
+<li id="GUID-9E6B180A-B360-58A6-B60E-8605E22F2C2E-GENID-1-7-1-14-1-1-7-1-7-1-11-1-7-1-5-1-9-1-3-1-6-8"><p> <xref href="GUID-BBF5941C-3369-3B56-A560-6E80A7CFFE0F.dita"><apiname>umemset</apiname></xref>, <xref href="GUID-08C2BCA6-6842-3D10-AB56-835B618317F9.dita"><apiname>kumemset</apiname></xref>, <xref href="GUID-B48B5214-ACDD-3E9B-AE07-1B40F645D959.dita"><apiname>umemset32</apiname></xref>, <xref href="GUID-5C1EB135-F9A7-37A5-B256-299CB9598DA9.dita"><apiname>kumemset32</apiname></xref> </p> </li>
+<li id="GUID-F307081B-7672-5C3F-869C-9B4B4F55CE62-GENID-1-7-1-14-1-1-7-1-7-1-11-1-7-1-5-1-9-1-3-1-6-9"><p> <xref href="GUID-C6946ECB-775F-3EC2-A56F-78F25B9FBE3D.dita#GUID-C6946ECB-775F-3EC2-A56F-78F25B9FBE3D/GUID-D0FCFD5B-2814-3D81-A54A-9E2FA226019B"><apiname>Kern::RequestComplete</apiname></xref> </p> </li>
+<li id="GUID-647B36DF-2124-5252-824E-E100695624C2-GENID-1-7-1-14-1-1-7-1-7-1-11-1-7-1-5-1-9-1-3-1-6-10"><p> <xref href="GUID-C6946ECB-775F-3EC2-A56F-78F25B9FBE3D.dita#GUID-C6946ECB-775F-3EC2-A56F-78F25B9FBE3D/GUID-589188FC-48E8-3973-B88B-D9E47CFE4403"><apiname>Kern::ThreadRawRead</apiname></xref> </p> </li>
+<li id="GUID-9776CFD1-B061-5FC1-B100-0A55D7E8BFA5-GENID-1-7-1-14-1-1-7-1-7-1-11-1-7-1-5-1-9-1-3-1-6-11"><p> <xref href="GUID-C6946ECB-775F-3EC2-A56F-78F25B9FBE3D.dita#GUID-C6946ECB-775F-3EC2-A56F-78F25B9FBE3D/GUID-68BFCE22-E05E-3710-9014-6E72FDE7891F"><apiname>Kern::ThreadRawWrite</apiname></xref> </p> </li>
+<li id="GUID-21F695FF-8933-5FF4-84DC-1F09056E36A6-GENID-1-7-1-14-1-1-7-1-7-1-11-1-7-1-5-1-9-1-3-1-6-12"><p> <xref href="GUID-C6946ECB-775F-3EC2-A56F-78F25B9FBE3D.dita#GUID-C6946ECB-775F-3EC2-A56F-78F25B9FBE3D/GUID-451FD979-14A8-3301-A389-7B509C969FE9"><apiname>Kern::ThreadDesRead</apiname></xref> </p> </li>
+<li id="GUID-B477D969-B73E-514B-8E40-565EE6C4490E-GENID-1-7-1-14-1-1-7-1-7-1-11-1-7-1-5-1-9-1-3-1-6-13"><p> <xref href="GUID-C6946ECB-775F-3EC2-A56F-78F25B9FBE3D.dita#GUID-C6946ECB-775F-3EC2-A56F-78F25B9FBE3D/GUID-B4A7AF78-179A-378B-9184-CCC2E31830F5"><apiname>Kern::ThreadDesWrite</apiname></xref> </p> </li>
+<li id="GUID-C8080F75-2F3B-5DBE-B0DE-D8518ED49516-GENID-1-7-1-14-1-1-7-1-7-1-11-1-7-1-5-1-9-1-3-1-6-14"><p> <xref href="GUID-C6946ECB-775F-3EC2-A56F-78F25B9FBE3D.dita#GUID-C6946ECB-775F-3EC2-A56F-78F25B9FBE3D/GUID-6668EA8F-AA55-3CB4-ADEA-879579E94729"><apiname>Kern::ThreadGetDesLength</apiname></xref> </p> </li>
+<li id="GUID-8D644BB0-9A01-5248-8DD2-95CDAE058B09-GENID-1-7-1-14-1-1-7-1-7-1-11-1-7-1-5-1-9-1-3-1-6-15"><p> <xref href="GUID-C6946ECB-775F-3EC2-A56F-78F25B9FBE3D.dita#GUID-C6946ECB-775F-3EC2-A56F-78F25B9FBE3D/GUID-53813A59-7CED-39E2-818A-D9E0374D2BFD"><apiname>Kern::ThreadGetDesMaxLength</apiname></xref> </p> </li>
+<li id="GUID-746E54A0-C6D0-5B90-89F3-D197DD04470C-GENID-1-7-1-14-1-1-7-1-7-1-11-1-7-1-5-1-9-1-3-1-6-16"><p> <xref href="GUID-C6946ECB-775F-3EC2-A56F-78F25B9FBE3D.dita#GUID-C6946ECB-775F-3EC2-A56F-78F25B9FBE3D/GUID-60E5E01D-2965-3E33-BC05-052A575303F8"><apiname>Kern::ThreadGetDesInfo</apiname></xref> </p> </li>
+</ul> </section>
+<section id="GUID-8C767668-D568-40E4-82F7-DD6FC6EA8132-GENID-1-7-1-14-1-1-7-1-7-1-11-1-7-1-5-1-9-1-3-2"><title>Impact of data paging on execution</title> <p>Device drivers
+use kernel side APIs to access user memory, and even when they are called
+in accordance with their preconditions they are no longer guaranteed to execute
+in a short and bounded time. This is because they may access paged memory
+and incur page faults which propagate from one thread to another. This document
+discusses how to mitigate the impact of data paging on device drivers. </p> </section>
+<section id="GUID-3903425C-EA48-44D6-B65E-253F583465BF-GENID-1-7-1-14-1-1-7-1-7-1-11-1-7-1-5-1-9-1-3-3"><title>Mitigating data paging: general principles</title> <p>Three
+general principles are involved in mitigating the impact of data paging on
+device drivers. </p> <ul>
+<li id="GUID-955ACDFA-CA71-5489-920F-B2F74039EA37-GENID-1-7-1-14-1-1-7-1-7-1-11-1-7-1-5-1-9-1-3-3-3-1"><p>Device drivers should
+not use shared DFC queues. </p> </li>
+<li id="GUID-3FD4823A-C1A0-53B2-8987-45313BC984C3-GENID-1-7-1-14-1-1-7-1-7-1-11-1-7-1-5-1-9-1-3-3-3-2"><p>Device drivers should,
+as far as possible, not access paged memory. </p> </li>
+<li id="GUID-3557B245-D479-5FA3-B039-092A8F1B7E06-GENID-1-7-1-14-1-1-7-1-7-1-11-1-7-1-5-1-9-1-3-3-3-3"><p>If a device driver needs
+to access paged memory, it should do so in the context of the client thread. </p> </li>
+</ul> </section>
+<section id="GUID-BE00235A-D227-4290-B3FA-93B20966073F-GENID-1-7-1-14-1-1-7-1-7-1-11-1-7-1-5-1-9-1-3-4"><title>Driver frameworks</title> <p>There are three main categories
+of device driver: </p> <ul>
+<li id="GUID-EAD164EF-A615-5AFE-A512-032C1C0CC0AC-GENID-1-7-1-14-1-1-7-1-7-1-11-1-7-1-5-1-9-1-3-4-3-1"><p>boot-loaded non-channel
+drivers, </p> </li>
+<li id="GUID-B82465B7-6306-5AAC-B6B4-FB5A4D07EBB2-GENID-1-7-1-14-1-1-7-1-7-1-11-1-7-1-5-1-9-1-3-4-3-2"><p>media drivers, and </p> </li>
+<li id="GUID-86AB0CC9-B147-5019-837C-B2A6B32A9F6B-GENID-1-7-1-14-1-1-7-1-7-1-11-1-7-1-5-1-9-1-3-4-3-3"><p>dynamically loaded,
+channel-based IO device drivers </p> </li>
+</ul> <p>The document <xref href="GUID-91C11D80-7A62-5135-8EE0-6EC5576D1118.dita">Demand
+Paged Device Drivers Writing Guide</xref> discusses these three frameworks
+and identifies areas where they are vulnerable to the impact of data paging. </p> </section>
+<section id="GUID-6CD39776-B448-4F7D-8EC2-727AF13B575B-GENID-1-7-1-14-1-1-7-1-7-1-11-1-7-1-5-1-9-1-3-5"><title>Mitigation techniques</title> <p>The impact of data paging
+on device drivers is mitigated by the use of various different techniques
+which are the subject of the rest of this document. </p> <p><b>Passing
+data by value</b> </p> <p>Clients should pass data by value not as pointers.
+Return values of calls should be return codes not data. </p> <p><b>Using dedicated DFC queues</b> </p> <p>All drivers which use DFCs should
+use a dedicated DFC queue to service them. You should not use the kernel queues <xref href="GUID-C6946ECB-775F-3EC2-A56F-78F25B9FBE3D.dita#GUID-C6946ECB-775F-3EC2-A56F-78F25B9FBE3D/GUID-96588DB1-6884-300F-A85B-EA14A8A1BFAD"><apiname>Kern::DfcQue0</apiname></xref> and <xref href="GUID-C6946ECB-775F-3EC2-A56F-78F25B9FBE3D.dita#GUID-C6946ECB-775F-3EC2-A56F-78F25B9FBE3D/GUID-7B1F53D8-7EC2-3A05-9F1B-240550A7283B"><apiname>Kern::DfcQue1</apiname></xref> for this purpose. How you create a dedicated DFC queue depends on the nature
+of the driver. </p> <p>To service boot loaded drivers and media drivers, you
+create a DFC queue by calling <xref href="GUID-C6946ECB-775F-3EC2-A56F-78F25B9FBE3D.dita#GUID-C6946ECB-775F-3EC2-A56F-78F25B9FBE3D/GUID-F8D26F25-FBFB-3D89-9A80-95719D165C8E"><apiname>Kern::DfcQueueCreate()</apiname></xref>. </p> <p>To
+service dynamically loaded drivers derived from DLogicalChannelBase you call <xref href="GUID-C6946ECB-775F-3EC2-A56F-78F25B9FBE3D.dita#GUID-C6946ECB-775F-3EC2-A56F-78F25B9FBE3D/GUID-ED1B8C3D-ABFB-37BD-A6E9-4080FCCE115C"><apiname>Kern::DynamicDfcQCreate()</apiname></xref> with
+a <xref href="GUID-D9111A26-FAA3-3D8E-AB41-5B1263FABB6A.dita"><apiname>TDynamicDfcQue</apiname></xref> as argument: </p> <codeblock id="GUID-73C0C08A-6BAC-5526-A987-57079ED762E7-GENID-1-7-1-14-1-1-7-1-7-1-11-1-7-1-5-1-9-1-3-5-9" xml:space="preserve">TInt Kern::DynamicDfcQCreate(TDynamicDfcQue*& aDfcQ, TInt aPriority, const TDesC& aBaseName);</codeblock> <p>To service a dynamically loaded driver derived from <xref href="GUID-A3CC1D95-4681-3349-A67C-F113A614041D.dita"><apiname>DLogicalChannel</apiname></xref>,
+you use the DFC queue supplied with it (the member <xref href="GUID-954F5891-8BF3-33B2-9F40-9D80A6D2A17C.dita"><apiname>iDfc</apiname></xref>,
+accessed by pointer). To use the queue you call the <xref href="GUID-2FC8CE8F-102C-3025-86B6-C903D26CD002.dita"><apiname>SetDfcQ()</apiname></xref> function
+during the second phase construction of the LDD. </p> <p>You destroy queues
+by calling their function <xref href="GUID-38F49D2C-2798-37DB-82CC-A49EAB22B829.dita"><apiname>Destroy()</apiname></xref> which also terminates
+the associated thread. </p> <p><b>Setting
+realtime state</b> </p> <p>The realtime state of a thread determines whether
+it is enabled to access paged memory. If a thread is realtime (its realtime
+state is on) it is guaranteed not to access paged memory, so avoiding unpredictable
+delays. The realtime state of a thread may be set to <xref href="GUID-0AD1C6D1-591E-3ED2-A4AA-2486A37AE5CE.dita"><apiname>ERealtimeStateOn</apiname></xref>, <xref href="GUID-19425C4A-0B5F-3D89-B5C9-C5DB7E984D7F.dita"><apiname>ERealtimeStateOff</apiname></xref> and <xref href="GUID-2AB828E6-39A5-377C-87B1-FA0CB886E2D7.dita"><apiname>ERealtimeStateWarn</apiname></xref> as defined in the enumeration <xref href="GUID-C9606015-7E55-338D-BE81-42AF50980F59.dita"><apiname>TThreadRealtimeState</apiname></xref> and
+set by the kernel function <xref href="GUID-802BE082-128E-3F1E-A8D5-304DCDABFCC8.dita"><apiname>SetRealtimeState</apiname></xref>. </p> <p>If
+a driver uses DFC threads and is subject to performance guarantees, their
+realtime state should be set to on (this is the default when data paging is
+enabled). Otherwise the state should be set to off: the warning state is used
+for debugging. </p> <p><b>Validating
+arguments in client context</b> </p> <p>It is often necessary to validate
+the arguments of a request function. This should be done in the context of
+the client thread as far as possible. </p> <p>When a driver derived from the
+class <xref href="GUID-E7550422-5121-3393-A85E-BB797969CD2A.dita"><apiname>DLogicalChannelBase</apiname></xref> makes a request this happens
+automatically as a call to the <xref href="GUID-92AA62BB-14F1-325D-9A22-9C87AAE0535C.dita"><apiname>Request()</apiname></xref> function takes
+place in the client thread. When the driver is derived from the class <xref href="GUID-A3CC1D95-4681-3349-A67C-F113A614041D.dita"><apiname>DLogicalChannel</apiname></xref> the
+request involves a call to the <xref href="GUID-E31B440A-A98E-30DA-B222-C8BA59A81A0E.dita"><apiname>SendMsg()</apiname></xref> function inherited
+from the base class and it is necessary to override the base implementation
+to force evaluation of the arguments within the client thread. </p> <p><b>Accessing user memory from client context</b> </p> <p>The DFC should access
+user memory as little as possible. Whenever there is a need to access user
+memory and it can be accessed in the context of the client thread, it should
+be. </p> <p>When the driver is derived from the class <xref href="GUID-E7550422-5121-3393-A85E-BB797969CD2A.dita"><apiname>DLogicalChannelBase</apiname></xref>,
+read and write operations on user memory can be performed with calls to the <xref href="GUID-92AA62BB-14F1-325D-9A22-9C87AAE0535C.dita"><apiname>Request()</apiname></xref> function
+and these take place in the context of the client thread. </p> <p>When the
+driver is derived from the class <xref href="GUID-A3CC1D95-4681-3349-A67C-F113A614041D.dita"><apiname>DLogicalChannel</apiname></xref> it is
+possible to read from and write to user memory by overriding the <xref href="GUID-E31B440A-A98E-30DA-B222-C8BA59A81A0E.dita"><apiname>SendMsg()</apiname></xref> function
+before passing the message on to be processed by the DFC thread if necessary.
+If the message is passed on, data must be stored kernel side either on the
+client thread's kernel stack or in the channel object. </p> <p>Message data
+can only be stored on the client thread's kernel stack if the message is synchronous
+and the size of the data is less than 4Kb. Since the stack is local to the
+client it can be used by more than one thread. One way of doing this is to
+implement <xref href="GUID-E31B440A-A98E-30DA-B222-C8BA59A81A0E.dita"><apiname>SendMsg()</apiname></xref> with a call to <xref href="GUID-4DF8919A-CAA2-36D5-B91B-E26D2A32F5F5.dita"><apiname>SendControl()</apiname></xref> which
+is itself implemented to perform the copying in the client thread context
+and independently call the <xref href="GUID-E31B440A-A98E-30DA-B222-C8BA59A81A0E.dita"><apiname>SendMsg()</apiname></xref> function of the parent
+class. </p> <p>Where the message is asynchronous you can use a similar strategy
+for overriding the <xref href="GUID-E31B440A-A98E-30DA-B222-C8BA59A81A0E.dita"><apiname>SendMsg()</apiname></xref> function but this time perform
+the copying to a buffer owned by the channel independently of a call to the <xref href="GUID-E31B440A-A98E-30DA-B222-C8BA59A81A0E.dita"><apiname>SendMsg()</apiname></xref> function
+of the parent class. In this case the size of the data must be small (in the
+region of 4Kb), there must be only one client using the buffer, and data cannot
+be written back to the client. </p> <p><b>Using
+TClientDataRequest</b> </p> <p>An asynchronous request often needs to copy
+a structure of fixed size to its client to complete a request. The <xref href="GUID-918410AB-63D3-3672-82BE-73289F88C03E.dita"><apiname>TClientDataRequest</apiname></xref> object
+exists for this purpose: it writes a fixed size structure to user memory and
+completes the request in the following steps. </p> <ol id="GUID-100FA302-3292-565D-A0BC-A7314C2E2499-GENID-1-7-1-14-1-1-7-1-7-1-11-1-7-1-5-1-9-1-3-5-26">
+<li id="GUID-41BF301F-9FC7-55F8-9346-42262F49B5EE-GENID-1-7-1-14-1-1-7-1-7-1-11-1-7-1-5-1-9-1-3-5-26-1"><p>The driver creates a <xref href="GUID-918410AB-63D3-3672-82BE-73289F88C03E.dita"><apiname>TClientDataRequest</apiname></xref> object
+for each asynchronous client which may be outstanding concurrently: either
+one per client or one per request as appropriate. </p> </li>
+<li id="GUID-D4322A3D-C2F7-52D2-B600-35A65EF460CD-GENID-1-7-1-14-1-1-7-1-7-1-11-1-7-1-5-1-9-1-3-5-26-2"><p>When the client makes
+a request the <xref href="GUID-918410AB-63D3-3672-82BE-73289F88C03E.dita"><apiname>TClientDataRequest</apiname></xref> object is set to contain
+the address of the client's buffer or descriptor and the address of the client's <xref href="GUID-E0B34F3E-D4C4-3232-B8B1-7DB35B454646.dita"><apiname>TRequestStatus</apiname></xref>.
+This takes place in the client context. </p> </li>
+<li id="GUID-6FBED29F-E54D-5C5C-A6E5-8DBA41625338-GENID-1-7-1-14-1-1-7-1-7-1-11-1-7-1-5-1-9-1-3-5-26-3"><p>The data to be written
+is copied into the buffer of the <xref href="GUID-918410AB-63D3-3672-82BE-73289F88C03E.dita"><apiname>TClientDataRequest</apiname></xref> object. </p> </li>
+<li id="GUID-3316EB6E-804D-5CBC-8930-68D8E226C955-GENID-1-7-1-14-1-1-7-1-7-1-11-1-7-1-5-1-9-1-3-5-26-4"><p>A call to <xref href="GUID-C6946ECB-775F-3EC2-A56F-78F25B9FBE3D.dita#GUID-C6946ECB-775F-3EC2-A56F-78F25B9FBE3D/GUID-DE0CF5BD-B166-3C5B-9E27-F95710322F21"><apiname>Kern::QueueRequestComplete()</apiname></xref> passes
+the address of the <xref href="GUID-918410AB-63D3-3672-82BE-73289F88C03E.dita"><apiname>TClientDataRequest</apiname></xref> object. </p> </li>
+<li id="GUID-39DE78F0-D6E0-582B-B3F1-3AEC6D0E12CE-GENID-1-7-1-14-1-1-7-1-7-1-11-1-7-1-5-1-9-1-3-5-26-5"><p>The client is signalled
+immediately. </p> </li>
+<li id="GUID-5FF0CD64-F05D-5DF2-BD96-6B5966119CA8-GENID-1-7-1-14-1-1-7-1-7-1-11-1-7-1-5-1-9-1-3-5-26-6"><p>When the client thread
+next runs, the buffer contents and completion value are written to the client. </p> </li>
+</ol> <p><b>Using
+TClientBufferRequest</b> </p> <p>When it is necessary to access user memory
+from a DFC thread context, that memory must be pinned for the duration of
+the request and unpinned when the request is completed. The pinning must be
+performed in the context of the client thread. The <xref href="GUID-5CD6D111-213B-31A2-AA46-C5598DDB7249.dita"><apiname>TClientBufferRequest</apiname></xref> object
+exists for this purpose.It is used in the following way. </p> <ol id="GUID-3FEB8983-0BF6-578D-856A-09433AD7182E-GENID-1-7-1-14-1-1-7-1-7-1-11-1-7-1-5-1-9-1-3-5-29">
+<li id="GUID-4C3FB914-624A-50FE-94E0-EFF85D6169F8-GENID-1-7-1-14-1-1-7-1-7-1-11-1-7-1-5-1-9-1-3-5-29-1"><p>The driver creates a <xref href="GUID-5CD6D111-213B-31A2-AA46-C5598DDB7249.dita"><apiname>TClientBufferRequest</apiname></xref> object
+for each client request which may be outstanding concurrently: either one
+per client or one per request as appropriate. </p> </li>
+<li id="GUID-CAD03D3A-19E6-5C3D-A203-1726917A50B2-GENID-1-7-1-14-1-1-7-1-7-1-11-1-7-1-5-1-9-1-3-5-29-2"><p>Whe a client makes a
+request, the <xref href="GUID-5CD6D111-213B-31A2-AA46-C5598DDB7249.dita"><apiname>TClientBufferRequest</apiname></xref> object is set to contain
+the address of any buffers used and the address of the client's <xref href="GUID-E0B34F3E-D4C4-3232-B8B1-7DB35B454646.dita"><apiname>TRequestStatus</apiname></xref>.
+Doing so pins the contents of the buffers: they can be specified as descriptors
+or by start address and length. This takes place in the client context. </p> </li>
+<li id="GUID-8493130F-9E96-580F-B509-5EB5B69852A0-GENID-1-7-1-14-1-1-7-1-7-1-11-1-7-1-5-1-9-1-3-5-29-3"><p>The driver calls <xref href="GUID-C6946ECB-775F-3EC2-A56F-78F25B9FBE3D.dita#GUID-C6946ECB-775F-3EC2-A56F-78F25B9FBE3D/GUID-A33C039B-981C-3234-A414-95487D4103A9"><apiname>Kern::ThreadBufRead()</apiname></xref> and <xref href="GUID-C6946ECB-775F-3EC2-A56F-78F25B9FBE3D.dita#GUID-C6946ECB-775F-3EC2-A56F-78F25B9FBE3D/GUID-0C62AA11-87B4-307A-B63E-08A6842C7283"><apiname>Kern::ThreadBufWrite()</apiname></xref> to access the client's buffers. This takes place in the context of the DFC. </p> </li>
+<li id="GUID-5C63E867-025B-5F67-90CE-CE960DC254BB-GENID-1-7-1-14-1-1-7-1-7-1-11-1-7-1-5-1-9-1-3-5-29-4"><p>When the request is
+complete, the driver calls <xref href="GUID-C6946ECB-775F-3EC2-A56F-78F25B9FBE3D.dita#GUID-C6946ECB-775F-3EC2-A56F-78F25B9FBE3D/GUID-ECE11E29-0831-3271-AFAA-88DAE4131BE1"><apiname>Kern::QueueBufferRequestComplete()</apiname></xref> passing
+the <xref href="GUID-5CD6D111-213B-31A2-AA46-C5598DDB7249.dita"><apiname>TClientBufferRequest</apiname></xref> object. This signals the client
+immediately and unpins the buffers. </p> </li>
+<li id="GUID-474B2BBE-F24E-5DB3-B83F-CDA95DDE0C3E-GENID-1-7-1-14-1-1-7-1-7-1-11-1-7-1-5-1-9-1-3-5-29-5"><p>When the client thread
+next runs, the completion value is written back to the client along with the
+updated length of any descriptors. </p> </li>
+</ol> <p><b>Using
+Kern::RequestComplete()</b> </p> <p>The function <xref href="GUID-C6946ECB-775F-3EC2-A56F-78F25B9FBE3D.dita#GUID-C6946ECB-775F-3EC2-A56F-78F25B9FBE3D/GUID-D720BB4C-5E31-3213-BB16-859AA325FE98"><apiname>Kern::RequestComplete()</apiname></xref> exists
+in two versions: </p> <codeblock id="GUID-11FEEAC7-3223-5B27-9FA2-0C71F5F55E8C-GENID-1-7-1-14-1-1-7-1-7-1-11-1-7-1-5-1-9-1-3-5-32" xml:space="preserve">static void Kern::RequestComplete(DThread* aThread, TRequestStatus*& aStatus, TInt aReason);</codeblock> <p>which is now deprecated, and its overloaded replacement </p> <codeblock id="GUID-AAAAF661-3C0F-5048-8AD2-16C085A65387-GENID-1-7-1-14-1-1-7-1-7-1-11-1-7-1-5-1-9-1-3-5-34" xml:space="preserve">static void Kern::RequestComplete(TRequestStatus*& aStatus, TInt aReason);</codeblock> <p>The
+overloaded version should always be used, as it does not take a thread pointer
+argument. </p> <p><b>Using
+shared chunks</b> </p> <p>Shared chunks are a mechanism by which kernel side
+code shares buffers with user side code. As an alternative to pinning memory
+they have the following advantages: </p> <ul>
+<li id="GUID-65C6ECA6-A89B-5303-B674-E90AA805841A-GENID-1-7-1-14-1-1-7-1-7-1-11-1-7-1-5-1-9-1-3-5-38-1"><p>Shared chunks cannot
+be paged and therefore paging faults never arise. </p> </li>
+<li id="GUID-D7B96CD0-725F-5FCB-A30A-6FFF55ADC439-GENID-1-7-1-14-1-1-7-1-7-1-11-1-7-1-5-1-9-1-3-5-38-2"><p>Shared chunks transfer
+data with a minimum number of copying operations and are useful where high
+speeds and large volumes are required. </p> </li>
+</ul> <p>Shared chunks present disadvantages when a driver is being migrated
+rather than written from scratch, as the client API must be rewritten as well
+as the driver code. </p> </section>
+<section id="GUID-143D7A45-D119-4AEF-8941-116C2567514F-GENID-1-7-1-14-1-1-7-1-7-1-11-1-7-1-5-1-9-1-3-6"><title>See Also</title> <p> <xref href="GUID-91C11D80-7A62-5135-8EE0-6EC5576D1118.dita">Demand
+Paged Device Drivers Overview</xref> </p> <p> <xref href="GUID-85C18DAF-DB76-51C6-B38D-A802E314F4D1.dita">Performance
+Guarantee Tutorial</xref> </p> </section>
</conbody></concept>
\ No newline at end of file