--- a/kernel/eka/memmodel/epoc/flexible/mmu/mpager.h Thu Aug 19 11:14:22 2010 +0300
+++ b/kernel/eka/memmodel/epoc/flexible/mmu/mpager.h Tue Aug 31 16:34:26 2010 +0300
@@ -152,6 +152,20 @@
void FlushAll();
/**
+ Flush demand paged pages in a specified region.
+
+ The memory must reside in a single memory object.
+
+ @param aProcess The process containing the pages to flush.
+ @param aStart The start address of the region.
+ @param aSize The size of the region in bytes.
+
+ @return KErrBadDescriptor If the memory region is invalid or spans more than one memory object,
+ otherwise KErrNone.
+ */
+ TInt FlushRegion(DMemModelProcess* aProcess, TLinAddr aStartAddress, TUint aSize);
+
+ /**
Give pages to paging system for managing.
*/
void DonatePages(TUint aCount, TPhysAddr* aPages);
@@ -404,6 +418,23 @@
*/
void SetCleanInSequence(TBool aCleanInSequence);
+ /**
+ Generate a new error code that includes both the original error code and some extra context
+ information. This is used to communicate context information from where it occurs to where it
+ is handled.
+ */
+ TInt EmbedErrorContext(TPagingErrorContext aContext, TInt aError);
+
+ /**
+ Extract the context information from a error code generated by #EmbedErrorContext.
+ */
+ static TPagingErrorContext ExtractErrorContext(TInt aContextError);
+
+ /**
+ Extract the original error code from a error code generated by #EmbedErrorContext.
+ */
+ static TInt ExtractErrorCode(TInt aContextError);
+
private:
/**
Add a page to the head of the live page list. I.e. make it the 'youngest' page.
@@ -626,6 +657,12 @@
TBool ReservePage();
/**
+ Determine the thread responsible for this page fault. This returns either NULL to indicate
+ the current thread, or a remote thread if the fault is caused by an IPC operation.
+ */
+ DThread* ResponsibleThread(DThread* aThread, TAny* aExceptionInfo);
+
+ /**
Called when a realtime thread takes a paging fault.
Checks whether it's OK for the thread to take to fault.
@return KErrNone if the paging fault should be further processed
@@ -633,6 +670,20 @@
TInt CheckRealtimeThreadFault(DThread* aThread, TAny* aExceptionInfo);
/**
+ Kills the thread responsible for causing a page fault.
+
+ This is called when a fatal error is encountered when handling a page fault, for example, if a
+ media access fails.
+
+ Originally the paging system reacted by faulting the system in such cases. However the current
+ approach was thought to be preferable as this kind of error can happen in practice (even though
+ in theory it should not) and it means that the error code is reported and can be captured by
+ MobileCrash.
+ */
+ void KillResponsibleThread(TPagingErrorContext aErrorCategory, TInt aErrorCode,
+ TAny* aExceptionInfo);
+
+ /**
Attempt to find the page table entry and page info for a page in the specified mapping.
@param aOsAsid The OsAsid of the process that owns the mapping.
@@ -694,11 +745,53 @@
TSpinLock iBenchmarkLock;
SPagingBenchmarkInfo iBenchmarkInfo[EMaxPagingBm];
#endif //__DEMAND_PAGING_BENCHMARKS__
+
+#ifdef _DEBUG
+ TPagingErrorContext iDebugFailContext;
+#endif
};
extern DPager ThePager;
+// Functions to embed context information into error codes, using the following scheme:
+//
+// bits 0-16 taken from original error code
+// bits 16-31 bitwise NOT of a TPagingErrorContext value
+//
+// Since the context informtion is a small positive integer, the resulting error code is still a
+// negative integer. The value EPagingErrorContextNone is zero, yeilding the original error code
+// unchanged if embedded.
+
+inline TInt DPager::EmbedErrorContext(TPagingErrorContext aContext, TInt aError)
+ {
+ __NK_ASSERT_DEBUG(aContext > 0 && aContext <= 0x7fff);
+#ifdef _DEBUG
+ if (aError >= KErrNone)
+ {
+ TUint32 match = aContext;
+ if (__e32_atomic_cas_ord32(&iDebugFailContext, &match, 0))
+ aError = KErrAbort;
+ }
+#endif
+ if (aError >= KErrNone)
+ return aError;
+ if (aError < (TInt)0xffff0000)
+ aError = KErrGeneral; // lose error code, but doesn't happen in practice
+ return (aError & 0x0000ffff) | ((~aContext) << 16);
+ }
+
+inline TPagingErrorContext DPager::ExtractErrorContext(TInt aContextError)
+ {
+ return (TPagingErrorContext)((~aContextError) >> 16);
+ }
+
+inline TInt DPager::ExtractErrorCode(TInt aContextError)
+ {
+ return aContextError | 0x7fff000;
+ }
+
+
#ifdef __DEMAND_PAGING_BENCHMARKS__
#define START_PAGING_BENCHMARK TUint32 _bmStart = NKern::FastCounter()
@@ -999,5 +1092,4 @@
static void Init();
};
-
#endif