author | mikek |
Sun, 27 Jun 2010 21:43:55 +0100 | |
branch | GCC_SURGE |
changeset 181 | bd8f1e65581b |
parent 0 | a41df078684a |
permissions | -rw-r--r-- |
// 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; } }