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