Hi,

I think we need to restart the time API discussion and specify it only wall 
time in mind. CPU cycle count APIs can be tuned as a next step. CPU cycle 
counters are affected by frequency scaling, which makes those difficult to use 
for counting linear, real time. The time API should specify an easy way to 
check and use the real, wall clock time. We need at least one time source that 
will not wrap in years - here it's the "global" time (e.g. in POSIX it's 
CLOCK_MONOTONIC). Global time can be also compared between threads. Local time 
is defined for optimizing short interval time checks. It's thread local, may 
wrap sooner than global time, but may be lower overhead to use.

There could be actually four time bases defined in the API, if we'd want to 
optimize for each use case (global.hi_res, global.low_res, local.hi_res and 
local.low_res). I'd propose to have only two and give system specific way to 
configure those (rate and duration). Typical config would be global.low_res and 
local.hi_res. User can check hz and max time value (wrap around time) with 
odp_time_info() and adapt (fall back to use global time) if e.g. local time 
wraps too quickly (e.g. in 4 sec).

See the proposal under.

-Petri




//
// Use cases
//
//             high resolution                 low resolution   
//             short interval                  long interval
//             low overhead                    high overhead
//
//
//  global     timestamp packets or       |    timestamp log entries or
//             other global resources     |    other global resources
//             at high rate               |    at low rate
//                                        |
//             ---------------------------+------------------------------
//                                        |
//  local      timestamp and sort items   |    measure execution time over
//             in thread local work queue,|    many iterations or over
//             measure execution time     |    a "long" function
//             of a "short" function,     |
//             spin and wait for a short  |
//             while
//
//

// time in nsec
// renamed to leave room for sec or other units in the future
#define ODP_TIME_NS_USEC 1000ULL       /**< Microsecond in nsec */
#define ODP_TIME_NS_MSEC 1000000ULL    /**< Millisecond in nsec */
#define ODP_TIME_NS_SEC  1000000000ULL /**< Second in nsec */
#define ODP_TIME_NS_DAY  ((24*60*60)*ODP_TIME_NS_SEC) /**< Day in nsec */



// Abstract time type
// Implementation specific type, includes e.g.
// - counter value
// - potentially other information: global vs. local time, ...
typedef odp_time_t

// Get global time
// Global time is common over all threads. Global timestamps can be compared
// between threads.
odp_time_t odp_time(void);

// Get thread local time
// Thread local time is only meaningful for the calling thread. It cannot be
// compare with other timestamps (global or local from other threads).
// May run from different clock source and different rate than global time.
// User must take care not to mix local and global time values in API calls.
odp_time_t odp_time_local(void);

// Compare time values
//
// Check if t1 is before t2 in absolute time, or if interval t1 is shorter
// than interval t2
//
// -1: t2 <  t1
//  0: t2 == t1
//  1: t2 >  t1
int odp_time_cmp(odp_time_t t1, odp_time_t t2);

// Sum of t1 and t2
//
// User can sum timestamps or accumulate multiple intervals before
// comparing or converting to nsec
odp_time_t odp_time_sum(odp_time_t t1, odp_time_t t2);

// Time difference between t1 and t2
//
// Calculate interval from timestamp t1 to t2, or difference of two intervals.
// T2 must be the latter timestamp, or the longer interval (t2 >= t1).
// Use cmp() first, if don't know which timestamp is the latter/longer.
odp_time_t odp_time_diff(odp_time_t t1, odp_time_t t2);

// Convert ODP time to wall clock time in nsec
//
// Wall clock time advances linearly in realtime and starts from 0 in ODP init.
//
// Global time must not wrap in several years (max time value is defined by
// info.global_nsec_max). Local time may have shorter wrap around time
// (info.local_nsec_max) than global, but it's also recommended to be years.
// 
// Global and local time may run from different time base and thus result
// different nsec values.
uint64_t odp_time_to_ns(odp_time_t time);

// convert nsec value to global time
odp_time_t odp_time_from_ns(uint64_t ns);

// convert nsec value to local time
odp_time_t odp_time_local_from_ns(uint64_t ns);

// Time info structure
typedef struct {
        // Global timestamp resolution in hz
        uint64_t global_hz;
        // Max global time value in nsec. Global time values (timestamps or
        // intervals) larger than this are not handled correctly.
      // Global wall clock time wraps back to zero after this value.
        uint64_t global_nsec_max;
        // Local timestamp resolution in hz
        uint64_t local_hz;
        // Max local time value in nsec. Local time values (timestamps or
        // intervals) larger than this are not handled correctly.
      // Local wall clock time wraps back to zero after this value.
        uint64_t local_nsec_max;
} odp_time_info_t;

// Time info request
//
// Fill in time info struct. User can check resolutions and max time values¨
// in nsec.
// 
// 0 on success
// <0 on failure
int odp_time_info(odp_time_info_t *info);
_______________________________________________
lng-odp mailing list
lng-odp@lists.linaro.org
https://lists.linaro.org/mailman/listinfo/lng-odp

Reply via email to