kernel/eka/memmodel/epoc/flexible/mmu/mdatapaging.cpp
branchRCL_3
changeset 43 c1f20ce4abcf
parent 42 a179b74831c9
child 44 3e88ff8f41d5
equal deleted inserted replaced
42:a179b74831c9 43:c1f20ce4abcf
    65 	/// Note that this does not always correspond to the state of the page in RAM - for example a
    65 	/// Note that this does not always correspond to the state of the page in RAM - for example a
    66 	/// page can be dirty in RAM but blank in swap if it has never been written out.
    66 	/// page can be dirty in RAM but blank in swap if it has never been written out.
    67 	enum TSwapState
    67 	enum TSwapState
    68 		{
    68 		{
    69 		EStateUnreserved = 0,	///< swap space not yet reserved, or page is being decommitted
    69 		EStateUnreserved = 0,	///< swap space not yet reserved, or page is being decommitted
    70 		EStateBlank      = 1,	///< swap page has never been written
    70 		EStateBlank      = 1,	///< swap page has never been written or the last write failed
    71 		EStateWritten    = 2,	///< swap page has been written out at least once
    71 		EStateWritten    = 2,	///< swap page has been written out at least once
    72 		EStateWriting    = 3	///< swap page is in the process of being written out
    72 		EStateWriting    = 3	///< swap page is in the process of being written out
    73 		};
    73 		};
    74 	
    74 	
    75 	enum
    75 	enum
   155 private:
   155 private:
   156 	TInt WritePages(DMemoryObject** aMemory, TUint* aIndex, TPhysAddr* aPages, TUint aCount, DPageWriteRequest *aRequest, TBool aAnyExecutable, TBool aBackground);
   156 	TInt WritePages(DMemoryObject** aMemory, TUint* aIndex, TPhysAddr* aPages, TUint aCount, DPageWriteRequest *aRequest, TBool aAnyExecutable, TBool aBackground);
   157 
   157 
   158 private:
   158 private:
   159 	/**
   159 	/**
   160 	   The paging device used for accessing the backing store.
   160 	The paging device used for accessing the backing store.
   161 	   This is set by #InstallPagingDevice.
   161 	This is set by #InstallPagingDevice.
   162 	*/
   162 	*/
   163 	DPagingDevice* iDevice;
   163 	DPagingDevice* iDevice;
   164 
   164 
   165 	/**
   165 	/**
   166 	   The instance of #DSwapManager being used by this manager.
   166 	The instance of #DSwapManager being used by this manager.
   167 	*/
   167 	*/
   168 	DSwapManager* iSwapManager;
   168 	DSwapManager* iSwapManager;
   169 
   169 
   170 	/**
   170 	/**
   171 	   Whether to read and write pages by physical address without mapping them first.
   171 	Whether to read and write pages by physical address without mapping them first.
   172 
   172 
   173 	   Set if the paging media driver supports it.
   173 	Set if the paging media driver supports it.
   174 	*/
   174 	*/
   175 	TBool iUsePhysicalAccess;
   175 	TBool iUsePhysicalAccess;
   176 
   176 
   177 public:
   177 public:
   178 	/**
   178 	/**
   179 	   The single instance of this manager class.
   179 	The single instance of this manager class.
   180 	*/
   180 	*/
   181 	static DDataPagedMemoryManager TheManager;
   181 	static DDataPagedMemoryManager TheManager;
   182 	};
   182 	};
   183 
   183 
   184 
   184 
   185 DDataPagedMemoryManager DDataPagedMemoryManager::TheManager;
   185 DDataPagedMemoryManager DDataPagedMemoryManager::TheManager;
   186 DPagedMemoryManager* TheDataPagedMemoryManager = &DDataPagedMemoryManager::TheManager;
   186 DPagedMemoryManager* TheDataPagedMemoryManager = &DDataPagedMemoryManager::TheManager;
   187 
   187 
   188 
   188 
   189 /**
   189 /**
   190    Create a swap manager.
   190 Create a swap manager.
   191 
   191 
   192    @param	aDevice	The demand paging device for access to the swap.
   192 @param	aDevice	The demand paging device for access to the swap.
   193 */
   193 */
   194 TInt DSwapManager::Create(DPagingDevice* aDevice)
   194 TInt DSwapManager::Create(DPagingDevice* aDevice)
   195 	{
   195 	{
   196 	__ASSERT_COMPILE(!(ESwapIndexMask & ESwapStateMask));
   196 	__ASSERT_COMPILE(!(ESwapIndexMask & ESwapStateMask));
   197 	__NK_ASSERT_DEBUG(iDevice == NULL);
   197 	__NK_ASSERT_DEBUG(iDevice == NULL);
   229 
   229 
   230 
   230 
   231 inline DSwapManager::TSwapState DSwapManager::SwapState(TUint aSwapData)
   231 inline DSwapManager::TSwapState DSwapManager::SwapState(TUint aSwapData)
   232 	{
   232 	{
   233 	TSwapState state = (TSwapState)(aSwapData & ESwapStateMask);
   233 	TSwapState state = (TSwapState)(aSwapData & ESwapStateMask);
   234 	__NK_ASSERT_DEBUG(state >= EStateWritten || (aSwapData & ~ESwapStateMask) == 0);
   234 	__NK_ASSERT_DEBUG(state >= EStateBlank || aSwapData == 0);
   235 	return state;
   235 	return state;
   236 	}
   236 	}
   237 
   237 
   238 
   238 
   239 inline TInt DSwapManager::SwapIndex(TUint aSwapData)
   239 inline TInt DSwapManager::SwapIndex(TUint aSwapData)
   242 	}
   242 	}
   243 
   243 
   244 
   244 
   245 inline TUint DSwapManager::SwapData(TSwapState aSwapState, TInt aSwapIndex)
   245 inline TUint DSwapManager::SwapData(TSwapState aSwapState, TInt aSwapIndex)
   246 	{
   246 	{
       
   247 	__NK_ASSERT_DEBUG(aSwapIndex < (1 << (32 - ESwapIndexShift)));
   247 	return (aSwapIndex << ESwapIndexShift) | aSwapState;
   248 	return (aSwapIndex << ESwapIndexShift) | aSwapState;
   248 	}
   249 	}
   249 
   250 
   250 
   251 
   251 /**
   252 /**
   252    Allocate one or more page's worth of space within the swap area.
   253 Allocate one or more page's worth of space within the swap area.
   253 
   254 
   254    The location is represented by a page-based index into the swap area.
   255 The location is represented by a page-based index into the swap area.
   255 
   256 
   256    @param aCount The number of page's worth of space to allocate.
   257 @param aCount The number of page's worth of space to allocate.
   257 
   258 
   258    @return The swap index of the first location allocated.
   259 @return The swap index of the first location allocated.
   259 */
   260 */
   260 TInt DSwapManager::AllocSwapIndex(TUint aCount)
   261 TInt DSwapManager::AllocSwapIndex(TUint aCount)
   261 	{
   262 	{
   262 	TRACE2(("DSwapManager::AllocSwapIndex %d", aCount));
   263 	TRACE2(("DSwapManager::AllocSwapIndex %d", aCount));
   263 		
   264 		
   311 	return swapIndex;
   312 	return swapIndex;
   312 	}
   313 	}
   313 
   314 
   314 
   315 
   315 /**
   316 /**
   316    Free one page's worth of space within the swap area.
   317 Free one page's worth of space within the swap area.
   317 
   318 
   318    The index must have been previously allocated with AllocSwapIndex().
   319 The index must have been previously allocated with AllocSwapIndex().
   319 */
   320 */
   320 void DSwapManager::FreeSwapIndex(TInt aSwapIndex)
   321 void DSwapManager::FreeSwapIndex(TInt aSwapIndex)
   321 	{
   322 	{
   322 	__NK_ASSERT_DEBUG(aSwapIndex >= 0 && aSwapIndex < iBitMap->iSize);
   323 	__NK_ASSERT_DEBUG(aSwapIndex >= 0 && aSwapIndex < iBitMap->iSize);
   323 	DoDeleteNotify(aSwapIndex);
   324 	DoDeleteNotify(aSwapIndex);
   326 	NKern::FMSignal(&iSwapLock);
   327 	NKern::FMSignal(&iSwapLock);
   327 	}
   328 	}
   328 
   329 
   329 
   330 
   330 /**
   331 /**
   331    Reserve some swap pages for the requested region of the memory object
   332 Reserve some swap pages for the requested region of the memory object
   332 
   333 
   333    @param aMemory		The memory object to reserve pages for.
   334 @param aMemory		The memory object to reserve pages for.
   334    @param aStartIndex	The page index in the memory object of the start of the region.
   335 @param aStartIndex	The page index in the memory object of the start of the region.
   335    @param aPageCount	The number of pages to reserve.
   336 @param aPageCount	The number of pages to reserve.
   336 
   337 
   337    @return KErrNone on success, KErrNoMemory if not enough swap space available.
   338 @return KErrNone on success, KErrNoMemory if not enough swap space available.
   338    @pre aMemory's lock is held.
   339 @pre aMemory's lock is held.
   339    @post aMemory's lock is held.
   340 @post aMemory's lock is held.
   340 */
   341 */
   341 TInt DSwapManager::ReserveSwap(DMemoryObject* aMemory, TUint aStartIndex, TUint aPageCount)
   342 TInt DSwapManager::ReserveSwap(DMemoryObject* aMemory, TUint aStartIndex, TUint aPageCount)
   342 	{
   343 	{
   343 	__NK_ASSERT_DEBUG(MemoryObjectLock::IsHeld(aMemory));
   344 	__NK_ASSERT_DEBUG(MemoryObjectLock::IsHeld(aMemory));
   344 
   345 
   367 	return KErrNone;
   368 	return KErrNone;
   368 	}
   369 	}
   369 
   370 
   370 
   371 
   371 /**
   372 /**
   372    Unreserve swap pages for the requested region of the memory object.
   373 Unreserve swap pages for the requested region of the memory object.
   373 
   374 
   374    @param aMemory		The memory object to unreserve pages for.
   375 @param aMemory		The memory object to unreserve pages for.
   375    @param aStartIndex	The page index in the memory object of the start of the region.
   376 @param aStartIndex	The page index in the memory object of the start of the region.
   376    @param aPageCount	The number of pages to unreserve.
   377 @param aPageCount	The number of pages to unreserve.
   377 
   378 
   378    @return The number of pages freed.
   379 @return The number of pages freed.
   379    @pre aMemory's lock is held.
   380 @pre aMemory's lock is held.
   380    @post aMemory's lock is held.
   381 @post aMemory's lock is held.
   381 */
   382 */
   382 TInt DSwapManager::UnreserveSwap(DMemoryObject* aMemory, TUint aStartIndex, TUint aPageCount)
   383 TInt DSwapManager::UnreserveSwap(DMemoryObject* aMemory, TUint aStartIndex, TUint aPageCount)
   383 	{
   384 	{
   384 	__NK_ASSERT_DEBUG(MemoryObjectLock::IsHeld(aMemory));
   385 	__NK_ASSERT_DEBUG(MemoryObjectLock::IsHeld(aMemory));
   385 
   386 
   422 	return freedPages;
   423 	return freedPages;
   423 	}
   424 	}
   424 
   425 
   425 
   426 
   426 /**
   427 /**
   427    Determine whether the specified pages in the memory object have swap reserved for them.
   428 Determine whether the specified pages in the memory object have swap reserved for them.
   428 
   429 
   429    @param aMemory		The memory object that owns the pages.
   430 @param aMemory		The memory object that owns the pages.
   430    @param aStartIndex	The first index of the pages to check.
   431 @param aStartIndex	The first index of the pages to check.
   431    @param aPageCount	The number of pages to check.
   432 @param aPageCount	The number of pages to check.
   432 
   433 
   433    @return ETrue if swap is reserved for all the pages, EFalse otherwise.
   434 @return ETrue if swap is reserved for all the pages, EFalse otherwise.
   434 */
   435 */
   435 TBool DSwapManager::IsReserved(DMemoryObject* aMemory, TUint aStartIndex, TUint aPageCount)
   436 TBool DSwapManager::IsReserved(DMemoryObject* aMemory, TUint aStartIndex, TUint aPageCount)
   436 	{// MmuLock required to protect manager data.
   437 	{// MmuLock required to protect manager data.
   437 	__NK_ASSERT_DEBUG(MmuLock::IsHeld());
   438 	__NK_ASSERT_DEBUG(MmuLock::IsHeld());
   438 	__NK_ASSERT_DEBUG(aStartIndex < aMemory->iSizeInPages);
   439 	__NK_ASSERT_DEBUG(aStartIndex < aMemory->iSizeInPages);
   449 	return ETrue;
   450 	return ETrue;
   450 	}
   451 	}
   451 
   452 
   452 
   453 
   453 /**
   454 /**
   454    Read from the swap the specified pages associated with the memory object.
   455 Read from the swap the specified pages associated with the memory object.
   455 
   456 
   456    @param aMemory 	The memory object to read the pages for
   457 @param aMemory 	The memory object to read the pages for
   457    @param aIndex	The index of the first page within the memory object.
   458 @param aIndex	The index of the first page within the memory object.
   458    @param aCount	The number of pages to read.
   459 @param aCount	The number of pages to read.
   459    @param aLinAddr	The address to copy the pages to.
   460 @param aLinAddr	The address to copy the pages to.
   460    @param aRequest	The request to use for the read.
   461 @param aRequest	The request to use for the read.
   461    @param aPhysAddrs	An array of the physical addresses for each page to read in.
   462 @param aPhysAddrs	An array of the physical addresses for each page to read in.
   462 */
   463 */
   463 TInt DSwapManager::ReadSwapPages(DMemoryObject* aMemory, TUint aIndex, TUint aCount, TLinAddr aLinAddr, TPhysAddr* aPhysAddrs)
   464 TInt DSwapManager::ReadSwapPages(DMemoryObject* aMemory, TUint aIndex, TUint aCount, TLinAddr aLinAddr, TPhysAddr* aPhysAddrs)
   464 	{
   465 	{
   465 	__ASSERT_CRITICAL;
   466 	__ASSERT_CRITICAL;
   466 	
   467 	
   467 	TInt r = KErrNone;
       
   468 	const TUint readUnitShift = iDevice->iReadUnitShift;
   468 	const TUint readUnitShift = iDevice->iReadUnitShift;
   469 	TUint readSize = KPageSize >> readUnitShift;
   469 	TUint readSize = KPageSize >> readUnitShift;
   470 	TThreadMessage message;
   470 	TThreadMessage message;
   471 
   471 
   472 	const TUint indexEnd = aIndex + aCount;
   472 	const TUint indexEnd = aIndex + aCount;
   475 		START_PAGING_BENCHMARK;
   475 		START_PAGING_BENCHMARK;
   476 
   476 
   477 		MmuLock::Lock();	// MmuLock required for atomic access to manager data.
   477 		MmuLock::Lock();	// MmuLock required for atomic access to manager data.
   478 		TUint swapData = aMemory->PagingManagerData(index);
   478 		TUint swapData = aMemory->PagingManagerData(index);
   479 		TSwapState state = SwapState(swapData);
   479 		TSwapState state = SwapState(swapData);
       
   480 		TUint swapPage = SwapIndex(swapData);
   480 
   481 
   481 		if (state == EStateUnreserved)
   482 		if (state == EStateUnreserved)
   482 			{// This page is not committed to the memory object
   483 			{
       
   484 			// This page is not committed to the memory object
   483 			MmuLock::Unlock();
   485 			MmuLock::Unlock();
   484 			return KErrNotFound;			
   486 			return KErrNotFound;			
   485 			}
   487 			}
   486 		else if (state == EStateBlank)
   488 		else if (state == EStateBlank)
   487 			{// This page has not been written to yet so don't read from swap 
   489 			{
   488 			// just wipe it if required.
   490 			if (swapPage != 0)
   489 			TUint allocFlags = aMemory->RamAllocFlags();
       
   490 			MmuLock::Unlock();
       
   491 			TBool wipePages = !(allocFlags & Mmu::EAllocNoWipe);
       
   492 			if (wipePages)
       
   493 				{
   491 				{
   494 				TUint8 wipeByte = (allocFlags & Mmu::EAllocUseCustomWipeByte) ?
   492 				// An error occured while writing the page out, so report it now
   495 					(allocFlags >> Mmu::EAllocWipeByteShift) & 0xff :
   493 				MmuLock::Unlock();
   496 					0x03;
   494 				return -swapPage; 
   497 				memset((TAny*)aLinAddr, wipeByte, KPageSize);
   495 				}
       
   496 			else
       
   497 				{
       
   498 				// This page has not been written to yet so don't read from swap 
       
   499 				// just wipe it if required.
       
   500 				TUint allocFlags = aMemory->RamAllocFlags();
       
   501 				MmuLock::Unlock();
       
   502 				TBool wipePages = !(allocFlags & Mmu::EAllocNoWipe);
       
   503 				if (wipePages)
       
   504 					{
       
   505 					TUint8 wipeByte = (allocFlags & Mmu::EAllocUseCustomWipeByte) ?
       
   506 						(allocFlags >> Mmu::EAllocWipeByteShift) & 0xff :
       
   507 						0x03;
       
   508 					memset((TAny*)aLinAddr, wipeByte, KPageSize);
       
   509 					}
   498 				}
   510 				}
   499 			}
   511 			}
   500 		else
   512 		else
   501 			{
   513 			{
   502 			// It is not possible to get here if the page is in state EStateWriting as if so it must
   514 			// It is not possible to get here if the page is in state EStateWriting as if so it must
   504 			__NK_ASSERT_DEBUG(state == EStateWritten);
   516 			__NK_ASSERT_DEBUG(state == EStateWritten);
   505 			
   517 			
   506 			// OK to release as if the object's data is decommitted the pager 
   518 			// OK to release as if the object's data is decommitted the pager 
   507 			// will check that data is still valid before mapping it.
   519 			// will check that data is still valid before mapping it.
   508 			MmuLock::Unlock();
   520 			MmuLock::Unlock();
   509 			TUint readStart = (SwapIndex(swapData) << KPageShift) >> readUnitShift;
   521 			TUint readStart = (swapPage << KPageShift) >> readUnitShift;
   510 			START_PAGING_BENCHMARK;
   522 			START_PAGING_BENCHMARK;
   511 			r = iDevice->Read(&message, aLinAddr, readStart, readSize, DPagingDevice::EDriveDataPaging);
   523 			TInt r = iDevice->Read(&message, aLinAddr, readStart, readSize, DPagingDevice::EDriveDataPaging);
       
   524 			END_PAGING_BENCHMARK(EPagingBmReadDataMedia);
       
   525 			__NK_ASSERT_DEBUG(r!=KErrNoMemory); // not allowed to allocate memory, therefore shouldn't fail with KErrNoMemory
   512 			if (r != KErrNone)
   526 			if (r != KErrNone)
   513 				__KTRACE_OPT(KPANIC, Kern::Printf("DSwapManager::ReadSwapPages: error reading media at %08x + %x: %d", readStart << readUnitShift, readSize << readUnitShift, r));				
   527 				__KTRACE_OPT(KPANIC, Kern::Printf("DSwapManager::ReadSwapPages: error reading media at %08x + %x: %d", readStart << readUnitShift, readSize << readUnitShift, r));
   514 			__NK_ASSERT_DEBUG(r!=KErrNoMemory); // not allowed to allocate memory, therefore can't fail with KErrNoMemory
   528 			r = ThePager.EmbedErrorContext(EPagingErrorContextDataRead, r);
   515 			END_PAGING_BENCHMARK(EPagingBmReadDataMedia);
   529 			if (r != KErrNone)
   516 			__NK_ASSERT_ALWAYS(r == KErrNone);
   530 				return r;
   517 			}
   531 			}
   518 		END_PAGING_BENCHMARK(EPagingBmReadDataPage);
   532 		END_PAGING_BENCHMARK(EPagingBmReadDataPage);
   519 		}
   533 		}
   520 
   534 	
   521 	return r;
   535 	return KErrNone;
   522 	}
   536 	}
   523 
   537 
   524 
   538 
   525 /**
   539 /**
   526    Write the specified memory object's pages from the RAM into the swap.
   540 Write the specified memory object's pages from the RAM into the swap.
   527 
   541 
   528    @param	aMemory		The memory object who owns the pages.
   542 @param	aMemory		The memory object who owns the pages.
   529    @param	aIndex		The index within the memory object.
   543 @param	aIndex		The index within the memory object.
   530    @param 	aCount		The number of pages to write out.
   544 @param 	aCount		The number of pages to write out.
   531    @param	aLinAddr	The location of the pages to write out.
   545 @param	aLinAddr	The location of the pages to write out.
   532    @param  aBackground Whether this is being called in the background by the page cleaning thread
   546 @param  aBackground Whether this is being called in the background by the page cleaning thread
   533    as opposed to on demand when a free page is required.
   547                     as opposed to on demand when a free page is required.
   534 
   548 
   535    @pre Called with page cleaning lock held
   549 @pre Called with page cleaning lock held
   536 */
   550 */
   537 TInt DSwapManager::WriteSwapPages(DMemoryObject** aMemory, TUint* aIndex, TUint aCount, TLinAddr aLinAddr, TPhysAddr* aPhysAddrs, TBool aBackground)
   551 TInt DSwapManager::WriteSwapPages(DMemoryObject** aMemory, TUint* aIndex, TUint aCount, TLinAddr aLinAddr, TPhysAddr* aPhysAddrs, TBool aBackground)
   538 	{
   552 	{
   539 	TRACE(("DSwapManager::WriteSwapPages %d pages", aCount));
   553 	TRACE(("DSwapManager::WriteSwapPages %d pages", aCount));
   540 	
   554 	
   624 	TInt r;
   638 	TInt r;
   625 	if (aLinAddr == 0)
   639 	if (aLinAddr == 0)
   626 		r = iDevice->WritePhysical(&msg, aPhysAddrs, aCount, writeOffset, aBackground);
   640 		r = iDevice->WritePhysical(&msg, aPhysAddrs, aCount, writeOffset, aBackground);
   627 	else
   641 	else
   628 		r = iDevice->Write(&msg, aLinAddr + (aPageIndex << KPageShift), writeOffset, writeSize, aBackground);
   642 		r = iDevice->Write(&msg, aLinAddr + (aPageIndex << KPageShift), writeOffset, writeSize, aBackground);
       
   643 	END_PAGING_BENCHMARK(EPagingBmWriteDataMedia);
   629 		
   644 		
   630 	if (r != KErrNone)
   645 	if (r != KErrNone)
   631 		{
   646 		{
   632 		__KTRACE_OPT(KPANIC, Kern::Printf("DSwapManager::WriteSwapPages: error writing media from %08x to %08x + %x: %d", aLinAddr, writeOffset << readUnitShift, writeSize << readUnitShift, r));
   647 		__KTRACE_OPT(KPANIC, Kern::Printf("DSwapManager::WriteSwapPages: error writing media from %08x to %08x + %x: %d", aLinAddr, writeOffset << readUnitShift, writeSize << readUnitShift, r));
       
   648 		if (r > 0)
       
   649 			r = KErrGeneral;
   633 		}
   650 		}
   634 	__NK_ASSERT_DEBUG(r!=KErrNoMemory); // not allowed to allocate memory, therefore can't fail with KErrNoMemory
   651 	__NK_ASSERT_DEBUG(r!=KErrNoMemory); // not allowed to allocate memory, therefore can't fail with KErrNoMemory
   635 	__NK_ASSERT_ALWAYS(r == KErrNone);
   652 	r = ThePager.EmbedErrorContext(EPagingErrorContextDataWrite, r); 
   636 	END_PAGING_BENCHMARK(EPagingBmWriteDataMedia);
       
   637 
   653 
   638 	TUint i;
   654 	TUint i;
   639 	TUint swapData[KMaxPagesToClean];
   655 	TUint swapData[KMaxPagesToClean];
   640 	
   656 	
   641 	MmuLock::Lock();
   657 	MmuLock::Lock();
   645 		swapData[i] = aMemory[i]->PagingManagerData(aIndex[i]);
   661 		swapData[i] = aMemory[i]->PagingManagerData(aIndex[i]);
   646 		TSwapState s = SwapState(swapData[i]);
   662 		TSwapState s = SwapState(swapData[i]);
   647 		__NK_ASSERT_DEBUG(s == EStateUnreserved || s == EStateWriting);
   663 		__NK_ASSERT_DEBUG(s == EStateUnreserved || s == EStateWriting);
   648 		if (s == EStateWriting)
   664 		if (s == EStateWriting)
   649 			{
   665 			{
   650 			// Store the new swap location and mark the page as saved.
   666 			// Store the new swap location and mark the page as saved, or if an error occured then
   651 			aMemory[i]->SetPagingManagerData(aIndex[i], SwapData(EStateWritten, aSwapIndex + i));
   667 			// record the error code instead
       
   668 			TUint swapData = (r == KErrNone) 
       
   669 				? SwapData(EStateWritten, aSwapIndex + i)
       
   670 				: SwapData(EStateBlank, -r);
       
   671 			aMemory[i]->SetPagingManagerData(aIndex[i], swapData);
   652 			}
   672 			}
   653 		}
   673 		}
   654 	MmuLock::Unlock();
   674 	MmuLock::Unlock();
   655 
   675 
   656 	for (i = 0 ; i < aCount ; ++i)
   676 	for (i = 0 ; i < aCount ; ++i)
   657 		{
   677 		{
   658 		TSwapState s = SwapState(swapData[i]);
   678 		TSwapState s = SwapState(swapData[i]);
   659 		if (s == EStateUnreserved)
   679 		if (s == EStateUnreserved || s == EStateBlank)
   660 			{
   680 			{
   661 			// The page was decommitted while we were cleaning it, so free the swap page we
   681 			// The page was either decommitted while we were cleaning it, or an error occured while
   662 			// allocated and continue, leaving this page in the unreserved state.
   682 			// writing.  Free the swap page and don't modify the state.
   663 			FreeSwapIndex(aSwapIndex + i);
   683 			FreeSwapIndex(aSwapIndex + i);
   664 			}
   684 			}
   665 		}
   685 		}
   666 
   686 
   667 	return KErrNone;
   687 	// write errors are not reported at this point as this will just kill a thread unrelated to the
       
   688 	// one whose data has been lost
       
   689 	return KErrNone;  
   668 	}
   690 	}
   669 	
   691 	
   670 
   692 
   671 /**
   693 /**
   672 Notify the media driver that the page written to swap is no longer required.
   694 Notify the media driver that the page written to swap is no longer required.