|
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-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>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-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 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-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 be |
|
22 held while calling them, and </p> </li> |
|
23 <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 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-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> |
|
27 <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> |
|
28 <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> |
|
29 <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> |
|
30 <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> |
|
31 <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> |
|
32 <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> |
|
33 <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> |
|
34 <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> |
|
35 <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> |
|
36 <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> |
|
37 <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> |
|
38 <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> |
|
39 <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> |
|
40 <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> |
|
41 <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> |
|
42 </ul> </section> |
|
43 <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 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-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>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-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 should |
|
54 not use shared DFC queues. </p> </li> |
|
55 <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, |
|
56 as far as possible, not access paged memory. </p> </li> |
|
57 <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 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-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>There |
|
61 are three main categories of device driver: </p> <ul> |
|
62 <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-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-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>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-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 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-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>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-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>, |
|
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-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"> |
|
152 <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> 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-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 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-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 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-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> 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-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 signalled |
|
164 immediately. </p> </li> |
|
165 <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 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-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"> |
|
173 <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> 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-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 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-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> |
|
182 <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 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-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 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-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>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-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 cannot |
|
198 be paged and therefore paging faults never arise. </p> </li> |
|
199 <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 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-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> |
|
206 </conbody></concept> |