kernel/eka/nkernsmp/nkerns.cpp
changeset 90 947f0dc9f7a8
parent 0 a41df078684a
child 109 b3a1d9898418
child 177 a232af6b0b1f
equal deleted inserted replaced
52:2d65c2f76d7b 90:947f0dc9f7a8
    45 	{
    45 	{
    46 	iPriority = 0;
    46 	iPriority = 0;
    47 	iReady = 0;
    47 	iReady = 0;
    48 	iCurrent = 0;
    48 	iCurrent = 0;
    49 	iLastCpu = 0;
    49 	iLastCpu = 0;
    50 	iNSchedulableSpare1 = 0;
       
    51 	iPauseCount = 0;
    50 	iPauseCount = 0;
    52 	iSuspended = 0;
    51 	iSuspended = 0;
    53 	iNSchedulableSpare2 = 0;
    52 	iACount = 0;
       
    53 	iPreferredCpu = 0;
       
    54 	iActiveState = 0;
       
    55 	i_NSchedulable_Spare2 = 0;
       
    56 	iTransientCpu = 0;
       
    57 	iForcedCpu = 0;
       
    58 	iLbState = ELbState_Inactive;
    54 	iCpuChange = 0;
    59 	iCpuChange = 0;
    55 	iStopping = 0;
    60 	iStopping = 0;
    56 	iFreezeCpu = 0;
    61 	iFreezeCpu = 0;
    57 	iParent = (NSchedulable*)0xdeadbeef;
    62 	iParent = (NSchedulable*)0xdeadbeef;
    58 	iCpuAffinity = 0;
    63 	iCpuAffinity = 0;
    59 	new (i_IDfcMem) TDfc(&DeferredReadyIDfcFn, this);
    64 	new (i_IDfcMem) TDfc(&DeferredReadyIDfcFn, this);
    60 	iEventState = 0;
    65 	iEventState = 0;
    61 	iTotalCpuTime64 = 0;
    66 	iRunCount.i64 = 0;
    62 	}
    67 	iLastRunTime.i64 = 0;
       
    68 	iTotalCpuTime.i64 = 0;
       
    69 	iLastActivationTime.i64 = 0;
       
    70 	iTotalActiveTime.i64 = 0;
       
    71 	iSavedCpuTime.i64 = 0;
       
    72 	iSavedActiveTime.i64 = 0;
       
    73 	iLbLink.iNext = 0;
       
    74 	memclr(&iLbInfo, EMaxLbInfoSize);
       
    75 	}
       
    76 
       
    77 void NSchedulable::AddToEnumerateList()
       
    78 	{
       
    79 	TScheduler& s = TheScheduler;
       
    80 	SIterDQ& dq = iParent ? s.iAllThreads : s.iAllGroups;
       
    81 	NKern::Lock();
       
    82 	s.iEnumerateLock.LockOnly();
       
    83 	dq.Add(&iEnumerateLink);
       
    84 	TUint32 active = s.iThreadAcceptCpus;
       
    85 	TUint32 cpus = active & iCpuAffinity;
       
    86 	if (!cpus)
       
    87 		cpus = active;	// can't run on any currently active CPU, just pick an active one until it becomes ready
       
    88 	TInt ecpu = __e32_find_ls1_32(cpus);
       
    89 	iEventState = (ecpu<<EEventCpuShift) | (ecpu<<EThreadCpuShift);
       
    90 	s.iEnumerateLock.UnlockOnly();
       
    91 	NKern::Unlock();
       
    92 	}
       
    93 
    63 
    94 
    64 /******************************************************************************
    95 /******************************************************************************
    65  * NThreadGroup
    96  * NThreadGroup
    66  ******************************************************************************/
    97  ******************************************************************************/
    67 NThreadGroup::NThreadGroup()
    98 NThreadGroup::NThreadGroup()
    68 	{
    99 	{
       
   100 	iACount = 1;
    69 	iParent = 0;
   101 	iParent = 0;
    70 	iThreadCount = 0;
   102 	iThreadCount = 0;
    71 	new (&iSSpinLock) TSpinLock(TSpinLock::EOrderThreadGroup);
   103 	new (&iSSpinLock) TSpinLock(TSpinLock::EOrderThreadGroup);
    72 	}
   104 	}
    73 
   105 
    77 	@prototype
   109 	@prototype
    78 */
   110 */
    79 EXPORT_C TInt NKern::GroupCreate(NThreadGroup* aGroup, SNThreadGroupCreateInfo& aInfo)
   111 EXPORT_C TInt NKern::GroupCreate(NThreadGroup* aGroup, SNThreadGroupCreateInfo& aInfo)
    80 	{
   112 	{
    81 	new (aGroup) NThreadGroup();
   113 	new (aGroup) NThreadGroup();
    82 	aGroup->iCpuAffinity = aInfo.iCpuAffinity;
   114 	aGroup->iDestructionDfc = aInfo.iDestructionDfc;
       
   115 	aGroup->iCpuAffinity = NSchedulable::PreprocessCpuAffinity(aInfo.iCpuAffinity);
       
   116 	aGroup->AddToEnumerateList();
       
   117 	aGroup->InitLbInfo();
    83 	return KErrNone;
   118 	return KErrNone;
    84 	}
   119 	}
    85 
   120 
    86 
   121 
    87 /** Destroy a thread group
   122 /** Destroy a thread group
    96 */
   131 */
    97 EXPORT_C void NKern::GroupDestroy(NThreadGroup* aGroup)
   132 EXPORT_C void NKern::GroupDestroy(NThreadGroup* aGroup)
    98 	{
   133 	{
    99 	NKern::ThreadEnterCS();
   134 	NKern::ThreadEnterCS();
   100 	aGroup->DetachTiedEvents();
   135 	aGroup->DetachTiedEvents();
       
   136 	NKern::Lock();
       
   137 	aGroup->AcqSLock();
       
   138 	if (aGroup->iLbLink.iNext)
       
   139 		aGroup->LbUnlink();
       
   140 	aGroup->RelSLock();
       
   141 	aGroup->DropRef();
       
   142 	NKern::Unlock();
   101 	NKern::ThreadLeaveCS();
   143 	NKern::ThreadLeaveCS();
   102 	}
   144 	}
   103 
   145 
   104 
   146 
   105 /******************************************************************************
   147 /******************************************************************************
   134 	{
   176 	{
   135 	iParent = this;
   177 	iParent = this;
   136 	iWaitLink.iPriority = 0;
   178 	iWaitLink.iPriority = 0;
   137 	iBasePri = 0;
   179 	iBasePri = 0;
   138 	iMutexPri = 0;
   180 	iMutexPri = 0;
   139 	i_NThread_Initial = 0;
   181 	iNominalPri = 0;
   140 	iLinkedObjType = EWaitNone;
   182 	iLinkedObjType = EWaitNone;
   141 	i_ThrdAttr = 0;
   183 	i_ThrdAttr = 0;
   142 	iNThreadBaseSpare10 = 0;
   184 	i_NThread_Initial = 0;
   143 	iFastMutexDefer = 0;
   185 	iFastMutexDefer = 0;
   144 	iRequestSemaphore.iOwningThread = (NThreadBase*)this;
   186 	iRequestSemaphore.iOwningThread = (NThreadBase*)this;
   145 	iTime = 0;
   187 	iTime = 0;
   146 	iTimeslice = 0;
   188 	iTimeslice = 0;
   147 	iSavedSP = 0;
   189 	iSavedSP = 0;
   158 	iSuspendCount = 0;
   200 	iSuspendCount = 0;
   159 	iStackBase = 0;
   201 	iStackBase = 0;
   160 	iStackSize = 0;
   202 	iStackSize = 0;
   161 	iExtraContext = 0;
   203 	iExtraContext = 0;
   162 	iExtraContextSize = 0;
   204 	iExtraContextSize = 0;
       
   205 	iCoreCycling = 0;
       
   206 	iRebalanceAttr = 0;
       
   207 	iNThreadBaseSpare4c = 0;
       
   208 	iNThreadBaseSpare4d = 0;
       
   209 	iNThreadBaseSpare5 = 0;
   163 	iNThreadBaseSpare6 = 0;
   210 	iNThreadBaseSpare6 = 0;
   164 	iNThreadBaseSpare7 = 0;
   211 	iNThreadBaseSpare7 = 0;
   165 	iNThreadBaseSpare8 = 0;
   212 	iNThreadBaseSpare8 = 0;
   166 	iNThreadBaseSpare9 = 0;
   213 	iNThreadBaseSpare9 = 0;
   167 
       
   168 	// KILL
       
   169 	iTag = 0;
       
   170 	iVemsData = 0;
       
   171 	}
   214 	}
   172 
   215 
   173 TInt NThreadBase::Create(SNThreadCreateInfo& aInfo, TBool aInitial)
   216 TInt NThreadBase::Create(SNThreadCreateInfo& aInfo, TBool aInitial)
   174 	{
   217 	{
   175 	__KTRACE_OPT(KNKERN,DEBUGPRINT(">NThreadBase::Create %08x(%08x,%d)", this, &aInfo, aInitial));
   218 	__KTRACE_OPT(KNKERN,DEBUGPRINT(">NThreadBase::Create %08x(%08x,%d)", this, &aInfo, aInitial));
   183 	iStackSize=aInfo.iStackSize;
   226 	iStackSize=aInfo.iStackSize;
   184 	iTimeslice=(aInfo.iTimeslice>0)?aInfo.iTimeslice:-1;
   227 	iTimeslice=(aInfo.iTimeslice>0)?aInfo.iTimeslice:-1;
   185 	iTime=iTimeslice;
   228 	iTime=iTimeslice;
   186 	iPriority=TUint8(aInfo.iPriority);
   229 	iPriority=TUint8(aInfo.iPriority);
   187 	iBasePri=TUint8(aInfo.iPriority);
   230 	iBasePri=TUint8(aInfo.iPriority);
   188 	iCpuAffinity = aInfo.iCpuAffinity;
   231 	iNominalPri=TUint8(aInfo.iPriority);
       
   232 	iCpuAffinity = NSchedulable::PreprocessCpuAffinity(aInfo.iCpuAffinity);
   189 	iHandlers = aInfo.iHandlers ? aInfo.iHandlers : &NThread_Default_Handlers;
   233 	iHandlers = aInfo.iHandlers ? aInfo.iHandlers : &NThread_Default_Handlers;
   190 	iFastExecTable=aInfo.iFastExecTable?aInfo.iFastExecTable:&DefaultFastExecTable;
   234 	iFastExecTable=aInfo.iFastExecTable?aInfo.iFastExecTable:&DefaultFastExecTable;
   191 	iSlowExecTable=(aInfo.iSlowExecTable?aInfo.iSlowExecTable:&DefaultSlowExecTable)->iEntries;
   235 	iSlowExecTable=(aInfo.iSlowExecTable?aInfo.iSlowExecTable:&DefaultSlowExecTable)->iEntries;
   192 	i_ThrdAttr=(TUint8)aInfo.iAttributes;
   236 	i_ThrdAttr=(TUint8)aInfo.iAttributes;
   193 	if (aInitial)
   237 	if (aInitial)
   196 		iLastCpu = (TUint8)ss.iCpuNum;
   240 		iLastCpu = (TUint8)ss.iCpuNum;
   197 		iReady = (TUint8)(iLastCpu | EReadyOffset);
   241 		iReady = (TUint8)(iLastCpu | EReadyOffset);
   198 		iCurrent = iReady;
   242 		iCurrent = iReady;
   199 		iCpuAffinity = iLastCpu;
   243 		iCpuAffinity = iLastCpu;
   200 		iEventState = (iLastCpu<<EEventCpuShift) | (iLastCpu<<EThreadCpuShift);
   244 		iEventState = (iLastCpu<<EEventCpuShift) | (iLastCpu<<EThreadCpuShift);
   201 		ss.Add(this);
   245 		ss.SSAddEntry(this);
   202 		i_NThread_Initial = TRUE;
   246 		i_NThread_Initial = TRUE;
       
   247 		iACount = 1;
   203 		ss.iInitialThread = (NThread*)this;
   248 		ss.iInitialThread = (NThread*)this;
   204 		NKern::Unlock();		// now that current thread is defined
   249 		NKern::Unlock();		// now that current thread is defined
   205 		}
   250 		}
   206 	else
   251 	else
   207 		{
   252 		{
   208 		iSuspendCount = 1;
   253 		iSuspendCount = 1;
   209 		iSuspended = 1;
   254 		iSuspended = 1;
   210 		TInt ecpu;
   255 		iEventState = 0;
   211 		if (iCpuAffinity & NTHREADBASE_CPU_AFFINITY_MASK)
       
   212 			{
       
   213 			ecpu = __e32_find_ls1_32(iCpuAffinity);
       
   214 			if (ecpu >= TheScheduler.iNumCpus)
       
   215 				ecpu = 0;	// FIXME: Inactive CPU?
       
   216 			}
       
   217 		else
       
   218 			ecpu = iCpuAffinity;
       
   219 		iEventState = (ecpu<<EEventCpuShift) | (ecpu<<EThreadCpuShift);
       
   220 		if (aInfo.iGroup)
   256 		if (aInfo.iGroup)
   221 			{
   257 			{
   222 			NKern::Lock();
   258 			NKern::Lock();
   223 			AcqSLock();
   259 			AcqSLock();
   224 			aInfo.iGroup->AcqSLock();
   260 			aInfo.iGroup->AcqSLock();
   245 void NThread_Default_Exception_Handler(TAny* aContext, NThread*)
   281 void NThread_Default_Exception_Handler(TAny* aContext, NThread*)
   246 	{
   282 	{
   247 	ExcFault(aContext);
   283 	ExcFault(aContext);
   248 	}
   284 	}
   249 
   285 
       
   286 //
       
   287 // Destroy a thread before it has ever run
       
   288 // Must be called before first resumption of thread
       
   289 //
       
   290 void NThread::Stillborn()
       
   291 	{
       
   292 	__NK_ASSERT_ALWAYS(iACount==0);	// ensure thread has never been resumed
       
   293 	NKern::Lock();
       
   294 	RemoveFromEnumerateList();
       
   295 	NKern::Unlock();
       
   296 	}
       
   297 
       
   298 
   250 
   299 
   251 /** Create a nanothread.
   300 /** Create a nanothread.
   252 
   301 
   253 	This function is intended to be used by the EPOC kernel and by personality
   302 	This function is intended to be used by the EPOC kernel and by personality
   254 	layers. A nanothread may not use most of the functions available to normal
   303 	layers. A nanothread may not use most of the functions available to normal
   268 	{
   317 	{
   269 	CHECK_PRECONDITIONS(MASK_KERNEL_UNLOCKED|MASK_INTERRUPTS_ENABLED|MASK_NOT_ISR|MASK_NOT_IDFC,"NKern::ThreadCreate");
   318 	CHECK_PRECONDITIONS(MASK_KERNEL_UNLOCKED|MASK_INTERRUPTS_ENABLED|MASK_NOT_ISR|MASK_NOT_IDFC,"NKern::ThreadCreate");
   270 	return aThread->Create(aInfo,FALSE);
   319 	return aThread->Create(aInfo,FALSE);
   271 	}
   320 	}
   272 
   321 
   273 // User-mode callbacks
   322 
   274 
   323 /******************************************************************************
       
   324  * User-mode callbacks
       
   325  ******************************************************************************/
   275 TUserModeCallback::TUserModeCallback(TUserModeCallbackFunc aFunc)
   326 TUserModeCallback::TUserModeCallback(TUserModeCallbackFunc aFunc)
   276 	:	iNext(KUserModeCallbackUnqueued),
   327 	:	iNext(KUserModeCallbackUnqueued),
   277 		iFunc(aFunc)
   328 		iFunc(aFunc)
   278 	{
   329 	{
   279 	}
   330 	}
   326 		__NK_ASSERT_DEBUG(((TUint)destListStart & 3) == 0);  // dest thread must not die
   377 		__NK_ASSERT_DEBUG(((TUint)destListStart & 3) == 0);  // dest thread must not die
   327 		sourceListEnd->iNext = destListStart;
   378 		sourceListEnd->iNext = destListStart;
   328 		} while (!__e32_atomic_cas_ord_ptr(&aDestThread->iUserModeCallbacks, &destListStart, sourceListStart));
   379 		} while (!__e32_atomic_cas_ord_ptr(&aDestThread->iUserModeCallbacks, &destListStart, sourceListStart));
   329 	NKern::Unlock();
   380 	NKern::Unlock();
   330 	}
   381 	}
       
   382 
   331 
   383 
   332 /** Initialise the null thread
   384 /** Initialise the null thread
   333 	@internalComponent
   385 	@internalComponent
   334 */
   386 */
   335 void NKern::Init(NThread* aThread, SNThreadCreateInfo& aInfo)
   387 void NKern::Init(NThread* aThread, SNThreadCreateInfo& aInfo)
   476 	return &BTraceLock;
   528 	return &BTraceLock;
   477 #else
   529 #else
   478 	return 0;
   530 	return 0;
   479 #endif
   531 #endif
   480 	}
   532 	}
       
   533 
       
   534 TDfcQue* TScheduler::RebalanceDfcQ()
       
   535 	{
       
   536 	return TheScheduler.iRebalanceDfcQ;
       
   537 	}
       
   538 
       
   539 NThread* TScheduler::LBThread()
       
   540 	{
       
   541 	return (NThread*)(TheScheduler.iRebalanceDfcQ->iThread);
       
   542 	}
       
   543