Symbian OS tick timers

Tick timers are general-purpose interval timers that are used where there is no need for high resolution or great accuracy. They correspond to the timing functions available to user-side code on EKA1. We represent a tick timer using a TTickLink object, which I will describe in detail later in this section. We keep active TTickLink objects on a doubly linked queue in order of expiry time. This queue is contained in a single TTickQ object instance, along with other global state related to Symbian OS timers. Adding TTickLinks to this queue is an O(N) operation so we use a mutex, TTickQ::Mutex, to protect the queue.

The tick queue operates according to a notional ''Symbian OS nominal tick'' which has a period of 15.625 ms (64 Hz frequency) - that is, the behavior is the same as that which would be obtained by using a 64 Hz periodic tick interrupt. In fact there is no such periodic tick-instead a single NTimer is used to trigger expiry of TTickLink timers. It is always set to expire either when the first TTickLink should expire or in 65536 Symbian OS ticks (1024 seconds), whichever is the sooner. The limit is imposed to ensure that differences calculated in microseconds never overflow a 32-bit signed quantity. When the NTimer expires, it activates a DFC that runs in the Symbian OS timer thread (TimerThread). This DFC dequeues and calls handlers for any TTickLink timers that have expired, and then requeues the NTimer for the next TTickLink timer expiry. The timer mutex is acquired at the beginning of the DFC and released at the end, so the mutex is held while the expiry handlers are called.

Under this system, adding a new TTickLink to the queue will in general mean that we need to requeue the NTimer if the new timer expires earlier than the previous earliest timer. The exception to this rule is if the TTickLink is added from another TTickLink expiry handler; in this case the main DFC routine will requeue the NTimer after all TTickLink expiry handlers for this tick have been called. We use the TTickQ::iInTick flag to indicate that the DFC is in progress; it is set by the DFC after acquiring the timer mutex, so the code to add a TTickLink (which also runs with the timer mutex held) will see it set if and only if called from the tick DFC itself.

We've seen that the usual NTimer resolution is 1 ms, which means that a period of 15.625 ms cannot be generated exactly. And, of course, the NTimer resolution may not be 1 ms for manufacturer/device-specific reasons. Hence the TTickLink timer queue uses a ''pulse swallowing''

type algorithm - it sets up the NTimer to generate intervals that are a multiple of 1 ms, such that the average period of the Symbian OS tick is 15.625 ms. For example, if a periodic TTickLink were active with a period of 1 nominal Symbian OS tick, the NTimer would actually trigger at either 15 ms or 16 ms intervals with five out of every eight intervals being 16 ms and the other three out of eight being 15 ms. This works by calculating the required NTimer interval in microseconds and accumulating the error incurred in rounding to the period of NTimer. The error is taken into account on the next calculation. In addition, we use the zero-drift mode of NTimer, where the interval is timed relative to the last timer expiry. In fact the Symbian OS timers are all calculated relative to the last such expiry. A count of nominal ticks is maintained to support the User::TickCount() function and a similar count is maintained to serve as universal time. These counts are updated at the beginning of the DFC that services the TTickQ. The nanokernel tick count at which the NTimer triggered is saved and the tick count and RTC count are incremented by the number of nominal ticks elapsed between this and the previous NTimer expiry. To obtain the current universal time in microseconds since 00:00:00 01-01-0AD (standard Symbian OS time storage format), we use the following formula:

iRtc*iNominalTickPeriod + (NTickCount()-iLastMs-1)*NTimer period where NTickCount() is the current NTimer tick count and the other fields are defined in the tables below. The extra —1 in the second term is due to the fact that NTickCount() is incremented immediately after determining which timers to complete. This scheme allows the system time to be obtained to a 1 ms resolution (or whatever the resolution of NTimer is on a particular platform).

Summary of fields in TTickLink:

Field

Description

iNext, iPrev

Link pointers used to attach this object to the system tick timer queue (TTickQ).

iDelta

Number of OS ticks between the expiry of this timer and the expiry of the following one (pointed to by iNext). Never negative, but could be zero for timers expiring at the same time.

iPeriod

Period of this timer in OS ticks or zero for a one-shot timer.

Field

Description

iPtr

Argument passed to callback function when this timer expires.

iCallBack

Pointer to function to be called when this timer expires.

iLastLock

If this timer is being used to implement a Symbian OS "locked" timer, this holds the value of TTickQ : : iRtc at the last expiry of this timer. If this timer is not being used for a locked timer or has not yet expired, this value is — 1.

Summary of fields in TTickQ:

Field

Description

iNext, iPrev

Link pointers used to point to first and last entries on a time-ordered queue of TTickLink objects.

iLastDelta

Number of OS ticks which elapse between the last tick timer expiry and the time when iMsTimer next triggers - used to increment iLastTicks and iRtc.

iLastTicks

OS tick count at point when iMsTimer last triggered.

iRtc

The absolute time at the point when iMsTimer last triggered, measured in nominal OS ticks from 00:00:00 1st January 0AD.

iTickPeriod

The current actual length of an OS tick in microseconds. This may differ from the nominal tick period if a tracking system is being used to make the iRtc value follow a hardware RTC. This value may change as a result of the operation of any such tracking system.

iTicksPerSecond

Number of nominal OS ticks in one second of elapsed time.

iNominalTickPeriod

The nominal length of an OS tick in microseconds. This value is never changed, unlike iTickPeriod.

ilnTick

Boolean flag set to indicate that processing of the tick queue initiated by iMsTimer expiry is underway.

iRounding

The number of microseconds added to the last delta value when iMsTimer was last set up in order to make the period an integral number of nanokernel timer ticks.

Field

Description

iPrevRounding

The value of iRounding at the point where iMsTimer last triggered. Each time the timer is queued, iPrevRounding is used in the calculation of when the timer should trigger and the rounding applied to that time to obtain an integral number of nanokernel ticks is stored in iRounding.

iLastMs

The nanokernel tick count at which iMsTimer last triggered.

iMsTickPeriod

The period of the nanokernel tick in microseconds.

iTickDfc

DFC queued by the expiry of iMsTimer. Runs in context of TimerThread and processes any Symbian OS timers which have just expired.

iMsTimer

Nanokernel timer used to initiate Symbian OS timer processing. It is always queued to trigger at the time when the next TtickLink timer should expire.

5.5.2.1 Second timers

Second timers are used when an event needs to occur at a specific date and time of day rather than after a specified interval, and are typically used for system alarms. They have a resolution of 1 second. They will also power up the system at the expiry time if they need to.

We represent a second timer by a TSecondLink object and attach active timers to a TSecondQ absolute timer queue object, of which a single instance exists. Each TSecondLink stores the absolute time at which it should trigger (measured in nominal OS ticks from 00:00:00 1st January 0AD UTC) and they are linked into the queue in chronological order of expiry time, earliest first. The second timer queue is driven from the tick timer queue. It contains a TTickLink timer which is set to expire at either the trigger time of the first TSecondLink on the queue or at the next midnight local time, whichever is the earlier. When this TTickLink timer triggers, it calls back the handlers for TSecondLink timers that have expired, and then requeues the TTickLink timer. The same mutex (timer mutex) is used to protect the TTickQ and TSecondQ objects, and the handlers are called with the timer mutex held. We use the expiry at midnight to signal change notifiers that midnight crossover has occurred. In a similar way to TTickQ, when a new TSecondLink is queued, the TTickLink timer may need to be canceled and requeued, unless it is queued from inside the TSecondQ expiry handler. Again we use an ilnTick field to indicate the latter condition.

Summary of fields in TSecondLink:

Field

Description

iNext, iPrev

Link pointers used to attach this object to the system absolute timer queue (TSecondQ).

iTime

The absolute time when this timer should trigger, measured in nominal OS ticks from 00:00:00 1st January 0AD.

iPtr

Argument passed to callback function when this timer expires.

iCallBack

Pointer to function to be called when this timer expires.

Summary of fields in TSecondQ:

Field

Description

iNext, iPrev

Link pointers used to point to first and last entries in a time-ordered queue of TSecondLink objects.

iExpired

Boolean flag set when any TSecondLink timer expires and cleared by the power model just before initiating the machine power down sequence. Used by the power model to abort power down if an absolute timer expires during the power-down sequence.

ilnTick

Boolean flag set to indicate that processing of the second timer queue initiated by iTimer expiry is underway.

iNextTrigger

The absolute time when iTimer will next trigger, measured in nominal OS ticks from 00:00:00 1st January 0AD.

iMidnight

The absolute time of the next midnight, measured in nominal OS ticks from 00:00:00 1st January 0AD.

iTicksPerDay

Number of nominal OS ticks in 1 day.

iTimer

TTickLink timer object used to initiate second queue timer processing. It is always queued to trigger either at the time when the next TSecondLink timer should expire or at the next midnight, whichever is earlier.

iWakeUpDfc

DFC used to restart the TTickQ and TSecondQ following machine power down and power up and changes to the system time.

0 0

Post a comment

  • Receive news updates via email from this site