sl@0: // Copyright (c) 1998-2009 Nokia Corporation and/or its subsidiary(-ies). sl@0: // All rights reserved. sl@0: // This component and the accompanying materials are made available sl@0: // under the terms of the License "Eclipse Public License v1.0" sl@0: // which accompanies this distribution, and is available sl@0: // at the URL "http://www.eclipse.org/legal/epl-v10.html". sl@0: // sl@0: // Initial Contributors: sl@0: // Nokia Corporation - initial contribution. sl@0: // sl@0: // Contributors: sl@0: // sl@0: // Description: sl@0: // e32\nkern\sched.cpp sl@0: // sl@0: // sl@0: sl@0: // TDfc member data sl@0: #define __INCLUDE_TDFC_DEFINES__ sl@0: #define __INCLUDE_NTHREADBASE_DEFINES__ sl@0: sl@0: #include "nk_priv.h" sl@0: sl@0: void ResumeDelayedThreads(TAny*) sl@0: { sl@0: TScheduler& s=TheScheduler; sl@0: while (!s.iDelayedQ.IsEmpty()) sl@0: { sl@0: NThreadBase& t = *(NThreadBase*)s.iDelayedQ.First()->Deque(); sl@0: t.i_ThrdAttr &= ~KThreadAttDelayed; sl@0: if (t.iSuspendCount==0) sl@0: t.DoReady(); sl@0: else sl@0: t.iNState=NThreadBase::ESuspended; sl@0: } sl@0: } sl@0: sl@0: // Don't need to zero initialise anything here since sl@0: // TheScheduler resides in .bss sl@0: TScheduler::TScheduler() sl@0: : TPriListBase(KNumPriorities), iKernCSLocked(1), iDelayDfc(ResumeDelayedThreads, NULL) sl@0: { sl@0: } sl@0: sl@0: sl@0: /** Return a pointer to the scheduler sl@0: Intended for use by the crash debugger, not for general device driver use. sl@0: sl@0: @return Pointer to the scheduler object sl@0: @internalTechnology sl@0: */ sl@0: EXPORT_C TScheduler* TScheduler::Ptr() sl@0: { sl@0: return &TheScheduler; sl@0: } sl@0: sl@0: sl@0: #ifndef __MSTIM_MACHINE_CODED__ sl@0: // Enter and leave with interrupts off sl@0: void TScheduler::TimesliceTick() sl@0: { sl@0: NThreadBase* pC=iCurrentThread; sl@0: if (pC->iTime>0 && --pC->iTime==0) sl@0: RescheduleNeeded(); sl@0: } sl@0: #endif sl@0: sl@0: #ifndef __SCHEDULER_MACHINE_CODED__ sl@0: void TScheduler::Remove(NThreadBase* aThread) sl@0: { sl@0: __NK_ASSERT_DEBUG(!aThread->iHeldFastMutex); // can't block while holding fast mutex sl@0: aThread->iTime=aThread->iTimeslice; // thread has blocked so it gets a fresh timeslice for next time sl@0: TPriListBase::Remove(aThread); sl@0: } sl@0: #endif sl@0: sl@0: void TScheduler::RotateReadyList(TInt p) sl@0: // sl@0: // rotate the ready list for priority p sl@0: // sl@0: { sl@0: __NK_ASSERT_DEBUG(p>=0 && piNext; sl@0: if (pN!=pQ) sl@0: { sl@0: NThread* pT=(NThread*)pQ; sl@0: pT->iTime=pT->iTimeslice; sl@0: iQueue[p]=pN; sl@0: if (pQ==iCurrentThread) sl@0: RescheduleNeeded(); sl@0: } sl@0: } sl@0: } sl@0: sl@0: /** Converts a time interval in microseconds to thread timeslice ticks sl@0: sl@0: @param aMicroseconds time interval in microseconds. sl@0: @return Number of thread timeslice ticks. Non-integral results are rounded up. sl@0: sl@0: @pre aMicroseconds should be nonnegative sl@0: @pre any context sl@0: */ sl@0: EXPORT_C TInt NKern::TimesliceTicks(TUint32 aMicroseconds) sl@0: { sl@0: TUint32 msp = TheTimerQ.iTickPeriod; sl@0: TUint32 ticks = (TUint32(aMicroseconds) + msp - 1) / msp; sl@0: return ticks; sl@0: } sl@0: sl@0: sl@0: /** Return the total CPU time so far used by the specified thread. sl@0: sl@0: @return The total CPU time in units of 1/NKern::CpuTimeMeasFreq(). sl@0: */ sl@0: EXPORT_C TUint64 NKern::ThreadCpuTime(NThread* aThread) sl@0: { sl@0: #ifdef MONITOR_THREAD_CPU_TIME sl@0: NKern::Lock(); sl@0: TUint64 t = aThread->iTotalCpuTime; sl@0: if (aThread == TheScheduler.iCurrentThread) sl@0: t += TUint64(NKern::FastCounter() - aThread->iLastStartTime); sl@0: NKern::Unlock(); sl@0: return t; sl@0: #else sl@0: return 0; sl@0: #endif sl@0: }