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