kernel/eka/memmodel/epoc/flexible/mmu/mpager.h
changeset 259 57b9594f5772
parent 201 43365a9b78a3
--- a/kernel/eka/memmodel/epoc/flexible/mmu/mpager.h	Wed Aug 18 11:08:29 2010 +0300
+++ b/kernel/eka/memmodel/epoc/flexible/mmu/mpager.h	Thu Sep 02 21:54:16 2010 +0300
@@ -418,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.
@@ -640,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
@@ -647,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.
@@ -708,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()
@@ -1013,5 +1092,4 @@
 	static void Init();	
 	};
 
-
 #endif