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\nkern\x86\ncthrd.cpp sl@0: // sl@0: // sl@0: sl@0: #include sl@0: sl@0: // Called by a thread when it first runs sl@0: void __StartThread(); sl@0: void __DoForcedExit(); sl@0: sl@0: void NThreadBase::OnKill() sl@0: { sl@0: } sl@0: sl@0: sl@0: void NThreadBase::OnExit() sl@0: { sl@0: } sl@0: sl@0: sl@0: void NThreadBase::SetEntry(NThreadFunction aFunc) sl@0: { sl@0: SThreadStack* stack=(SThreadStack*)iSavedSP; sl@0: stack->iEdi=(TUint32)aFunc; sl@0: } sl@0: sl@0: sl@0: TInt NThread::Create(SNThreadCreateInfo& anInfo, TBool aInitial) sl@0: { sl@0: if (!anInfo.iStackBase || anInfo.iStackSize<0x100) sl@0: return KErrArgument; sl@0: TInt r=NThreadBase::Create(anInfo,aInitial); sl@0: if (r!=KErrNone) sl@0: return r; sl@0: if (!aInitial) sl@0: { sl@0: TUint32* sp=(TUint32*)(iStackBase+iStackSize-anInfo.iParameterBlockSize); sl@0: TUint32 esi=(TUint32)anInfo.iParameterBlock; sl@0: if (anInfo.iParameterBlockSize) sl@0: { sl@0: wordmove(sp,anInfo.iParameterBlock,anInfo.iParameterBlockSize); sl@0: esi=(TUint32)sp; sl@0: } sl@0: SThreadStack* stack=((SThreadStack*)sp)-1; sl@0: stack->iCR0=X86::DefaultCR0 | KX86CR0_TS; sl@0: stack->iEbx=0; sl@0: stack->iEsi=esi; // parameter block pointer sl@0: stack->iEdi=(TUint32)anInfo.iFunction; sl@0: stack->iEbp=0; sl@0: stack->iGs=KRing0DS; sl@0: stack->iFs=0; sl@0: stack->iReschedFlag=1; sl@0: stack->iEip=(TUint32)__StartThread; sl@0: iSavedSP=(TLinAddr)stack; sl@0: wordmove(&iCoprocessorState, DefaultCoprocessorState, sizeof(iCoprocessorState)); sl@0: } sl@0: else sl@0: { sl@0: #ifdef MONITOR_THREAD_CPU_TIME sl@0: iLastStartTime = NKern::FastCounter(); sl@0: #endif sl@0: NKern::EnableAllInterrupts(); sl@0: } sl@0: #ifdef BTRACE_THREAD_IDENTIFICATION sl@0: BTrace4(BTrace::EThreadIdentification,BTrace::ENanoThreadCreate,this); sl@0: #endif sl@0: return KErrNone; sl@0: } sl@0: sl@0: sl@0: void NThreadBase::ForceExit() sl@0: { sl@0: SThreadStack* stack=(SThreadStack*)iSavedSP; sl@0: stack->iEip=(TUint32)__DoForcedExit; sl@0: } sl@0: sl@0: sl@0: void DumpExcInfo(TX86ExcInfo& a) sl@0: { sl@0: DEBUGPRINT("Exc %02x EFLAGS=%08x FAR=%08x ErrCode=%08x",a.iExcId,a.iEflags,a.iFaultAddress,a.iExcErrorCode); sl@0: DEBUGPRINT("EAX=%08x EBX=%08x ECX=%08x EDX=%08x",a.iEax,a.iEbx,a.iEcx,a.iEdx); sl@0: DEBUGPRINT("ESP=%08x EBP=%08x ESI=%08x EDI=%08x",a.iEsp,a.iEbp,a.iEsi,a.iEdi); sl@0: DEBUGPRINT(" CS=%08x EIP=%08x DS=%08x SS=%08x",a.iCs,a.iEip,a.iDs,a.iSs); sl@0: DEBUGPRINT(" ES=%08x FS=%08x GS=%08x",a.iEs,a.iFs,a.iGs); sl@0: if (a.iCs&3) sl@0: { sl@0: DEBUGPRINT("SS3=%08x ESP3=%08x",a.iSs3,a.iEsp3); sl@0: } sl@0: DEBUGPRINT("Thread %T, KernCSLocked=%d, IrqNest=%d",TheScheduler.iCurrentThread,TheScheduler.iKernCSLocked,X86_IrqNestCount); sl@0: } sl@0: sl@0: sl@0: EXPORT_C void NKern::ThreadGetUserContext(NThread* aThread, TAny* aContext, TUint32& aAvailMask) sl@0: { sl@0: CHECK_PRECONDITIONS(MASK_INTERRUPTS_ENABLED|MASK_NOT_ISR|MASK_NOT_IDFC, "NKern::ThreadGetUserContext"); sl@0: TUint32* sp; sl@0: TUint32* stackTop; sl@0: TX86RegSet* regSet = (TX86RegSet*)aContext; sl@0: TInt delta; sl@0: sl@0: NKern::Lock(); sl@0: sl@0: NThread* currentThread = NCurrentThread(); sl@0: DEBUGPRINT(" NCurrentThread()=0x%x, aThread=0x%x", currentThread, aThread); sl@0: sl@0: switch (NKern::CurrentContext()) sl@0: { sl@0: case NKern::EThread: DEBUGPRINT(" CurrentContext=NKern::EThread"); break; sl@0: case NKern::EIDFC: DEBUGPRINT(" CurrentContext=NKern::EIDFC"); break; sl@0: case NKern::EInterrupt: DEBUGPRINT(" CurrentContext=NKern::EInterrupt"); break; sl@0: default: DEBUGPRINT(" CurrentContext= Unknown"); break; sl@0: } sl@0: sl@0: DEBUGPRINT(" Attributes (iSpare2)=0x%x", aThread->iSpare2); sl@0: DEBUGPRINT(" iExtraContext=0x%x, iExtraContextSize=0x%x", aThread->iExtraContext, aThread->iExtraContextSize); sl@0: sl@0: DEBUGPRINT(" iSuspendCount=%d", aThread->iSuspendCount); sl@0: sl@0: DEBUGPRINT(" X86_IrqStack=%x", X86_IrqStack); sl@0: sl@0: TBool isCurrentThread = (currentThread == aThread); sl@0: sl@0: sp = (TUint32*)aThread->iSavedSP; sl@0: stackTop = (TUint32*)((TUint32)aThread->iStackBase+(TUint32)aThread->iStackSize); sl@0: delta = stackTop - sp; // number of words on the supervisor stack sl@0: sl@0: DEBUGPRINT(" Stack Top=iStackBase+iStackSize=0x%x iSavedSP=0x%x, delta=0x%x", stackTop, sp, delta); sl@0: DEBUGPRINT(" iUserContextType (iSpare3)=0x%x", aThread->iSpare3); sl@0: sl@0: DEBUGPRINT(" NThreadState:"); sl@0: switch(aThread->iSpare1) sl@0: { sl@0: case NThreadBase::EReady: sl@0: DEBUGPRINT(" EReady"); sl@0: break; sl@0: case NThreadBase::ESuspended: sl@0: DEBUGPRINT(" ESuspended"); sl@0: break; sl@0: case NThreadBase::EWaitFastSemaphore: sl@0: DEBUGPRINT(" EWaitFastSemaphore"); sl@0: break; sl@0: case NThreadBase::ESleep: sl@0: DEBUGPRINT(" ESleep"); sl@0: break; sl@0: case NThreadBase::EBlocked: sl@0: DEBUGPRINT(" EBlocked"); sl@0: break; sl@0: case NThreadBase::EDead: sl@0: DEBUGPRINT(" EDead"); sl@0: break; sl@0: case NThreadBase::EWaitDfc: sl@0: DEBUGPRINT(" EWaitDfc"); sl@0: break; sl@0: default: sl@0: DEBUGPRINT(" *Unknown"); sl@0: } sl@0: sl@0: if (aAvailMask) sl@0: { sl@0: DEBUGPRINT(" Setting Stack-Saved Registers"); sl@0: // Hack while ThreadSetUserContext is not implemented sl@0: sl@0: if (0 == aThread->iSpare3) sl@0: { sl@0: // Context when interrupted by user sl@0: if (aAvailMask & 1<<13) sl@0: stackTop[-1] = regSet->iSs; sl@0: sl@0: if (aAvailMask & 1<<4) sl@0: stackTop[-2] = regSet->iEsp; sl@0: sl@0: if (aAvailMask & 1<<14) sl@0: { sl@0: DEBUGPRINT(" Setting EFLAGS to %x", regSet->iEflags); sl@0: stackTop[-3] = regSet->iEflags; sl@0: } sl@0: sl@0: if (aAvailMask & 1<<8) sl@0: stackTop[-4] = regSet->iCs; sl@0: sl@0: if (aAvailMask & 1<<15) sl@0: stackTop[-5] = regSet->iEip; sl@0: sl@0: if (aAvailMask & 1<<9) sl@0: stackTop[-8] = regSet->iDs; sl@0: sl@0: if (aAvailMask & 1<<0) sl@0: stackTop[-9] = regSet->iEax; sl@0: sl@0: if (aAvailMask & 1<<2) sl@0: stackTop[-10] = regSet->iEcx; sl@0: sl@0: if (aAvailMask & 1<<5) sl@0: stackTop[-16] = regSet->iEbp; sl@0: sl@0: if (aAvailMask & 1<<7) sl@0: stackTop[-17] = regSet->iEdi; sl@0: sl@0: if (aAvailMask & 1<<6) sl@0: stackTop[-18] = regSet->iEsi; sl@0: } sl@0: else sl@0: { sl@0: if (aAvailMask & 1<<13) sl@0: stackTop[-1] = regSet->iSs; sl@0: sl@0: if (aAvailMask & 1<<4) sl@0: stackTop[-2] = regSet->iEsp; sl@0: sl@0: if (aAvailMask & 1<<14) sl@0: { sl@0: stackTop[-3] = regSet->iEflags; sl@0: DEBUGPRINT(" Setting EFLAGS to %x", regSet->iEflags); sl@0: } sl@0: sl@0: if (aAvailMask & 1<<8) sl@0: stackTop[-4] = regSet->iCs; sl@0: sl@0: if (aAvailMask & 1<<15) sl@0: stackTop[-5] = regSet->iEip; sl@0: sl@0: /* -6 and -7 are not used since they are the vector number and the error code, sl@0: * which are 3 and 0 resp. for breakpoints. sl@0: */ sl@0: sl@0: /* The following are from the push instructions in __X86VectorExc */ sl@0: if (aAvailMask & 1<<9) sl@0: stackTop[-8] = regSet->iDs; sl@0: sl@0: if (aAvailMask & 1<<10) sl@0: stackTop[-9] = regSet->iEs; sl@0: sl@0: if (aAvailMask & 1<<11) sl@0: stackTop[-10] = regSet->iFs; sl@0: sl@0: if (aAvailMask & 1<<12) sl@0: stackTop[-11] = regSet->iGs; sl@0: sl@0: if (aAvailMask & 1<<5) sl@0: stackTop[-12] = regSet->iEbp; sl@0: sl@0: if (aAvailMask & 1<<7) sl@0: stackTop[-13] = regSet->iEdi; sl@0: sl@0: if (aAvailMask & 1<<6) sl@0: stackTop[-14] = regSet->iEsi; sl@0: sl@0: if (aAvailMask & 1<<1) sl@0: stackTop[-15] = regSet->iEbx; sl@0: sl@0: if (aAvailMask & 1<<2) sl@0: stackTop[-16] = regSet->iEcx; sl@0: sl@0: if (aAvailMask & 1<<3) sl@0: stackTop[-17] = regSet->iEdx; sl@0: sl@0: if (aAvailMask & 1<<0) sl@0: stackTop[-18] = regSet->iEax; sl@0: } sl@0: sl@0: DEBUGPRINT("stack from stack top, after changes " ); sl@0: if (delta < 128) sl@0: { sl@0: delta = -delta; sl@0: } sl@0: else sl@0: { sl@0: delta = -128; sl@0: } sl@0: sl@0: for ( ; delta < 0; delta++) sl@0: { sl@0: DEBUGPRINT("stackTop[%d]=%x", delta, stackTop[delta]); sl@0: } sl@0: } sl@0: else sl@0: { sl@0: memclr(aContext, sizeof(TX86RegSet)); sl@0: sl@0: if (isCurrentThread) sl@0: { sl@0: // Not yet supported sl@0: DEBUGPRINT(" NThread::GetContext() : Don't know how to obtain context for current thread\n Use TSS?"); sl@0: } sl@0: else sl@0: { sl@0: DEBUGPRINT("stack from stack top " ); sl@0: sl@0: if (delta < 128) sl@0: { sl@0: delta = -delta; sl@0: } sl@0: else sl@0: { sl@0: delta = -128; sl@0: } sl@0: sl@0: for( ; delta < 0; delta++) sl@0: { sl@0: DEBUGPRINT("stackTop[%d]=%x", delta, stackTop[delta]); sl@0: } sl@0: sl@0: if (0 == aThread->iSpare3) sl@0: { sl@0: // Context when interrupted by user sl@0: regSet->iSs = stackTop[-1]; sl@0: aAvailMask |= 1<<13; sl@0: sl@0: regSet->iEsp = stackTop[-2]; sl@0: aAvailMask |= 1<<4; sl@0: sl@0: regSet->iEflags = stackTop[-3]; sl@0: aAvailMask |= 1<<14; sl@0: sl@0: regSet->iCs = stackTop[-4]; sl@0: aAvailMask |= 1<<8; sl@0: sl@0: regSet->iEip = stackTop[-5]; sl@0: aAvailMask |= 1<<15; sl@0: sl@0: regSet->iDs = stackTop[-8]; sl@0: aAvailMask |= 1<<9; sl@0: sl@0: regSet->iEax = stackTop[-9]; sl@0: aAvailMask |= 1<<0; sl@0: sl@0: regSet->iEcx = stackTop[-10]; sl@0: aAvailMask |= 1<<2; sl@0: sl@0: regSet->iEbp = stackTop[-16]; sl@0: aAvailMask |= 1<<5; sl@0: sl@0: regSet->iEdi = stackTop[-17]; sl@0: aAvailMask |= 1<<7; sl@0: sl@0: regSet->iEsi = stackTop[-18]; sl@0: aAvailMask |= 1<<6; sl@0: } sl@0: else sl@0: { sl@0: // Now populate the TX86RegSet with the contents of the stack sl@0: sl@0: /* sl@0: * The first 5 are from the comments at the start of __X86VectorExc : sl@0: * [ESP+0] = vector number sl@0: * [ESP+4] = error code (filled with 0 for exceptions without error codes) sl@0: * [ESP+8] = return EIP sl@0: * [ESP+12] = return CS sl@0: * [ESP+16] = return EFLAGS sl@0: * [ESP+20] = return ESP if privilege change occurred sl@0: * [ESP+24] = return SS if privilege change occurred sl@0: */ sl@0: regSet->iSs = stackTop[-1]; sl@0: aAvailMask |= 1<<13; sl@0: sl@0: regSet->iEsp = stackTop[-2]; sl@0: aAvailMask |= 1<<4; sl@0: sl@0: regSet->iEflags = stackTop[-3]; sl@0: aAvailMask |= 1<<14; sl@0: sl@0: regSet->iCs = stackTop[-4]; sl@0: aAvailMask |= 1<<8; sl@0: sl@0: regSet->iEip = stackTop[-5]; sl@0: aAvailMask |= 1<<15; sl@0: sl@0: /* -6 and -7 are not used since they are the vector number and the error code, sl@0: * which for a breakpoint are 3 and 0 resp. sl@0: */ sl@0: sl@0: /* The following are from the push instructions in __X86VectorExc */ sl@0: regSet->iDs = stackTop[-8]; sl@0: aAvailMask |= 1<<9; sl@0: sl@0: regSet->iEs = stackTop[-9]; sl@0: aAvailMask |= 1<<10; sl@0: sl@0: regSet->iFs = stackTop[-10]; sl@0: aAvailMask |= 1<<11; sl@0: sl@0: regSet->iGs = stackTop[-11]; sl@0: aAvailMask |= 1<<12; sl@0: sl@0: regSet->iEbp = stackTop[-12]; sl@0: aAvailMask |= 1<<5; sl@0: sl@0: regSet->iEdi = stackTop[-13]; sl@0: aAvailMask |= 1<<7; sl@0: sl@0: regSet->iEsi = stackTop[-14]; sl@0: aAvailMask |= 1<<6; sl@0: sl@0: regSet->iEbx = stackTop[-15]; sl@0: aAvailMask |= 1<<1; sl@0: sl@0: regSet->iEcx = stackTop[-16]; sl@0: aAvailMask |= 1<<2; sl@0: sl@0: regSet->iEdx = stackTop[-17]; sl@0: aAvailMask |= 1<<3; sl@0: sl@0: regSet->iEax = stackTop[-18]; sl@0: aAvailMask |= 1<<0; sl@0: } // else if (0 == aThread->iSpare3) sl@0: sl@0: } // else if (isCurrentThread) sl@0: sl@0: } // else if (aAvailMask) sl@0: sl@0: NKern::Unlock(); sl@0: } sl@0: sl@0: sl@0: void NKern::ThreadModifyUsp(NThread* aThread, TLinAddr aUsp) sl@0: { sl@0: }