--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/kernel/eka/memmodel/epoc/multiple/mkernel.cpp Mon Oct 19 15:55:17 2009 +0100
@@ -0,0 +1,157 @@
+// Copyright (c) 1994-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+// e32\memmodel\epoc\multiple\mkernel.cpp
+//
+//
+
+#include "memmodel.h"
+
+/********************************************
+ * Thread
+ ********************************************/
+
+TInt DThread::AllocateSupervisorStack()
+ {
+ __KTRACE_OPT(KTHREAD,Kern::Printf("DThread::AllocateSupervisorStack %O %x",this,iSupervisorStackSize));
+ iSupervisorStackSize=Mmu::RoundToPageSize(iSupervisorStackSize);
+ if (iThreadType!=EThreadInitial)
+ {
+ TInt offset=MM::SvStackChunk->Allocate(iSupervisorStackSize,PP::SupervisorThreadStackGuard);
+ if (offset<0)
+ {
+ __KTRACE_FAIL(KErrNoMemory,Kern::Printf("ASS: %d",KErrNoMemory));
+ return KErrNoMemory;
+ }
+ iSupervisorStack=MM::SvStackChunk->Base()+offset+PP::SupervisorThreadStackGuard;
+ iSupervisorStackAllocated = TRUE;
+ __KTRACE_OPT(KTHREAD,Kern::Printf("Supervisor stack at %x, size %x",iSupervisorStack,iSupervisorStackSize));
+ }
+ return KErrNone;
+ }
+
+void DMemModelThread::DoExit1()
+ {
+ // Regularize the thread state before main exit processing.
+ // We must remove any existing alias before we do any operation
+ // which requires aliasing (e.g. logon completion).
+ __KTRACE_OPT(KTHREAD,Kern::Printf("DMemModelThread %O DoExit1",this));
+ NKern::LockSystem();
+ RemoveAlias();
+ NKern::UnlockSystem();
+ }
+
+void DThread::FreeSupervisorStack()
+ {
+ __KTRACE_OPT(KTHREAD,Kern::Printf("DThread::FreeSupervisorStack %O",this));
+ if (iSupervisorStackAllocated)
+ {
+ TAny* pStack = __e32_atomic_swp_ord_ptr(&iSupervisorStack, 0);
+ if (pStack && iThreadType!=EThreadInitial)
+ {
+ __KTRACE_OPT(KTHREAD,Kern::Printf("Freeing supervisor stack at %08x, size %x",pStack,iSupervisorStackSize));
+ TInt offset=(TUint8*)pStack-MM::SvStackChunk->Base();
+ TInt r=MM::SvStackChunk->Decommit(offset-PP::SupervisorThreadStackGuard,iSupervisorStackSize+PP::SupervisorThreadStackGuard);
+ __ASSERT_DEBUG(r==KErrNone, MM::Panic(MM::EDecommitFailed));
+ (void)r; //Supress the warning in urel build
+ }
+ }
+ iSupervisorStackAllocated = FALSE;
+ }
+
+TInt DThread::AllocateUserStack(TInt aSize, TBool /*aPaged*/)
+ {
+ __KTRACE_OPT(KTHREAD,Kern::Printf("DThread::AllocateUserStack %O %x",this,aSize));
+
+ aSize=Mmu::RoundToPageSize(aSize);
+ if (aSize>PP::MaxUserThreadStack)
+ return KErrTooBig;
+ TInt guard=PP::UserThreadStackGuard;
+ DProcess* pP=iOwningProcess;
+ NKern::LockSystem();
+ DChunk* pC=pP->iDataBssStackChunk;
+ if (!pC || pC->Open()!=KErrNone) // so chunk doesn't disappear during Allocate()
+ {
+ NKern::UnlockSystem();
+ __KTRACE_FAIL(KErrDied,Kern::Printf("AUS1: %d",KErrDied));
+ return KErrDied;
+ }
+ NKern::UnlockSystem();
+ TInt r=pC->Allocate(aSize,guard);
+ TInt s=pC->Close(NULL); // NULL since we didn't add chunk to process again
+ if (s & EObjectDeleted)
+ {
+ __KTRACE_FAIL(KErrDied,Kern::Printf("AUS2: %d",KErrDied));
+ return KErrDied;
+ }
+ if (r<0)
+ {
+ __KTRACE_FAIL(r,Kern::Printf("AUS3: %d",r));
+ return r;
+ }
+ iUserStackSize=aSize;
+ iUserStackRunAddress=pP->iDataBssRunAddress+r+guard;
+ __KTRACE_OPT(KTHREAD,Kern::Printf("User stack run address at %x",iUserStackRunAddress));
+ return KErrNone;
+ }
+
+void DThread::FreeUserStack()
+ {
+ __KTRACE_OPT(KTHREAD,Kern::Printf("DThread::FreeUserStack %O",this));
+ TLinAddr usr_stack = (TLinAddr)__e32_atomic_swp_ord_ptr(&iUserStackRunAddress, 0);
+ if (usr_stack)
+ {
+ __KTRACE_OPT(KTHREAD,Kern::Printf("Freeing user stack at %x",usr_stack));
+ DMemModelProcess* pP=(DMemModelProcess*)iOwningProcess;
+ NKern::LockSystem();
+ DMemModelChunk* pC=(DMemModelChunk*)pP->iDataBssStackChunk;
+ if (!pC || pC->Open()!=KErrNone) // so chunk doesn't disappear during Decommit()
+ {
+ NKern::UnlockSystem();
+ __KTRACE_FAIL(KErrDied,Kern::Printf("FUS"));
+ return;
+ }
+ NKern::UnlockSystem();
+ TInt offset=usr_stack-pP->iDataBssRunAddress;
+ TInt r=pC->Decommit(offset-PP::UserThreadStackGuard,iUserStackSize+PP::UserThreadStackGuard);
+ __ASSERT_DEBUG(r==KErrNone, MM::Panic(MM::EDecommitFailed));
+ pC->Close(NULL); // NULL since we didn't add chunk to process again
+ (void)r; //Supress the warning in urel build
+ }
+ }
+
+void DThread::IpcExcHandler(TExcTrap* aTrap, DThread* aThread, TAny* aContext)
+ {
+ aThread->iIpcClient = 0;
+ TIpcExcTrap& xt=*(TIpcExcTrap*)aTrap;
+ switch (xt.ExcLocation(aThread, aContext))
+ {
+ case TIpcExcTrap::EExcRemote:
+ // problem accessing remote address - 'leave' so an error code will be returned
+ NKern::LockSystem();
+ ((DMemModelThread*)aThread)->RemoveAlias();
+ xt.Exception(KErrBadDescriptor); // does not return
+
+ case TIpcExcTrap::EExcLocal:
+ // problem accessing local address - return and panic current thread as usual
+ NKern::LockSystem();
+ ((DMemModelThread*)aThread)->RemoveAlias();
+ NKern::UnlockSystem();
+ return;
+
+ default:
+ // otherwise return and fault kernel
+ NKern::LockSystem();
+ return;
+ }
+ }