kernel/eka/nkernsmp/arm/ncthrd.cpp
branchRCL_3
changeset 256 c1f20ce4abcf
parent 0 a41df078684a
child 257 3e88ff8f41d5
equal deleted inserted replaced
249:a179b74831c9 256:c1f20ce4abcf
    34 extern void initialiseState(TInt aCpu, TSubScheduler* aSS);
    34 extern void initialiseState(TInt aCpu, TSubScheduler* aSS);
    35 
    35 
    36 extern "C" void ExcFault(TAny*);
    36 extern "C" void ExcFault(TAny*);
    37 
    37 
    38 extern TUint32 __mpid();
    38 extern TUint32 __mpid();
    39 extern void InitAPTimestamp(SNThreadCreateInfo& aInfo);
    39 extern void InitTimestamp(TSubScheduler* aSS, SNThreadCreateInfo& aInfo);
    40 
    40 
    41 TInt NThread::Create(SNThreadCreateInfo& aInfo, TBool aInitial)
    41 TInt NThread::Create(SNThreadCreateInfo& aInfo, TBool aInitial)
    42 	{
    42 	{
    43 	// Assert ParameterBlockSize is not negative and is a multiple of 8 bytes
    43 	// Assert ParameterBlockSize is not negative and is a multiple of 8 bytes
    44 	__NK_ASSERT_ALWAYS((aInfo.iParameterBlockSize&0x80000007)==0);
    44 	__NK_ASSERT_ALWAYS((aInfo.iParameterBlockSize&0x80000007)==0);
    45 	__NK_ASSERT_ALWAYS(aInfo.iStackBase && aInfo.iStackSize>=aInfo.iParameterBlockSize+KNThreadMinStackSize);
    45 	__NK_ASSERT_ALWAYS(aInfo.iStackBase && aInfo.iStackSize>=aInfo.iParameterBlockSize+KNThreadMinStackSize);
    46 	TInt cpu = -1;
    46 	TInt cpu = -1;
       
    47 	TSubScheduler* ss = 0;
    47 	new (this) NThread;
    48 	new (this) NThread;
    48 	if (aInitial)
    49 	if (aInitial)
    49 		{
    50 		{
    50 		cpu = __e32_atomic_add_ord32(&TheScheduler.iNumCpus, 1);
    51 		cpu = __e32_atomic_add_ord32(&TheScheduler.iNumCpus, 1);
    51 		aInfo.iCpuAffinity = cpu;
    52 		aInfo.iCpuAffinity = cpu;
    52 		// OK since we can't migrate yet
    53 		// OK since we can't migrate yet
    53 		TSubScheduler& ss = TheSubSchedulers[cpu];
    54 		ss = &TheSubSchedulers[cpu];
    54 		ss.iCurrentThread = this;
    55 		ss->iCurrentThread = this;
    55 		iRunCount64 = UI64LIT(1);
    56 		ss->iDeferShutdown = 0;
    56 		__KTRACE_OPT(KBOOT,DEBUGPRINT("Init: cpu=%d ss=%08x", cpu, &ss));
    57 		iRunCount.i64 = UI64LIT(1);
       
    58 		iActiveState = 1;
       
    59 		__KTRACE_OPT(KBOOT,DEBUGPRINT("Init: cpu=%d ss=%08x", cpu, ss));
    57 		if (cpu)
    60 		if (cpu)
    58 			{
    61 			{
    59 			initialiseState(cpu,&ss);
    62 			initialiseState(cpu,ss);
    60 
    63 
    61 			ArmLocalTimer& T = LOCAL_TIMER;
    64 			ArmLocalTimer& T = LOCAL_TIMER;
    62 			T.iWatchdogDisable = E_ArmTmrWDD_1;
    65 			T.iWatchdogDisable = E_ArmTmrWDD_1;
    63 			T.iWatchdogDisable = E_ArmTmrWDD_2;
    66 			T.iWatchdogDisable = E_ArmTmrWDD_2;
    64 			T.iTimerCtrl = 0;
    67 			T.iTimerCtrl = 0;
    67 			T.iWatchdogIntStatus = E_ArmTmrIntStatus_Event;
    70 			T.iWatchdogIntStatus = E_ArmTmrIntStatus_Event;
    68 
    71 
    69 			NIrq::HwInit2AP();
    72 			NIrq::HwInit2AP();
    70 			T.iTimerCtrl = E_ArmTmrCtrl_IntEn | E_ArmTmrCtrl_Reload | E_ArmTmrCtrl_Enable;
    73 			T.iTimerCtrl = E_ArmTmrCtrl_IntEn | E_ArmTmrCtrl_Reload | E_ArmTmrCtrl_Enable;
    71 
    74 
    72 			__e32_atomic_ior_ord32(&TheScheduler.iActiveCpus1, 1<<cpu);
    75 			__e32_atomic_ior_ord32(&TheScheduler.iThreadAcceptCpus, 1<<cpu);
    73 			__e32_atomic_ior_ord32(&TheScheduler.iActiveCpus2, 1<<cpu);
    76 			__e32_atomic_ior_ord32(&TheScheduler.iIpiAcceptCpus, 1<<cpu);
    74 			__e32_atomic_ior_ord32(&TheScheduler.iCpusNotIdle, 1<<cpu);
    77 			__e32_atomic_ior_ord32(&TheScheduler.iCpusNotIdle, 1<<cpu);
       
    78 			__e32_atomic_add_ord32(&TheScheduler.iCCRequestLevel, 1);
    75 			__KTRACE_OPT(KBOOT,DEBUGPRINT("AP MPID=%08x",__mpid()));
    79 			__KTRACE_OPT(KBOOT,DEBUGPRINT("AP MPID=%08x",__mpid()));
    76 			}
    80 			}
    77 		else
    81 		else
    78 			{
    82 			{
    79 			Arm::DefaultDomainAccess = Arm::Dacr();
    83 			Arm::DefaultDomainAccess = Arm::Dacr();
   126 		}
   130 		}
   127 	else
   131 	else
   128 		{
   132 		{
   129 		NKern::EnableAllInterrupts();
   133 		NKern::EnableAllInterrupts();
   130 
   134 
       
   135 #if defined(__CPU_ARM_HAS_GLOBAL_TIMER_BLOCK) && defined(__NKERN_TIMESTAMP_USE_SCU_GLOBAL_TIMER__)
       
   136 
       
   137 		if (cpu == 0) 
       
   138 			{
       
   139 			// start global timer if necessary
       
   140 			ArmGlobalTimer& GT = GLOBAL_TIMER;
       
   141 			if (!(GT.iTimerCtrl & E_ArmGTmrCtrl_TmrEnb))
       
   142 				{
       
   143 				// timer not currently enabled
       
   144 				GT.iTimerCtrl = 0;
       
   145 				__e32_io_completion_barrier();
       
   146 				GT.iTimerStatus = E_ArmGTmrStatus_Event;
       
   147 				__e32_io_completion_barrier();
       
   148 				GT.iTimerCountLow = 0;
       
   149 				GT.iTimerCountHigh = 0;
       
   150 				__e32_io_completion_barrier();
       
   151 				GT.iTimerCtrl = E_ArmGTmrCtrl_TmrEnb;	// enable timer with prescale factor of 1
       
   152 				__e32_io_completion_barrier();
       
   153 				}
       
   154 			}
       
   155 		
       
   156 #endif
       
   157 
   131 		// start local timer
   158 		// start local timer
   132 		ArmLocalTimer& T = LOCAL_TIMER;
   159 		ArmLocalTimer& T = LOCAL_TIMER;
   133 		T.iTimerCtrl = E_ArmTmrCtrl_IntEn | E_ArmTmrCtrl_Reload | E_ArmTmrCtrl_Enable;
   160 		T.iTimerCtrl = E_ArmTmrCtrl_IntEn | E_ArmTmrCtrl_Reload | E_ArmTmrCtrl_Enable;
   134 
   161 		// Initialise timestamp
   135 		// synchronize AP's timestamp with BP's
   162 		InitTimestamp(ss, aInfo);
   136 		if (cpu>0)
   163 		}
   137 			InitAPTimestamp(aInfo);
   164 	AddToEnumerateList();
   138 		}
   165 	InitLbInfo();
   139 #ifdef BTRACE_THREAD_IDENTIFICATION
   166 #ifdef BTRACE_THREAD_IDENTIFICATION
   140 	BTrace4(BTrace::EThreadIdentification,BTrace::ENanoThreadCreate,this);
   167 	BTrace4(BTrace::EThreadIdentification,BTrace::ENanoThreadCreate,this);
   141 #endif
   168 #endif
   142 	return KErrNone;
   169 	return KErrNone;
   143 	}
   170 	}
   182 	DEBUGPRINT("R13Svc=%08x R14Svc=%08x SpsrSvc=%08x",a.iR13Svc,a.iR14Svc,a.iSpsrSvc);
   209 	DEBUGPRINT("R13Svc=%08x R14Svc=%08x SpsrSvc=%08x",a.iR13Svc,a.iR14Svc,a.iSpsrSvc);
   183 
   210 
   184 	TInt irq = NKern::DisableAllInterrupts();
   211 	TInt irq = NKern::DisableAllInterrupts();
   185 	TSubScheduler& ss = SubScheduler();
   212 	TSubScheduler& ss = SubScheduler();
   186 	NThreadBase* ct = ss.iCurrentThread;
   213 	NThreadBase* ct = ss.iCurrentThread;
   187 	TInt inc = TInt(ss.i_IrqNestCount);
   214 	TInt inc = TInt(ss.iSSX.iIrqNestCount);
   188 	TInt cpu = ss.iCpuNum;
   215 	TInt cpu = ss.iCpuNum;
   189 	TInt klc = ss.iKernLockCount;
   216 	TInt klc = ss.iKernLockCount;
   190 	NKern::RestoreInterrupts(irq);
   217 	NKern::RestoreInterrupts(irq);
   191 	DEBUGPRINT("Thread %T, CPU %d, KLCount=%d, IrqNest=%d", ct, cpu, klc, inc);
   218 	DEBUGPRINT("Thread %T, CPU %d, KLCount=%d, IrqNest=%d", ct, cpu, klc, inc);
   192 	}
   219 	}
   650 	NThread* pC = NCurrentThreadL();
   677 	NThread* pC = NCurrentThreadL();
   651 	TSubScheduler* ss = 0;
   678 	TSubScheduler* ss = 0;
   652 	if (pC != this)
   679 	if (pC != this)
   653 		{
   680 		{
   654 		AcqSLock();
   681 		AcqSLock();
   655 		if (iWaitState.ThreadIsDead())
   682 		if (iWaitState.ThreadIsDead() || i_NThread_Initial)
   656 			{
   683 			{
   657 			RelSLock();
   684 			RelSLock();
   658 			aAvailRegistersMask = 0;
   685 			aAvailRegistersMask = 0;
   659 			return;
   686 			return;
   660 			}
   687 			}
   838 	NThread* pC = NCurrentThreadL();
   865 	NThread* pC = NCurrentThreadL();
   839 	TSubScheduler* ss = 0;
   866 	TSubScheduler* ss = 0;
   840 	if (pC != this)
   867 	if (pC != this)
   841 		{
   868 		{
   842 		AcqSLock();
   869 		AcqSLock();
   843 		if (iWaitState.ThreadIsDead())
   870 		if (iWaitState.ThreadIsDead() || i_NThread_Initial)
   844 			{
   871 			{
   845 			RelSLock();
   872 			RelSLock();
   846 			aRegMask = 0;
   873 			aRegMask = 0;
   847 			return;
   874 			return;
   848 			}
   875 			}
  1055 		return 1;
  1082 		return 1;
  1056 		}
  1083 		}
  1057 	return 0;
  1084 	return 0;
  1058 	}
  1085 	}
  1059 
  1086 
  1060 /** Return the total CPU time so far used by the specified thread.
       
  1061 
       
  1062 	@return The total CPU time in units of 1/NKern::CpuTimeMeasFreq().
       
  1063 */
       
  1064 EXPORT_C TUint64 NKern::ThreadCpuTime(NThread* aThread)
       
  1065 	{
       
  1066 	TSubScheduler* ss = 0;
       
  1067 	NKern::Lock();
       
  1068 	aThread->AcqSLock();
       
  1069 	if (aThread->i_NThread_Initial)
       
  1070 		ss = &TheSubSchedulers[aThread->iLastCpu];
       
  1071 	else if (aThread->iReady && aThread->iParent->iReady)
       
  1072 		ss = &TheSubSchedulers[aThread->iParent->iReady & NSchedulable::EReadyCpuMask];
       
  1073 	if (ss)
       
  1074 		ss->iReadyListLock.LockOnly();
       
  1075 	TUint64 t = aThread->iTotalCpuTime64;
       
  1076 	if (aThread->iCurrent || (aThread->i_NThread_Initial && !ss->iCurrentThread))
       
  1077 		t += (NKern::Timestamp() - ss->iLastTimestamp64);
       
  1078 	if (ss)
       
  1079 		ss->iReadyListLock.UnlockOnly();
       
  1080 	aThread->RelSLock();
       
  1081 	NKern::Unlock();
       
  1082 	return t;
       
  1083 	}
       
  1084 
  1087 
  1085 TInt NKern::QueueUserModeCallback(NThreadBase* aThread, TUserModeCallback* aCallback)
  1088 TInt NKern::QueueUserModeCallback(NThreadBase* aThread, TUserModeCallback* aCallback)
  1086 	{
  1089 	{
  1087 	__e32_memory_barrier();
  1090 	__e32_memory_barrier();
  1088 	if (aCallback->iNext != KUserModeCallbackUnqueued)
  1091 	if (aCallback->iNext != KUserModeCallbackUnqueued)
  1089 		return KErrInUse;
  1092 		return KErrInUse;
       
  1093 	if (aThread->i_NThread_Initial)
       
  1094 		return KErrArgument;
  1090 	TInt result = KErrDied;
  1095 	TInt result = KErrDied;
  1091 	NKern::Lock();
  1096 	NKern::Lock();
  1092 	TUserModeCallback* listHead = aThread->iUserModeCallbacks;
  1097 	TUserModeCallback* listHead = aThread->iUserModeCallbacks;
  1093 	do	{
  1098 	do	{
  1094 		if (TLinAddr(listHead) & 3)
  1099 		if (TLinAddr(listHead) & 3)