|
|
|
|
|
|
|
|
|
|
xen-devel
[Xen-devel] RE: [RFC] Correct/fast timestamping in apps under Xen [0 of
OK, here'e some pseudo-code to describe the
decision tree an app would go through -- once
at startup -- to probe the environment and
determine which timestamp mechanism is the
best, meaning all of correct AND fastest
AND highest resolution. Also following
that is the code an app would use whenever
a timestamp is needed (could be a static
inline function to avoid function call
overhead).
Remember that this is ONLY needed by apps
that must obtain a timestamp at a
high frequency, say >2K/core/sec. At lower
frequencies, TSC emulation or calling an
OS intrinsic should be sufficient.
In some environments (e.g. if/when pvclock+
vsyscall is implemented), an OS intrinsic
may be faster than emulation. However,
there is no way to probe this so, if necessary,
we determine which is fastest by measuring both.
The pvrdtscp mechanism, which must be proactively
configured for a guest, uses the rdtscp
instruction to return TSC and the guest
incarnation number (which changes infrequently).
If the app is currently running on hardware
which either does not support rdtscp or
doesn't have a reliable TSC, zero is
returned in place of the incarnation number
and Xen system time (in nsec) is returned
instead of TSC.
Legend: XEN_* indicates information obtained
by the app directly from Xen (using a TBD
mechanism). All other functions are in-app
calls.
Dan
====================
/* run once at app startup */
if (running_on_xen())
timestamp_mech = TS_NATIVE;
if (XEN_guest_is_landlocked() && XEN_tsc_is_reliable())
timestamp_mech = TS_RDTSC_SCALE;
timestamp_scale = XEN_tsc_scale();
}
else if (XEN_guest_has_pvrdtscp())
timestamp_mech = TS_PVRDTSCP;
else if (XEN_guest_tsc_emulated()) {
os_intr_cycles = measure_os_intrinsic();
tsc_emul_cycles = measure_tsc_emulation();
if (tsc_emul_cycles < os_intr_cycles) {
timestamp_mech = TS_RDTSC_NSEC;
else
timestamp_mech = TS_OS_INTRINSIC;
}
/* returns monotonically increasing timestamp (nsec) */
u64 get_nsec_timestamp(void)
{
static u64 last = 0;
u64 now;
if (timestamp_mech == TS_NATIVE)
now = native_timestamp();
else if (timestamp_mech == TS_PVRDTSCP) {
static u32 last_aux = 0;
u32 this_aux;
now = rdtscp(&this_aux);
if (this_aux != 0) {
while (this_aux != last_aux) {
/* occurs only very rarely */
last_aux = this_aux;
timestamp_scale = XEN_tsc_scale();
now = rdtscp(&this_aux);
}
now = ts_scale(timestamp_scale,now);
}
/* this_aux == 0 means was emulated and
already have nsec */
}
else if (timestamp_mech == TS_RDTSC_NSEC)
now = rdtsc();
else if (timestamp_mech == TS_RDTSC_SCALE)
now = ts_scale(timestamp_scale,rdtsc());
else /* TS_OS_INTRINSIC */
now = os_intrinsic_get_nsec();
/* ensure monotonically increasing */
if ((s64)(now - last) > 0)
last = now;
else
now = ++last;
return now;
}
_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-devel
|
|
|
|
|