[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Xen-devel] RE: [RFC] Correct/fast timestamping in apps under Xen [0 of 4]

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

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



/* 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;
        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;
        now = ++last;
    return now;

Xen-devel mailing list



Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.