blob: 8f1bdda0227de17cfb25c068dc687f2dfc58159f [file] [log] [blame]
/* ------------------------------------------------------------------
* Copyright (C) 1998-2009 PacketVideo
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
* express or implied.
* See the License for the specific language governing permissions
* and limitations under the License.
* -------------------------------------------------------------------
*/
/*! \addtogroup osclproc OSCL Proc
*
* @{
*/
/** \file pvscheduler.h
\brief Main include file for Oscl Scheduler
*/
#ifndef OSCL_SCHEDULER_H_INCLUDED
#define OSCL_SCHEDULER_H_INCLUDED
#ifndef OSCL_SCHEDULER_TYPES_H_INCLUDED
#include "oscl_scheduler_types.h"
#endif
#ifndef OSCL_SCHEDULER_AO_H_INCLUDED
#include "oscl_scheduler_ao.h"
#endif
#ifndef OSCL_SCHEDULER_THREADCONTEXT_H_INCLUDED
#include "oscl_scheduler_threadcontext.h"
#endif
#ifndef OSCL_MUTEX_H_INCLUDED
#include "oscl_mutex.h"
#endif
#ifndef OSCL_SEMAPHORE_H_INCLUDED
#include "oscl_semaphore.h"
#endif
#ifndef OSCL_SCHEDULER_READYQ_H_INCLUDED
#include "oscl_scheduler_readyq.h"
#endif
#ifndef OSCL_DEFALLOC_H_INCLUDED
#include "oscl_defalloc.h"
#endif
#ifndef OSCL_MEM_H_INCLUDED
#include "oscl_mem.h"
#endif
class Oscl_DefAlloc;
class OsclCoeActiveScheduler;
/**
* Per-thread scheduler initialization and cleanup.
*/
class OsclScheduler
{
public:
/**
* This routine creates and installs a scheduler in
* the calling thread.
* @param name: (input param) scheduler name.
* @param alloc: (input param) optional allocator to use for
* the internal implementation.
* @param nreserve: (input param) optional value for ready queue
* reserve size.
*/
OSCL_IMPORT_REF static void Init(const char *name, Oscl_DefAlloc *alloc = NULL, int nreserve = 20);
/**
* This routine uninstalls and destroys Oscl scheduler
* for the calling thread.
*/
OSCL_IMPORT_REF static void Cleanup();
};
/**
* PV Scheduler class
*/
#define PVSCHEDNAMELEN 30
class PVSchedulerStopper;
class PVJump;
class PVLogger;
/**
* OsclSchedulerObserver is an observer class for use when running scheduler
* in non-blocking mode.
* The scheduler observer can register for callbacks so it
* will be notified when it is necessary to run scheduler again.
* Note: non-blocking mode and scheduler callbacks are not supported on Symbian.
*/
class OsclSchedulerObserver
{
public:
/**
* OsclSchedulerTimerCallback is called when the front of the timer queue
* is updated. This means the minimum delay has changed and scheduler needs
* to be run again after aDelayMsec. Calling context is in-thread.
*
* The current observer is cleared before making the callback, so the
* observer must call RegisterForCallback again if it wants further
* notifications.
*/
virtual void OsclSchedulerTimerCallback(OsclAny* aContext, uint32 aDelayMsec) = 0;
/**
* OsclSchedulerReadyCallback is called when the ready queue is updated, meaning
* an AO is ready to run. Scheduler needs to be run ASAP.
* Calling context may be any thread, so be careful!
*
* The current observer is cleared before making the callback, so the
* observer must call RegisterForCallback again if it wants further
* notifications.
*/
virtual void OsclSchedulerReadyCallback(OsclAny* aContext) = 0;
virtual ~OsclSchedulerObserver() {}
};
/*
** A common base class for variations of OsclExecScheduler
**/
class OsclExecSchedulerCommonBase
{
public:
/**
* Start scheduling. This call blocks until scheduler
* is stopped or an error occurs.
* @param sem: optional startup semaphore. If provied,
* the scheduler will signal this semaphore when
* the startup has progressed to the point that it's
* safe to call StopScheduler or SuspendScheduler
* from another thread.
*/
OSCL_IMPORT_REF void StartScheduler(OsclSemaphore *sem = NULL);
/**
* Stop scheduling. This API may be called from the
* scheduling thread or some other thread.
*/
OSCL_IMPORT_REF void StopScheduler();
/**
* Suspend scheduling when the current Run is complete.
* This API only applies to a blocking loop scheduler.
*/
OSCL_IMPORT_REF void SuspendScheduler();
/**
* Resume scheduling immediately.
* This API only applies to a blocking loop scheduler.
*/
OSCL_IMPORT_REF void ResumeScheduler();
/**
* Start the OS native scheduling loop. This is an alternative
* to the PV scheduling loop.
* To stop the native scheduler, use the StopScheduler API.
*/
OSCL_IMPORT_REF void StartNativeScheduler();
/**
* Get name of scheduler for current thread.
*/
OSCL_IMPORT_REF static OsclNameString<PVSCHEDNAMELEN> *GetName();
/**
* Get numeric ID of current thread.
*/
OSCL_IMPORT_REF static uint32 GetId();
protected:
/*
static OsclExecScheduler *NewL(const char *name,Oscl_DefAlloc *a,int nreserve);
*/
virtual ~OsclExecSchedulerCommonBase();
void InstallScheduler();
void UninstallScheduler();
friend class OsclScheduler;
protected:
void Error(int32 anError) const;
protected:
static OsclExecSchedulerCommonBase* GetScheduler();
static OsclExecSchedulerCommonBase* SetScheduler(OsclExecSchedulerCommonBase*);
friend class PVThreadContext;
friend class OsclCoeActiveScheduler;
protected:
OsclExecSchedulerCommonBase(Oscl_DefAlloc*);
virtual void ConstructL(const char *name, int);
void BeginScheduling(bool blocking, bool native);
void EndScheduling();
void BlockingLoopL();
bool iBlockingMode;//current blocking mode setting.
bool iNativeMode;//current native mode setting.
bool IsStarted();
inline bool IsInstalled();
//Stopper AO is a special PV AO used to implement
//the StopScheduler and SuspendScheduler functions.
PVSchedulerStopper *iStopper;
OsclNoYieldMutex iStopperCrit;
//Scheduler thread context
PVThreadContext iThreadContext;
//Scheduler name
OsclNameString<PVSCHEDNAMELEN> iName;
//For stop, suspend, and resume commands.
bool iDoStop;
bool iDoSuspend;
bool iSuspended;
OsclSemaphore iResumeSem;
OsclErrorTrapImp* iErrorTrapImp;
//Ready AO queue. The AOs in this queue are ready to run.
OsclReadyQ iReadyQ;
//Pending Timer AO queue. The AOs in this queue are OsclTimerObjects
//and have a timeout pending.
OsclTimerQ iExecTimerQ;
void AddToExecTimerQ(PVActiveBase *active, uint32);
void PendComplete(PVActiveBase *, int32 aReason, TPVThreadContext aContext);
void RequestCanceled(PVActiveBase*);
//Scheduling loop implementation.
PVActiveBase* UpdateTimers(uint32 &aDelay);
PVActiveBase* UpdateTimersMsec(uint32 &aDelay);
PVActiveBase* WaitForReadyAO();
void CallRunExec(PVActiveBase*);
static const uint32 iTimeCompareThreshold;
friend class OsclTimerCompare;
friend class OsclReadyQ;
friend class OsclError;
uint32 iNumAOAdded;//for non-fair-scheduling sorts.
//For statistics
#if (PV_SCHED_ENABLE_AO_STATS)
OsclDoubleList<PVActiveStats> iPVStatQ;//queue of all PV ExecObjs.
enum TOtherExecStats
{
EOtherExecStats_WaitTime //scheduler wait time
, EOtherExecStats_QueueTime //scheduler queue operation time
, EOtherExecStats_NativeOS //time in symbian native ExecObjs, not added by PV code (symbian only)
, EOtherExecStats_ReleaseTime //thread release time (Brew only)
, EOtherExecStats_Last
};
PVActiveStats* iOtherExecStats[EOtherExecStats_Last];//placeholder for stats of all ExecObjs.
void ConstructStatQ();
void BeginStats();
void EndStats();
static void ShowStats(PVActiveStats *active);
static void ShowSummaryStats(PVActiveStats *active, PVLogger*, int64, int64&, float&);
void CleanupStatQ();
uint8* iTotalTicksTemp;
int64 iGrandTotalTicks;
float iTotalPercent;
friend class PVActiveStats;
uint32 iTime;
int32 iDelta;
PVActiveStats* iPVStats;
#endif //PV_SCHED_ENABLE_AO_STATS
//Queue utils.
PVActiveBase *FindPVBase(PVActiveBase *active, OsclDoubleList<PVActiveBase> &);
void CleanupExecQ();
void InitExecQ(int);
PVLogger *iLogger;
PVLogger* iDebugLogger;
#if(PV_SCHED_ENABLE_PERF_LOGGING)
//for perf logging
char* iLogPerfIndentStr;
int32 iLogPerfIndentStrLen;
uint32 iLogPerfTotal;
void ResetLogPerf();
void IncLogPerf(uint32);
#endif
Oscl_DefAlloc *iAlloc;//allocator for scheduler.
// iDefAlloc is static because we need it to still be valid after ~OsclExecSchedulerCommonBase is called */
static OsclMemAllocator iDefAlloc;//default allocator
friend class OsclActiveObject;
friend class OsclTimerObject;
friend class PVActiveBase;
friend class PVSchedulerStopper;
friend class OsclExecScheduler;
};
class OsclErrorTrapImp;
class OsclExecScheduler: public OsclExecSchedulerCommonBase
, public OsclExecSchedulerBase
{
public:
/**
* Get currently installed scheduler for calling thread,
* or NULL if no scheduler is installed.
*/
OSCL_IMPORT_REF static OsclExecScheduler* Current();
/**
* Non-Blocking scheduler APIs.
*/
/**
* Run PV scheduler in non-blocking mode. This call returns
* when the desired number of Run calls have been made,
* or when there are no more active objects that are ready
* to run.
*
* @param aTargetCount: (input param) the maximum number of Run calls to make.
* @param aReady: (output param) tells the number of active objects that
* are currently ready to run.
* @param aDelayMsec: (output param) If no active objects are ready to
* run, but one or more active objects are waiting on timers, this
* parameter will tell the time interval from the current time until the
* first of the pending timer objects will be ready to run, in milliseconds.
*
* Note: On Symbian, non-blocking mode is not supported and this call will
* leave.
*
*/
OSCL_IMPORT_REF void RunSchedulerNonBlocking(int32 aTargetCount, int32 &aReady, uint32 &aDelayMsec);
/**
* Register for a notification when non-blocking scheduler needs to run
* again.
*
* Note: On Symbian, non-blocking mode is not supported and this call will
* leave.
*/
OSCL_IMPORT_REF void RegisterForCallback(OsclSchedulerObserver* aCallback, OsclAny* aCallbackContext);
private:
static OsclExecScheduler *NewL(const char *name, Oscl_DefAlloc *a, int nreserve);
~OsclExecScheduler();
friend class OsclScheduler;
OsclExecScheduler(Oscl_DefAlloc*);
void ConstructL(const char *name, int);
};
/**
* Scheduler stopper AO class, for internal use
* by scheduler.
*/
class PVSchedulerStopper: public OsclActiveObject
{
public:
PVSchedulerStopper();
~PVSchedulerStopper();
private:
void Run();
};
#endif
/*! @} */