Symbian3/PDK/Source/GUID-E7C55048-5B7A-5BF2-B7F4-4D731659B88C-GENID-1-7-1-14-1-1-7-1-7-1-11-1-7-1-4-1-9-1.dita
author Dominic Pinkman <Dominic.Pinkman@Nokia.com>
Tue, 30 Mar 2010 11:42:04 +0100
changeset 4 4816d766a08a
parent 3 46218c8b8afa
permissions -rw-r--r--
Week 12 contribution of SDK documentation_content. See release notes for details. Fixes Bug 1892, Bug 1522, Bug 1520, Bug 394, Bug 1319, Bug 344, Bug 1897

<?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-4-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-4-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-4-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-4-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-4-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-4-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-4-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-4-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-4-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-4-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-4-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-4-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-4-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-4-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-4-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-4-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-4-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-4-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-4-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-4-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-4-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-4-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-4-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-4-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-4-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-4-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-4-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-4-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-4-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-4-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-4-1-9-1-3-5-9" xml:space="preserve">TInt Kern::DynamicDfcQCreate(TDynamicDfcQue*&amp; aDfcQ, TInt aPriority, const TDesC&amp; 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-4-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-4-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-4-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-4-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-4-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-4-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-4-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-4-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-4-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-4-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-4-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-4-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-4-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-4-1-9-1-3-5-32" xml:space="preserve">static void Kern::RequestComplete(DThread* aThread, TRequestStatus*&amp; 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-4-1-9-1-3-5-34" xml:space="preserve">static void Kern::RequestComplete(TRequestStatus*&amp; 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-4-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-4-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-4-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>