kernel/eka/memmodel/epoc/flexible/mmu/mdatapaging.cpp
changeset 259 57b9594f5772
parent 201 43365a9b78a3
equal deleted inserted replaced
247:d8d70de2bd36 259:57b9594f5772
    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
   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 /**
   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.
   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.