Adaptation/GUID-E7C55048-5B7A-5BF2-B7F4-4D731659B88C.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-E7C55048-5B7A-5BF2-B7F4-4D731659B88C" xml:lang="en"><title>Device
       
    13 Driver Writing and Migration Technology Tutorial</title><shortdesc>Explains techniques for writing device drivers on data paged systems
       
    14 and migrating device drivers to data paged systems. </shortdesc><prolog><metadata><keywords/></metadata></prolog><conbody>
       
    15 <section id="GUID-8629C08B-C1C8-4435-962A-A57F11EB25CF"><title>Impact of data
       
    16 paging on kernel APIs</title> <p>The use of data paging impacts on the task
       
    17 of writing and migrating device drivers in two main ways: the preconditions
       
    18 for kernel API calls and the performance of the kernel APIs. </p> <p>Firstly,
       
    19 kernel APIs which access user memory may only be called subject to preconditions.
       
    20 The preconditions are that </p> <ul>
       
    21 <li id="GUID-81B56316-97C6-5EE8-BD88-D0741F9301F9"><p>no fast mutex may be
       
    22 held while calling them, and </p> </li>
       
    23 <li id="GUID-507412E1-1CA8-5590-B974-809B51C3D79D"><p>no kernel mutex may
       
    24 be held while calling them. </p> </li>
       
    25 </ul> <p>The APIs are these: </p> <ul>
       
    26 <li id="GUID-7A4E9152-8BFA-515E-A115-265436C843F4"><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>
       
    27 <li id="GUID-3C31D5D3-48E9-5D6D-8489-8259D98BF117"><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>
       
    28 <li id="GUID-FCE0C3D6-EE49-5AC9-856E-9833D22D541A"><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>
       
    29 <li id="GUID-72D4E609-B189-570A-B4D6-D2F4F1289EC1"><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>
       
    30 <li id="GUID-EE2D8F45-5B12-5D69-A9FD-7ED47A0B5EAD"><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>
       
    31 <li id="GUID-46805316-D1D5-5477-8287-FBF43DD8D3C4"><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>
       
    32 <li id="GUID-DB8BF5C7-2444-5B8F-8F66-12383ECB6A81"><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>
       
    33 <li id="GUID-9E6B180A-B360-58A6-B60E-8605E22F2C2E"><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>
       
    34 <li id="GUID-F307081B-7672-5C3F-869C-9B4B4F55CE62"><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>
       
    35 <li id="GUID-647B36DF-2124-5252-824E-E100695624C2"><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>
       
    36 <li id="GUID-9776CFD1-B061-5FC1-B100-0A55D7E8BFA5"><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>
       
    37 <li id="GUID-21F695FF-8933-5FF4-84DC-1F09056E36A6"><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>
       
    38 <li id="GUID-B477D969-B73E-514B-8E40-565EE6C4490E"><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>
       
    39 <li id="GUID-C8080F75-2F3B-5DBE-B0DE-D8518ED49516"><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>
       
    40 <li id="GUID-8D644BB0-9A01-5248-8DD2-95CDAE058B09"><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>
       
    41 <li id="GUID-746E54A0-C6D0-5B90-89F3-D197DD04470C"><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>
       
    42 </ul> </section>
       
    43 <section id="GUID-8C767668-D568-40E4-82F7-DD6FC6EA8132"><title>Impact of data
       
    44 paging on execution</title> <p>Device drivers use kernel side APIs to access
       
    45 user memory, and even when they are called in accordance with their preconditions
       
    46 they are no longer guaranteed to execute in a short and bounded time. This
       
    47 is because they may access paged memory and incur page faults which propagate
       
    48 from one thread to another. This document discusses how to mitigate the impact
       
    49 of data paging on device drivers. </p> </section>
       
    50 <section id="GUID-3903425C-EA48-44D6-B65E-253F583465BF"><title>Mitigating
       
    51 data paging: general principles</title> <p>Three general principles are involved
       
    52 in mitigating the impact of data paging on device drivers. </p> <ul>
       
    53 <li id="GUID-955ACDFA-CA71-5489-920F-B2F74039EA37"><p>Device drivers should
       
    54 not use shared DFC queues. </p> </li>
       
    55 <li id="GUID-3FD4823A-C1A0-53B2-8987-45313BC984C3"><p>Device drivers should,
       
    56 as far as possible, not access paged memory. </p> </li>
       
    57 <li id="GUID-3557B245-D479-5FA3-B039-092A8F1B7E06"><p>If a device driver needs
       
    58 to access paged memory, it should do so in the context of the client thread. </p> </li>
       
    59 </ul> </section>
       
    60 <section id="GUID-BE00235A-D227-4290-B3FA-93B20966073F"><title>Driver frameworks</title> <p>There
       
    61 are three main categories of device driver: </p> <ul>
       
    62 <li id="GUID-EAD164EF-A615-5AFE-A512-032C1C0CC0AC"><p><b>Boot-Loaded Non-Channel
       
    63 Drivers</b></p><p>Boot loaded drivers are built as kernel extensions. They
       
    64 are typically simple device drivers such as keyboard drivers with limited
       
    65 or no client side interface and are not much impacted by data paging. It is
       
    66 generally safe for them to pass data structures using the HAL in the context
       
    67 of a kernel thread and for them to execute in the context of a kernel thread:
       
    68 however, this assumption must always be verified for individual cases. </p></li>
       
    69 <li id="GUID-B82465B7-6306-5AAC-B6B4-FB5A4D07EBB2"><p><b>Media Drivers</b> </p><p>Media
       
    70 drivers are both channel based drivers and kernel extensions. When written
       
    71 according to the recommended model they either execute wholly in the context
       
    72 of their clients or use a unique DFC queue and associated kernel thread. If
       
    73 these recommendations are followed, no additional measures to mitigate the
       
    74 impact of data paging are required. </p> </li>
       
    75 <li id="GUID-86AB0CC9-B147-5019-837C-B2A6B32A9F6B"><p><b>Dynamically loaded
       
    76 channel based IO device drivers</b> </p><p>Channel based IO device drivers
       
    77 are based on various models: all are dynamically loaded. They are derived
       
    78 either from <xref href="GUID-E7550422-5121-3393-A85E-BB797969CD2A.dita"><apiname>DLogicalChannelBase</apiname></xref> or <xref href="GUID-A3CC1D95-4681-3349-A67C-F113A614041D.dita"><apiname>DLogicalChannel</apiname></xref>.
       
    79   </p><p>Channel based drivers derived from <xref href="GUID-E7550422-5121-3393-A85E-BB797969CD2A.dita"><apiname>DLogicalChannelBase</apiname></xref> usually
       
    80 execute in the context of their client, mitigating the impact of data paging.
       
    81 Where they are multi-threaded, they typically create separate and unique kernel
       
    82 threads and do not use shared DFC queues, mitigating the impact of data paging:
       
    83 if they use a shared DFC queue and associated kernel thread, they are impacted
       
    84 by data paging and must be written so as to mitigate the effects.  Channel
       
    85 based drivers derived from <xref href="GUID-A3CC1D95-4681-3349-A67C-F113A614041D.dita"><apiname>DLogicalChannel</apiname></xref> may communicate
       
    86 with the hardware directly (LDD to hardware) or indirectly (LDD to PDD to
       
    87 hardware). If a PDD is involved, mitigation of data paging should take place
       
    88 at that level and not the LDD.   Channel based drivers may have single or
       
    89 multiple clients, channels and hardware. It is these drivers which require
       
    90 most work to mitigate the impact of data paging. </p> </li>
       
    91 </ul> </section>
       
    92 <section id="GUID-6CD39776-B448-4F7D-8EC2-727AF13B575B"><title>Mitigation
       
    93 techniques</title> <p>The impact of data paging on device drivers is mitigated
       
    94 by the use of various different techniques which are the subject of the rest
       
    95 of this document. </p> <p><b>Passing
       
    96 data by value</b> </p> <p>Clients should pass data by value not as pointers.
       
    97 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
       
    98 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
       
    99 of the driver. </p> <p>To service boot loaded drivers and media drivers, you
       
   100 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
       
   101 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
       
   102 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" 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>,
       
   103 you use the DFC queue supplied with it (the member <xref href="GUID-954F5891-8BF3-33B2-9F40-9D80A6D2A17C.dita"><apiname>iDfc</apiname></xref>,
       
   104 accessed by pointer). To use the queue you call the <xref href="GUID-2FC8CE8F-102C-3025-86B6-C903D26CD002.dita"><apiname>SetDfcQ()</apiname></xref> function
       
   105 during the second phase construction of the LDD. </p> <p>You destroy queues
       
   106 by calling their function <xref href="GUID-38F49D2C-2798-37DB-82CC-A49EAB22B829.dita"><apiname>Destroy()</apiname></xref> which also terminates
       
   107 the associated thread. </p> <p><b>Setting
       
   108 realtime state</b> </p> <p>The realtime state of a thread determines whether
       
   109 it is enabled to access paged memory. If a thread is realtime (its realtime
       
   110 state is on) it is guaranteed not to access paged memory, so avoiding unpredictable
       
   111 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
       
   112 set by the kernel function <xref href="GUID-802BE082-128E-3F1E-A8D5-304DCDABFCC8.dita"><apiname>SetRealtimeState</apiname></xref>. </p> <p>If
       
   113 a driver uses DFC threads and is subject to performance guarantees, their
       
   114 realtime state should be set to on (this is the default when data paging is
       
   115 enabled). Otherwise the state should be set to off: the warning state is used
       
   116 for debugging. </p> <p><b>Validating
       
   117 arguments in client context</b> </p> <p>It is often necessary to validate
       
   118 the arguments of a request function. This should be done in the context of
       
   119 the client thread as far as possible. </p> <p>When a driver derived from the
       
   120 class <xref href="GUID-E7550422-5121-3393-A85E-BB797969CD2A.dita"><apiname>DLogicalChannelBase</apiname></xref> makes a request this happens
       
   121 automatically as a call to the <xref href="GUID-92AA62BB-14F1-325D-9A22-9C87AAE0535C.dita"><apiname>Request()</apiname></xref> function takes
       
   122 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
       
   123 request involves a call to the <xref href="GUID-E31B440A-A98E-30DA-B222-C8BA59A81A0E.dita"><apiname>SendMsg()</apiname></xref> function inherited
       
   124 from the base class and it is necessary to override the base implementation
       
   125 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
       
   126 user memory as little as possible. Whenever there is a need to access user
       
   127 memory and it can be accessed in the context of the client thread, it should
       
   128 be. </p> <p>When the driver is derived from the class <xref href="GUID-E7550422-5121-3393-A85E-BB797969CD2A.dita"><apiname>DLogicalChannelBase</apiname></xref>,
       
   129 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
       
   130 and these take place in the context of the client thread. </p> <p>When the
       
   131 driver is derived from the class <xref href="GUID-A3CC1D95-4681-3349-A67C-F113A614041D.dita"><apiname>DLogicalChannel</apiname></xref> it is
       
   132 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
       
   133 before passing the message on to be processed by the DFC thread if necessary.
       
   134 If the message is passed on, data must be stored kernel side either on the
       
   135 client thread's kernel stack or in the channel object. </p> <p>Message data
       
   136 can only be stored on the client thread's kernel stack if the message is synchronous
       
   137 and the size of the data is less than 4Kb. Since the stack is local to the
       
   138 client it can be used by more than one thread. One way of doing this is to
       
   139 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
       
   140 is itself implemented to perform the copying in the client thread context
       
   141 and independently call the <xref href="GUID-E31B440A-A98E-30DA-B222-C8BA59A81A0E.dita"><apiname>SendMsg()</apiname></xref> function of the parent
       
   142 class. </p> <p>Where the message is asynchronous you can use a similar strategy
       
   143 for overriding the <xref href="GUID-E31B440A-A98E-30DA-B222-C8BA59A81A0E.dita"><apiname>SendMsg()</apiname></xref> function but this time perform
       
   144 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
       
   145 of the parent class. In this case the size of the data must be small (in the
       
   146 region of 4Kb), there must be only one client using the buffer, and data cannot
       
   147 be written back to the client. </p> <p><b>Using
       
   148 TClientDataRequest</b> </p> <p>An asynchronous request often needs to copy
       
   149 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
       
   150 exists for this purpose: it writes a fixed size structure to user memory and
       
   151 completes the request in the following steps. </p> <ol id="GUID-100FA302-3292-565D-A0BC-A7314C2E2499">
       
   152 <li id="GUID-41BF301F-9FC7-55F8-9346-42262F49B5EE"><p>The driver creates a <xref href="GUID-918410AB-63D3-3672-82BE-73289F88C03E.dita"><apiname>TClientDataRequest</apiname></xref> object
       
   153 for each asynchronous client which may be outstanding concurrently: either
       
   154 one per client or one per request as appropriate. </p> </li>
       
   155 <li id="GUID-D4322A3D-C2F7-52D2-B600-35A65EF460CD"><p>When the client makes
       
   156 a request the <xref href="GUID-918410AB-63D3-3672-82BE-73289F88C03E.dita"><apiname>TClientDataRequest</apiname></xref> object is set to contain
       
   157 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>.
       
   158 This takes place in the client context. </p> </li>
       
   159 <li id="GUID-6FBED29F-E54D-5C5C-A6E5-8DBA41625338"><p>The data to be written
       
   160 is copied into the buffer of the <xref href="GUID-918410AB-63D3-3672-82BE-73289F88C03E.dita"><apiname>TClientDataRequest</apiname></xref> object. </p> </li>
       
   161 <li id="GUID-3316EB6E-804D-5CBC-8930-68D8E226C955"><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
       
   162 the address of the <xref href="GUID-918410AB-63D3-3672-82BE-73289F88C03E.dita"><apiname>TClientDataRequest</apiname></xref> object. </p> </li>
       
   163 <li id="GUID-39DE78F0-D6E0-582B-B3F1-3AEC6D0E12CE"><p>The client is signalled
       
   164 immediately. </p> </li>
       
   165 <li id="GUID-5FF0CD64-F05D-5DF2-BD96-6B5966119CA8"><p>When the client thread
       
   166 next runs, the buffer contents and completion value are written to the client. </p> </li>
       
   167 </ol> <p><b>Using
       
   168 TClientBufferRequest</b> </p> <p>When it is necessary to access user memory
       
   169 from a DFC thread context, that memory must be pinned for the duration of
       
   170 the request and unpinned when the request is completed. The pinning must be
       
   171 performed in the context of the client thread. The <xref href="GUID-5CD6D111-213B-31A2-AA46-C5598DDB7249.dita"><apiname>TClientBufferRequest</apiname></xref> object
       
   172 exists for this purpose.It is used in the following way. </p> <ol id="GUID-3FEB8983-0BF6-578D-856A-09433AD7182E">
       
   173 <li id="GUID-4C3FB914-624A-50FE-94E0-EFF85D6169F8"><p>The driver creates a <xref href="GUID-5CD6D111-213B-31A2-AA46-C5598DDB7249.dita"><apiname>TClientBufferRequest</apiname></xref> object
       
   174 for each client request which may be outstanding concurrently: either one
       
   175 per client or one per request as appropriate. </p> </li>
       
   176 <li id="GUID-CAD03D3A-19E6-5C3D-A203-1726917A50B2"><p>Whe a client makes a
       
   177 request, the <xref href="GUID-5CD6D111-213B-31A2-AA46-C5598DDB7249.dita"><apiname>TClientBufferRequest</apiname></xref> object is set to contain
       
   178 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>.
       
   179 Doing so pins the contents of the buffers: they can be specified as descriptors
       
   180 or by start address and length. This takes place in the client context. </p> </li>
       
   181 <li id="GUID-8493130F-9E96-580F-B509-5EB5B69852A0"><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>
       
   182 <li id="GUID-5C63E867-025B-5F67-90CE-CE960DC254BB"><p>When the request is
       
   183 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
       
   184 the <xref href="GUID-5CD6D111-213B-31A2-AA46-C5598DDB7249.dita"><apiname>TClientBufferRequest</apiname></xref> object. This signals the client
       
   185 immediately and unpins the buffers. </p> </li>
       
   186 <li id="GUID-474B2BBE-F24E-5DB3-B83F-CDA95DDE0C3E"><p>When the client thread
       
   187 next runs, the completion value is written back to the client along with the
       
   188 updated length of any descriptors. </p> </li>
       
   189 </ol> <p><b>Using
       
   190 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
       
   191 in two versions: </p> <codeblock id="GUID-11FEEAC7-3223-5B27-9FA2-0C71F5F55E8C" 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" xml:space="preserve">static void Kern::RequestComplete(TRequestStatus*&amp; aStatus, TInt aReason);</codeblock> <p>The
       
   192 overloaded version should always be used, as it does not take a thread pointer
       
   193 argument. </p> <p><b>Using
       
   194 shared chunks</b> </p> <p>Shared chunks are a mechanism by which kernel side
       
   195 code shares buffers with user side code. As an alternative to pinning memory
       
   196 they have the following advantages: </p> <ul>
       
   197 <li id="GUID-65C6ECA6-A89B-5303-B674-E90AA805841A"><p>Shared chunks cannot
       
   198 be paged and therefore paging faults never arise. </p> </li>
       
   199 <li id="GUID-D7B96CD0-725F-5FCB-A30A-6FFF55ADC439"><p>Shared chunks transfer
       
   200 data with a minimum number of copying operations and are useful where high
       
   201 speeds and large volumes are required. </p> </li>
       
   202 </ul> <p>Shared chunks present disadvantages when a driver is being migrated
       
   203 rather than written from scratch, as the client API must be rewritten as well
       
   204 as the driver code. </p> </section>
       
   205 <section id="GUID-143D7A45-D119-4AEF-8941-116C2567514F"><title>See Also</title> <p> <xref href="GUID-85C18DAF-DB76-51C6-B38D-A802E314F4D1.dita">Performance Guarantee Tutorial</xref>  </p> </section>
       
   206 </conbody></concept>