kernel/eka/nkernsmp/x86/ncthrd.cpp
branchRCL_3
changeset 44 3e88ff8f41d5
parent 43 c1f20ce4abcf
equal deleted inserted replaced
43:c1f20ce4abcf 44:3e88ff8f41d5
    34 	}
    34 	}
    35 
    35 
    36 extern void __ltr(TInt /*aSelector*/);
    36 extern void __ltr(TInt /*aSelector*/);
    37 
    37 
    38 extern "C" TUint __tr();
    38 extern "C" TUint __tr();
    39 extern void InitTimestamp(TSubScheduler* aSS, SNThreadCreateInfo& aInfo);
    39 extern void InitAPTimestamp(SNThreadCreateInfo& aInfo);
    40 
    40 
    41 TInt NThread::Create(SNThreadCreateInfo& aInfo, TBool aInitial)
    41 TInt NThread::Create(SNThreadCreateInfo& aInfo, TBool aInitial)
    42 	{
    42 	{
    43 	if (!aInfo.iStackBase || aInfo.iStackSize<0x100)
    43 	if (!aInfo.iStackBase || aInfo.iStackSize<0x100)
    44 		return KErrArgument;
    44 		return KErrArgument;
    45 	new (this) NThread;
    45 	new (this) NThread;
    46 	TInt cpu = -1;
    46 	TInt cpu = -1;
    47 	TSubScheduler* ss = 0;
       
    48 	if (aInitial)
    47 	if (aInitial)
    49 		{
    48 		{
    50 		cpu = __e32_atomic_add_ord32(&TheScheduler.iNumCpus, 1);
    49 		cpu = __e32_atomic_add_ord32(&TheScheduler.iNumCpus, 1);
    51 		if (cpu==0)
    50 		if (cpu==0)
    52 			memset(SubSchedulerLookupTable, 0x9a, sizeof(SubSchedulerLookupTable));
    51 			memset(SubSchedulerLookupTable, 0x9a, sizeof(SubSchedulerLookupTable));
    53 		aInfo.iCpuAffinity = cpu;
    52 		aInfo.iCpuAffinity = cpu;
    54 		// OK since we can't migrate yet
    53 		// OK since we can't migrate yet
    55 		TUint32 apicid = *(volatile TUint32*)(X86_LOCAL_APIC_BASE + X86_LOCAL_APIC_OFFSET_ID) >> 24;
    54 		TUint32 apicid = *(volatile TUint32*)(X86_LOCAL_APIC_BASE + X86_LOCAL_APIC_OFFSET_ID) >> 24;
    56 		ss = &TheSubSchedulers[cpu];
    55 		TSubScheduler& ss = TheSubSchedulers[cpu];
    57 		ss->iSSX.iAPICID = apicid << 24;
    56 		ss.i_APICID = (TAny*)(apicid<<24);
    58 		ss->iCurrentThread = this;
    57 		ss.iCurrentThread = this;
    59 		ss->iDeferShutdown = 0;
    58 		SubSchedulerLookupTable[apicid] = &ss;
    60 		SubSchedulerLookupTable[apicid] = ss;
    59 		ss.iLastTimestamp64 = NKern::Timestamp();
    61 		iRunCount.i64 = UI64LIT(1);
    60 		iRunCount64 = UI64LIT(1);
    62 		iActiveState = 1;
    61 		__KTRACE_OPT(KBOOT,DEBUGPRINT("Init: cpu=%d APICID=%08x ss=%08x", cpu, apicid, &ss));
    63 		__KTRACE_OPT(KBOOT,DEBUGPRINT("Init: cpu=%d APICID=%08x ss=%08x", cpu, apicid, ss));
       
    64 		if (cpu)
    62 		if (cpu)
    65 			{
    63 			{
    66 			__ltr(TSS_SELECTOR(cpu));
    64 			__ltr(TSS_SELECTOR(cpu));
    67 			NIrq::HwInit2AP();
    65 			NIrq::HwInit2AP();
    68 			__e32_atomic_ior_ord32(&TheScheduler.iThreadAcceptCpus, 1<<cpu);
    66 			__e32_atomic_ior_ord32(&TheScheduler.iActiveCpus1, 1<<cpu);
    69 			__e32_atomic_ior_ord32(&TheScheduler.iIpiAcceptCpus, 1<<cpu);
    67 			__e32_atomic_ior_ord32(&TheScheduler.iActiveCpus2, 1<<cpu);
    70 			__e32_atomic_ior_ord32(&TheScheduler.iCpusNotIdle, 1<<cpu);
    68 			__e32_atomic_ior_ord32(&TheScheduler.iCpusNotIdle, 1<<cpu);
    71 			__e32_atomic_add_ord32(&TheScheduler.iCCRequestLevel, 1);
       
    72 			__KTRACE_OPT(KBOOT,DEBUGPRINT("AP TR=%x",__tr()));
    69 			__KTRACE_OPT(KBOOT,DEBUGPRINT("AP TR=%x",__tr()));
    73 			}
    70 			}
    74 		}
    71 		}
    75 	TInt r=NThreadBase::Create(aInfo,aInitial);
    72 	TInt r=NThreadBase::Create(aInfo,aInitial);
    76 	if (r!=KErrNone)
    73 	if (r!=KErrNone)
   125 		}
   122 		}
   126 	else
   123 	else
   127 		{
   124 		{
   128 		NKern::EnableAllInterrupts();
   125 		NKern::EnableAllInterrupts();
   129 
   126 
   130 		// Initialise timestamp
   127 		// synchronize AP's timestamp with BP's
   131 		InitTimestamp(ss, aInfo);
   128 		if (cpu>0)
   132 		}
   129 			InitAPTimestamp(aInfo);
   133 	AddToEnumerateList();
   130 		}
   134 	InitLbInfo();
       
   135 #ifdef BTRACE_THREAD_IDENTIFICATION
   131 #ifdef BTRACE_THREAD_IDENTIFICATION
   136 	BTrace4(BTrace::EThreadIdentification,BTrace::ENanoThreadCreate,this);
   132 	BTrace4(BTrace::EThreadIdentification,BTrace::ENanoThreadCreate,this);
   137 #endif
   133 #endif
   138 	return KErrNone;
   134 	return KErrNone;
   139 	}
   135 	}
   151 		}
   147 		}
   152 	TScheduler& s = TheScheduler;
   148 	TScheduler& s = TheScheduler;
   153 	TInt irq = NKern::DisableAllInterrupts();
   149 	TInt irq = NKern::DisableAllInterrupts();
   154 	TSubScheduler& ss = SubScheduler();
   150 	TSubScheduler& ss = SubScheduler();
   155 	NThreadBase* ct = ss.iCurrentThread;
   151 	NThreadBase* ct = ss.iCurrentThread;
   156 	TInt inc = TInt(ss.iSSX.iIrqNestCount);
   152 	TInt inc = TInt(ss.i_IrqNestCount);
   157 	TInt cpu = ss.iCpuNum;
   153 	TInt cpu = ss.iCpuNum;
   158 	NKern::RestoreInterrupts(irq);
   154 	NKern::RestoreInterrupts(irq);
   159 	DEBUGPRINT("Thread %T, CPU %d, KLCount=%08x, IrqNest=%d",ct,cpu,ss.iKernLockCount,inc);
   155 	DEBUGPRINT("Thread %T, CPU %d, KLCount=%08x, IrqNest=%d",ct,cpu,ss.iKernLockCount,inc);
   160 	}
   156 	}
   161 
   157 
   230 	NThread* pC = NCurrentThreadL();
   226 	NThread* pC = NCurrentThreadL();
   231 	TSubScheduler* ss = 0;
   227 	TSubScheduler* ss = 0;
   232 	if (pC != this)
   228 	if (pC != this)
   233 		{
   229 		{
   234 		AcqSLock();
   230 		AcqSLock();
   235 		if (iWaitState.ThreadIsDead() || i_NThread_Initial)
   231 		if (iWaitState.ThreadIsDead())
   236 			{
   232 			{
   237 			RelSLock();
   233 			RelSLock();
   238 			aAvailRegistersMask = 0;
   234 			aAvailRegistersMask = 0;
   239 			return;
   235 			return;
   240 			}
   236 			}
   281 void TGetContextIPI::Isr(TGenericIPI* aPtr)
   277 void TGetContextIPI::Isr(TGenericIPI* aPtr)
   282 	{
   278 	{
   283 	TGetContextIPI& ipi = *(TGetContextIPI*)aPtr;
   279 	TGetContextIPI& ipi = *(TGetContextIPI*)aPtr;
   284 	TX86RegSet& a = *ipi.iContext;
   280 	TX86RegSet& a = *ipi.iContext;
   285 	TSubScheduler& ss = SubScheduler();
   281 	TSubScheduler& ss = SubScheduler();
   286 	TUint32* irqstack = (TUint32*)ss.iSSX.iIrqStackTop;
   282 	TUint32* irqstack = (TUint32*)ss.i_IrqStackTop;
   287 	SThreadExcStack* txs = (SThreadExcStack*)irqstack[-1];	// first word pushed on IRQ stack points to thread supervisor stack
   283 	SThreadExcStack* txs = (SThreadExcStack*)irqstack[-1];	// first word pushed on IRQ stack points to thread supervisor stack
   288 	GetContextAfterExc(a, txs, *ipi.iAvailRegsMask, TRUE);
   284 	GetContextAfterExc(a, txs, *ipi.iAvailRegsMask, TRUE);
   289 	}
   285 	}
   290 
   286 
   291 void TGetContextIPI::Get(TInt aCpu, TX86RegSet& aContext, TUint32& aAvailRegsMask)
   287 void TGetContextIPI::Get(TInt aCpu, TX86RegSet& aContext, TUint32& aAvailRegsMask)
   392 	NThread* pC = NCurrentThreadL();
   388 	NThread* pC = NCurrentThreadL();
   393 	TSubScheduler* ss = 0;
   389 	TSubScheduler* ss = 0;
   394 	if (pC != this)
   390 	if (pC != this)
   395 		{
   391 		{
   396 		AcqSLock();
   392 		AcqSLock();
   397 		if (iWaitState.ThreadIsDead() || i_NThread_Initial)
   393 		if (iWaitState.ThreadIsDead())
   398 			{
   394 			{
   399 			RelSLock();
   395 			RelSLock();
   400 			aRegMask = 0;
   396 			aRegMask = 0;
   401 			return;
   397 			return;
   402 			}
   398 			}
   569 	aThread->SetUserContext(a, mask);
   565 	aThread->SetUserContext(a, mask);
   570 	NKern::Unlock();
   566 	NKern::Unlock();
   571 	}
   567 	}
   572 
   568 
   573 
   569 
       
   570 /** Return the total CPU time so far used by the specified thread.
       
   571 
       
   572 	@return The total CPU time in units of 1/NKern::CpuTimeMeasFreq().
       
   573 */
       
   574 EXPORT_C TUint64 NKern::ThreadCpuTime(NThread* aThread)
       
   575 	{
       
   576 	TSubScheduler* ss = 0;
       
   577 	NKern::Lock();
       
   578 	aThread->AcqSLock();
       
   579 	if (aThread->i_NThread_Initial)
       
   580 		ss = &TheSubSchedulers[aThread->iLastCpu];
       
   581 	else if (aThread->iReady && aThread->iParent->iReady)
       
   582 		ss = &TheSubSchedulers[aThread->iParent->iReady & NSchedulable::EReadyCpuMask];
       
   583 	if (ss)
       
   584 		ss->iReadyListLock.LockOnly();
       
   585 	TUint64 t = aThread->iTotalCpuTime64;
       
   586 	if (aThread->iCurrent || (aThread->i_NThread_Initial && !ss->iCurrentThread))
       
   587 		t += (NKern::Timestamp() - ss->iLastTimestamp64);
       
   588 	if (ss)
       
   589 		ss->iReadyListLock.UnlockOnly();
       
   590 	aThread->RelSLock();
       
   591 	NKern::Unlock();
       
   592 	return t;
       
   593 	}
       
   594 
   574 extern "C" void __fastcall add_dfc(TDfc* aDfc)
   595 extern "C" void __fastcall add_dfc(TDfc* aDfc)
   575 	{
   596 	{
   576 	aDfc->Add();
   597 	aDfc->Add();
   577 	}
   598 	}
   578 
   599 
   580 TInt NKern::QueueUserModeCallback(NThreadBase* aThread, TUserModeCallback* aCallback)
   601 TInt NKern::QueueUserModeCallback(NThreadBase* aThread, TUserModeCallback* aCallback)
   581 	{
   602 	{
   582 	__e32_memory_barrier();
   603 	__e32_memory_barrier();
   583 	if (aCallback->iNext != KUserModeCallbackUnqueued)
   604 	if (aCallback->iNext != KUserModeCallbackUnqueued)
   584 		return KErrInUse;
   605 		return KErrInUse;
   585 	if (aThread->i_NThread_Initial)
       
   586 		return KErrArgument;
       
   587 	TInt result = KErrDied;
   606 	TInt result = KErrDied;
   588 	NKern::Lock();
   607 	NKern::Lock();
   589 	TUserModeCallback* listHead = aThread->iUserModeCallbacks;
   608 	TUserModeCallback* listHead = aThread->iUserModeCallbacks;
   590 	do	{
   609 	do	{
   591 		if (TLinAddr(listHead) & 3)
   610 		if (TLinAddr(listHead) & 3)