os/kernelhwsrv/kernel/eka/nkern/x86/ncthrd.cpp
author sl@SLION-WIN7.fritz.box
Fri, 15 Jun 2012 03:10:57 +0200
changeset 0 bde4ae8d615e
permissions -rw-r--r--
First public contribution.
sl@0
     1
// Copyright (c) 1994-2009 Nokia Corporation and/or its subsidiary(-ies).
sl@0
     2
// All rights reserved.
sl@0
     3
// This component and the accompanying materials are made available
sl@0
     4
// under the terms of the License "Eclipse Public License v1.0"
sl@0
     5
// which accompanies this distribution, and is available
sl@0
     6
// at the URL "http://www.eclipse.org/legal/epl-v10.html".
sl@0
     7
//
sl@0
     8
// Initial Contributors:
sl@0
     9
// Nokia Corporation - initial contribution.
sl@0
    10
//
sl@0
    11
// Contributors:
sl@0
    12
//
sl@0
    13
// Description:
sl@0
    14
// e32\nkern\x86\ncthrd.cpp
sl@0
    15
// 
sl@0
    16
//
sl@0
    17
sl@0
    18
#include <x86.h>
sl@0
    19
sl@0
    20
// Called by a thread when it first runs
sl@0
    21
void __StartThread();
sl@0
    22
void __DoForcedExit();
sl@0
    23
sl@0
    24
void NThreadBase::OnKill()
sl@0
    25
	{
sl@0
    26
	}
sl@0
    27
sl@0
    28
sl@0
    29
void NThreadBase::OnExit()
sl@0
    30
	{
sl@0
    31
	}
sl@0
    32
sl@0
    33
sl@0
    34
void NThreadBase::SetEntry(NThreadFunction aFunc)
sl@0
    35
	{
sl@0
    36
	SThreadStack* stack=(SThreadStack*)iSavedSP;
sl@0
    37
	stack->iEdi=(TUint32)aFunc;
sl@0
    38
	}
sl@0
    39
sl@0
    40
sl@0
    41
TInt NThread::Create(SNThreadCreateInfo& anInfo, TBool aInitial)
sl@0
    42
	{
sl@0
    43
	if (!anInfo.iStackBase || anInfo.iStackSize<0x100)
sl@0
    44
		return KErrArgument;
sl@0
    45
	TInt r=NThreadBase::Create(anInfo,aInitial);
sl@0
    46
	if (r!=KErrNone)
sl@0
    47
		return r;
sl@0
    48
	if (!aInitial)
sl@0
    49
		{
sl@0
    50
		TUint32* sp=(TUint32*)(iStackBase+iStackSize-anInfo.iParameterBlockSize);
sl@0
    51
		TUint32 esi=(TUint32)anInfo.iParameterBlock;
sl@0
    52
		if (anInfo.iParameterBlockSize)
sl@0
    53
			{
sl@0
    54
			wordmove(sp,anInfo.iParameterBlock,anInfo.iParameterBlockSize);
sl@0
    55
			esi=(TUint32)sp;
sl@0
    56
			}
sl@0
    57
		SThreadStack* stack=((SThreadStack*)sp)-1;
sl@0
    58
		stack->iCR0=X86::DefaultCR0 | KX86CR0_TS;
sl@0
    59
		stack->iEbx=0;
sl@0
    60
		stack->iEsi=esi;					// parameter block pointer
sl@0
    61
		stack->iEdi=(TUint32)anInfo.iFunction;
sl@0
    62
		stack->iEbp=0;
sl@0
    63
		stack->iGs=KRing0DS;
sl@0
    64
		stack->iFs=0;
sl@0
    65
		stack->iReschedFlag=1;
sl@0
    66
		stack->iEip=(TUint32)__StartThread;
sl@0
    67
		iSavedSP=(TLinAddr)stack;
sl@0
    68
		wordmove(&iCoprocessorState, DefaultCoprocessorState, sizeof(iCoprocessorState));
sl@0
    69
		}
sl@0
    70
	else
sl@0
    71
		{
sl@0
    72
#ifdef MONITOR_THREAD_CPU_TIME
sl@0
    73
		iLastStartTime = NKern::FastCounter();
sl@0
    74
#endif
sl@0
    75
		NKern::EnableAllInterrupts();
sl@0
    76
		}
sl@0
    77
#ifdef BTRACE_THREAD_IDENTIFICATION
sl@0
    78
	BTrace4(BTrace::EThreadIdentification,BTrace::ENanoThreadCreate,this);
sl@0
    79
#endif
sl@0
    80
	return KErrNone;
sl@0
    81
	}
sl@0
    82
sl@0
    83
sl@0
    84
void NThreadBase::ForceExit()
sl@0
    85
	{
sl@0
    86
	SThreadStack* stack=(SThreadStack*)iSavedSP;
sl@0
    87
	stack->iEip=(TUint32)__DoForcedExit;
sl@0
    88
	}
sl@0
    89
sl@0
    90
sl@0
    91
void DumpExcInfo(TX86ExcInfo& a)
sl@0
    92
	{
sl@0
    93
	DEBUGPRINT("Exc %02x EFLAGS=%08x FAR=%08x ErrCode=%08x",a.iExcId,a.iEflags,a.iFaultAddress,a.iExcErrorCode);
sl@0
    94
	DEBUGPRINT("EAX=%08x EBX=%08x ECX=%08x EDX=%08x",a.iEax,a.iEbx,a.iEcx,a.iEdx);
sl@0
    95
	DEBUGPRINT("ESP=%08x EBP=%08x ESI=%08x EDI=%08x",a.iEsp,a.iEbp,a.iEsi,a.iEdi);
sl@0
    96
	DEBUGPRINT(" CS=%08x EIP=%08x  DS=%08x  SS=%08x",a.iCs,a.iEip,a.iDs,a.iSs);
sl@0
    97
	DEBUGPRINT(" ES=%08x  FS=%08x  GS=%08x",a.iEs,a.iFs,a.iGs);
sl@0
    98
	if (a.iCs&3)
sl@0
    99
		{
sl@0
   100
		DEBUGPRINT("SS3=%08x ESP3=%08x",a.iSs3,a.iEsp3);
sl@0
   101
		}
sl@0
   102
	DEBUGPRINT("Thread %T, KernCSLocked=%d, IrqNest=%d",TheScheduler.iCurrentThread,TheScheduler.iKernCSLocked,X86_IrqNestCount);
sl@0
   103
	}
sl@0
   104
sl@0
   105
sl@0
   106
EXPORT_C void NKern::ThreadGetUserContext(NThread* aThread, TAny* aContext, TUint32& aAvailMask)
sl@0
   107
	{
sl@0
   108
	CHECK_PRECONDITIONS(MASK_INTERRUPTS_ENABLED|MASK_NOT_ISR|MASK_NOT_IDFC, "NKern::ThreadGetUserContext");
sl@0
   109
	TUint32* sp;
sl@0
   110
	TUint32* stackTop;
sl@0
   111
	TX86RegSet* regSet = (TX86RegSet*)aContext;
sl@0
   112
	TInt delta;
sl@0
   113
sl@0
   114
	NKern::Lock();
sl@0
   115
sl@0
   116
	NThread* currentThread = NCurrentThread();
sl@0
   117
	DEBUGPRINT(" NCurrentThread()=0x%x, aThread=0x%x", currentThread, aThread);
sl@0
   118
sl@0
   119
	switch (NKern::CurrentContext())
sl@0
   120
		{
sl@0
   121
		case NKern::EThread: DEBUGPRINT(" CurrentContext=NKern::EThread"); break;
sl@0
   122
		case NKern::EIDFC: DEBUGPRINT(" CurrentContext=NKern::EIDFC"); break;
sl@0
   123
		case NKern::EInterrupt: DEBUGPRINT(" CurrentContext=NKern::EInterrupt"); break;
sl@0
   124
		default: DEBUGPRINT(" CurrentContext= Unknown"); break;
sl@0
   125
		}
sl@0
   126
sl@0
   127
	DEBUGPRINT(" Attributes (iSpare2)=0x%x", aThread->iSpare2);
sl@0
   128
	DEBUGPRINT(" iExtraContext=0x%x, iExtraContextSize=0x%x", aThread->iExtraContext, aThread->iExtraContextSize);
sl@0
   129
sl@0
   130
	DEBUGPRINT(" iSuspendCount=%d", aThread->iSuspendCount);
sl@0
   131
sl@0
   132
	DEBUGPRINT(" X86_IrqStack=%x", X86_IrqStack);
sl@0
   133
sl@0
   134
	TBool isCurrentThread = (currentThread == aThread);
sl@0
   135
sl@0
   136
	sp = (TUint32*)aThread->iSavedSP;
sl@0
   137
	stackTop = (TUint32*)((TUint32)aThread->iStackBase+(TUint32)aThread->iStackSize);
sl@0
   138
	delta = stackTop - sp;	// number of words on the supervisor stack
sl@0
   139
sl@0
   140
	DEBUGPRINT(" Stack Top=iStackBase+iStackSize=0x%x iSavedSP=0x%x, delta=0x%x", stackTop, sp, delta);
sl@0
   141
	DEBUGPRINT(" iUserContextType (iSpare3)=0x%x", aThread->iSpare3);
sl@0
   142
sl@0
   143
	DEBUGPRINT(" NThreadState:");
sl@0
   144
	switch(aThread->iSpare1)
sl@0
   145
		{
sl@0
   146
		case NThreadBase::EReady:
sl@0
   147
			DEBUGPRINT(" EReady");
sl@0
   148
			break;
sl@0
   149
		case NThreadBase::ESuspended:
sl@0
   150
			DEBUGPRINT(" ESuspended");
sl@0
   151
			break;
sl@0
   152
		case NThreadBase::EWaitFastSemaphore:
sl@0
   153
			DEBUGPRINT(" EWaitFastSemaphore");
sl@0
   154
			break;
sl@0
   155
		case NThreadBase::ESleep:
sl@0
   156
			DEBUGPRINT(" ESleep");
sl@0
   157
			break;
sl@0
   158
		case NThreadBase::EBlocked:
sl@0
   159
			DEBUGPRINT(" EBlocked");
sl@0
   160
			break;
sl@0
   161
		case NThreadBase::EDead:
sl@0
   162
			DEBUGPRINT(" EDead");
sl@0
   163
			break;
sl@0
   164
		case NThreadBase::EWaitDfc:
sl@0
   165
			DEBUGPRINT(" EWaitDfc");
sl@0
   166
			break;
sl@0
   167
		default:
sl@0
   168
			DEBUGPRINT(" *Unknown");
sl@0
   169
		}
sl@0
   170
sl@0
   171
	if (aAvailMask)
sl@0
   172
		{
sl@0
   173
		DEBUGPRINT(" Setting Stack-Saved Registers");
sl@0
   174
		// Hack while ThreadSetUserContext is not implemented
sl@0
   175
sl@0
   176
		if (0 == aThread->iSpare3)
sl@0
   177
			{
sl@0
   178
			// Context when interrupted by user
sl@0
   179
			if (aAvailMask & 1<<13)
sl@0
   180
				stackTop[-1] = regSet->iSs;
sl@0
   181
sl@0
   182
			if (aAvailMask & 1<<4)
sl@0
   183
				stackTop[-2] = regSet->iEsp;
sl@0
   184
sl@0
   185
			if (aAvailMask & 1<<14)
sl@0
   186
				{
sl@0
   187
				DEBUGPRINT(" Setting EFLAGS to %x", regSet->iEflags);
sl@0
   188
				stackTop[-3] = regSet->iEflags;
sl@0
   189
				}
sl@0
   190
sl@0
   191
			if (aAvailMask & 1<<8)
sl@0
   192
				stackTop[-4] = regSet->iCs;
sl@0
   193
sl@0
   194
			if (aAvailMask & 1<<15)
sl@0
   195
				stackTop[-5] = regSet->iEip;
sl@0
   196
sl@0
   197
			if (aAvailMask & 1<<9)
sl@0
   198
				stackTop[-8] = regSet->iDs;
sl@0
   199
sl@0
   200
			if (aAvailMask & 1<<0)
sl@0
   201
				stackTop[-9] = regSet->iEax;
sl@0
   202
sl@0
   203
			if (aAvailMask & 1<<2)
sl@0
   204
				stackTop[-10] = regSet->iEcx;
sl@0
   205
sl@0
   206
			if (aAvailMask & 1<<5)
sl@0
   207
				stackTop[-16] = regSet->iEbp;
sl@0
   208
sl@0
   209
			if (aAvailMask & 1<<7)
sl@0
   210
				stackTop[-17] = regSet->iEdi;
sl@0
   211
sl@0
   212
			if (aAvailMask & 1<<6)
sl@0
   213
				stackTop[-18] = regSet->iEsi;
sl@0
   214
			}
sl@0
   215
		else
sl@0
   216
			{
sl@0
   217
			if (aAvailMask & 1<<13)
sl@0
   218
				stackTop[-1] = regSet->iSs;
sl@0
   219
sl@0
   220
			if (aAvailMask & 1<<4)
sl@0
   221
				stackTop[-2] = regSet->iEsp;
sl@0
   222
sl@0
   223
			if (aAvailMask & 1<<14)
sl@0
   224
				{
sl@0
   225
				stackTop[-3] = regSet->iEflags;
sl@0
   226
				DEBUGPRINT(" Setting EFLAGS to %x", regSet->iEflags);
sl@0
   227
				}
sl@0
   228
sl@0
   229
			if (aAvailMask & 1<<8)
sl@0
   230
				stackTop[-4] = regSet->iCs;
sl@0
   231
sl@0
   232
			if (aAvailMask & 1<<15)
sl@0
   233
				stackTop[-5] = regSet->iEip;
sl@0
   234
sl@0
   235
			/* -6 and -7 are not used since they are the vector number and the error code,
sl@0
   236
			 * which are 3 and 0 resp. for breakpoints.
sl@0
   237
			 */
sl@0
   238
sl@0
   239
			/* The following are from the push instructions in __X86VectorExc */
sl@0
   240
			if (aAvailMask & 1<<9)
sl@0
   241
				stackTop[-8] = regSet->iDs;
sl@0
   242
sl@0
   243
			if (aAvailMask & 1<<10)
sl@0
   244
				stackTop[-9] = regSet->iEs;
sl@0
   245
sl@0
   246
			if (aAvailMask & 1<<11)
sl@0
   247
				stackTop[-10] = regSet->iFs;
sl@0
   248
sl@0
   249
			if (aAvailMask & 1<<12)
sl@0
   250
				stackTop[-11] = regSet->iGs;
sl@0
   251
sl@0
   252
			if (aAvailMask & 1<<5)
sl@0
   253
				stackTop[-12] = regSet->iEbp;
sl@0
   254
sl@0
   255
			if (aAvailMask & 1<<7)
sl@0
   256
				stackTop[-13] = regSet->iEdi;
sl@0
   257
sl@0
   258
			if (aAvailMask & 1<<6)
sl@0
   259
				stackTop[-14] = regSet->iEsi;
sl@0
   260
sl@0
   261
			if (aAvailMask & 1<<1)
sl@0
   262
				stackTop[-15] = regSet->iEbx;
sl@0
   263
sl@0
   264
			if (aAvailMask & 1<<2)
sl@0
   265
				stackTop[-16] = regSet->iEcx;
sl@0
   266
sl@0
   267
			if (aAvailMask & 1<<3)
sl@0
   268
				stackTop[-17] = regSet->iEdx;
sl@0
   269
sl@0
   270
			if (aAvailMask & 1<<0)
sl@0
   271
				stackTop[-18] = regSet->iEax;
sl@0
   272
			}
sl@0
   273
sl@0
   274
		DEBUGPRINT("stack from stack top, after changes " );
sl@0
   275
		if (delta < 128)
sl@0
   276
			{
sl@0
   277
			delta = -delta;
sl@0
   278
			}
sl@0
   279
		else
sl@0
   280
			{
sl@0
   281
			delta = -128;
sl@0
   282
			}
sl@0
   283
sl@0
   284
		for ( ; delta < 0; delta++)
sl@0
   285
			{
sl@0
   286
			DEBUGPRINT("stackTop[%d]=%x", delta, stackTop[delta]);
sl@0
   287
			}
sl@0
   288
		}
sl@0
   289
	else
sl@0
   290
		{
sl@0
   291
 		memclr(aContext, sizeof(TX86RegSet));
sl@0
   292
sl@0
   293
		if (isCurrentThread)
sl@0
   294
			{
sl@0
   295
			// Not yet supported
sl@0
   296
			DEBUGPRINT(" NThread::GetContext() : Don't know how to obtain context for current thread\n Use TSS?");
sl@0
   297
			}
sl@0
   298
		else
sl@0
   299
			{
sl@0
   300
			DEBUGPRINT("stack from stack top " );
sl@0
   301
sl@0
   302
			if (delta < 128)
sl@0
   303
				{
sl@0
   304
				delta = -delta;
sl@0
   305
				}
sl@0
   306
			else
sl@0
   307
				{
sl@0
   308
				delta = -128;
sl@0
   309
				}
sl@0
   310
sl@0
   311
			for( ; delta < 0; delta++)
sl@0
   312
				{
sl@0
   313
				DEBUGPRINT("stackTop[%d]=%x", delta, stackTop[delta]);
sl@0
   314
				}
sl@0
   315
sl@0
   316
			if (0 == aThread->iSpare3)
sl@0
   317
				{
sl@0
   318
				// Context when interrupted by user
sl@0
   319
				regSet->iSs		= stackTop[-1];
sl@0
   320
				aAvailMask |= 1<<13;
sl@0
   321
sl@0
   322
				regSet->iEsp	= stackTop[-2];
sl@0
   323
				aAvailMask |= 1<<4;
sl@0
   324
sl@0
   325
				regSet->iEflags = stackTop[-3];
sl@0
   326
				aAvailMask |= 1<<14;
sl@0
   327
sl@0
   328
				regSet->iCs		= stackTop[-4];
sl@0
   329
				aAvailMask |= 1<<8;
sl@0
   330
sl@0
   331
				regSet->iEip	= stackTop[-5];
sl@0
   332
				aAvailMask |= 1<<15;
sl@0
   333
sl@0
   334
				regSet->iDs		= stackTop[-8];
sl@0
   335
				aAvailMask |= 1<<9;
sl@0
   336
sl@0
   337
				regSet->iEax	= stackTop[-9];
sl@0
   338
				aAvailMask |= 1<<0;
sl@0
   339
sl@0
   340
				regSet->iEcx	= stackTop[-10];
sl@0
   341
				aAvailMask |= 1<<2;
sl@0
   342
sl@0
   343
				regSet->iEbp	= stackTop[-16];
sl@0
   344
				aAvailMask |= 1<<5;
sl@0
   345
sl@0
   346
				regSet->iEdi	= stackTop[-17];
sl@0
   347
				aAvailMask |= 1<<7;
sl@0
   348
sl@0
   349
				regSet->iEsi	= stackTop[-18];
sl@0
   350
				aAvailMask |= 1<<6;
sl@0
   351
				}
sl@0
   352
			else
sl@0
   353
				{
sl@0
   354
				// Now populate the TX86RegSet with the contents of the stack
sl@0
   355
sl@0
   356
				/*
sl@0
   357
				 * The first 5 are from the comments at the start of __X86VectorExc :
sl@0
   358
				 * [ESP+0] = vector number
sl@0
   359
				 * [ESP+4] = error code (filled with 0 for exceptions without error codes)
sl@0
   360
				 * [ESP+8] = return EIP
sl@0
   361
				 * [ESP+12] = return CS
sl@0
   362
				 * [ESP+16] = return EFLAGS
sl@0
   363
				 * [ESP+20] = return ESP if privilege change occurred
sl@0
   364
				 * [ESP+24] = return SS if privilege change occurred
sl@0
   365
				 */
sl@0
   366
				regSet->iSs		= stackTop[-1];
sl@0
   367
				aAvailMask |= 1<<13;
sl@0
   368
sl@0
   369
				regSet->iEsp	= stackTop[-2];
sl@0
   370
				aAvailMask |= 1<<4;
sl@0
   371
sl@0
   372
				regSet->iEflags = stackTop[-3];
sl@0
   373
				aAvailMask |= 1<<14;
sl@0
   374
sl@0
   375
				regSet->iCs		= stackTop[-4];
sl@0
   376
				aAvailMask |= 1<<8;
sl@0
   377
sl@0
   378
				regSet->iEip	= stackTop[-5];
sl@0
   379
				aAvailMask |= 1<<15;
sl@0
   380
sl@0
   381
				/* -6 and -7 are not used since they are the vector number and the error code,
sl@0
   382
				 * which for a breakpoint are 3 and 0 resp.
sl@0
   383
				 */
sl@0
   384
sl@0
   385
				/* The following are from the push instructions in __X86VectorExc */
sl@0
   386
				regSet->iDs		= stackTop[-8];
sl@0
   387
				aAvailMask |= 1<<9;
sl@0
   388
sl@0
   389
				regSet->iEs		= stackTop[-9];
sl@0
   390
				aAvailMask |= 1<<10;
sl@0
   391
sl@0
   392
				regSet->iFs		= stackTop[-10];
sl@0
   393
				aAvailMask |= 1<<11;
sl@0
   394
sl@0
   395
				regSet->iGs		= stackTop[-11];
sl@0
   396
				aAvailMask |= 1<<12;
sl@0
   397
sl@0
   398
				regSet->iEbp	= stackTop[-12];
sl@0
   399
				aAvailMask |= 1<<5;
sl@0
   400
sl@0
   401
				regSet->iEdi	= stackTop[-13];
sl@0
   402
				aAvailMask |= 1<<7;
sl@0
   403
sl@0
   404
				regSet->iEsi	= stackTop[-14];
sl@0
   405
				aAvailMask |= 1<<6;
sl@0
   406
sl@0
   407
				regSet->iEbx	= stackTop[-15];
sl@0
   408
				aAvailMask |= 1<<1;
sl@0
   409
sl@0
   410
				regSet->iEcx	= stackTop[-16];
sl@0
   411
				aAvailMask |= 1<<2;
sl@0
   412
sl@0
   413
				regSet->iEdx	= stackTop[-17];
sl@0
   414
				aAvailMask |= 1<<3;
sl@0
   415
sl@0
   416
				regSet->iEax = stackTop[-18];
sl@0
   417
				aAvailMask |= 1<<0;
sl@0
   418
				} // else if (0 == aThread->iSpare3)
sl@0
   419
sl@0
   420
			} // else if (isCurrentThread)
sl@0
   421
sl@0
   422
		} // else if (aAvailMask)
sl@0
   423
sl@0
   424
	NKern::Unlock();
sl@0
   425
	}
sl@0
   426
sl@0
   427
sl@0
   428
void NKern::ThreadModifyUsp(NThread* aThread, TLinAddr aUsp)
sl@0
   429
	{
sl@0
   430
	}