kernel/eka/memmodel/epoc/flexible/mmu/mpagearray.h
changeset 9 96e5fb8b040d
child 22 2f92ad2dc5db
equal deleted inserted replaced
-1:000000000000 9:96e5fb8b040d
       
     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