|
1 // Copyright (c) 2007-2009 Nokia Corporation and/or its subsidiary(-ies). |
|
2 // All rights reserved. |
|
3 // This component and the accompanying materials are made available |
|
4 // under the terms of the License "Eclipse Public License v1.0" |
|
5 // which accompanies this distribution, and is available |
|
6 // at the URL "http://www.eclipse.org/legal/epl-v10.html". |
|
7 // |
|
8 // Initial Contributors: |
|
9 // Nokia Corporation - initial contribution. |
|
10 // |
|
11 // Contributors: |
|
12 // |
|
13 // Description: |
|
14 // |
|
15 |
|
16 #ifndef MPAGEARRAY_H |
|
17 #define MPAGEARRAY_H |
|
18 |
|
19 #include "mmu.h" |
|
20 |
|
21 const TUint KPageArraySegmentShift = 4; |
|
22 |
|
23 /** |
|
24 Number of entries in each segment RPageArray::TSegment. |
|
25 */ |
|
26 const TUint KPageArraySegmentSize = (1<<KPageArraySegmentShift); |
|
27 |
|
28 const TUint KPageArraySegmentMask = KPageArraySegmentSize-1; |
|
29 |
|
30 /** |
|
31 Bit position in RPageArray::TSegment::iCount for the least significant bit |
|
32 of the 'AllocCount'. I.e. the number of entries which are not empty. |
|
33 */ |
|
34 const TUint KPageArraySegmentAllocCountShift = 31-KPageArraySegmentShift; |
|
35 |
|
36 const TUint KPageArraySegmentLockCountMask = (1<<KPageArraySegmentAllocCountShift)-1; |
|
37 |
|
38 /** |
|
39 Array which contains the physical addresses of all the pages contained in a DMemoryObject. |
|
40 This is a sparse array, therefore memory storage may not exist for unallocated pages entries. |
|
41 Where storage does exists for unallocated entries, a state value of ENotPresent indicates this. |
|
42 For allocated entries, the redundant least significant bits of each entry contain flags and state |
|
43 from from enum TFlags and TState. |
|
44 |
|
45 To add pages to the array: |
|
46 |
|
47 @code |
|
48 RPageArray::TIter iter; |
|
49 array.AddStart(index,count,iter); |
|
50 RPageArray::TIter pageList; |
|
51 while(n = iter.AddFind(pageList)) |
|
52 { |
|
53 pageList.Add(n,pages); |
|
54 // or pageList.AddContiguous |
|
55 } |
|
56 array.AddEnd(index,count); |
|
57 @endcode |
|
58 |
|
59 |
|
60 To remove pages from the array: |
|
61 |
|
62 @code |
|
63 RPageArray::TIter iter; |
|
64 array.FindStart(index,count,iter); |
|
65 RPageArray::TIter pageList; |
|
66 while(n = iter.RemoveFind(pageList)) |
|
67 { |
|
68 pageList.Remove(n,pages); |
|
69 iter.FindRelease(n); |
|
70 } |
|
71 array.FindEnd(index,count); |
|
72 @endcode |
|
73 |
|
74 Mutual exclusion must be used to ensure that only a single Add or Remove operation is in |
|
75 progress at any time. |
|
76 |
|
77 |
|
78 To query the contents of the array: |
|
79 |
|
80 @code |
|
81 RPageArray::TIter iter; |
|
82 array.FindStart(index,count,iter); |
|
83 RPageArray::TIter pageList; |
|
84 while(n=iter.Find(pageList)); |
|
85 { |
|
86 TPhysAddr* pages; |
|
87 while(n = pageList.Pages(pages,max)) |
|
88 { |
|
89 // do something with pages |
|
90 pageList.Skip(n); |
|
91 } |
|
92 iter.FindRelease(n); |
|
93 } |
|
94 array.FindEnd(index,count); |
|
95 @endcode |
|
96 |
|
97 */ |
|
98 class RPageArray |
|
99 { |
|
100 public: |
|
101 class TSegment; |
|
102 class TIter; |
|
103 |
|
104 /** |
|
105 States for pages stored in the array. These are stored in least significant part of each entry. |
|
106 */ |
|
107 enum TState |
|
108 { |
|
109 ENotPresent = 0x000, ///< No page present. |
|
110 EDecommitted = 0x001, ///< Paged Decommitted, but is pinned |
|
111 EDecommitting = 0x002, ///< Page is in the process of being decommitted |
|
112 EStealing = 0x003, ///< Page is in the process of being stolen |
|
113 ERestrictingNA = 0x004, ///< Page is in the process of having no-access restrictions applied |
|
114 EMoving = 0x005, ///< Page is in the process of being moved to another physical page |
|
115 ECommitted = 0x006, ///< Page is committed |
|
116 |
|
117 EStateShift = 3, ///< Number of bits needed to store state values. |
|
118 EStateMask = (1<<EStateShift)-1, ///< Mask for state values |
|
119 |
|
120 EEmptyEntry = ENotPresent ///< Value of an empty array entry |
|
121 }; |
|
122 |
|
123 /** |
|
124 Flags stored in array entries in addition to the state. |
|
125 */ |
|
126 enum TFlags |
|
127 { |
|
128 EUnmapVetoed = 1<<EStateShift, ///< A Steal or Decommit operation on the page has been vetoed |
|
129 |
|
130 EFlagsShift = 1, ///< Number of bits needed to store flags. |
|
131 EFlagsMask = ((1<<EFlagsShift)-1)<<EStateShift ///< Mask for flags values |
|
132 }; |
|
133 |
|
134 /** |
|
135 Return true if the array entry \a aPage is currently being decommitted. |
|
136 */ |
|
137 static FORCE_INLINE TBool TargetStateIsDecommitted(TPhysAddr aPage) |
|
138 { |
|
139 return State(aPage)<=EStealing; |
|
140 } |
|
141 |
|
142 /** |
|
143 Return true if the array entry \a aPage is currently committed and may be being moved. |
|
144 */ |
|
145 static FORCE_INLINE TBool TargetStateIsCommitted(TPhysAddr aPage) |
|
146 { |
|
147 __ASSERT_COMPILE(RPageArray::EMoving == RPageArray::ECommitted - 1); |
|
148 return State(aPage)>=EMoving; |
|
149 } |
|
150 |
|
151 /** |
|
152 Return true if the array entry \a aPage is not present. |
|
153 */ |
|
154 static FORCE_INLINE TBool IsPresent(TPhysAddr aPage) |
|
155 { |
|
156 return State(aPage)!=ENotPresent; |
|
157 } |
|
158 |
|
159 /** |
|
160 Return the TState value in the array entry \a aPage. |
|
161 */ |
|
162 static FORCE_INLINE TState State(TPhysAddr aPage) |
|
163 { |
|
164 return (TState)(aPage&EStateMask); |
|
165 } |
|
166 |
|
167 /** |
|
168 Page moving has ended so set the page back to committed if no other |
|
169 operation has occurred/is occurring. |
|
170 |
|
171 @param aEntry A reference to the entry to update. |
|
172 */ |
|
173 static FORCE_INLINE void MovePageEnd(TPhysAddr& aEntry) |
|
174 { |
|
175 if (State(aEntry) == EMoving) |
|
176 aEntry = (aEntry & ~EStateMask) | ECommitted; |
|
177 } |
|
178 |
|
179 /** |
|
180 Update the physical address in the array entry \a aEntry. |
|
181 @param aEntry A reference to the entry to update. |
|
182 @param aPhysAddr The new physical address. |
|
183 */ |
|
184 static FORCE_INLINE void PageMoveNewAddr(TPhysAddr& aEntry, TPhysAddr aPhysAddr) |
|
185 { |
|
186 __NK_ASSERT_DEBUG(!(aPhysAddr & EStateMask)); |
|
187 __NK_ASSERT_DEBUG(State(aEntry) == EMoving); |
|
188 aEntry = (aEntry & EStateMask) | aPhysAddr; |
|
189 } |
|
190 |
|
191 static void Init2A(); |
|
192 static void Init2B(DMutex* aLock); |
|
193 |
|
194 RPageArray(); |
|
195 ~RPageArray(); |
|
196 |
|
197 /** |
|
198 Second stage constructor for the array. |
|
199 |
|
200 @param aMaxPages The maximum number of entries to be stored in the array. |
|
201 @param aPreallocateMemory If true, then all the memory required to store the array |
|
202 entries is allocated immediately - rather than on demand |
|
203 as entries are added. |
|
204 */ |
|
205 TInt Construct(TUint aMaxPages, TBool aPreallocateMemory=EFalse); |
|
206 |
|
207 /** |
|
208 Allocate all memory required to store array entries. |
|
209 This is only for use during system boot. |
|
210 */ |
|
211 TInt PreallocateMemory(); |
|
212 |
|
213 /** |
|
214 Ensures the memory to store a region of array entries is allocated and locked. |
|
215 |
|
216 @param aIndex Start index of region. |
|
217 @param aCount Number of pages in region. |
|
218 |
|
219 @see RPageArray::Free() |
|
220 */ |
|
221 TInt Alloc(TUint aIndex, TUint aCount); |
|
222 |
|
223 /** |
|
224 Revert the action of #Alloc by unlocking the memory used for a region of array entries. |
|
225 Note, calling #Free for any entry more times than #Alloc was used will have |
|
226 unpredictable results. |
|
227 |
|
228 @param aIndex Start index of region. |
|
229 @param aCount Number of pages in region. |
|
230 */ |
|
231 void Free(TUint aIndex, TUint aCount); |
|
232 |
|
233 /** |
|
234 Prepare to add (commit) pages to a region in this array. |
|
235 This ensures the memory to store the entries is allocated and locked. It also, |
|
236 optionally and by default, check that these entries are empty. |
|
237 |
|
238 @param aIndex Start index of region. |
|
239 @param aCount Number of pages in region. |
|
240 @param[out] aIter An iterator which covers the specified region. |
|
241 @param aAllowExisting True if the region may contain non-empty entries. |
|
242 False to assert entries are empty. |
|
243 |
|
244 @see RPageArray::AddEnd() |
|
245 */ |
|
246 TInt AddStart(TUint aIndex, TUint aCount, TIter& aIter, TBool aAllowExisting=EFalse); |
|
247 |
|
248 /** |
|
249 End an 'add' operation started with #AddStart. |
|
250 This must be called to unlock any page array memory which #AddStart locked. |
|
251 |
|
252 @param aIndex Start index of region. Must be same value as corresponding call to #AddStart. |
|
253 @param aCount Number of pages in region. Must be same value as corresponding call to #AddStart. |
|
254 */ |
|
255 void AddEnd(TUint aIndex, TUint aCount); |
|
256 |
|
257 /** |
|
258 Prepare to search a region in this array. |
|
259 |
|
260 @param aIndex Start index of region. |
|
261 @param aCount Number of pages in region. |
|
262 @param[out] aIter An iterator which covers the specified region. |
|
263 |
|
264 @see RPageArray::AddEnd() |
|
265 */ |
|
266 void FindStart(TUint aIndex, TUint aCount, TIter& aIter); |
|
267 |
|
268 /** |
|
269 End a find operation started with #FindStart. |
|
270 |
|
271 @param aIndex Start index of region. Must be same value as corresponding call to #FindStart. |
|
272 @param aCount Number of pages in region. Must be same value as corresponding call to #FindStart. |
|
273 */ |
|
274 void FindEnd(TUint aIndex, TUint aCount); |
|
275 |
|
276 /** |
|
277 Prepare to add (commit) a single page to this array. |
|
278 This ensures the memory to store the entry is allocated and locked. |
|
279 |
|
280 @param aIndex Index of entry. |
|
281 @param[out] aPageList An iterator represents the single array entry. |
|
282 |
|
283 @return Pointer to the array entry, |
|
284 or the null pointer if memory allocation failed. |
|
285 |
|
286 @see RPageArray::AddPage() |
|
287 @see RPageArray::AddPageEnd() |
|
288 */ |
|
289 TPhysAddr* AddPageStart(TUint aIndex, TIter& aPageList); |
|
290 |
|
291 /** |
|
292 Add (commit) a single page to the array. |
|
293 |
|
294 @param aPageEntry The address of the array entry as returned by AddPageStart. |
|
295 @param aPage The physical address of the page being added. |
|
296 */ |
|
297 static void AddPage(TPhysAddr* aPageEntry, TPhysAddr aPage); |
|
298 |
|
299 /** |
|
300 End an 'add' operation started with #AddPageStart. |
|
301 This must be called to unlock any page array memory which #AddPageStart locked. |
|
302 |
|
303 @param aIndex Index of entry. Must be same value as corresponding call to #AddPageStart. |
|
304 @param aDelta 1 (one), if the array entry was changed from ENotPresent state (e.g. AddPage called), |
|
305 zero otherwise. |
|
306 */ |
|
307 void AddPageEnd(TUint aIndex, TInt aDelta); |
|
308 |
|
309 /** |
|
310 Prepare to remove (decommit) a single page from this array. |
|
311 |
|
312 This function is similar to TIter::RemoveFind and updates the array entry and |
|
313 memory locking in the same way. |
|
314 |
|
315 @param aIndex Index of entry. |
|
316 @param[out] aPageList An iterator representing the single array entry. |
|
317 Not set if this method returns the null pointer. |
|
318 |
|
319 @return Pointer to the array entry, |
|
320 or the null pointer if entry does not need decommitting. |
|
321 |
|
322 @see RPageArray::RemovePage() |
|
323 @see RPageArray::RemovePageEnd() |
|
324 */ |
|
325 TPhysAddr* RemovePageStart(TUint aIndex, TIter& aPageList); |
|
326 |
|
327 /** |
|
328 Remove a single page from the array. |
|
329 |
|
330 This function is similar to TIter::Remove and updates the array entry in the same way. |
|
331 |
|
332 @param aPageEntry The address of the array entry as returned by RemovePageStart. |
|
333 |
|
334 @return The physical address of the page which was removed, |
|
335 or KPhysAddrInvalid if no page was removed. |
|
336 */ |
|
337 static TPhysAddr RemovePage(TPhysAddr* aPageEntry); |
|
338 |
|
339 /** |
|
340 End an 'remove' operation started with #RemovePageStart. |
|
341 This must be called to unlock any page array memory which #RemovePageStart locked. |
|
342 |
|
343 @param aIndex Index of entry. Must be same value as corresponding call to #RemovePageStart. |
|
344 @param aDelta 1 (one), if the array entry was set ENotPresent state (RemovePage succeeded), |
|
345 zero otherwise. |
|
346 */ |
|
347 void RemovePageEnd(TUint aIndex, TInt aDelta); |
|
348 |
|
349 /** |
|
350 Prepare to restrict access to a single page in this array. |
|
351 |
|
352 If the page entry state indicates that the page is already more restricted |
|
353 than being requested, then the function returns the null pointer and does nothing. |
|
354 |
|
355 If the page does need its access restricting then its entry in the array is set to |
|
356 ERestrictingNA and the memory for the entry is locked. |
|
357 |
|
358 @param aIndex Index of entry. |
|
359 @param[out] aPageList An iterator representing the single array entry. |
|
360 Not set if this method returns the null pointer. |
|
361 |
|
362 @return Pointer to the array entry, |
|
363 or the null pointer if entry does not need it's access restricting further. |
|
364 |
|
365 @see RPageArray::RestrictPageNAEnd() |
|
366 */ |
|
367 TPhysAddr* RestrictPageNAStart(TUint aIndex, TIter& aPageList); |
|
368 |
|
369 /** |
|
370 End an 'restrict' operation started with #RestrictPageStart. |
|
371 This must be called to unlock any page array memory which #RestrictPageStart locked. |
|
372 |
|
373 @param aIndex Index of entry. Must be same value as corresponding call to #RestrictPageStart. |
|
374 */ |
|
375 void RestrictPageNAEnd(TUint aIndex); |
|
376 |
|
377 /** |
|
378 Prepare to steal a single page from this array. |
|
379 |
|
380 The memory for the entry is locked and if the page entry is is in one of the committed |
|
381 states then it is changed to state EStealing. |
|
382 |
|
383 @param aIndex Index of entry. |
|
384 @param[out] aPageList An iterator representing the single array entry. |
|
385 Not set if this method returns the null pointer. |
|
386 |
|
387 @return Pointer to the array entry. |
|
388 |
|
389 @see RPageArray::StealPageEnd() |
|
390 */ |
|
391 TPhysAddr* StealPageStart(TUint aIndex, TIter& aPageList); |
|
392 |
|
393 /** |
|
394 End an 'steal' operation started with #StealPageStart. |
|
395 This must be called to unlock any page array memory which #StealPageStart locked. |
|
396 |
|
397 @param aIndex Index of entry. Must be same value as corresponding call to #StealPageStart. |
|
398 @param aDelta 1 (one), if the array entry was set ENotPresent state (the page was stolen), |
|
399 zero otherwise. |
|
400 */ |
|
401 void StealPageEnd(TUint aIndex, TInt aDelta); |
|
402 |
|
403 /** |
|
404 Prepare to move a page in this array by changing its state to EMoving. |
|
405 |
|
406 Note - the memory entry isn't locked as the RamAllocLock mutex must be held |
|
407 through out the page moving process and therefore the page cannot be removed. |
|
408 |
|
409 @param aIndex The index of the entry to be moved. |
|
410 @param[out] aPageList An iterator representing the single array entry. |
|
411 Not set if this method returns the null pointer. |
|
412 |
|
413 @return Pointer to the array entry, NULL if the page cannot be moved. |
|
414 |
|
415 @see RPageArray::MovePageEnd() |
|
416 */ |
|
417 TPhysAddr* MovePageStart(TUint aIndex, TIter& aPageList); |
|
418 |
|
419 /** |
|
420 Return the array entry for index \a aIndex. |
|
421 */ |
|
422 TPhysAddr Page(TUint aIndex); |
|
423 |
|
424 |
|
425 /** |
|
426 Return a pointer to the array entry for index \a aIndex. |
|
427 |
|
428 @return Pointer to the array entry, NULL if the page cannot found. |
|
429 */ |
|
430 TPhysAddr* PageEntry(TUint aIndex); |
|
431 |
|
432 /** |
|
433 Return the physical address of the page at index \a aIndex, or KPhysAddrInvalid if none present. |
|
434 */ |
|
435 TPhysAddr PhysAddr(TUint aIndex); |
|
436 |
|
437 /** |
|
438 Get the physical address for the pages stored in the specified region in the array. |
|
439 |
|
440 @param aIndex Start index of region. |
|
441 @param aCount Number of pages in region. |
|
442 @param[out] aPhysicalAddress If all pages are physically contiguous this is set to the start address, |
|
443 otherwise this is set to KPhysAddrInvalid. |
|
444 @param[out] aPhysicalPageList Pointer to array of \a aCount physical addresses which |
|
445 will be filled with the physical addressed of each page in the region. |
|
446 |
|
447 @return 0 (zero) if all pages in region are physically contiguous; |
|
448 1 (one) if pages are not physically contiguous; |
|
449 KErrNotFound, if any page in the region is not present. |
|
450 */ |
|
451 TInt PhysAddr(TUint aIndex, TUint aCount, TPhysAddr& aPhysicalAddress, TPhysAddr* aPhysicalPageList); |
|
452 |
|
453 enum |
|
454 { |
|
455 /** |
|
456 Maximum number of bits which can be stored in an array entry by SetPagingManagerData. |
|
457 */ |
|
458 KPagingManagerDataBits = 32-(EFlagsShift+EStateShift), |
|
459 }; |
|
460 |
|
461 enum |
|
462 { |
|
463 /** |
|
464 Maximum value which can be stored in an array entry by SetPagingManagerData. |
|
465 */ |
|
466 KMaxPagingManagerData = (1u<<KPagingManagerDataBits)-1u |
|
467 }; |
|
468 |
|
469 /** |
|
470 Write \a aValue to the paging manager data for index \a aIndex. |
|
471 The value must not exceed KMaxPagingManagerData. |
|
472 |
|
473 This value is stored in the page array entry, if it's state is ENotPresent; |
|
474 otherwise it is stored in the SPageInfo object for the page in the array entry. |
|
475 */ |
|
476 void SetPagingManagerData(TUint aIndex, TUint aValue); |
|
477 |
|
478 /** |
|
479 Return the paging manager data for index \a aIndex. |
|
480 @see RPageArray::SetPagingManagerData() |
|
481 */ |
|
482 TUint PagingManagerData(TUint aIndex); |
|
483 |
|
484 |
|
485 private: |
|
486 /** |
|
487 Unlock the memory used for a region of array entries. |
|
488 |
|
489 @param aSegments Copy of RPageArray::iSegments from the array. |
|
490 @param aIndex Start index of region. |
|
491 @param aCount Number of pages in region. |
|
492 */ |
|
493 static void Release(TSegment** aSegments, TUint aIndex, TUint aCount); |
|
494 |
|
495 /** |
|
496 Unlocking the memory used for a single array entry. |
|
497 This also updates |
|
498 |
|
499 @param aIndex The index of the array entry. |
|
500 @param aDelta The change in the 'present' state for the entry. This is |
|
501 1 if the entry was added (state changed from ENotPresent), |
|
502 -1 if the entry was removed (state changed to ENotPresent), |
|
503 0 otherwise. |
|
504 */ |
|
505 void ReleasePage(TUint aIndex, TInt aDelta); |
|
506 |
|
507 /** |
|
508 Return the array segment in at \a aSegmentEntry, allocating a new one to this if |
|
509 none previously existed. Return the null pointer in no segment could be allocated |
|
510 (out of memory). |
|
511 |
|
512 The returned segment is locked (TSegment::Lock) \a aLockCount times; this normally |
|
513 represents the number of entries in the segment which are to be accesses. |
|
514 */ |
|
515 TSegment* GetOrAllocateSegment(TSegment** aSegmentEntry, TUint aLockCount); |
|
516 private: |
|
517 TUint8 iPreallocatedMemory; ///< Set true, if this array was constructed with pre-allocated memory. See #Construct. |
|
518 TUint iNumSegments; ///< The number of segments in array iSegments. |
|
519 TSegment** iSegments; ///< Array of TSegment objects allocated for this array. May contain null pointers. |
|
520 |
|
521 public: |
|
522 /** |
|
523 Class for iterating through and manipulating a section of entries in an RPageArray. |
|
524 */ |
|
525 class TIter |
|
526 { |
|
527 public: |
|
528 /** |
|
529 Find the next region of empty entries. |
|
530 |
|
531 @param[out] aPageList The found region. |
|
532 The #Add or #AddContiguous method is normally subsequently used on this. |
|
533 |
|
534 @return The number of pages in the found region. Zero indicating no more empty entries were found. |
|
535 |
|
536 @post This iterator is updated start immediately after the found region returned in \a aPageList. |
|
537 */ |
|
538 TUint AddFind(TIter& aPageList); |
|
539 |
|
540 /** |
|
541 Add pages to the array, setting each entry state as ECommitted. |
|
542 |
|
543 @param aCount The number of pages to add. |
|
544 @param aPages Pointer to list of \a aCount physical page addresses to add. |
|
545 */ |
|
546 void Add(TUint aCount, TPhysAddr* aPages); |
|
547 |
|
548 /** |
|
549 Add contiguous pages to the array, setting each entry state as ECommitted. |
|
550 |
|
551 @param aCount The number of pages to add. |
|
552 @param aPhysAddr The physical address of the first page to add. |
|
553 */ |
|
554 void AddContiguous(TUint aCount, TPhysAddr aPhysAddr); |
|
555 |
|
556 /** |
|
557 Update iterator and array state as if pages had been added with #Add. |
|
558 This is used after array entries have been directly manipulated rather |
|
559 than being updated through #Add. |
|
560 |
|
561 @param aCount The number of pages to move this iterator on by. |
|
562 @param aChanged The number of new entries which have been added to the array. |
|
563 */ |
|
564 void Added(TUint aCount, TUint aChanged); |
|
565 |
|
566 /** |
|
567 Find the next region of non-empty entries and lock the memory used to store these. |
|
568 |
|
569 @param[out] aPageList The found region. |
|
570 The #Pages method is normally subsequently used on this. |
|
571 |
|
572 @return The number of pages in the found region. Zero indicating no more empty entries were found. |
|
573 |
|
574 @post This iterator is updated to start at the first found entry. |
|
575 |
|
576 @see RPageArray::FindRelease() |
|
577 */ |
|
578 TUint Find(TIter& aPageList); |
|
579 |
|
580 /** |
|
581 Unlock the page array memory locked by #Find or #RemoveFind and move this iterator |
|
582 past this region in preparation for a subsequent find operation. |
|
583 |
|
584 @param aCount The number of pages returned by the corresponding find function. |
|
585 |
|
586 @post This iterator is updated to start immediately after the region |
|
587 returned by the corresponding find function. |
|
588 */ |
|
589 void FindRelease(TUint aCount); |
|
590 |
|
591 /** |
|
592 Find the next region of entries to be removed (decommitted). |
|
593 The entries found are those which are neither empty nor in state EDecommitted. |
|
594 They are updated to state EDecommitting and the memory used to store these entries |
|
595 is locked. To unlock the memory and continue searching FindRelease |
|
596 |
|
597 @param[out] aPageList The found region. |
|
598 The #Remove method is normally subsequently used on this. |
|
599 |
|
600 @return The number of pages in the found region. Zero indicating no more empty entries were found. |
|
601 |
|
602 @post This iterator is updated to start at the first found entry. |
|
603 |
|
604 @see RPageArray::FindRelease() |
|
605 @see RPageArray::Remove() |
|
606 */ |
|
607 TUint RemoveFind(TIter& aPageList); |
|
608 |
|
609 /** |
|
610 Remove pages from the array. |
|
611 |
|
612 For each entry found to be in the EDecommitting state (as set by #RemoveFind) |
|
613 the page address in the entry is appended to the supplied array (\a aPages) and |
|
614 the entry set to EEmptyEntry. However, if the array entry has the EUnmapVetoed flag set |
|
615 then instead the entry state is set to EDecommitted and the page address is not appended |
|
616 to \a aPages. |
|
617 |
|
618 @param aMaxCount The maximum number of pages to remove. |
|
619 @param[out] aPages Pointer to array of \a aMaxCount physical addresses which |
|
620 will be set to the physical addresses of the pages removed. |
|
621 |
|
622 @return The number of pages removed from the array and stored at \a aPages. |
|
623 |
|
624 @post This iterator is updated start immediately after the last removed entry. |
|
625 */ |
|
626 TUint Remove(TUint aMaxCount, TPhysAddr* aPages); |
|
627 |
|
628 /** |
|
629 Return a pointer to the array entries represented by this iterator. |
|
630 |
|
631 As array entries may not be stored contiguously in memory this method returns the |
|
632 number of valid entries. |
|
633 |
|
634 This method should only be used for array entries which have had their |
|
635 memory locked or for which there are other guarantees that the memory is present. |
|
636 |
|
637 @param[out] aStart Set to the address of the first array entry. |
|
638 @param aMaxCount The maximum count this function should return. |
|
639 |
|
640 @return The number of array entries starting at \a aStart which are valid. |
|
641 */ |
|
642 TUint Pages(TPhysAddr*& aStart, TUint aMaxCount=~0u); |
|
643 |
|
644 /** |
|
645 Move this iterator on by \a aCount pages. |
|
646 */ |
|
647 void Skip(TUint aCount); |
|
648 |
|
649 /** |
|
650 Prevent pages in the region covered by this iterator from having their |
|
651 access restricted. This is achieved by returning any entries currently |
|
652 in the specified 'being restricted' state to be fully committed again (state ECommitted). |
|
653 |
|
654 @param aPageMoving ETrue to veto pages being restricted for page moving (EMoving). Set to EFalse otherwise. |
|
655 */ |
|
656 void VetoRestrict(TBool aPageMoving); |
|
657 |
|
658 /** |
|
659 Prevent pages in the region covered by this iterator from being removed from the array. |
|
660 This is achieved by setting the EUnmapVetoed flag for all entries with a current state |
|
661 indicating they are being decommitted, c.f. TargetStateIsDecommitted. |
|
662 */ |
|
663 void VetoUnmap(); |
|
664 |
|
665 /** |
|
666 Default constructor which does not initialise members. |
|
667 */ |
|
668 TIter(); |
|
669 |
|
670 /** |
|
671 Return a new iterator which represents the array region [aIndex..aEndIndex). |
|
672 The new region is asserted to be within that specified by this iterator. |
|
673 */ |
|
674 TIter Slice(TUint aIndex, TUint aEndIndex); |
|
675 |
|
676 /** |
|
677 Return a new iterator which represents the first \a aCount pages of this one. |
|
678 */ |
|
679 TIter Left(TUint aCount); |
|
680 |
|
681 /** |
|
682 Return the start index of the region being represented by this iterator. |
|
683 */ |
|
684 FORCE_INLINE TUint Index() const |
|
685 { return iIndex; } |
|
686 |
|
687 /** |
|
688 Return the index immediately after the being represented by this iterator. |
|
689 */ |
|
690 FORCE_INLINE TUint IndexEnd() const |
|
691 { return iEndIndex; } |
|
692 |
|
693 /** |
|
694 Return the number of entries in the region represented by this iterator. |
|
695 */ |
|
696 FORCE_INLINE TUint Count() const |
|
697 { return iEndIndex-iIndex; } |
|
698 |
|
699 private: |
|
700 TIter(TSegment** aSegments, TUint aIndex, TUint aEndIndex); |
|
701 void Set(TSegment** aSegments, TUint aIndex, TUint aEndIndex); |
|
702 private: |
|
703 TSegment** iSegments; ///< Copy of RPageArray::iSegments of the array being represented by this iterator. |
|
704 TUint iIndex; ///< Start index of the array region being represented by this iterator. |
|
705 TUint iEndIndex; ///< The index immediately after the array region being represented by this iterator. |
|
706 |
|
707 friend class RPageArray; |
|
708 }; |
|
709 |
|
710 /** |
|
711 Class representing the memory storage for a 'segment' of entries in an RPageArray. |
|
712 Each segment contains storage for #KPageArraySegmentSize entries and the number |
|
713 of these which are not #EEmptyEntry are counted by the 'alloc count'. |
|
714 Each segment also has a 'lock count' which acts as a reference count preventing |
|
715 the segment from being deleted whilst it is being manipulated. |
|
716 Both of these counts are combined in #iCounts. |
|
717 */ |
|
718 class TSegment |
|
719 { |
|
720 private: |
|
721 /** |
|
722 Return a newly allocated segment or the null pointer if out-ot-memory. |
|
723 */ |
|
724 static TSegment* New(); |
|
725 |
|
726 /** |
|
727 Delete \a aSegment and return the null pointer. |
|
728 */ |
|
729 static TSegment* Delete(TSegment* aSegment); |
|
730 |
|
731 /** |
|
732 Lock this segment \a aCount times. This prevents the segment being deleted. |
|
733 */ |
|
734 void Lock(TUint aCount=1); |
|
735 |
|
736 /** |
|
737 Unlock \a aSegment \a aCount times. |
|
738 If the lock count reaches zero and the segment has no allocated entries |
|
739 then it is deleted and \a aSegment set to the null pointer. |
|
740 */ |
|
741 static TBool Unlock(TSegment*& aSegment, TUint aCount=1); |
|
742 |
|
743 /** |
|
744 Adjust the allocation count for this segment by \a aDelta. |
|
745 The allocation count keeps count of the number of entries which are not #EEmptyEntry. |
|
746 */ |
|
747 void AdjustAllocCount(TInt aDelta); |
|
748 |
|
749 /** |
|
750 Debug function which outputs the contents of this segment to the kernel debug port. |
|
751 */ |
|
752 void Dump(); |
|
753 private: |
|
754 /** |
|
755 Storage for each array entry. |
|
756 */ |
|
757 TPhysAddr iPages[KPageArraySegmentSize]; |
|
758 |
|
759 /** |
|
760 Two count values are stored in this member. |
|
761 Bits 0..KPageArraySegmentAllocCountShift-1 is the 'lock count' modified by the |
|
762 Lock and Unlock methods. |
|
763 Bits KPageArraySegmentAllocCountShift..31 is the 'alloc count' modified by the |
|
764 AdjustAllocCount method. |
|
765 When both counts are zero, this segment is empty and not being used, |
|
766 and can therefore be deleted. |
|
767 Note, the alloc count is only valid when the lock count is zero, i.e. |
|
768 after all users have finished updating this segment. |
|
769 */ |
|
770 TUint iCounts; |
|
771 |
|
772 friend class RPageArray; |
|
773 friend class TIter; |
|
774 }; |
|
775 |
|
776 friend class RPageArray::TSegment; |
|
777 friend class RPageArray::TIter; |
|
778 }; |
|
779 |
|
780 |
|
781 |
|
782 // |
|
783 // RPageArray::TIter |
|
784 // |
|
785 |
|
786 FORCE_INLINE RPageArray::TIter::TIter() |
|
787 { |
|
788 #ifdef _DEBUG |
|
789 iSegments = 0; |
|
790 iIndex = 0; |
|
791 iEndIndex = ~0u; |
|
792 #endif |
|
793 } |
|
794 |
|
795 FORCE_INLINE RPageArray::TIter::TIter(RPageArray::TSegment** aSegments, TUint aIndex, TUint aEndIndex) |
|
796 : iSegments(aSegments), iIndex(aIndex), iEndIndex(aEndIndex) |
|
797 { |
|
798 __NK_ASSERT_DEBUG(iEndIndex>=aIndex); |
|
799 } |
|
800 |
|
801 FORCE_INLINE RPageArray::TIter RPageArray::TIter::Slice(TUint aIndex, TUint aEndIndex) |
|
802 { |
|
803 __NK_ASSERT_DEBUG(aEndIndex>=aIndex); |
|
804 __NK_ASSERT_DEBUG(aIndex>=iIndex); |
|
805 __NK_ASSERT_DEBUG(aEndIndex<=iEndIndex); |
|
806 return TIter(iSegments,aIndex,aEndIndex); |
|
807 } |
|
808 |
|
809 FORCE_INLINE RPageArray::TIter RPageArray::TIter::Left(TUint aCount) |
|
810 { |
|
811 __NK_ASSERT_DEBUG(aCount<=Count()); |
|
812 return TIter(iSegments,iIndex,iIndex+aCount); |
|
813 } |
|
814 |
|
815 FORCE_INLINE void RPageArray::TIter::Skip(TUint aCount) |
|
816 { |
|
817 __NK_ASSERT_DEBUG(iIndex+aCount>=iIndex); |
|
818 __NK_ASSERT_DEBUG(iIndex+aCount<=iEndIndex); |
|
819 iIndex += aCount; |
|
820 } |
|
821 |
|
822 |
|
823 // |
|
824 // RPageArray |
|
825 // |
|
826 |
|
827 FORCE_INLINE void RPageArray::FindEnd(TUint /*aIndex*/, TUint /*aCount*/) |
|
828 { |
|
829 // nothing to do |
|
830 } |
|
831 |
|
832 FORCE_INLINE void RPageArray::AddPageEnd(TUint aIndex, TInt aDelta) |
|
833 { |
|
834 MmuLock::Lock(); |
|
835 ReleasePage(aIndex,aDelta); |
|
836 MmuLock::Unlock(); |
|
837 } |
|
838 |
|
839 FORCE_INLINE void RPageArray::AddPage(TPhysAddr* aPageEntry, TPhysAddr aPage) |
|
840 { |
|
841 __NK_ASSERT_DEBUG(MmuLock::IsHeld()); |
|
842 __NK_ASSERT_DEBUG((aPage&KPageMask)==0); |
|
843 __NK_ASSERT_DEBUG(!RPageArray::IsPresent(*aPageEntry)); |
|
844 *aPageEntry = aPage|RPageArray::ECommitted; |
|
845 } |
|
846 |
|
847 FORCE_INLINE void RPageArray::RestrictPageNAEnd(TUint aIndex) |
|
848 { |
|
849 ReleasePage(aIndex,0); |
|
850 } |
|
851 |
|
852 FORCE_INLINE void RPageArray::StealPageEnd(TUint aIndex, TInt aDelta) |
|
853 { |
|
854 ReleasePage(aIndex,-aDelta); |
|
855 } |
|
856 |
|
857 FORCE_INLINE void RPageArray::RemovePageEnd(TUint aIndex, TInt aDelta) |
|
858 { |
|
859 MmuLock::Lock(); |
|
860 ReleasePage(aIndex,-aDelta); |
|
861 MmuLock::Unlock(); |
|
862 } |
|
863 |
|
864 #endif |