1 /* ------------------------------------------------------------------ 2 * Copyright (C) 1998-2009 PacketVideo 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 13 * express or implied. 14 * See the License for the specific language governing permissions 15 * and limitations under the License. 16 * ------------------------------------------------------------------- 17 */ 18 /*! \addtogroup osclproc OSCL Proc 19 * 20 * @{ 21 */ 22 23 24 25 /** \file pvscheduler.h 26 \brief Main include file for Oscl Scheduler 27 */ 28 29 30 #ifndef OSCL_SCHEDULER_H_INCLUDED 31 #define OSCL_SCHEDULER_H_INCLUDED 32 33 #ifndef OSCL_SCHEDULER_TYPES_H_INCLUDED 34 #include "oscl_scheduler_types.h" 35 #endif 36 37 #ifndef OSCL_SCHEDULER_AO_H_INCLUDED 38 #include "oscl_scheduler_ao.h" 39 #endif 40 41 #ifndef OSCL_SCHEDULER_THREADCONTEXT_H_INCLUDED 42 #include "oscl_scheduler_threadcontext.h" 43 #endif 44 45 #ifndef OSCL_MUTEX_H_INCLUDED 46 #include "oscl_mutex.h" 47 #endif 48 49 #ifndef OSCL_SEMAPHORE_H_INCLUDED 50 #include "oscl_semaphore.h" 51 #endif 52 53 #ifndef OSCL_SCHEDULER_READYQ_H_INCLUDED 54 #include "oscl_scheduler_readyq.h" 55 #endif 56 57 #ifndef OSCL_DEFALLOC_H_INCLUDED 58 #include "oscl_defalloc.h" 59 #endif 60 61 #ifndef OSCL_MEM_H_INCLUDED 62 #include "oscl_mem.h" 63 #endif 64 65 class Oscl_DefAlloc; 66 class OsclCoeActiveScheduler; 67 68 69 /** 70 * Per-thread scheduler initialization and cleanup. 71 */ 72 class OsclScheduler 73 { 74 public: 75 /** 76 * This routine creates and installs a scheduler in 77 * the calling thread. 78 * @param name: (input param) scheduler name. 79 * @param alloc: (input param) optional allocator to use for 80 * the internal implementation. 81 * @param nreserve: (input param) optional value for ready queue 82 * reserve size. 83 */ 84 OSCL_IMPORT_REF static void Init(const char *name, Oscl_DefAlloc *alloc = NULL, int nreserve = 20); 85 86 87 /** 88 * This routine uninstalls and destroys Oscl scheduler 89 * for the calling thread. 90 */ 91 OSCL_IMPORT_REF static void Cleanup(); 92 }; 93 94 95 /** 96 * PV Scheduler class 97 */ 98 99 #define PVSCHEDNAMELEN 30 100 101 class PVSchedulerStopper; 102 class PVJump; 103 class PVLogger; 104 105 /** 106 * OsclSchedulerObserver is an observer class for use when running scheduler 107 * in non-blocking mode. 108 * The scheduler observer can register for callbacks so it 109 * will be notified when it is necessary to run scheduler again. 110 * Note: non-blocking mode and scheduler callbacks are not supported on Symbian. 111 */ 112 class OsclSchedulerObserver 113 { 114 public: 115 /** 116 * OsclSchedulerTimerCallback is called when the front of the timer queue 117 * is updated. This means the minimum delay has changed and scheduler needs 118 * to be run again after aDelayMsec. Calling context is in-thread. 119 * 120 * The current observer is cleared before making the callback, so the 121 * observer must call RegisterForCallback again if it wants further 122 * notifications. 123 */ 124 virtual void OsclSchedulerTimerCallback(OsclAny* aContext, uint32 aDelayMsec) = 0; 125 126 /** 127 * OsclSchedulerReadyCallback is called when the ready queue is updated, meaning 128 * an AO is ready to run. Scheduler needs to be run ASAP. 129 * Calling context may be any thread, so be careful! 130 * 131 * The current observer is cleared before making the callback, so the 132 * observer must call RegisterForCallback again if it wants further 133 * notifications. 134 */ 135 virtual void OsclSchedulerReadyCallback(OsclAny* aContext) = 0; 136 ~OsclSchedulerObserver()137 virtual ~OsclSchedulerObserver() {} 138 }; 139 140 141 /* 142 ** A common base class for variations of OsclExecScheduler 143 **/ 144 145 class OsclExecSchedulerCommonBase 146 { 147 public: 148 /** 149 * Start scheduling. This call blocks until scheduler 150 * is stopped or an error occurs. 151 * @param sem: optional startup semaphore. If provied, 152 * the scheduler will signal this semaphore when 153 * the startup has progressed to the point that it's 154 * safe to call StopScheduler or SuspendScheduler 155 * from another thread. 156 */ 157 OSCL_IMPORT_REF void StartScheduler(OsclSemaphore *sem = NULL); 158 159 /** 160 * Stop scheduling. This API may be called from the 161 * scheduling thread or some other thread. 162 */ 163 OSCL_IMPORT_REF void StopScheduler(); 164 165 /** 166 * Suspend scheduling when the current Run is complete. 167 * This API only applies to a blocking loop scheduler. 168 */ 169 OSCL_IMPORT_REF void SuspendScheduler(); 170 171 /** 172 * Resume scheduling immediately. 173 * This API only applies to a blocking loop scheduler. 174 */ 175 OSCL_IMPORT_REF void ResumeScheduler(); 176 177 /** 178 * Start the OS native scheduling loop. This is an alternative 179 * to the PV scheduling loop. 180 * To stop the native scheduler, use the StopScheduler API. 181 */ 182 OSCL_IMPORT_REF void StartNativeScheduler(); 183 184 /** 185 * Get name of scheduler for current thread. 186 */ 187 OSCL_IMPORT_REF static OsclNameString<PVSCHEDNAMELEN> *GetName(); 188 189 /** 190 * Get numeric ID of current thread. 191 */ 192 OSCL_IMPORT_REF static uint32 GetId(); 193 194 195 protected: 196 /* 197 static OsclExecScheduler *NewL(const char *name,Oscl_DefAlloc *a,int nreserve); 198 */ 199 virtual ~OsclExecSchedulerCommonBase(); 200 void InstallScheduler(); 201 void UninstallScheduler(); 202 friend class OsclScheduler; 203 204 protected: 205 void Error(int32 anError) const; 206 207 protected: 208 static OsclExecSchedulerCommonBase* GetScheduler(); 209 static OsclExecSchedulerCommonBase* SetScheduler(OsclExecSchedulerCommonBase*); 210 friend class PVThreadContext; 211 friend class OsclCoeActiveScheduler; 212 213 protected: 214 OsclExecSchedulerCommonBase(Oscl_DefAlloc*); 215 virtual void ConstructL(const char *name, int); 216 217 void BeginScheduling(bool blocking, bool native); 218 void EndScheduling(); 219 220 void BlockingLoopL(); 221 222 bool iBlockingMode;//current blocking mode setting. 223 bool iNativeMode;//current native mode setting. 224 225 bool IsStarted(); 226 inline bool IsInstalled(); 227 228 //Stopper AO is a special PV AO used to implement 229 //the StopScheduler and SuspendScheduler functions. 230 PVSchedulerStopper *iStopper; 231 OsclNoYieldMutex iStopperCrit; 232 233 //Scheduler thread context 234 PVThreadContext iThreadContext; 235 236 //Scheduler name 237 OsclNameString<PVSCHEDNAMELEN> iName; 238 239 //For stop, suspend, and resume commands. 240 bool iDoStop; 241 bool iDoSuspend; 242 bool iSuspended; 243 OsclSemaphore iResumeSem; 244 245 OsclErrorTrapImp* iErrorTrapImp; 246 247 //Ready AO queue. The AOs in this queue are ready to run. 248 OsclReadyQ iReadyQ; 249 250 //Pending Timer AO queue. The AOs in this queue are OsclTimerObjects 251 //and have a timeout pending. 252 OsclTimerQ iExecTimerQ; 253 void AddToExecTimerQ(PVActiveBase *active, uint32); 254 255 void PendComplete(PVActiveBase *, int32 aReason, TPVThreadContext aContext); 256 void RequestCanceled(PVActiveBase*); 257 258 //Scheduling loop implementation. 259 PVActiveBase* UpdateTimers(uint32 &aDelay); 260 PVActiveBase* UpdateTimersMsec(uint32 &aDelay); 261 PVActiveBase* WaitForReadyAO(); 262 void CallRunExec(PVActiveBase*); 263 264 static const uint32 iTimeCompareThreshold; 265 friend class OsclTimerCompare; 266 friend class OsclReadyQ; 267 268 friend class OsclError; 269 270 271 272 uint32 iNumAOAdded;//for non-fair-scheduling sorts. 273 274 //For statistics 275 #if (PV_SCHED_ENABLE_AO_STATS) 276 OsclDoubleList<PVActiveStats> iPVStatQ;//queue of all PV ExecObjs. 277 enum TOtherExecStats 278 { 279 EOtherExecStats_WaitTime //scheduler wait time 280 , EOtherExecStats_QueueTime //scheduler queue operation time 281 , EOtherExecStats_NativeOS //time in symbian native ExecObjs, not added by PV code (symbian only) 282 , EOtherExecStats_ReleaseTime //thread release time (Brew only) 283 , EOtherExecStats_Last 284 }; 285 PVActiveStats* iOtherExecStats[EOtherExecStats_Last];//placeholder for stats of all ExecObjs. 286 void ConstructStatQ(); 287 void BeginStats(); 288 void EndStats(); 289 static void ShowStats(PVActiveStats *active); 290 static void ShowSummaryStats(PVActiveStats *active, PVLogger*, int64, int64&, float&); 291 void CleanupStatQ(); 292 uint8* iTotalTicksTemp; 293 int64 iGrandTotalTicks; 294 float iTotalPercent; 295 friend class PVActiveStats; 296 uint32 iTime; 297 int32 iDelta; 298 PVActiveStats* iPVStats; 299 #endif //PV_SCHED_ENABLE_AO_STATS 300 301 //Queue utils. 302 PVActiveBase *FindPVBase(PVActiveBase *active, OsclDoubleList<PVActiveBase> &); 303 void CleanupExecQ(); 304 void InitExecQ(int); 305 306 PVLogger *iLogger; 307 PVLogger* iDebugLogger; 308 309 #if(PV_SCHED_ENABLE_PERF_LOGGING) 310 //for perf logging 311 char* iLogPerfIndentStr; 312 int32 iLogPerfIndentStrLen; 313 uint32 iLogPerfTotal; 314 void ResetLogPerf(); 315 void IncLogPerf(uint32); 316 #endif 317 318 Oscl_DefAlloc *iAlloc;//allocator for scheduler. 319 // iDefAlloc is static because we need it to still be valid after ~OsclExecSchedulerCommonBase is called */ 320 static OsclMemAllocator iDefAlloc;//default allocator 321 322 friend class OsclActiveObject; 323 friend class OsclTimerObject; 324 friend class PVActiveBase; 325 friend class PVSchedulerStopper; 326 327 328 friend class OsclExecScheduler; 329 }; 330 331 class OsclErrorTrapImp; 332 333 class OsclExecScheduler: public OsclExecSchedulerCommonBase 334 , public OsclExecSchedulerBase 335 { 336 public: 337 /** 338 * Get currently installed scheduler for calling thread, 339 * or NULL if no scheduler is installed. 340 */ 341 OSCL_IMPORT_REF static OsclExecScheduler* Current(); 342 343 /** 344 * Non-Blocking scheduler APIs. 345 */ 346 347 /** 348 * Run PV scheduler in non-blocking mode. This call returns 349 * when the desired number of Run calls have been made, 350 * or when there are no more active objects that are ready 351 * to run. 352 * 353 * @param aTargetCount: (input param) the maximum number of Run calls to make. 354 * @param aReady: (output param) tells the number of active objects that 355 * are currently ready to run. 356 * @param aDelayMsec: (output param) If no active objects are ready to 357 * run, but one or more active objects are waiting on timers, this 358 * parameter will tell the time interval from the current time until the 359 * first of the pending timer objects will be ready to run, in milliseconds. 360 * 361 * Note: On Symbian, non-blocking mode is not supported and this call will 362 * leave. 363 * 364 */ 365 OSCL_IMPORT_REF void RunSchedulerNonBlocking(int32 aTargetCount, int32 &aReady, uint32 &aDelayMsec); 366 367 /** 368 * Register for a notification when non-blocking scheduler needs to run 369 * again. 370 * 371 * Note: On Symbian, non-blocking mode is not supported and this call will 372 * leave. 373 */ 374 OSCL_IMPORT_REF void RegisterForCallback(OsclSchedulerObserver* aCallback, OsclAny* aCallbackContext); 375 376 377 private: 378 static OsclExecScheduler *NewL(const char *name, Oscl_DefAlloc *a, int nreserve); 379 ~OsclExecScheduler(); 380 friend class OsclScheduler; 381 382 383 OsclExecScheduler(Oscl_DefAlloc*); 384 void ConstructL(const char *name, int); 385 386 }; 387 388 389 /** 390 * Scheduler stopper AO class, for internal use 391 * by scheduler. 392 */ 393 class PVSchedulerStopper: public OsclActiveObject 394 { 395 public: 396 PVSchedulerStopper(); 397 ~PVSchedulerStopper(); 398 private: 399 void Run(); 400 }; 401 402 403 #endif 404 405 406 /*! @} */ 407