kernel/eka/memmodel/epoc/flexible/mmu/x86/xmmu.cpp
changeset 45 329ab0095843
parent 43 96e5fb8b040d
child 109 b3a1d9898418
--- a/kernel/eka/memmodel/epoc/flexible/mmu/x86/xmmu.cpp	Thu Jan 07 13:38:45 2010 +0200
+++ b/kernel/eka/memmodel/epoc/flexible/mmu/x86/xmmu.cpp	Mon Jan 18 21:31:10 2010 +0200
@@ -572,11 +572,13 @@
 	// Now we have the os asid check access to kernel memory.
 	if(aAddr >= KUserMemoryLimit && osAsid != (TUint)KKernelOsAsid)
 		{
+		NKern::ThreadEnterCS();
+		MmuLock::Unlock();
 		if (!iAliasLinAddr)
 			{// Close the new reference as RemoveAlias won't do as iAliasLinAddr is not set.
-			aProcess->AsyncCloseOsAsid();
+			aProcess->AsyncCloseOsAsid();	// Asynchronous close as this method should be quick.
 			}
-		MmuLock::Unlock();
+		NKern::ThreadLeaveCS();
 		return KErrBadDescriptor; // prevent access to supervisor only memory
 		}
 
@@ -586,13 +588,15 @@
 		// address is in global section, don't bother aliasing it...
 		if (!iAliasLinAddr)
 			{// Close the new reference as not required.
-			aProcess->AsyncCloseOsAsid();
+			NKern::ThreadEnterCS();
+			MmuLock::Unlock();
+			aProcess->AsyncCloseOsAsid();	// Asynchronous close as this method should be quick.
+			NKern::ThreadLeaveCS();
 			}
 		else
 			{// Remove the existing alias as it is not required.
-			DoRemoveAlias(iAliasLinAddr);
+			DoRemoveAlias(iAliasLinAddr);	// Releases mmulock.
 			}
-		MmuLock::Unlock();
 		aAliasAddr = aAddr;
 		TInt maxSize = KChunkSize-(aAddr&KChunkMask);
 		aAliasSize = aSize<maxSize ? aSize : maxSize;
@@ -666,9 +670,7 @@
 		{
 		MmuLock::Lock();
 
-		DoRemoveAlias(addr);
-
-		MmuLock::Unlock();
+		DoRemoveAlias(addr);	// Unlocks mmulock.
 		}
 	}
 
@@ -692,10 +694,16 @@
 	NKern::EndFreezeCpu(iCpuRestoreCookie);
 	iCpuRestoreCookie = -1;
 #endif
-	// Must close the os asid while the mmu lock is held to prevent it being 
-	// leaked, however this requires that it is closed asynchronously as can't
-	// delete os asid with mmu lock held.
-	iAliasProcess->AsyncCloseOsAsid();
+
+	// Must close the os asid while in critical section to prevent it being 
+	// leaked.  However, we can't hold the mmu lock so we have to enter an 
+	// explict crtical section. It is ok to release the mmu lock as the 
+	// iAliasLinAddr and iAliasProcess members are only ever updated by the 
+	// current thread.
+	NKern::ThreadEnterCS();
+	MmuLock::Unlock();
+	iAliasProcess->AsyncCloseOsAsid();	// Asynchronous close as this method should be quick.
+	NKern::ThreadLeaveCS();
 	}