<?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-10-1-15-1-1-7-1-1-5-1-8-1-11-1-7-1-5-1-9-1" xml:lang="en"><title>DeviceDriver Writing and Migration Technology Tutorial</title><shortdesc>Explains techniques for writing device drivers on data paged systemsand migrating device drivers to data paged systems. </shortdesc><prolog><metadata><keywords/></metadata></prolog><conbody><section id="GUID-8629C08B-C1C8-4435-962A-A57F11EB25CF-GENID-1-10-1-15-1-1-7-1-1-5-1-8-1-11-1-7-1-5-1-9-1-3-1"><title>Impact of datapaging on kernel APIs</title> <p>The use of data paging impacts on the taskof writing and migrating device drivers in two main ways: the preconditionsfor 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-10-1-15-1-1-7-1-1-5-1-8-1-11-1-7-1-5-1-9-1-3-1-4-1"><p>no fast mutex may beheld while calling them, and </p> </li><li id="GUID-507412E1-1CA8-5590-B974-809B51C3D79D-GENID-1-10-1-15-1-1-7-1-1-5-1-8-1-11-1-7-1-5-1-9-1-3-1-4-2"><p>no kernel mutex maybe held while calling them. </p> </li></ul> <p>The APIs are these: </p> <ul><li id="GUID-7A4E9152-8BFA-515E-A115-265436C843F4-GENID-1-10-1-15-1-1-7-1-1-5-1-8-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-10-1-15-1-1-7-1-1-5-1-8-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-10-1-15-1-1-7-1-1-5-1-8-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-10-1-15-1-1-7-1-1-5-1-8-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-10-1-15-1-1-7-1-1-5-1-8-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-10-1-15-1-1-7-1-1-5-1-8-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-10-1-15-1-1-7-1-1-5-1-8-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-10-1-15-1-1-7-1-1-5-1-8-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-10-1-15-1-1-7-1-1-5-1-8-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-10-1-15-1-1-7-1-1-5-1-8-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-10-1-15-1-1-7-1-1-5-1-8-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-10-1-15-1-1-7-1-1-5-1-8-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-10-1-15-1-1-7-1-1-5-1-8-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-10-1-15-1-1-7-1-1-5-1-8-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-10-1-15-1-1-7-1-1-5-1-8-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-10-1-15-1-1-7-1-1-5-1-8-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-10-1-15-1-1-7-1-1-5-1-8-1-11-1-7-1-5-1-9-1-3-2"><title>Impact of datapaging on execution</title> <p>Device drivers use kernel side APIs to accessuser memory, and even when they are called in accordance with their preconditionsthey are no longer guaranteed to execute in a short and bounded time. Thisis because they may access paged memory and incur page faults which propagatefrom one thread to another. This document discusses how to mitigate the impactof data paging on device drivers. </p> </section><section id="GUID-3903425C-EA48-44D6-B65E-253F583465BF-GENID-1-10-1-15-1-1-7-1-1-5-1-8-1-11-1-7-1-5-1-9-1-3-3"><title>Mitigatingdata paging: general principles</title> <p>Three general principles are involvedin mitigating the impact of data paging on device drivers. </p> <ul><li id="GUID-955ACDFA-CA71-5489-920F-B2F74039EA37-GENID-1-10-1-15-1-1-7-1-1-5-1-8-1-11-1-7-1-5-1-9-1-3-3-3-1"><p>Device drivers shouldnot use shared DFC queues. </p> </li><li id="GUID-3FD4823A-C1A0-53B2-8987-45313BC984C3-GENID-1-10-1-15-1-1-7-1-1-5-1-8-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-10-1-15-1-1-7-1-1-5-1-8-1-11-1-7-1-5-1-9-1-3-3-3-3"><p>If a device driver needsto 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-10-1-15-1-1-7-1-1-5-1-8-1-11-1-7-1-5-1-9-1-3-4"><title>Driver frameworks</title> <p>Thereare three main categories of device driver: </p> <ul><li id="GUID-EAD164EF-A615-5AFE-A512-032C1C0CC0AC-GENID-1-10-1-15-1-1-7-1-1-5-1-8-1-11-1-7-1-5-1-9-1-3-4-3-1"><p><b>Boot-Loaded Non-ChannelDrivers</b></p><p>Boot loaded drivers are built as kernel extensions. Theyare typically simple device drivers such as keyboard drivers with limitedor no client side interface and are not much impacted by data paging. It isgenerally safe for them to pass data structures using the HAL in the contextof a kernel thread and for them to execute in the context of a kernel thread:however, this assumption must always be verified for individual cases. </p></li><li id="GUID-B82465B7-6306-5AAC-B6B4-FB5A4D07EBB2-GENID-1-10-1-15-1-1-7-1-1-5-1-8-1-11-1-7-1-5-1-9-1-3-4-3-2"><p><b>Media Drivers</b> </p><p>Mediadrivers are both channel based drivers and kernel extensions. When writtenaccording to the recommended model they either execute wholly in the contextof their clients or use a unique DFC queue and associated kernel thread. Ifthese recommendations are followed, no additional measures to mitigate theimpact of data paging are required. </p> </li><li id="GUID-86AB0CC9-B147-5019-837C-B2A6B32A9F6B-GENID-1-10-1-15-1-1-7-1-1-5-1-8-1-11-1-7-1-5-1-9-1-3-4-3-3"><p><b>Dynamically loadedchannel based IO device drivers</b> </p><p>Channel based IO device driversare based on various models: all are dynamically loaded. They are derivedeither 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>. </p><p>Channel based drivers derived from <xref href="GUID-E7550422-5121-3393-A85E-BB797969CD2A.dita"><apiname>DLogicalChannelBase</apiname></xref> usuallyexecute in the context of their client, mitigating the impact of data paging.Where they are multi-threaded, they typically create separate and unique kernelthreads and do not use shared DFC queues, mitigating the impact of data paging:if they use a shared DFC queue and associated kernel thread, they are impactedby data paging and must be written so as to mitigate the effects. Channelbased drivers derived from <xref href="GUID-A3CC1D95-4681-3349-A67C-F113A614041D.dita"><apiname>DLogicalChannel</apiname></xref> may communicatewith the hardware directly (LDD to hardware) or indirectly (LDD to PDD tohardware). If a PDD is involved, mitigation of data paging should take placeat that level and not the LDD. Channel based drivers may have single ormultiple clients, channels and hardware. It is these drivers which requiremost work to mitigate the impact of data paging. </p> </li></ul> </section><section id="GUID-6CD39776-B448-4F7D-8EC2-727AF13B575B-GENID-1-10-1-15-1-1-7-1-1-5-1-8-1-11-1-7-1-5-1-9-1-3-5"><title>Mitigationtechniques</title> <p>The impact of data paging on device drivers is mitigatedby the use of various different techniques which are the subject of the restof this document. </p> <p><b>Passingdata 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 shoulduse 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 natureof the driver. </p> <p>To service boot loaded drivers and media drivers, youcreate 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>Toservice 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> witha <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-10-1-15-1-1-7-1-1-5-1-8-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> functionduring the second phase construction of the LDD. </p> <p>You destroy queuesby calling their function <xref href="GUID-38F49D2C-2798-37DB-82CC-A49EAB22B829.dita"><apiname>Destroy()</apiname></xref> which also terminatesthe associated thread. </p> <p><b>Settingrealtime state</b> </p> <p>The realtime state of a thread determines whetherit is enabled to access paged memory. If a thread is realtime (its realtimestate is on) it is guaranteed not to access paged memory, so avoiding unpredictabledelays. 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> andset by the kernel function <xref href="GUID-802BE082-128E-3F1E-A8D5-304DCDABFCC8.dita"><apiname>SetRealtimeState</apiname></xref>. </p> <p>Ifa driver uses DFC threads and is subject to performance guarantees, theirrealtime state should be set to on (this is the default when data paging isenabled). Otherwise the state should be set to off: the warning state is usedfor debugging. </p> <p><b>Validatingarguments in client context</b> </p> <p>It is often necessary to validatethe arguments of a request function. This should be done in the context ofthe client thread as far as possible. </p> <p>When a driver derived from theclass <xref href="GUID-E7550422-5121-3393-A85E-BB797969CD2A.dita"><apiname>DLogicalChannelBase</apiname></xref> makes a request this happensautomatically as a call to the <xref href="GUID-92AA62BB-14F1-325D-9A22-9C87AAE0535C.dita"><apiname>Request()</apiname></xref> function takesplace 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> therequest involves a call to the <xref href="GUID-E31B440A-A98E-30DA-B222-C8BA59A81A0E.dita"><apiname>SendMsg()</apiname></xref> function inheritedfrom the base class and it is necessary to override the base implementationto force evaluation of the arguments within the client thread. </p> <p><b>Accessing user memory from client context</b> </p> <p>The DFC should accessuser memory as little as possible. Whenever there is a need to access usermemory and it can be accessed in the context of the client thread, it shouldbe. </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> functionand these take place in the context of the client thread. </p> <p>When thedriver is derived from the class <xref href="GUID-A3CC1D95-4681-3349-A67C-F113A614041D.dita"><apiname>DLogicalChannel</apiname></xref> it ispossible to read from and write to user memory by overriding the <xref href="GUID-E31B440A-A98E-30DA-B222-C8BA59A81A0E.dita"><apiname>SendMsg()</apiname></xref> functionbefore 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 theclient thread's kernel stack or in the channel object. </p> <p>Message datacan only be stored on the client thread's kernel stack if the message is synchronousand the size of the data is less than 4Kb. Since the stack is local to theclient it can be used by more than one thread. One way of doing this is toimplement <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> whichis itself implemented to perform the copying in the client thread contextand independently call the <xref href="GUID-E31B440A-A98E-30DA-B222-C8BA59A81A0E.dita"><apiname>SendMsg()</apiname></xref> function of the parentclass. </p> <p>Where the message is asynchronous you can use a similar strategyfor overriding the <xref href="GUID-E31B440A-A98E-30DA-B222-C8BA59A81A0E.dita"><apiname>SendMsg()</apiname></xref> function but this time performthe 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> functionof the parent class. In this case the size of the data must be small (in theregion of 4Kb), there must be only one client using the buffer, and data cannotbe written back to the client. </p> <p><b>UsingTClientDataRequest</b> </p> <p>An asynchronous request often needs to copya 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> objectexists for this purpose: it writes a fixed size structure to user memory andcompletes the request in the following steps. </p> <ol id="GUID-100FA302-3292-565D-A0BC-A7314C2E2499-GENID-1-10-1-15-1-1-7-1-1-5-1-8-1-11-1-7-1-5-1-9-1-3-5-26"><li id="GUID-41BF301F-9FC7-55F8-9346-42262F49B5EE-GENID-1-10-1-15-1-1-7-1-1-5-1-8-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> objectfor each asynchronous client which may be outstanding concurrently: eitherone per client or one per request as appropriate. </p> </li><li id="GUID-D4322A3D-C2F7-52D2-B600-35A65EF460CD-GENID-1-10-1-15-1-1-7-1-1-5-1-8-1-11-1-7-1-5-1-9-1-3-5-26-2"><p>When the client makesa request the <xref href="GUID-918410AB-63D3-3672-82BE-73289F88C03E.dita"><apiname>TClientDataRequest</apiname></xref> object is set to containthe 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-10-1-15-1-1-7-1-1-5-1-8-1-11-1-7-1-5-1-9-1-3-5-26-3"><p>The data to be writtenis 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-10-1-15-1-1-7-1-1-5-1-8-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> passesthe 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-10-1-15-1-1-7-1-1-5-1-8-1-11-1-7-1-5-1-9-1-3-5-26-5"><p>The client is signalledimmediately. </p> </li><li id="GUID-5FF0CD64-F05D-5DF2-BD96-6B5966119CA8-GENID-1-10-1-15-1-1-7-1-1-5-1-8-1-11-1-7-1-5-1-9-1-3-5-26-6"><p>When the client threadnext runs, the buffer contents and completion value are written to the client. </p> </li></ol> <p><b>UsingTClientBufferRequest</b> </p> <p>When it is necessary to access user memoryfrom a DFC thread context, that memory must be pinned for the duration ofthe request and unpinned when the request is completed. The pinning must beperformed in the context of the client thread. The <xref href="GUID-5CD6D111-213B-31A2-AA46-C5598DDB7249.dita"><apiname>TClientBufferRequest</apiname></xref> objectexists for this purpose.It is used in the following way. </p> <ol id="GUID-3FEB8983-0BF6-578D-856A-09433AD7182E-GENID-1-10-1-15-1-1-7-1-1-5-1-8-1-11-1-7-1-5-1-9-1-3-5-29"><li id="GUID-4C3FB914-624A-50FE-94E0-EFF85D6169F8-GENID-1-10-1-15-1-1-7-1-1-5-1-8-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> objectfor each client request which may be outstanding concurrently: either oneper client or one per request as appropriate. </p> </li><li id="GUID-CAD03D3A-19E6-5C3D-A203-1726917A50B2-GENID-1-10-1-15-1-1-7-1-1-5-1-8-1-11-1-7-1-5-1-9-1-3-5-29-2"><p>Whe a client makes arequest, the <xref href="GUID-5CD6D111-213B-31A2-AA46-C5598DDB7249.dita"><apiname>TClientBufferRequest</apiname></xref> object is set to containthe 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 descriptorsor by start address and length. This takes place in the client context. </p> </li><li id="GUID-8493130F-9E96-580F-B509-5EB5B69852A0-GENID-1-10-1-15-1-1-7-1-1-5-1-8-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-10-1-15-1-1-7-1-1-5-1-8-1-11-1-7-1-5-1-9-1-3-5-29-4"><p>When the request iscomplete, 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> passingthe <xref href="GUID-5CD6D111-213B-31A2-AA46-C5598DDB7249.dita"><apiname>TClientBufferRequest</apiname></xref> object. This signals the clientimmediately and unpins the buffers. </p> </li><li id="GUID-474B2BBE-F24E-5DB3-B83F-CDA95DDE0C3E-GENID-1-10-1-15-1-1-7-1-1-5-1-8-1-11-1-7-1-5-1-9-1-3-5-29-5"><p>When the client threadnext runs, the completion value is written back to the client along with theupdated length of any descriptors. </p> </li></ol> <p><b>UsingKern::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> existsin two versions: </p> <codeblock id="GUID-11FEEAC7-3223-5B27-9FA2-0C71F5F55E8C-GENID-1-10-1-15-1-1-7-1-1-5-1-8-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-10-1-15-1-1-7-1-1-5-1-8-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>Theoverloaded version should always be used, as it does not take a thread pointerargument. </p> <p><b>Usingshared chunks</b> </p> <p>Shared chunks are a mechanism by which kernel sidecode shares buffers with user side code. As an alternative to pinning memorythey have the following advantages: </p> <ul><li id="GUID-65C6ECA6-A89B-5303-B674-E90AA805841A-GENID-1-10-1-15-1-1-7-1-1-5-1-8-1-11-1-7-1-5-1-9-1-3-5-38-1"><p>Shared chunks cannotbe paged and therefore paging faults never arise. </p> </li><li id="GUID-D7B96CD0-725F-5FCB-A30A-6FFF55ADC439-GENID-1-10-1-15-1-1-7-1-1-5-1-8-1-11-1-7-1-5-1-9-1-3-5-38-2"><p>Shared chunks transferdata with a minimum number of copying operations and are useful where highspeeds and large volumes are required. </p> </li></ul> <p>Shared chunks present disadvantages when a driver is being migratedrather than written from scratch, as the client API must be rewritten as wellas the driver code. </p> </section><section id="GUID-143D7A45-D119-4AEF-8941-116C2567514F-GENID-1-10-1-15-1-1-7-1-1-5-1-8-1-11-1-7-1-5-1-9-1-3-6"><title>See Also</title> <p> <xref href="GUID-85C18DAF-DB76-51C6-B38D-A802E314F4D1.dita">Performance Guarantee Tutorial</xref> </p> </section></conbody></concept>