There are several functions that you can use to determine the current time,
for use in timestamps or for calculating execution times:
-
time()
- This is the fastest generic time function we have.
It's fast because it just reads from the qtime entries from the
system page (see
SYSPAGE_ENTRY()).
-
ClockTime()
- The kernel call for time functions.
Using CLOCK_MONOTONIC is typically better than using
CLOCK_REALTIME because the monotonic clock is always
increasing, so you don't have to worry that someone might be changing
the clock.
Changing the realtime clock just modifies
SYSPAGE_ENTRY(qtime)->nsec_tod_adjust to be the difference
between the monotonic and realtime clocks.
-
clock_gettime()
- A POSIX cover function for ClockTime().
All the above methods have an accuracy based on the system timer tick.
If you need more accuracy, you can use
ClockCycles()
.
This function is implemented differently for each processor, so there are
tradeoffs.
The implementation tries to be as quick as possible, so it tries to use a
CPU register if possible.
Because of this, to get accurate times on SMP machines, you need to use
thread affinity to lock the thread to a processor, because each processor
can have a ClockCycles() base value that may not be synchronized
with the values on other processors.
Some caveats for each processor:
- PPC
- Reads 64 bits from one of two CPU registers (the TIMEBASE or a SPR),
depending on the processor.
A runtime check determines which register to use.
On the PPC 400 series, a fault occurs and the fault handler maps the
PPC400 SPRs to the normal SPRs.
- MIPS
- Reads from a 32-bit register, but this register is privileged.
If I/O privileges aren't set, then a fault occurs, and the handler returns
the value.
- x86
- Reads from a 64-bit register, except for 486s, where it causes
a fault and the fault handler reads from an external clock chip.
- SH
- Reads from a 32-bit on-chip clock.
- ARM
- Always faults, and the fault handler reads from an external clock chip
to make a 64-bit value.
To convert the cycle number to real time, use
SYSPAGE_ENTRY(qtime)->cycles_per_sec.
Note:
SH and MIPS are based on a 32-bit clock, so they can wrap around.
You should use ClockCycles() only for short durations.
If you need a pause, use
delay()
or the POSIX
clock_nanosleep().
If you need a very short delay (e.g. for accessing hardware),
you should look at the
nanospin*()
functions:
They basically do a while loop to a calibrated number of
iterations to delay the proper amount of time.
This wastes CPU, so you should use these functions only if necessary.