First public contribution.
1 // Copyright (c) 1994-2009 Nokia Corporation and/or its subsidiary(-ies).
2 // All rights reserved.
3 // This component and the accompanying materials are made available
4 // under the terms of the License "Eclipse Public License v1.0"
5 // which accompanies this distribution, and is available
6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
8 // Initial Contributors:
9 // Nokia Corporation - initial contribution.
14 // e32\nkern\x86\ncthrd.cpp
20 // Called by a thread when it first runs
22 void __DoForcedExit();
24 void NThreadBase::OnKill()
29 void NThreadBase::OnExit()
34 void NThreadBase::SetEntry(NThreadFunction aFunc)
36 SThreadStack* stack=(SThreadStack*)iSavedSP;
37 stack->iEdi=(TUint32)aFunc;
41 TInt NThread::Create(SNThreadCreateInfo& anInfo, TBool aInitial)
43 if (!anInfo.iStackBase || anInfo.iStackSize<0x100)
45 TInt r=NThreadBase::Create(anInfo,aInitial);
50 TUint32* sp=(TUint32*)(iStackBase+iStackSize-anInfo.iParameterBlockSize);
51 TUint32 esi=(TUint32)anInfo.iParameterBlock;
52 if (anInfo.iParameterBlockSize)
54 wordmove(sp,anInfo.iParameterBlock,anInfo.iParameterBlockSize);
57 SThreadStack* stack=((SThreadStack*)sp)-1;
58 stack->iCR0=X86::DefaultCR0 | KX86CR0_TS;
60 stack->iEsi=esi; // parameter block pointer
61 stack->iEdi=(TUint32)anInfo.iFunction;
65 stack->iReschedFlag=1;
66 stack->iEip=(TUint32)__StartThread;
67 iSavedSP=(TLinAddr)stack;
68 wordmove(&iCoprocessorState, DefaultCoprocessorState, sizeof(iCoprocessorState));
72 #ifdef MONITOR_THREAD_CPU_TIME
73 iLastStartTime = NKern::FastCounter();
75 NKern::EnableAllInterrupts();
77 #ifdef BTRACE_THREAD_IDENTIFICATION
78 BTrace4(BTrace::EThreadIdentification,BTrace::ENanoThreadCreate,this);
84 void NThreadBase::ForceExit()
86 SThreadStack* stack=(SThreadStack*)iSavedSP;
87 stack->iEip=(TUint32)__DoForcedExit;
91 void DumpExcInfo(TX86ExcInfo& a)
93 DEBUGPRINT("Exc %02x EFLAGS=%08x FAR=%08x ErrCode=%08x",a.iExcId,a.iEflags,a.iFaultAddress,a.iExcErrorCode);
94 DEBUGPRINT("EAX=%08x EBX=%08x ECX=%08x EDX=%08x",a.iEax,a.iEbx,a.iEcx,a.iEdx);
95 DEBUGPRINT("ESP=%08x EBP=%08x ESI=%08x EDI=%08x",a.iEsp,a.iEbp,a.iEsi,a.iEdi);
96 DEBUGPRINT(" CS=%08x EIP=%08x DS=%08x SS=%08x",a.iCs,a.iEip,a.iDs,a.iSs);
97 DEBUGPRINT(" ES=%08x FS=%08x GS=%08x",a.iEs,a.iFs,a.iGs);
100 DEBUGPRINT("SS3=%08x ESP3=%08x",a.iSs3,a.iEsp3);
102 DEBUGPRINT("Thread %T, KernCSLocked=%d, IrqNest=%d",TheScheduler.iCurrentThread,TheScheduler.iKernCSLocked,X86_IrqNestCount);
106 EXPORT_C void NKern::ThreadGetUserContext(NThread* aThread, TAny* aContext, TUint32& aAvailMask)
108 CHECK_PRECONDITIONS(MASK_INTERRUPTS_ENABLED|MASK_NOT_ISR|MASK_NOT_IDFC, "NKern::ThreadGetUserContext");
111 TX86RegSet* regSet = (TX86RegSet*)aContext;
116 NThread* currentThread = NCurrentThread();
117 DEBUGPRINT(" NCurrentThread()=0x%x, aThread=0x%x", currentThread, aThread);
119 switch (NKern::CurrentContext())
121 case NKern::EThread: DEBUGPRINT(" CurrentContext=NKern::EThread"); break;
122 case NKern::EIDFC: DEBUGPRINT(" CurrentContext=NKern::EIDFC"); break;
123 case NKern::EInterrupt: DEBUGPRINT(" CurrentContext=NKern::EInterrupt"); break;
124 default: DEBUGPRINT(" CurrentContext= Unknown"); break;
127 DEBUGPRINT(" Attributes (iSpare2)=0x%x", aThread->iSpare2);
128 DEBUGPRINT(" iExtraContext=0x%x, iExtraContextSize=0x%x", aThread->iExtraContext, aThread->iExtraContextSize);
130 DEBUGPRINT(" iSuspendCount=%d", aThread->iSuspendCount);
132 DEBUGPRINT(" X86_IrqStack=%x", X86_IrqStack);
134 TBool isCurrentThread = (currentThread == aThread);
136 sp = (TUint32*)aThread->iSavedSP;
137 stackTop = (TUint32*)((TUint32)aThread->iStackBase+(TUint32)aThread->iStackSize);
138 delta = stackTop - sp; // number of words on the supervisor stack
140 DEBUGPRINT(" Stack Top=iStackBase+iStackSize=0x%x iSavedSP=0x%x, delta=0x%x", stackTop, sp, delta);
141 DEBUGPRINT(" iUserContextType (iSpare3)=0x%x", aThread->iSpare3);
143 DEBUGPRINT(" NThreadState:");
144 switch(aThread->iSpare1)
146 case NThreadBase::EReady:
147 DEBUGPRINT(" EReady");
149 case NThreadBase::ESuspended:
150 DEBUGPRINT(" ESuspended");
152 case NThreadBase::EWaitFastSemaphore:
153 DEBUGPRINT(" EWaitFastSemaphore");
155 case NThreadBase::ESleep:
156 DEBUGPRINT(" ESleep");
158 case NThreadBase::EBlocked:
159 DEBUGPRINT(" EBlocked");
161 case NThreadBase::EDead:
162 DEBUGPRINT(" EDead");
164 case NThreadBase::EWaitDfc:
165 DEBUGPRINT(" EWaitDfc");
168 DEBUGPRINT(" *Unknown");
173 DEBUGPRINT(" Setting Stack-Saved Registers");
174 // Hack while ThreadSetUserContext is not implemented
176 if (0 == aThread->iSpare3)
178 // Context when interrupted by user
179 if (aAvailMask & 1<<13)
180 stackTop[-1] = regSet->iSs;
182 if (aAvailMask & 1<<4)
183 stackTop[-2] = regSet->iEsp;
185 if (aAvailMask & 1<<14)
187 DEBUGPRINT(" Setting EFLAGS to %x", regSet->iEflags);
188 stackTop[-3] = regSet->iEflags;
191 if (aAvailMask & 1<<8)
192 stackTop[-4] = regSet->iCs;
194 if (aAvailMask & 1<<15)
195 stackTop[-5] = regSet->iEip;
197 if (aAvailMask & 1<<9)
198 stackTop[-8] = regSet->iDs;
200 if (aAvailMask & 1<<0)
201 stackTop[-9] = regSet->iEax;
203 if (aAvailMask & 1<<2)
204 stackTop[-10] = regSet->iEcx;
206 if (aAvailMask & 1<<5)
207 stackTop[-16] = regSet->iEbp;
209 if (aAvailMask & 1<<7)
210 stackTop[-17] = regSet->iEdi;
212 if (aAvailMask & 1<<6)
213 stackTop[-18] = regSet->iEsi;
217 if (aAvailMask & 1<<13)
218 stackTop[-1] = regSet->iSs;
220 if (aAvailMask & 1<<4)
221 stackTop[-2] = regSet->iEsp;
223 if (aAvailMask & 1<<14)
225 stackTop[-3] = regSet->iEflags;
226 DEBUGPRINT(" Setting EFLAGS to %x", regSet->iEflags);
229 if (aAvailMask & 1<<8)
230 stackTop[-4] = regSet->iCs;
232 if (aAvailMask & 1<<15)
233 stackTop[-5] = regSet->iEip;
235 /* -6 and -7 are not used since they are the vector number and the error code,
236 * which are 3 and 0 resp. for breakpoints.
239 /* The following are from the push instructions in __X86VectorExc */
240 if (aAvailMask & 1<<9)
241 stackTop[-8] = regSet->iDs;
243 if (aAvailMask & 1<<10)
244 stackTop[-9] = regSet->iEs;
246 if (aAvailMask & 1<<11)
247 stackTop[-10] = regSet->iFs;
249 if (aAvailMask & 1<<12)
250 stackTop[-11] = regSet->iGs;
252 if (aAvailMask & 1<<5)
253 stackTop[-12] = regSet->iEbp;
255 if (aAvailMask & 1<<7)
256 stackTop[-13] = regSet->iEdi;
258 if (aAvailMask & 1<<6)
259 stackTop[-14] = regSet->iEsi;
261 if (aAvailMask & 1<<1)
262 stackTop[-15] = regSet->iEbx;
264 if (aAvailMask & 1<<2)
265 stackTop[-16] = regSet->iEcx;
267 if (aAvailMask & 1<<3)
268 stackTop[-17] = regSet->iEdx;
270 if (aAvailMask & 1<<0)
271 stackTop[-18] = regSet->iEax;
274 DEBUGPRINT("stack from stack top, after changes " );
284 for ( ; delta < 0; delta++)
286 DEBUGPRINT("stackTop[%d]=%x", delta, stackTop[delta]);
291 memclr(aContext, sizeof(TX86RegSet));
296 DEBUGPRINT(" NThread::GetContext() : Don't know how to obtain context for current thread\n Use TSS?");
300 DEBUGPRINT("stack from stack top " );
311 for( ; delta < 0; delta++)
313 DEBUGPRINT("stackTop[%d]=%x", delta, stackTop[delta]);
316 if (0 == aThread->iSpare3)
318 // Context when interrupted by user
319 regSet->iSs = stackTop[-1];
322 regSet->iEsp = stackTop[-2];
325 regSet->iEflags = stackTop[-3];
328 regSet->iCs = stackTop[-4];
331 regSet->iEip = stackTop[-5];
334 regSet->iDs = stackTop[-8];
337 regSet->iEax = stackTop[-9];
340 regSet->iEcx = stackTop[-10];
343 regSet->iEbp = stackTop[-16];
346 regSet->iEdi = stackTop[-17];
349 regSet->iEsi = stackTop[-18];
354 // Now populate the TX86RegSet with the contents of the stack
357 * The first 5 are from the comments at the start of __X86VectorExc :
358 * [ESP+0] = vector number
359 * [ESP+4] = error code (filled with 0 for exceptions without error codes)
360 * [ESP+8] = return EIP
361 * [ESP+12] = return CS
362 * [ESP+16] = return EFLAGS
363 * [ESP+20] = return ESP if privilege change occurred
364 * [ESP+24] = return SS if privilege change occurred
366 regSet->iSs = stackTop[-1];
369 regSet->iEsp = stackTop[-2];
372 regSet->iEflags = stackTop[-3];
375 regSet->iCs = stackTop[-4];
378 regSet->iEip = stackTop[-5];
381 /* -6 and -7 are not used since they are the vector number and the error code,
382 * which for a breakpoint are 3 and 0 resp.
385 /* The following are from the push instructions in __X86VectorExc */
386 regSet->iDs = stackTop[-8];
389 regSet->iEs = stackTop[-9];
392 regSet->iFs = stackTop[-10];
395 regSet->iGs = stackTop[-11];
398 regSet->iEbp = stackTop[-12];
401 regSet->iEdi = stackTop[-13];
404 regSet->iEsi = stackTop[-14];
407 regSet->iEbx = stackTop[-15];
410 regSet->iEcx = stackTop[-16];
413 regSet->iEdx = stackTop[-17];
416 regSet->iEax = stackTop[-18];
418 } // else if (0 == aThread->iSpare3)
420 } // else if (isCurrentThread)
422 } // else if (aAvailMask)
428 void NKern::ThreadModifyUsp(NThread* aThread, TLinAddr aUsp)