|
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-EB2566BD-8F65-5A81-B215-E8B05CFE21C3" xml:lang="en"><title>Migration |
|
13 Tutorial: Demand Paging and Media Drivers</title><shortdesc>Describes how to change media drivers when demand paging is used.</shortdesc><prolog><metadata><keywords/></metadata></prolog><conbody> |
|
14 <p>Demand paging is a change made from Symbian platform v9.3 to how the Kernel |
|
15 uses RAM and storage media. This topic </p> |
|
16 <section id="GUID-AD70C4EE-F7E8-473D-B917-819B9852CB31"><title>Introduction</title> <p>If the ROM has been built with paging |
|
17 enabled, the image is divided into two sections: an unpaged section and a |
|
18 paged section. In addition to this, code that is not part of the ROM can be |
|
19 loaded on demand into RAM from other non-XIP partitions and/or media, for |
|
20 example FAT or ROFS partitions. </p> <p>Two types of paging are currently |
|
21 supported: </p> <ul> |
|
22 <li id="GUID-E838F239-2F8A-5441-AE76-59382AA75FF6"><p>ROM paging - paging |
|
23 from the paged section of the ROM image </p> </li> |
|
24 <li id="GUID-28970AFC-33C6-56B7-BBD3-383220359A90"><p>code paging - paging |
|
25 from non-removable media, for example, a FAT partition on an internal Multi |
|
26 Media Card (MMC) drive or an internal NAND ROFS/FAT partition. </p> <p>See |
|
27 also <xref href="GUID-90B5FDD9-7D59-5035-BF53-2B177655DCD6.dita">Paging from an |
|
28 internal MMC</xref>. </p> </li> |
|
29 </ul> <p> <note>: A difference between ROM paging and code paging is that |
|
30 all ROM pages are contiguous, whereas code that is paged from other drives |
|
31 may be split over several potentially non-contiguous clusters. This puts an |
|
32 extra burden on the paging subsystem as it needs to identify the layout of |
|
33 the DLL on the media before it is deemed pageable. This is achieved by using |
|
34 the file servers blockmap API.</note> </p> <p>Media drivers are typically |
|
35 PDDs with a filename of <filepath>med.pdd</filepath>. Normally they are declared |
|
36 in the <filepath>rombuild.oby</filepath> file with the keyword <codeph>extension</codeph> or <codeph>device</codeph> and |
|
37 are therefore flagged as unpaged. That is, once loaded their code and read-only |
|
38 data sections are not paged out. </p> <p>A media driver that is capable of |
|
39 servicing page requests from the paging subsystem must ensure that the thread |
|
40 in which the media driver runs takes the page fault itself otherwise a deadlock |
|
41 could occur. In theory, the only time this can happen is when a media driver |
|
42 accepts a write request from a user side client that points to data in the |
|
43 paged section of the ROM or to code that has been loaded into RAM from code |
|
44 paging enabled media. To remedy this, the local media subsystem has been modified |
|
45 to lock write requests to paging media drivers before they are dispatched |
|
46 and to split large write requests into a series of smaller ones to avoid exhausting |
|
47 available RAM. </p> <p>The two initial stages relevant to this discussion |
|
48 are: </p> <ul> |
|
49 <li id="GUID-02D2CBAA-8393-52C2-B940-31603B4AF9FA"><p>the kernel extension |
|
50 entry point - identified by the <codeph>DECLARE_STANDARD_EXTENSION</codeph> macro </p> </li> |
|
51 <li id="GUID-1EFE9978-780D-507C-B408-E0C3AE97A0A7"><p>the PDD entry point |
|
52 - identified by the <codeph>DECLARE_EXTENSION_PDD</codeph> macro. </p> </li> |
|
53 </ul> <p>To enable demand paging as soon as possible in the boot sequence |
|
54 it is desirable to instantiate and install the PDD factory object earlier, |
|
55 for example in the kernel extension entry point. </p> <p> <note> Some media |
|
56 drivers have no kernel extension entry point defined, the MMC media driver |
|
57 is an example. These drivers have a <xref href="GUID-73947402-2F32-35C7-94C4-22B4D63D5FB3.dita"><apiname>DECLARE_STANDARD_PDD</apiname></xref> macro |
|
58 defined rather than <xref href="GUID-52853C0D-CA98-3B92-B7D4-FF1C1F06C1A6.dita"><apiname>DECLARE_EXTENSION_PDD</apiname></xref>. They require |
|
59 modification to have a <xref href="GUID-52853C0D-CA98-3B92-B7D4-FF1C1F06C1A6.dita"><apiname>DECLARE_EXTENSION_PDD</apiname></xref> and a <xref href="GUID-8B6DF6D7-4995-3564-9303-272500D7E747.dita"><apiname>DECLARE_STANDARD_EXTENSION</apiname></xref>.</note> </p> <p>The |
|
60 steps needed to support ROM and/or code paging are as follows: </p> <ol id="GUID-CADDDC61-A3A2-5AC3-AD69-739FD61FA9CC"> |
|
61 <li id="GUID-4D14D36E-5F3A-55E6-BAB8-A45243B34928"><p>determine whether code |
|
62 paging is supported, and if so, identify the relevant local drive number or |
|
63 numbers </p> </li> |
|
64 <li id="GUID-F97B3965-020F-5C16-9D09-5861C0B6C695"><p> <xref href="GUID-EB2566BD-8F65-5A81-B215-E8B05CFE21C3.dita#GUID-EB2566BD-8F65-5A81-B215-E8B05CFE21C3/GUID-77FBA53A-CC78-5CD1-8FDF-F6A8001DE466">modify variantmediadef.h</xref> </p> </li> |
|
65 <li id="GUID-D608C61F-E297-5A0C-B0FD-4F0F98B36EEF"><p> <xref href="GUID-EB2566BD-8F65-5A81-B215-E8B05CFE21C3.dita#GUID-EB2566BD-8F65-5A81-B215-E8B05CFE21C3/GUID-686EFEF4-A514-51BC-8378-962A8899F270">modify the media drivers kernel extension entry point</xref> to register |
|
66 the media driver with the paging subsystem and to instantiate and install |
|
67 the <xref href="GUID-A5484A7F-94B9-34C7-9F88-82B1BF516930.dita"><apiname>DPhysicalDevice</apiname></xref> derived factory object </p> </li> |
|
68 <li id="GUID-5DEA2654-8954-52EC-B498-066AE05AB209"><p> <xref href="GUID-EB2566BD-8F65-5A81-B215-E8B05CFE21C3.dita#GUID-EB2566BD-8F65-5A81-B215-E8B05CFE21C3/GUID-C32CF25E-553B-5786-88ED-4587AC0DF3BA">modify the DLocalDrive::Ecaps() handling</xref> </p> </li> |
|
69 <li id="GUID-CED0CA1D-44EF-51DC-BC56-60B88A9D0494"><p>modify the media drivers <xref href="GUID-A0D4EB25-0BA4-39EE-874B-465EB9628DCC.dita#GUID-A0D4EB25-0BA4-39EE-874B-465EB9628DCC/GUID-EB244422-0BEC-3D3F-BDDA-3F050A2697A7"><apiname>DMediaDriver::Request</apiname></xref> function |
|
70 to accept the four new <xref href="GUID-EB2566BD-8F65-5A81-B215-E8B05CFE21C3.dita#GUID-EB2566BD-8F65-5A81-B215-E8B05CFE21C3/GUID-AE44672E-F60D-563C-BB6A-B70AF187C366">paging |
|
71 request</xref> types </p> </li> |
|
72 <li id="GUID-A7CFB8AA-4D95-5DD3-AF3F-0FAB0448F218"><p> <xref href="GUID-EB2566BD-8F65-5A81-B215-E8B05CFE21C3.dita#GUID-EB2566BD-8F65-5A81-B215-E8B05CFE21C3/GUID-0EA673E6-FEE4-51F6-9C84-9411316D7357">Handling fragmented write requests</xref>. </p> </li> |
|
73 </ol> </section> |
|
74 <section id="GUID-77FBA53A-CC78-5CD1-8FDF-F6A8001DE466"><title>Changes to |
|
75 variantmediadef.h</title> <p>The following should be defined using appropriate |
|
76 names in the variant's <i>variantmediadef.h</i> file: </p> <ul> |
|
77 <li id="GUID-F5EFB1C8-B7C4-52AD-88A2-8A7659527373"><p> <codeph>PAGING_TYPE</codeph> - |
|
78 flags that indicate whether code paging and/or ROM paging is supported </p> </li> |
|
79 <li id="GUID-2745304A-2FAF-5DCB-88D3-74BD56B475E0"><p> <codeph>NAND_PAGEDRIVELIST</codeph> - |
|
80 a list of the paging drives </p> </li> |
|
81 <li id="GUID-507FB105-E254-501E-B22A-33E93C3CABA5"><p> <codeph>NAND_PAGEDRIVECOUNT</codeph> - |
|
82 the total number of paging drives </p> </li> |
|
83 <li id="GUID-F3D6494E-A14D-5FB1-A3E7-3D75D3753E12"><p> <codeph>NUM_PAGES</codeph> - |
|
84 if a write request points to data that resides in paged ROM, the request is |
|
85 split up into separate fragments of the specified size. This value needs to |
|
86 be chosen with care, as if it is too small writes can take too long to finish. </p> </li> |
|
87 </ul><p> <note> Normal write requests which point to data that is not in paged |
|
88 ROM are not fragmented. However, large requests are split up into smaller |
|
89 requests by the file server, providing clients with a more responsive system.</note> </p> <p>The |
|
90 macros defined in the file <i>variantmediadef.h</i> are passed to <xref href="GUID-9E60E8D9-619E-3A76-BAC8-93A60D62C7DF.dita#GUID-9E60E8D9-619E-3A76-BAC8-93A60D62C7DF/GUID-5FDD89C6-C34A-3A0D-A422-D148DDE23E42"><apiname>LocDrv::RegisterPagingDevice()</apiname></xref>. |
|
91 This function is similar to <xref href="GUID-9E60E8D9-619E-3A76-BAC8-93A60D62C7DF.dita#GUID-9E60E8D9-619E-3A76-BAC8-93A60D62C7DF/GUID-647D0858-FE04-3A4F-99CE-81CD0B34CE7B"><apiname>LocDrv::RegisterMediaDevice()</apiname></xref> in |
|
92 that it takes a drive list as a parameter, but it identifies the drive or |
|
93 drives to be used for code paging. If code only ROM paging is needed, set |
|
94 the drive count to zero. </p> <p>Changes made to support paging on NAND: </p> <codeblock id="GUID-1425F457-8F28-5CD7-B8A4-3FC3D2777D73" xml:space="preserve">// Variant parameters for NAND flash media driver (mednand.pdd) |
|
95 #define NAND_DRIVECOUNT 8 |
|
96 #define NAND_DRIVELIST 2,3,5,6,7,9,10,11 |
|
97 #define NAND_NUMMEDIA 1 |
|
98 #define NAND_DRIVENAME "Nand" |
|
99 |
|
100 #define PAGING_TYPE DPagingDevice::ERom | DPagingDevice::ECode |
|
101 |
|
102 // code paging from writeable FAT, Composite FAT and first ROFS |
|
103 #define NAND_PAGEDRIVELIST 2,5,6 |
|
104 #define NAND_PAGEDRIVECOUNT 3 |
|
105 |
|
106 // defines the size of fragment |
|
107 #define NUM_PAGES 8</codeblock> </section> |
|
108 <section id="GUID-686EFEF4-A514-51BC-8378-962A8899F270"><title>Changes to |
|
109 the media driver kernel extension point</title> <p>The kernel-extension entry |
|
110 point must create a DFC queue to satisfy any page fault that occurs in the |
|
111 drive thread. Failure to do so results in a kernel fault. The entry point |
|
112 must then create a <xref href="GUID-3715787E-9ADD-39E7-B22A-62CBBD2CEF1B.dita"><apiname>DPrimaryMediaBase</apiname></xref> object and register |
|
113 it with the local media subsystem. To support paging, the entry point needs |
|
114 altering to register the paging device with the demand paging subsystem and |
|
115 instantiate and install the factory object. </p> <codeblock id="GUID-885C8178-46FB-5F4B-9755-E048A48C42A7" xml:space="preserve">DECLARE_STANDARD_EXTENSION() |
|
116 { |
|
117 TInt r=Kern::DfcQInit(&TestMediaDfcQ,KTestThreadPriority,&KTestMediaThreadName); |
|
118 if (r|=KErrNone) |
|
119 return r; |
|
120 |
|
121 DPrimaryMediaBase* pM=new DPrimaryMediaBase; |
|
122 if (!pM) |
|
123 return r; |
|
124 |
|
125 pM->iDfcQ=&TestMediaDfcQ; |
|
126 r=LocDrv::RegisterMediaDevice( |
|
127 MEDIA_DEVICE_NAND, |
|
128 NAND_DRIVECOUNT, |
|
129 NAND_DRIVELIST, |
|
130 pM, |
|
131 NAND_NUMMEDIA, |
|
132 NAND_DRIVENAME); |
|
133 if (r != KErrNone) |
|
134 return r; |
|
135 |
|
136 r = LocDrv::RegisterPagingDevice( |
|
137 pM, |
|
138 NAND_PAGEDRIVELIST, |
|
139 NAND_PAGEDRIVECOUNT, |
|
140 PAGING_TYPE, |
|
141 SECTOR_SHIFT, |
|
142 NUM_PAGES); |
|
143 if (r == KErrNone) |
|
144 { |
|
145 device = new DPhysicalDeviceMediaTest; |
|
146 if (device == NULL) |
|
147 return KErrNoMemory; |
|
148 r = Kern::InstallPhysicalDevice(device); |
|
149 } |
|
150 // Ignore error if demand paging not supported by kernel |
|
151 else if (r == KErrNotSupported) |
|
152 r = KErrNone; |
|
153 else |
|
154 return r; |
|
155 |
|
156 pM->iMsgQ.Receive(); |
|
157 return KErrNone; |
|
158 }</codeblock> <p>The fifth parameter passed to the function <xref href="GUID-9E60E8D9-619E-3A76-BAC8-93A60D62C7DF.dita#GUID-9E60E8D9-619E-3A76-BAC8-93A60D62C7DF/GUID-5FDD89C6-C34A-3A0D-A422-D148DDE23E42"><apiname>LocDrv::RegisterPagingDevice()</apiname></xref> named <codeph>SECTOR_SHIFT</codeph> is the log2 of the sector size for the given media. For example, passing |
|
159 a value of 9 corresponds to a sector size of 512 for most media. </p> <p> <note> The <xref href="GUID-52853C0D-CA98-3B92-B7D4-FF1C1F06C1A6.dita"><apiname>DECLARE_EXTENSION_PDD</apiname></xref> entry |
|
160 point is called some time later when the file server tries to load all the |
|
161 media drivers in the system. When this happens a second factory object is |
|
162 created by the media driver, but this is deleted by the kernel when it discovers |
|
163 that another factory object bearing the same name is already in its internal |
|
164 list.</note> </p> </section> |
|
165 <section id="GUID-C32CF25E-553B-5786-88ED-4587AC0DF3BA"><title>Changes to |
|
166 DLocalDrive::ECaps handling</title> <p>The <xref href="GUID-C57F8D34-DAB5-388F-A99F-A952916B7EA6.dita"><apiname>TLocalDriveCaps</apiname></xref> structure |
|
167 needs to be modified so that: </p> <ul> |
|
168 <li id="GUID-FECDE295-A9D3-5373-BD01-F2A7EAB83897"><p>the <xref href="GUID-FF7F3425-9F7C-3146-BA0A-FB68D1A2381C.dita"><apiname>KMediaAttPageable</apiname></xref> flag |
|
169 is set in <xref href="GUID-722A1F4D-3A76-3BE3-95AB-2AA7745930D0.dita"><apiname>iMediaAtt</apiname></xref> </p> </li> |
|
170 <li id="GUID-82EC6B7C-FF34-5E2C-BFF1-832C0769B517"><p>the <xref href="GUID-ED80FF32-9226-31E4-8717-D4A29948A75B.dita"><apiname>KDriveAttPageable</apiname></xref> flag |
|
171 is set if a particular drive has been registered as code paging. This is determined |
|
172 by testing <xref href="GUID-D84A9903-AE0F-3F54-8833-E8956A88E26C.dita#GUID-D84A9903-AE0F-3F54-8833-E8956A88E26C/GUID-F5F80522-E23D-3A3D-86B5-6DC6C9E5C3B1"><apiname>TLocDrvRequest::Drive()</apiname></xref> <codeph>->iPagingDrv</codeph>. </p> </li> |
|
173 </ul> <p>Additionally, the <xref href="GUID-C57F8D34-DAB5-388F-A99F-A952916B7EA6.dita"><apiname>TLocalDriveCaps</apiname></xref> <codeph>::iDriveAtt</codeph> must |
|
174 have the <xref href="GUID-89ABFCAC-65EF-3DF3-83B8-2B0A169CCAFA.dita"><apiname>KDriveAttLocal</apiname></xref> and <xref href="GUID-78343374-6F5D-365D-BF3E-9AD19C77FB80.dita"><apiname>KDriveAttInternal</apiname></xref> bits |
|
175 set and the <xref href="GUID-88C9C181-3BC3-35FB-BF82-A81C40EEDEB8.dita"><apiname>KDriveAttRemovable</apiname></xref> bit cleared. </p> <codeblock id="GUID-04F15DFB-144E-5966-88B5-227B7FC97B55" xml:space="preserve">TInt DMediaDriverTest::Request(TLocDrvRequest& aRequest) |
|
176 { |
|
177 TInt r=KErrNotSupported; |
|
178 TInt id=aRequest.Id(); |
|
179 |
|
180 if (id == DLocalDrive::ECaps) |
|
181 { |
|
182 TLocDrv* drive = aRequest.Drive(); |
|
183 TLocalDriveCapsV4& c = *(TLocalDriveCapsV4*)aRequest.RemoteDes(); |
|
184 r=Caps(*drive,c); |
|
185 } |
|
186 // etc… |
|
187 } |
|
188 |
|
189 TInt DMediaDriverTest::Caps(TLocDrv& aDrive, TLocalDriveCapsV4& caps) |
|
190 { |
|
191 // fill in rest of caps structure as usual… |
|
192 |
|
193 if(aDrive.iPrimaryMedia->iPagingMedia) |
|
194 caps.iMediaAtt|=KMediaAttPageable; |
|
195 if(aDrive.iPagingDrv) |
|
196 caps.iDriveAtt|=KDriveAttPageable; |
|
197 }</codeblock> </section> |
|
198 <section id="GUID-AE44672E-F60D-563C-BB6A-B70AF187C366"><title>Handling page |
|
199 requests</title> <p>Four new request types need to be handled to support paging: </p> <ul> |
|
200 <li id="GUID-703713F1-9276-583A-9963-325C04F8D4B6"><p> <xref href="GUID-951FB996-24B3-3340-8386-24B1A895EA16.dita"><apiname>EWriteRequestFragment</apiname></xref> marks |
|
201 the start and middle of a sequence of writes. </p> </li> |
|
202 <li id="GUID-F40CCE14-17DF-52EB-937F-CEBC2B78CC94"><p>Each sequence is terminated |
|
203 by a <xref href="GUID-8B4109E6-B9F8-3C18-9F9A-0AB20FDA5E86.dita"><apiname>EWriteRequestFragmentLast</apiname></xref> request as long as none |
|
204 of the prior requests completed with an error. </p> </li> |
|
205 <li id="GUID-47C8C482-77B4-5447-8497-E8185BF1350B"><p> <xref href="GUID-F20251F4-A72D-32E5-B2AF-87F71CD5CD87.dita"><apiname>ERomPageInRequest</apiname></xref> is |
|
206 treated as a normal read except that: </p> <ol id="GUID-DEEF7484-32E1-5739-839D-D1257A51B83C"> |
|
207 <li id="GUID-A90D4A45-05E4-5F9C-B47E-26F67F5462EE"><p>the list of partitions |
|
208 reported by <xref href="GUID-A0D4EB25-0BA4-39EE-874B-465EB9628DCC.dita#GUID-A0D4EB25-0BA4-39EE-874B-465EB9628DCC/GUID-B2F42829-028C-341A-B34D-A8243CA434EB"><apiname>DMediaDriver::PartitionInfo</apiname></xref> does not normally |
|
209 include the partition containing the ROM image. Therefore, the local media |
|
210 subsystem does not know the absolute position from the start of the media |
|
211 of a particular ROM page. The position stored in <xref href="GUID-F20251F4-A72D-32E5-B2AF-87F71CD5CD87.dita"><apiname>ERomPageInRequest</apiname></xref> is |
|
212 offset from the start of the ROM image, rather than the start of the media. |
|
213 Therefore, the media driver must add the offset of the start of the ROM image |
|
214 to the position stored in <xref href="GUID-F20251F4-A72D-32E5-B2AF-87F71CD5CD87.dita"><apiname>ERomPageInRequest</apiname></xref> to obtain the |
|
215 absolute position before issuing a read request. </p> </li> |
|
216 <li id="GUID-E020A5D1-82FA-5857-AB1D-42A59D337EFD"><p>when the read is complete |
|
217 the media driver needs to call <xref href="GUID-D84A9903-AE0F-3F54-8833-E8956A88E26C.dita#GUID-D84A9903-AE0F-3F54-8833-E8956A88E26C/GUID-362AB6B2-9C3D-342F-BB4A-F252ECD7EF3A"><apiname>TLocDrvRequest::WriteToPageHandler</apiname></xref> to |
|
218 write the data back to the client, rather than <xref href="GUID-D84A9903-AE0F-3F54-8833-E8956A88E26C.dita#GUID-D84A9903-AE0F-3F54-8833-E8956A88E26C/GUID-2AC4DBA4-5C87-39C7-B6CF-95ECB7286339"><apiname>TLocDrvRequest::WriteRemote</apiname></xref> as |
|
219 for a normal read, </p> </li> |
|
220 </ol> </li> |
|
221 <li id="GUID-50298F39-D1A0-5731-8E50-D18514941D70"><p> <xref href="GUID-E42B407D-8E18-337B-9CBB-4DCDD0AABBE9.dita"><apiname>ECodePageInRequest</apiname></xref> is |
|
222 treated as a normal read, except that the function <xref href="GUID-D84A9903-AE0F-3F54-8833-E8956A88E26C.dita#GUID-D84A9903-AE0F-3F54-8833-E8956A88E26C/GUID-362AB6B2-9C3D-342F-BB4A-F252ECD7EF3A"><apiname>TLocDrvRequest::WriteToPageHandler</apiname></xref> should |
|
223 be used to write the data back to the demand paging subsystem. However, the |
|
224 position in the request is offset from the start of the media as for a normal |
|
225 read. </p> </li> |
|
226 </ul> <p>These request types are enumerated in the <xref href="GUID-6C039CFA-BF2F-3272-80FE-71430C12F0F4.dita"><apiname>DMediaPagingDevice</apiname></xref> class: </p> <codeblock id="GUID-AD9B48CF-7757-5C8A-A2EF-B27F2DC9BDD8" xml:space="preserve">NONSHARABLE_CLASS(DMediaPagingDevice) : public DPagingDevice |
|
227 { |
|
228 public: |
|
229 enum TPagingRequestId |
|
230 { |
|
231 /** |
|
232 Identifies any middle fragment of a Write request on a partition of a media that supports paging. |
|
233 */ |
|
234 EWriteRequestFragment = |
|
235 DLocalDrive::EFirstReqNumberReservedForPaging, |
|
236 |
|
237 /** |
|
238 Identifies the last fragment of a Write request on a partition of a media that supports paging. |
|
239 */ |
|
240 EWriteRequestFragmentLast = |
|
241 DLocalDrive::EFirstReqNumberReservedForPaging+1, |
|
242 |
|
243 /** |
|
244 Request for paging in (read) data from the ROM store area. |
|
245 */ |
|
246 ERomPageInRequest = |
|
247 DLocalDrive::EFirstReqNumberReservedForPaging+2, |
|
248 |
|
249 /** |
|
250 Request for paging in (read) data from the code store area. |
|
251 */ |
|
252 ECodePageInRequest = |
|
253 DLocalDrive::ELastReqNumberReservedForPaging |
|
254 }; |
|
255 //etc… |
|
256 }</codeblock> </section> |
|
257 <section id="GUID-0EA673E6-FEE4-51F6-9C84-9411316D7357"><title>Handling fragmented |
|
258 write requests</title> <p>In many respects, <xref href="GUID-951FB996-24B3-3340-8386-24B1A895EA16.dita"><apiname>EWriteRequestFragment</apiname></xref> and <xref href="GUID-8B4109E6-B9F8-3C18-9F9A-0AB20FDA5E86.dita"><apiname>EWriteRequestFragmentLast</apiname></xref> can |
|
259 be treated as normal write requests. It should be noted however, that these |
|
260 write requests can be interleaved with requests from other file server threads |
|
261 if the media supports more than one partition, the resulting operations may |
|
262 be perceived as a functional break in behaviour. </p> <p>If it is important |
|
263 to maintain backwards compatibility and to prevent write requests from being |
|
264 interleaved, the media driver must keep track of the current write-request |
|
265 chain and defer requests from other drive threads while a write-fragment chain |
|
266 is in progress by: </p> <ul> |
|
267 <li id="GUID-311A0DF2-601D-5623-A059-7E20FAFEEF1C"><p>ensuring the local media |
|
268 subsystem LDD has been built with the <codeph>__ALLOW_CONCURRENT_FRAGMENTATION__</codeph> macro |
|
269 undefined. This ensures that the local media subsystem never issues more than |
|
270 one write fragment at a time </p> </li> |
|
271 <li id="GUID-9504A0D1-2147-5968-AB8C-2B9D99A48C0F"><p>modifying the paging-media |
|
272 driver so that it keeps track of write-request chains and defers any read |
|
273 or format requests received after the first fragment and before the last in |
|
274 a sequence. When undefined, the macro subsystem does not issue more than one |
|
275 write-request chain at a time. </p> </li> |
|
276 </ul><p><note> Write fragments should never be deferred, only read or format |
|
277 requests may be deferred. </note></p> <p>To achieve this the media driver |
|
278 can maintain a bit mask, each bit of which represents a write in progress |
|
279 flag for a particular drive: </p> <codeblock id="GUID-CB127C9B-51D5-5D1A-BAF6-4F8CEF308912" xml:space="preserve">iFragmenting|=(0x1<<iCurrentReq->Drive()->iDriveNumber);</codeblock> <p>If a read or format request is received while any of the bits in <codeph>iFragmenting</codeph> are |
|
280 set, that request may be deferred. </p> </section> |
|
281 </conbody></concept> |