--- a/kernel/eka/memmodel/epoc/flexible/mmu/mdatapaging.cpp Thu Aug 19 11:14:22 2010 +0300
+++ b/kernel/eka/memmodel/epoc/flexible/mmu/mdatapaging.cpp Tue Aug 31 16:34:26 2010 +0300
@@ -67,7 +67,7 @@
enum TSwapState
{
EStateUnreserved = 0, ///< swap space not yet reserved, or page is being decommitted
- EStateBlank = 1, ///< swap page has never been written
+ EStateBlank = 1, ///< swap page has never been written or the last write failed
EStateWritten = 2, ///< swap page has been written out at least once
EStateWriting = 3 ///< swap page is in the process of being written out
};
@@ -157,26 +157,26 @@
private:
/**
- The paging device used for accessing the backing store.
- This is set by #InstallPagingDevice.
+ The paging device used for accessing the backing store.
+ This is set by #InstallPagingDevice.
*/
DPagingDevice* iDevice;
/**
- The instance of #DSwapManager being used by this manager.
+ The instance of #DSwapManager being used by this manager.
*/
DSwapManager* iSwapManager;
/**
- Whether to read and write pages by physical address without mapping them first.
+ Whether to read and write pages by physical address without mapping them first.
- Set if the paging media driver supports it.
+ Set if the paging media driver supports it.
*/
TBool iUsePhysicalAccess;
public:
/**
- The single instance of this manager class.
+ The single instance of this manager class.
*/
static DDataPagedMemoryManager TheManager;
};
@@ -187,9 +187,9 @@
/**
- Create a swap manager.
+Create a swap manager.
- @param aDevice The demand paging device for access to the swap.
+@param aDevice The demand paging device for access to the swap.
*/
TInt DSwapManager::Create(DPagingDevice* aDevice)
{
@@ -231,7 +231,7 @@
inline DSwapManager::TSwapState DSwapManager::SwapState(TUint aSwapData)
{
TSwapState state = (TSwapState)(aSwapData & ESwapStateMask);
- __NK_ASSERT_DEBUG(state >= EStateWritten || (aSwapData & ~ESwapStateMask) == 0);
+ __NK_ASSERT_DEBUG(state >= EStateBlank || aSwapData == 0);
return state;
}
@@ -244,18 +244,19 @@
inline TUint DSwapManager::SwapData(TSwapState aSwapState, TInt aSwapIndex)
{
+ __NK_ASSERT_DEBUG(aSwapIndex < (1 << (32 - ESwapIndexShift)));
return (aSwapIndex << ESwapIndexShift) | aSwapState;
}
/**
- Allocate one or more page's worth of space within the swap area.
+Allocate one or more page's worth of space within the swap area.
- The location is represented by a page-based index into the swap area.
+The location is represented by a page-based index into the swap area.
- @param aCount The number of page's worth of space to allocate.
+@param aCount The number of page's worth of space to allocate.
- @return The swap index of the first location allocated.
+@return The swap index of the first location allocated.
*/
TInt DSwapManager::AllocSwapIndex(TUint aCount)
{
@@ -313,9 +314,9 @@
/**
- Free one page's worth of space within the swap area.
+Free one page's worth of space within the swap area.
- The index must have been previously allocated with AllocSwapIndex().
+The index must have been previously allocated with AllocSwapIndex().
*/
void DSwapManager::FreeSwapIndex(TInt aSwapIndex)
{
@@ -328,15 +329,15 @@
/**
- Reserve some swap pages for the requested region of the memory object
+Reserve some swap pages for the requested region of the memory object
- @param aMemory The memory object to reserve pages for.
- @param aStartIndex The page index in the memory object of the start of the region.
- @param aPageCount The number of pages to reserve.
+@param aMemory The memory object to reserve pages for.
+@param aStartIndex The page index in the memory object of the start of the region.
+@param aPageCount The number of pages to reserve.
- @return KErrNone on success, KErrNoMemory if not enough swap space available.
- @pre aMemory's lock is held.
- @post aMemory's lock is held.
+@return KErrNone on success, KErrNoMemory if not enough swap space available.
+@pre aMemory's lock is held.
+@post aMemory's lock is held.
*/
TInt DSwapManager::ReserveSwap(DMemoryObject* aMemory, TUint aStartIndex, TUint aPageCount)
{
@@ -369,15 +370,15 @@
/**
- Unreserve swap pages for the requested region of the memory object.
+Unreserve swap pages for the requested region of the memory object.
- @param aMemory The memory object to unreserve pages for.
- @param aStartIndex The page index in the memory object of the start of the region.
- @param aPageCount The number of pages to unreserve.
+@param aMemory The memory object to unreserve pages for.
+@param aStartIndex The page index in the memory object of the start of the region.
+@param aPageCount The number of pages to unreserve.
- @return The number of pages freed.
- @pre aMemory's lock is held.
- @post aMemory's lock is held.
+@return The number of pages freed.
+@pre aMemory's lock is held.
+@post aMemory's lock is held.
*/
TInt DSwapManager::UnreserveSwap(DMemoryObject* aMemory, TUint aStartIndex, TUint aPageCount)
{
@@ -424,13 +425,13 @@
/**
- Determine whether the specified pages in the memory object have swap reserved for them.
+Determine whether the specified pages in the memory object have swap reserved for them.
- @param aMemory The memory object that owns the pages.
- @param aStartIndex The first index of the pages to check.
- @param aPageCount The number of pages to check.
+@param aMemory The memory object that owns the pages.
+@param aStartIndex The first index of the pages to check.
+@param aPageCount The number of pages to check.
- @return ETrue if swap is reserved for all the pages, EFalse otherwise.
+@return ETrue if swap is reserved for all the pages, EFalse otherwise.
*/
TBool DSwapManager::IsReserved(DMemoryObject* aMemory, TUint aStartIndex, TUint aPageCount)
{// MmuLock required to protect manager data.
@@ -451,20 +452,19 @@
/**
- Read from the swap the specified pages associated with the memory object.
+Read from the swap the specified pages associated with the memory object.
- @param aMemory The memory object to read the pages for
- @param aIndex The index of the first page within the memory object.
- @param aCount The number of pages to read.
- @param aLinAddr The address to copy the pages to.
- @param aRequest The request to use for the read.
- @param aPhysAddrs An array of the physical addresses for each page to read in.
+@param aMemory The memory object to read the pages for
+@param aIndex The index of the first page within the memory object.
+@param aCount The number of pages to read.
+@param aLinAddr The address to copy the pages to.
+@param aRequest The request to use for the read.
+@param aPhysAddrs An array of the physical addresses for each page to read in.
*/
TInt DSwapManager::ReadSwapPages(DMemoryObject* aMemory, TUint aIndex, TUint aCount, TLinAddr aLinAddr, TPhysAddr* aPhysAddrs)
{
__ASSERT_CRITICAL;
- TInt r = KErrNone;
const TUint readUnitShift = iDevice->iReadUnitShift;
TUint readSize = KPageSize >> readUnitShift;
TThreadMessage message;
@@ -477,24 +477,36 @@
MmuLock::Lock(); // MmuLock required for atomic access to manager data.
TUint swapData = aMemory->PagingManagerData(index);
TSwapState state = SwapState(swapData);
+ TUint swapPage = SwapIndex(swapData);
if (state == EStateUnreserved)
- {// This page is not committed to the memory object
+ {
+ // This page is not committed to the memory object
MmuLock::Unlock();
return KErrNotFound;
}
else if (state == EStateBlank)
- {// This page has not been written to yet so don't read from swap
- // just wipe it if required.
- TUint allocFlags = aMemory->RamAllocFlags();
- MmuLock::Unlock();
- TBool wipePages = !(allocFlags & Mmu::EAllocNoWipe);
- if (wipePages)
+ {
+ if (swapPage != 0)
+ {
+ // An error occured while writing the page out, so report it now
+ MmuLock::Unlock();
+ return -swapPage;
+ }
+ else
{
- TUint8 wipeByte = (allocFlags & Mmu::EAllocUseCustomWipeByte) ?
- (allocFlags >> Mmu::EAllocWipeByteShift) & 0xff :
- 0x03;
- memset((TAny*)aLinAddr, wipeByte, KPageSize);
+ // This page has not been written to yet so don't read from swap
+ // just wipe it if required.
+ TUint allocFlags = aMemory->RamAllocFlags();
+ MmuLock::Unlock();
+ TBool wipePages = !(allocFlags & Mmu::EAllocNoWipe);
+ if (wipePages)
+ {
+ TUint8 wipeByte = (allocFlags & Mmu::EAllocUseCustomWipeByte) ?
+ (allocFlags >> Mmu::EAllocWipeByteShift) & 0xff :
+ 0x03;
+ memset((TAny*)aLinAddr, wipeByte, KPageSize);
+ }
}
}
else
@@ -506,33 +518,35 @@
// OK to release as if the object's data is decommitted the pager
// will check that data is still valid before mapping it.
MmuLock::Unlock();
- TUint readStart = (SwapIndex(swapData) << KPageShift) >> readUnitShift;
+ TUint readStart = (swapPage << KPageShift) >> readUnitShift;
START_PAGING_BENCHMARK;
- r = iDevice->Read(&message, aLinAddr, readStart, readSize, DPagingDevice::EDriveDataPaging);
+ TInt r = iDevice->Read(&message, aLinAddr, readStart, readSize, DPagingDevice::EDriveDataPaging);
+ END_PAGING_BENCHMARK(EPagingBmReadDataMedia);
+ __NK_ASSERT_DEBUG(r!=KErrNoMemory); // not allowed to allocate memory, therefore shouldn't fail with KErrNoMemory
if (r != KErrNone)
- __KTRACE_OPT(KPANIC, Kern::Printf("DSwapManager::ReadSwapPages: error reading media at %08x + %x: %d", readStart << readUnitShift, readSize << readUnitShift, r));
- __NK_ASSERT_DEBUG(r!=KErrNoMemory); // not allowed to allocate memory, therefore can't fail with KErrNoMemory
- END_PAGING_BENCHMARK(EPagingBmReadDataMedia);
- __NK_ASSERT_ALWAYS(r == KErrNone);
+ __KTRACE_OPT(KPANIC, Kern::Printf("DSwapManager::ReadSwapPages: error reading media at %08x + %x: %d", readStart << readUnitShift, readSize << readUnitShift, r));
+ r = ThePager.EmbedErrorContext(EPagingErrorContextDataRead, r);
+ if (r != KErrNone)
+ return r;
}
END_PAGING_BENCHMARK(EPagingBmReadDataPage);
}
-
- return r;
+
+ return KErrNone;
}
/**
- Write the specified memory object's pages from the RAM into the swap.
+Write the specified memory object's pages from the RAM into the swap.
- @param aMemory The memory object who owns the pages.
- @param aIndex The index within the memory object.
- @param aCount The number of pages to write out.
- @param aLinAddr The location of the pages to write out.
- @param aBackground Whether this is being called in the background by the page cleaning thread
- as opposed to on demand when a free page is required.
+@param aMemory The memory object who owns the pages.
+@param aIndex The index within the memory object.
+@param aCount The number of pages to write out.
+@param aLinAddr The location of the pages to write out.
+@param aBackground Whether this is being called in the background by the page cleaning thread
+ as opposed to on demand when a free page is required.
- @pre Called with page cleaning lock held
+@pre Called with page cleaning lock held
*/
TInt DSwapManager::WriteSwapPages(DMemoryObject** aMemory, TUint* aIndex, TUint aCount, TLinAddr aLinAddr, TPhysAddr* aPhysAddrs, TBool aBackground)
{
@@ -626,14 +640,16 @@
r = iDevice->WritePhysical(&msg, aPhysAddrs, aCount, writeOffset, aBackground);
else
r = iDevice->Write(&msg, aLinAddr + (aPageIndex << KPageShift), writeOffset, writeSize, aBackground);
+ END_PAGING_BENCHMARK(EPagingBmWriteDataMedia);
if (r != KErrNone)
{
__KTRACE_OPT(KPANIC, Kern::Printf("DSwapManager::WriteSwapPages: error writing media from %08x to %08x + %x: %d", aLinAddr, writeOffset << readUnitShift, writeSize << readUnitShift, r));
+ if (r > 0)
+ r = KErrGeneral;
}
__NK_ASSERT_DEBUG(r!=KErrNoMemory); // not allowed to allocate memory, therefore can't fail with KErrNoMemory
- __NK_ASSERT_ALWAYS(r == KErrNone);
- END_PAGING_BENCHMARK(EPagingBmWriteDataMedia);
+ r = ThePager.EmbedErrorContext(EPagingErrorContextDataWrite, r);
TUint i;
TUint swapData[KMaxPagesToClean];
@@ -647,8 +663,12 @@
__NK_ASSERT_DEBUG(s == EStateUnreserved || s == EStateWriting);
if (s == EStateWriting)
{
- // Store the new swap location and mark the page as saved.
- aMemory[i]->SetPagingManagerData(aIndex[i], SwapData(EStateWritten, aSwapIndex + i));
+ // Store the new swap location and mark the page as saved, or if an error occured then
+ // record the error code instead
+ TUint swapData = (r == KErrNone)
+ ? SwapData(EStateWritten, aSwapIndex + i)
+ : SwapData(EStateBlank, -r);
+ aMemory[i]->SetPagingManagerData(aIndex[i], swapData);
}
}
MmuLock::Unlock();
@@ -656,15 +676,17 @@
for (i = 0 ; i < aCount ; ++i)
{
TSwapState s = SwapState(swapData[i]);
- if (s == EStateUnreserved)
+ if (s == EStateUnreserved || s == EStateBlank)
{
- // The page was decommitted while we were cleaning it, so free the swap page we
- // allocated and continue, leaving this page in the unreserved state.
+ // The page was either decommitted while we were cleaning it, or an error occured while
+ // writing. Free the swap page and don't modify the state.
FreeSwapIndex(aSwapIndex + i);
}
}
- return KErrNone;
+ // write errors are not reported at this point as this will just kill a thread unrelated to the
+ // one whose data has been lost
+ return KErrNone;
}