diff mbox

[API-NEXT,v8,3/6] api: time: unbind CPU cycles from time API

Message ID 1446815335-26122-1-git-send-email-ivan.khoronzhuk@linaro.org
State Accepted
Commit 166a3134b43621ed466f56eed6f38cd552443d77
Headers show

Commit Message

Ivan Khoronzhuk Nov. 6, 2015, 1:08 p.m. UTC
Current time API supposes that frequency of counter is equal
to CPU frequency. But that's not always true, for instance,
in case if no access to CPU cycle counter, another hi-resolution
timer can be used, and it`s rate can be different from CPU
rate. There is no big difference in which cycles to measure
time, the better hi-resolution timer the better measurements.
So, unbind CPU cycle counter from time API by eliminating word
"cycle" as it's believed to be used with CPU.

Also add new opaque type for time odp_time_t, as it asks user to use
API and abstracts time from units. New odp_time_t requires several
additional API functions to be added:

odp_time_t odp_time_sum(odp_time_t t1, odp_time_t t2);
int odp_time_cmp(odp_time_t t1, odp_time_t t2);
uint64_t odp_time_to_u64(odp_time_t hdl);

Also added new definition that represents 0 ticks for time -
ODP_TIME_NULL. It can be used instead of odp_time_from_ns(0) for
comparison and initialization.

This patch changes only used time API, it doesn't change used var
names for simplicity.

This time API can be implemented with local timer counter, so
shouldn't be used between threads.

Signed-off-by: Ivan Khoronzhuk <ivan.khoronzhuk@linaro.org>
---
 example/generator/odp_generator.c                  | 16 ++---
 example/timer/odp_timer_test.c                     | 10 +--
 include/odp/api/time.h                             | 77 +++++++++++++++++-----
 test/performance/odp_l2fwd.c                       |  2 +-
 test/performance/odp_pktio_perf.c                  | 55 +++++++++-------
 .../classification/odp_classification_test_pmr.c   | 20 +++---
 .../classification/odp_classification_tests.c      | 14 ++--
 test/validation/pktio/pktio.c                      | 31 ++++-----
 test/validation/scheduler/scheduler.c              |  5 +-
 test/validation/time/time.c                        | 27 ++++----
 test/validation/timer/timer.c                      | 14 ++--
 11 files changed, 162 insertions(+), 109 deletions(-)

Comments

Maxim Uvarov Nov. 10, 2015, 8:06 a.m. UTC | #1
this patch refers to odp_time_t which is defined in patch 4.

and I have that error:
../../include/odp/api/time.h:52:1: error: unknown type name 'odp_time_t'
  odp_time_t odp_time_local(void);

Hole patches looks good for me. But or you need merge 3 and 4 or move 
that defines from 4 to 3.

Please send updated version.

Maxim.

On 11/06/2015 16:08, Ivan Khoronzhuk wrote:
> Current time API supposes that frequency of counter is equal
> to CPU frequency. But that's not always true, for instance,
> in case if no access to CPU cycle counter, another hi-resolution
> timer can be used, and it`s rate can be different from CPU
> rate. There is no big difference in which cycles to measure
> time, the better hi-resolution timer the better measurements.
> So, unbind CPU cycle counter from time API by eliminating word
> "cycle" as it's believed to be used with CPU.
>
> Also add new opaque type for time odp_time_t, as it asks user to use
> API and abstracts time from units. New odp_time_t requires several
> additional API functions to be added:
>
> odp_time_t odp_time_sum(odp_time_t t1, odp_time_t t2);
> int odp_time_cmp(odp_time_t t1, odp_time_t t2);
> uint64_t odp_time_to_u64(odp_time_t hdl);
>
> Also added new definition that represents 0 ticks for time -
> ODP_TIME_NULL. It can be used instead of odp_time_from_ns(0) for
> comparison and initialization.
>
> This patch changes only used time API, it doesn't change used var
> names for simplicity.
>
> This time API can be implemented with local timer counter, so
> shouldn't be used between threads.
>
> Signed-off-by: Ivan Khoronzhuk <ivan.khoronzhuk@linaro.org>
> ---
>   example/generator/odp_generator.c                  | 16 ++---
>   example/timer/odp_timer_test.c                     | 10 +--
>   include/odp/api/time.h                             | 77 +++++++++++++++++-----
>   test/performance/odp_l2fwd.c                       |  2 +-
>   test/performance/odp_pktio_perf.c                  | 55 +++++++++-------
>   .../classification/odp_classification_test_pmr.c   | 20 +++---
>   .../classification/odp_classification_tests.c      | 14 ++--
>   test/validation/pktio/pktio.c                      | 31 ++++-----
>   test/validation/scheduler/scheduler.c              |  5 +-
>   test/validation/time/time.c                        | 27 ++++----
>   test/validation/timer/timer.c                      | 14 ++--
>   11 files changed, 162 insertions(+), 109 deletions(-)
>
> diff --git a/example/generator/odp_generator.c b/example/generator/odp_generator.c
> index dd30403..d476240 100644
> --- a/example/generator/odp_generator.c
> +++ b/example/generator/odp_generator.c
> @@ -586,7 +586,7 @@ static void *gen_recv_thread(void *arg)
>    */
>   static void print_global_stats(int num_workers)
>   {
> -	uint64_t start, wait, diff;
> +	odp_time_t start, wait, diff;
>   	uint64_t pkts, pkts_prev = 0, pps, maximum_pps = 0;
>   	int verbose_interval = 20;
>   	odp_thrmask_t thrd_mask;
> @@ -594,8 +594,8 @@ static void print_global_stats(int num_workers)
>   	while (odp_thrmask_worker(&thrd_mask) < num_workers)
>   		continue;
>   
> -	wait = odp_time_ns_to_cycles(verbose_interval * ODP_TIME_SEC);
> -	start = odp_time_cycles();
> +	wait = odp_time_local_from_ns(verbose_interval * ODP_TIME_SEC_IN_NS);
> +	start = odp_time_local();
>   
>   	while (odp_thrmask_worker(&thrd_mask) == num_workers) {
>   		if (args->appl.number != -1 &&
> @@ -604,11 +604,11 @@ static void print_global_stats(int num_workers)
>   			break;
>   		}
>   
> -		diff = odp_time_diff_cycles(start, odp_time_cycles());
> -		if (diff < wait)
> +		diff = odp_time_diff(start, odp_time_local());
> +		if (odp_time_cmp(wait, diff) > 0)
>   			continue;
>   
> -		start = odp_time_cycles();
> +		start = odp_time_local();
>   
>   		if (args->appl.mode == APPL_MODE_RCV) {
>   			pkts = odp_atomic_load_u64(&counters.udp);
> @@ -730,9 +730,9 @@ int main(int argc, char *argv[])
>   	odp_pool_print(pool);
>   
>   	/* Create timer pool */
> -	tparams.res_ns = 1 * ODP_TIME_MSEC;
> +	tparams.res_ns = 1 * ODP_TIME_MSEC_IN_NS;
>   	tparams.min_tmo = 0;
> -	tparams.max_tmo = 10000 * ODP_TIME_SEC;
> +	tparams.max_tmo = 10000 * ODP_TIME_SEC_IN_NS;
>   	tparams.num_timers = num_workers; /* One timer per worker */
>   	tparams.priv = 0; /* Shared */
>   	tparams.clk_src = ODP_CLOCK_CPU;
> diff --git a/example/timer/odp_timer_test.c b/example/timer/odp_timer_test.c
> index d3f2ca0..7d305cd 100644
> --- a/example/timer/odp_timer_test.c
> +++ b/example/timer/odp_timer_test.c
> @@ -95,7 +95,7 @@ static void test_abs_timeouts(int thr, test_globals_t *gbls)
>   
>   	queue = odp_queue_lookup("timer_queue");
>   
> -	period_ns = gbls->args.period_us*ODP_TIME_USEC;
> +	period_ns = gbls->args.period_us * ODP_TIME_USEC_IN_NS;
>   	period    = odp_timer_ns_to_tick(gbls->tp, period_ns);
>   
>   	EXAMPLE_DBG("  [%i] period %"PRIu64" ticks,  %"PRIu64" ns\n", thr,
> @@ -408,9 +408,9 @@ int main(int argc, char *argv[])
>   		return -1;
>   	}
>   
> -	tparams.res_ns = gbls->args.resolution_us*ODP_TIME_USEC;
> -	tparams.min_tmo = gbls->args.min_us*ODP_TIME_USEC;
> -	tparams.max_tmo = gbls->args.max_us*ODP_TIME_USEC;
> +	tparams.res_ns = gbls->args.resolution_us * ODP_TIME_USEC_IN_NS;
> +	tparams.min_tmo = gbls->args.min_us * ODP_TIME_USEC_IN_NS;
> +	tparams.max_tmo = gbls->args.max_us * ODP_TIME_USEC_IN_NS;
>   	tparams.num_timers = num_workers; /* One timer per worker */
>   	tparams.priv = 0; /* Shared */
>   	tparams.clk_src = ODP_CLOCK_CPU;
> @@ -455,7 +455,7 @@ int main(int argc, char *argv[])
>   	printf("  %12" PRIu64 " ticks   ->  %12" PRIu64 " ns\n", tick,
>   	       odp_timer_tick_to_ns(gbls->tp, tick));
>   
> -	for (ns = 1; ns <= 100*ODP_TIME_SEC; ns *= 10) {
> +	for (ns = 1; ns <= 100 * ODP_TIME_SEC_IN_NS; ns *= 10) {
>   		tick = odp_timer_ns_to_tick(gbls->tp, ns);
>   
>   		printf("  %12" PRIu64 " ns      ->  %12" PRIu64 " ticks\n", ns,
> diff --git a/include/odp/api/time.h b/include/odp/api/time.h
> index b0072fc..f119733 100644
> --- a/include/odp/api/time.h
> +++ b/include/odp/api/time.h
> @@ -24,18 +24,32 @@ extern "C" {
>    */
>   
>   /* Time in nanoseconds */
> -#define ODP_TIME_USEC 1000ULL       /**< Microsecond in nsec */
> -#define ODP_TIME_MSEC 1000000ULL    /**< Millisecond in nsec */
> -#define ODP_TIME_SEC  1000000000ULL /**< Second in nsec */
> +#define ODP_TIME_USEC_IN_NS	1000ULL       /**< Microsecond in nsec */
> +#define ODP_TIME_MSEC_IN_NS	1000000ULL    /**< Millisecond in nsec */
> +#define ODP_TIME_SEC_IN_NS	1000000000ULL /**< Second in nsec */
>   
> +/**
> + * @typedef odp_time_t
> + * ODP time stamp. Time stamp can represent a time stamp from local or global
> + * time source. A local time stamp must not be shared between threads. API calls
> + * work correctly only when all time stamps for input are from the same time
> + * source.
> + */
>   
>   /**
> - * Current time in CPU cycles
> - *
> - * @return Current time in CPU cycles
> + * @def ODP_TIME_NULL
> + * Zero time stamp
>    */
> -uint64_t odp_time_cycles(void);
>   
> +/**
> + * Current local time
> + *
> + * Returns current local time stamp value. The local time source provides high
> + * resolution time.
> + *
> + * @return Local time stamp.
> + */
> +odp_time_t odp_time_local(void);
>   
>   /**
>    * Time difference
> @@ -43,29 +57,60 @@ uint64_t odp_time_cycles(void);
>    * @param t1    First time stamp
>    * @param t2    Second time stamp
>    *
> - * @return Difference of time stamps in CPU cycles
> + * @return Difference of time stamps
>    */
> -uint64_t odp_time_diff_cycles(uint64_t t1, uint64_t t2);
> +odp_time_t odp_time_diff(odp_time_t t1, odp_time_t t2);
>   
> +/**
> + * Time sum
> + *
> + * @param t1    Time stamp
> + * @param t2    Time stamp
> + *
> + * @return Sum of time stamps
> + */
> +odp_time_t odp_time_sum(odp_time_t t1, odp_time_t t2);
>   
>   /**
> - * Convert CPU cycles to nanoseconds
> + * Convert time to nanoseconds
>    *
> - * @param cycles  Time in CPU cycles
> + * @param time  Time
>    *
>    * @return Time in nanoseconds
>    */
> -uint64_t odp_time_cycles_to_ns(uint64_t cycles);
> +uint64_t odp_time_to_ns(odp_time_t time);
>   
> +/**
> + * Convert nanoseconds to local time
> + *
> + * @param ns    Time in nanoseconds
> + *
> + * @return Local time stamp
> + */
> +odp_time_t odp_time_local_from_ns(uint64_t ns);
> +
> +/**
> + * Compare two times
> + *
> + * @param t2    Second time
> + * @param t1    First time
> + *
> + * @retval <0 if t2 < t1, >0 if t1 = t2, 1 if t2 > t1
> + */
> +int odp_time_cmp(odp_time_t t2, odp_time_t t1);
>   
>   /**
> - * Convert nanoseconds to CPU cycles
> + * Get printable value for an odp_time_t
> + *
> + * @param time time to be printed
>    *
> - * @param ns      Time in nanoseconds
> + * @return uint64_t value that can be used to print/display this time
>    *
> - * @return Time in CPU cycles
> + * @note This routine is intended to be used for diagnostic purposes
> + * to enable applications to generate a printable value that represents
> + * an odp_time_t time.
>    */
> -uint64_t odp_time_ns_to_cycles(uint64_t ns);
> +uint64_t odp_time_to_u64(odp_time_t time);
>   
>   /**
>    * @}
> diff --git a/test/performance/odp_l2fwd.c b/test/performance/odp_l2fwd.c
> index f7ccdce..d201186 100644
> --- a/test/performance/odp_l2fwd.c
> +++ b/test/performance/odp_l2fwd.c
> @@ -157,7 +157,7 @@ static void *pktio_queue_thread(void *arg)
>   	printf("[%02i] QUEUE mode\n", thr);
>   	odp_barrier_wait(&barrier);
>   
> -	wait = odp_schedule_wait_time(ODP_TIME_MSEC * 100);
> +	wait = odp_schedule_wait_time(ODP_TIME_MSEC_IN_NS * 100);
>   
>   	/* Loop packets */
>   	while (!exit_threads) {
> diff --git a/test/performance/odp_pktio_perf.c b/test/performance/odp_pktio_perf.c
> index ae5b4c0..2d64b40 100644
> --- a/test/performance/odp_pktio_perf.c
> +++ b/test/performance/odp_pktio_perf.c
> @@ -50,7 +50,7 @@
>   /* Amount of time to wait, in nanoseconds, between the transmitter(s)
>    * completing and the receiver(s) being shutdown. Any packets not
>    * received by this time will be assumed to have been lost. */
> -#define SHUTDOWN_DELAY_NS (ODP_TIME_MSEC*100)
> +#define SHUTDOWN_DELAY_NS (ODP_TIME_MSEC_IN_NS * 100)
>   
>   #define VPRINT(fmt, ...) \
>   	do { \
> @@ -106,7 +106,7 @@ struct tx_stats_s {
>   	uint64_t tx_cnt;	/* Packets transmitted */
>   	uint64_t alloc_failures;/* Packet allocation failures */
>   	uint64_t enq_failures;	/* Enqueue failures */
> -	uint64_t idle_cycles;	/* Idle cycle count in TX loop */
> +	odp_time_t idle_cycles;	/* Idle cycle count in TX loop */
>   };
>   
>   typedef union tx_stats_u {
> @@ -305,12 +305,12 @@ static void *run_thread_tx(void *arg)
>   	int thr_id;
>   	odp_queue_t outq;
>   	pkt_tx_stats_t *stats;
> -	uint64_t burst_start_cycles, start_cycles, cur_cycles, send_duration;
> -	uint64_t burst_gap_cycles;
> +	odp_time_t start_cycles, cur_cycles, send_duration;
> +	odp_time_t burst_start_cycles, burst_gap_cycles;
>   	uint32_t batch_len;
>   	int unsent_pkts = 0;
>   	odp_event_t  tx_event[BATCH_LEN_MAX];
> -	uint64_t idle_start = 0;
> +	odp_time_t idle_start = ODP_TIME_NULL;
>   
>   	thread_args_t *targs = arg;
>   
> @@ -328,30 +328,34 @@ static void *run_thread_tx(void *arg)
>   	if (outq == ODP_QUEUE_INVALID)
>   		LOG_ABORT("Failed to get output queue for thread %d\n", thr_id);
>   
> -	burst_gap_cycles = odp_time_ns_to_cycles(
> -				ODP_TIME_SEC / (targs->pps / targs->batch_len));
> -	send_duration = odp_time_ns_to_cycles(targs->duration * ODP_TIME_SEC);
> +	burst_gap_cycles = odp_time_local_from_ns(
> +			ODP_TIME_SEC_IN_NS / (targs->pps / targs->batch_len));
> +	send_duration =
> +		odp_time_local_from_ns(targs->duration * ODP_TIME_SEC_IN_NS);
>   
>   	odp_barrier_wait(&globals->tx_barrier);
>   
> -	cur_cycles     = odp_time_cycles();
> +	cur_cycles     = odp_time_local();
>   	start_cycles   = cur_cycles;
> -	burst_start_cycles = odp_time_diff_cycles(burst_gap_cycles, cur_cycles);
> -	while (odp_time_diff_cycles(start_cycles, cur_cycles) < send_duration) {
> +	burst_start_cycles = odp_time_diff(burst_gap_cycles, cur_cycles);
> +	while (odp_time_diff(start_cycles, cur_cycles) < send_duration) {
>   		unsigned alloc_cnt = 0, tx_cnt;
>   
> -		if (odp_time_diff_cycles(burst_start_cycles, cur_cycles)
> +		if (odp_time_diff(burst_start_cycles, cur_cycles)
>   							< burst_gap_cycles) {
> -			cur_cycles = odp_time_cycles();
> -			if (idle_start == 0)
> +			cur_cycles = odp_time_local();
> +			if (!odp_time_cmp(idle_start, ODP_TIME_NULL))
>   				idle_start = cur_cycles;
>   			continue;
>   		}
>   
> -		if (idle_start) {
> -			stats->s.idle_cycles += odp_time_diff_cycles(
> -							idle_start, cur_cycles);
> -			idle_start = 0;
> +		if (odp_time_cmp(idle_start, ODP_TIME_NULL)) {
> +			odp_time_t diff = odp_time_diff(idle_start, cur_cycles);
> +
> +			stats->s.idle_cycles =
> +				odp_time_sum(diff, stats->s.idle_cycles);
> +
> +			idle_start = ODP_TIME_NULL;
>   		}
>   
>   		burst_start_cycles += burst_gap_cycles;
> @@ -365,14 +369,15 @@ static void *run_thread_tx(void *arg)
>   		stats->s.enq_failures += unsent_pkts;
>   		stats->s.tx_cnt += tx_cnt;
>   
> -		cur_cycles = odp_time_cycles();
> +		cur_cycles = odp_time_local();
>   	}
>   
>   	VPRINT(" %02d: TxPkts %-8"PRIu64" EnqFail %-6"PRIu64
>   	       " AllocFail %-6"PRIu64" Idle %"PRIu64"ms\n",
>   	       thr_id, stats->s.tx_cnt,
>   	       stats->s.enq_failures, stats->s.alloc_failures,
> -	       odp_time_cycles_to_ns(stats->s.idle_cycles)/1000/1000);
> +	       odp_time_to_ns(stats->s.idle_cycles) /
> +	       (uint64_t)ODP_TIME_MSEC_IN_NS);
>   
>   	return NULL;
>   }
> @@ -591,13 +596,13 @@ static int setup_txrx_masks(odp_cpumask_t *thd_mask_tx,
>    */
>   static void busy_loop_ns(uint64_t wait_ns)
>   {
> -	uint64_t diff;
> -	uint64_t start_time = odp_time_cycles();
> -	uint64_t wait = odp_time_ns_to_cycles(wait_ns);
> +	odp_time_t diff;
> +	odp_time_t start_time = odp_time_local();
> +	odp_time_t wait = odp_time_local_from_ns(wait_ns);
>   
>   	do {
> -		diff = odp_time_diff_cycles(start_time, odp_time_cycles());
> -	} while (diff < wait);
> +		diff = odp_time_diff(start_time, odp_time_local());
> +	} while (odp_time_cmp(wait, diff) > 0);
>   }
>   
>   /*
> diff --git a/test/validation/classification/odp_classification_test_pmr.c b/test/validation/classification/odp_classification_test_pmr.c
> index 73ba6f5..3f49d4c 100644
> --- a/test/validation/classification/odp_classification_test_pmr.c
> +++ b/test/validation/classification/odp_classification_test_pmr.c
> @@ -168,7 +168,7 @@ static void classification_test_pmr_term_tcp_dport(void)
>   
>   	enqueue_pktio_interface(pkt, pktio);
>   
> -	pkt = receive_packet(&retqueue, ODP_TIME_SEC);
> +	pkt = receive_packet(&retqueue, ODP_TIME_SEC_IN_NS);
>   	CU_ASSERT(pkt != ODP_PACKET_INVALID);
>   	CU_ASSERT(retqueue == queue);
>   	CU_ASSERT(seqno == cls_pkt_get_seq(pkt));
> @@ -185,7 +185,7 @@ static void classification_test_pmr_term_tcp_dport(void)
>   
>   	enqueue_pktio_interface(pkt, pktio);
>   
> -	pkt = receive_packet(&retqueue, ODP_TIME_SEC);
> +	pkt = receive_packet(&retqueue, ODP_TIME_SEC_IN_NS);
>   	CU_ASSERT(pkt != ODP_PACKET_INVALID);
>   	CU_ASSERT(seqno == cls_pkt_get_seq(pkt));
>   	CU_ASSERT(retqueue == defqueue);
> @@ -255,7 +255,7 @@ static void classification_test_pmr_term_tcp_sport(void)
>   
>   	enqueue_pktio_interface(pkt, pktio);
>   
> -	pkt = receive_packet(&retqueue, ODP_TIME_SEC);
> +	pkt = receive_packet(&retqueue, ODP_TIME_SEC_IN_NS);
>   	CU_ASSERT(pkt != ODP_PACKET_INVALID);
>   	CU_ASSERT(seqno == cls_pkt_get_seq(pkt));
>   	CU_ASSERT(retqueue == queue);
> @@ -270,7 +270,7 @@ static void classification_test_pmr_term_tcp_sport(void)
>   
>   	enqueue_pktio_interface(pkt, pktio);
>   
> -	pkt = receive_packet(&retqueue, ODP_TIME_SEC);
> +	pkt = receive_packet(&retqueue, ODP_TIME_SEC_IN_NS);
>   	CU_ASSERT(pkt != ODP_PACKET_INVALID);
>   	CU_ASSERT(seqno == cls_pkt_get_seq(pkt));
>   	CU_ASSERT(retqueue == defqueue);
> @@ -340,7 +340,7 @@ static void classification_test_pmr_term_udp_dport(void)
>   
>   	enqueue_pktio_interface(pkt, pktio);
>   
> -	pkt = receive_packet(&retqueue, ODP_TIME_SEC);
> +	pkt = receive_packet(&retqueue, ODP_TIME_SEC_IN_NS);
>   	CU_ASSERT(pkt != ODP_PACKET_INVALID);
>   	CU_ASSERT(seqno == cls_pkt_get_seq(pkt));
>   	CU_ASSERT(retqueue == queue);
> @@ -356,7 +356,7 @@ static void classification_test_pmr_term_udp_dport(void)
>   
>   	enqueue_pktio_interface(pkt, pktio);
>   
> -	pkt = receive_packet(&retqueue, ODP_TIME_SEC);
> +	pkt = receive_packet(&retqueue, ODP_TIME_SEC_IN_NS);
>   	CU_ASSERT(pkt != ODP_PACKET_INVALID);
>   	CU_ASSERT(seqno == cls_pkt_get_seq(pkt));
>   	CU_ASSERT(retqueue == defqueue);
> @@ -426,7 +426,7 @@ static void classification_test_pmr_term_udp_sport(void)
>   
>   	enqueue_pktio_interface(pkt, pktio);
>   
> -	pkt = receive_packet(&retqueue, ODP_TIME_SEC);
> +	pkt = receive_packet(&retqueue, ODP_TIME_SEC_IN_NS);
>   	CU_ASSERT(pkt != ODP_PACKET_INVALID);
>   	CU_ASSERT(seqno == cls_pkt_get_seq(pkt));
>   	CU_ASSERT(retqueue == queue);
> @@ -441,7 +441,7 @@ static void classification_test_pmr_term_udp_sport(void)
>   
>   	enqueue_pktio_interface(pkt, pktio);
>   
> -	pkt = receive_packet(&retqueue, ODP_TIME_SEC);
> +	pkt = receive_packet(&retqueue, ODP_TIME_SEC_IN_NS);
>   	CU_ASSERT(pkt != ODP_PACKET_INVALID);
>   	CU_ASSERT(seqno == cls_pkt_get_seq(pkt));
>   	CU_ASSERT(retqueue == defqueue);
> @@ -507,7 +507,7 @@ static void classification_test_pmr_term_ipproto(void)
>   
>   	enqueue_pktio_interface(pkt, pktio);
>   
> -	pkt = receive_packet(&retqueue, ODP_TIME_SEC);
> +	pkt = receive_packet(&retqueue, ODP_TIME_SEC_IN_NS);
>   	CU_ASSERT(pkt != ODP_PACKET_INVALID);
>   	CU_ASSERT(seqno == cls_pkt_get_seq(pkt));
>   	CU_ASSERT(retqueue == queue);
> @@ -520,7 +520,7 @@ static void classification_test_pmr_term_ipproto(void)
>   
>   	enqueue_pktio_interface(pkt, pktio);
>   
> -	pkt = receive_packet(&retqueue, ODP_TIME_SEC);
> +	pkt = receive_packet(&retqueue, ODP_TIME_SEC_IN_NS);
>   	CU_ASSERT(pkt != ODP_PACKET_INVALID);
>   	CU_ASSERT(seqno == cls_pkt_get_seq(pkt));
>   	CU_ASSERT(retqueue == defqueue);
> diff --git a/test/validation/classification/odp_classification_tests.c b/test/validation/classification/odp_classification_tests.c
> index 823e30f..3944d94 100644
> --- a/test/validation/classification/odp_classification_tests.c
> +++ b/test/validation/classification/odp_classification_tests.c
> @@ -225,7 +225,7 @@ void test_cls_pmr_chain(void)
>   
>   	enqueue_pktio_interface(pkt, pktio_loop);
>   
> -	pkt = receive_packet(&queue, ODP_TIME_SEC);
> +	pkt = receive_packet(&queue, ODP_TIME_SEC_IN_NS);
>   	CU_ASSERT(pkt != ODP_PACKET_INVALID);
>   	CU_ASSERT(queue == queue_list[CLS_PMR_CHAIN_DST]);
>   	CU_ASSERT(seqno == cls_pkt_get_seq(pkt));
> @@ -242,7 +242,7 @@ void test_cls_pmr_chain(void)
>   	ip->chksum = odph_ipv4_csum_update(pkt);
>   
>   	enqueue_pktio_interface(pkt, pktio_loop);
> -	pkt = receive_packet(&queue, ODP_TIME_SEC);
> +	pkt = receive_packet(&queue, ODP_TIME_SEC_IN_NS);
>   	CU_ASSERT(pkt != ODP_PACKET_INVALID);
>   	CU_ASSERT(queue == queue_list[CLS_PMR_CHAIN_SRC]);
>   	CU_ASSERT(seqno == cls_pkt_get_seq(pkt));
> @@ -289,7 +289,7 @@ void test_pktio_default_cos(void)
>   
>   	enqueue_pktio_interface(pkt, pktio_loop);
>   
> -	pkt = receive_packet(&queue, ODP_TIME_SEC);
> +	pkt = receive_packet(&queue, ODP_TIME_SEC_IN_NS);
>   	CU_ASSERT(pkt != ODP_PACKET_INVALID);
>   	/* Default packet should be received in default queue */
>   	CU_ASSERT(queue == queue_list[CLS_DEFAULT]);
> @@ -341,7 +341,7 @@ void test_pktio_error_cos(void)
>   	ip->chksum = 0;
>   	enqueue_pktio_interface(pkt, pktio_loop);
>   
> -	pkt = receive_packet(&queue, ODP_TIME_SEC);
> +	pkt = receive_packet(&queue, ODP_TIME_SEC_IN_NS);
>   	CU_ASSERT(pkt != ODP_PACKET_INVALID);
>   	/* Error packet should be received in error queue */
>   	CU_ASSERT(queue == queue_list[CLS_ERROR]);
> @@ -436,7 +436,7 @@ void test_cos_with_l2_priority(void)
>   		vlan = (odph_vlanhdr_t *)(&ethhdr->type);
>   		vlan->tci = odp_cpu_to_be_16(i << 13);
>   		enqueue_pktio_interface(pkt, pktio_loop);
> -		pkt = receive_packet(&queue, ODP_TIME_SEC);
> +		pkt = receive_packet(&queue, ODP_TIME_SEC_IN_NS);
>   		CU_ASSERT(pkt != ODP_PACKET_INVALID);
>   		CU_ASSERT(queue == queue_list[CLS_L2_QOS_0 + i]);
>   		CU_ASSERT(seqno == cls_pkt_get_seq(pkt));
> @@ -501,7 +501,7 @@ void test_pmr_cos(void)
>   	udp = (odph_udphdr_t *)odp_packet_l4_ptr(pkt, NULL);
>   	udp->src_port = odp_cpu_to_be_16(CLS_PMR_SPORT);
>   	enqueue_pktio_interface(pkt, pktio_loop);
> -	pkt = receive_packet(&queue, ODP_TIME_SEC);
> +	pkt = receive_packet(&queue, ODP_TIME_SEC_IN_NS);
>   	CU_ASSERT(pkt != ODP_PACKET_INVALID);
>   	CU_ASSERT(queue == queue_list[CLS_PMR]);
>   	CU_ASSERT(seqno == cls_pkt_get_seq(pkt));
> @@ -585,7 +585,7 @@ void test_pktio_pmr_match_set_cos(void)
>   	udp = (odph_udphdr_t *)odp_packet_l4_ptr(pkt, NULL);
>   	udp->src_port = odp_cpu_to_be_16(CLS_PMR_SET_SPORT);
>   	enqueue_pktio_interface(pkt, pktio_loop);
> -	pkt = receive_packet(&queue, ODP_TIME_SEC);
> +	pkt = receive_packet(&queue, ODP_TIME_SEC_IN_NS);
>   	CU_ASSERT(pkt != ODP_PACKET_INVALID);
>   	CU_ASSERT(queue == queue_list[CLS_PMR_SET]);
>   	CU_ASSERT(seqno == cls_pkt_get_seq(pkt));
> diff --git a/test/validation/pktio/pktio.c b/test/validation/pktio/pktio.c
> index b3738ce..9435a22 100644
> --- a/test/validation/pktio/pktio.c
> +++ b/test/validation/pktio/pktio.c
> @@ -336,18 +336,18 @@ static int destroy_inq(odp_pktio_t pktio)
>   
>   static odp_event_t queue_deq_wait_time(odp_queue_t queue, uint64_t ns)
>   {
> -	uint64_t start, now, diff;
> +	odp_time_t start, now, diff;
>   	odp_event_t ev;
>   
> -	start = odp_time_cycles();
> +	start = odp_time_local();
>   
>   	do {
>   		ev = odp_queue_deq(queue);
>   		if (ev != ODP_EVENT_INVALID)
>   			return ev;
> -		now = odp_time_cycles();
> -		diff = odp_time_diff_cycles(start, now);
> -	} while (odp_time_cycles_to_ns(diff) < ns);
> +		now = odp_time_local();
> +		diff = odp_time_diff(start, now);
> +	} while (odp_time_to_ns(diff) < ns);
>   
>   	return ODP_EVENT_INVALID;
>   }
> @@ -355,12 +355,12 @@ static odp_event_t queue_deq_wait_time(odp_queue_t queue, uint64_t ns)
>   static odp_packet_t wait_for_packet(pktio_info_t *pktio_rx,
>   				    uint32_t seq, uint64_t ns)
>   {
> -	uint64_t start, now, diff;
> +	odp_time_t start, now, diff;
>   	odp_event_t ev;
>   	odp_packet_t pkt;
>   	uint64_t wait;
>   
> -	start = odp_time_cycles();
> +	start = odp_time_local();
>   	wait = odp_schedule_wait_time(ns);
>   
>   	do {
> @@ -389,9 +389,9 @@ static odp_packet_t wait_for_packet(pktio_info_t *pktio_rx,
>   			odp_packet_free(pkt);
>   		}
>   
> -		now = odp_time_cycles();
> -		diff = odp_time_diff_cycles(start, now);
> -	} while (odp_time_cycles_to_ns(diff) < ns);
> +		now = odp_time_local();
> +		diff = odp_time_diff(start, now);
> +	} while (odp_time_to_ns(diff) < ns);
>   
>   	CU_FAIL("failed to receive transmitted packet");
>   
> @@ -450,7 +450,8 @@ static void pktio_txrx_multi(pktio_info_t *pktio_a, pktio_info_t *pktio_b,
>   
>   	/* and wait for them to arrive back */
>   	for (i = 0; i < num_pkts; ++i) {
> -		rx_pkt = wait_for_packet(pktio_b, tx_seq[i], ODP_TIME_SEC);
> +		rx_pkt = wait_for_packet(pktio_b, tx_seq[i],
> +					 ODP_TIME_SEC_IN_NS);
>   
>   		if (rx_pkt == ODP_PACKET_INVALID)
>   			break;
> @@ -627,7 +628,7 @@ void pktio_test_inq_remdef(void)
>   	CU_ASSERT(inq != ODP_QUEUE_INVALID);
>   	CU_ASSERT(odp_pktio_inq_remdef(pktio) == 0);
>   
> -	wait = odp_schedule_wait_time(ODP_TIME_MSEC);
> +	wait = odp_schedule_wait_time(ODP_TIME_MSEC_IN_NS);
>   	for (i = 0; i < 100; i++) {
>   		ev = odp_schedule(NULL, wait);
>   		if (ev != ODP_EVENT_INVALID) {
> @@ -703,7 +704,7 @@ static void pktio_test_start_stop(void)
>   	odp_event_t ev;
>   	int i, pkts, ret, alloc = 0;
>   	odp_queue_t outq;
> -	uint64_t wait = odp_schedule_wait_time(ODP_TIME_MSEC);
> +	uint64_t wait = odp_schedule_wait_time(ODP_TIME_MSEC_IN_NS);
>   
>   	for (i = 0; i < num_ifaces; i++) {
>   		pktio[i] = create_pktio(i, ODP_PKTIN_MODE_SCHED);
> @@ -918,8 +919,8 @@ static void pktio_test_send_failure(void)
>   		info_rx.in_mode = ODP_PKTIN_MODE_RECV;
>   
>   		for (i = 0; i < ret; ++i) {
> -			pkt_tbl[i] = wait_for_packet(&info_rx,
> -						     pkt_seq[i], ODP_TIME_SEC);
> +			pkt_tbl[i] = wait_for_packet(&info_rx, pkt_seq[i],
> +						     ODP_TIME_SEC_IN_NS);
>   			if (pkt_tbl[i] == ODP_PACKET_INVALID)
>   				break;
>   		}
> diff --git a/test/validation/scheduler/scheduler.c b/test/validation/scheduler/scheduler.c
> index 042d7b4..e813f82 100644
> --- a/test/validation/scheduler/scheduler.c
> +++ b/test/validation/scheduler/scheduler.c
> @@ -514,10 +514,11 @@ static void *schedule_common_(void *arg)
>   			CU_ASSERT(from != ODP_QUEUE_INVALID);
>   			if (locked) {
>   				int cnt;
> -				uint64_t cycles = 0;
> +				odp_time_t cycles = ODP_TIME_NULL;
>   				/* Do some work here to keep the thread busy */
>   				for (cnt = 0; cnt < 1000; cnt++)
> -					cycles += odp_time_cycles();
> +					cycles = odp_time_sum(cycles,
> +							      odp_time_local());
>   
>   				odp_spinlock_unlock(&globals->atomic_lock);
>   			}
> diff --git a/test/validation/time/time.c b/test/validation/time/time.c
> index 41db0e9..231f50e 100644
> --- a/test/validation/time/time.c
> +++ b/test/validation/time/time.c
> @@ -16,43 +16,44 @@ void time_test_odp_cycles_diff(void)
>   {
>   	/* volatile to stop optimization of busy loop */
>   	volatile int count = 0;
> -	uint64_t diff, cycles1, cycles2;
> +	odp_time_t diff, cycles1, cycles2;
>   
> -	cycles1 = odp_time_cycles();
> +	cycles1 = odp_time_local();
>   
>   	while (count < BUSY_LOOP_CNT) {
>   		count++;
>   	};
>   
> -	cycles2 = odp_time_cycles();
> -	CU_ASSERT(cycles2 > cycles1);
> +	cycles2 = odp_time_local();
> +	CU_ASSERT((odp_time_cmp(cycles2, cycles1) > 0));
>   
> -	diff = odp_time_diff_cycles(cycles1, cycles2);
> -	CU_ASSERT(diff > 0);
> +	diff = odp_time_diff(cycles1, cycles2);
> +	CU_ASSERT(odp_time_cmp(diff, ODP_TIME_NULL) > 0);
>   }
>   
>   /* check that a negative cycles difference gives a reasonable result */
>   void time_test_odp_cycles_negative_diff(void)
>   {
> -	uint64_t diff, cycles1, cycles2;
> +	odp_time_t diff, cycles1, cycles2;
>   
>   	cycles1 = 10;
>   	cycles2 = 5;
> -	diff = odp_time_diff_cycles(cycles1, cycles2);
> -	CU_ASSERT(diff > 0);
> +	diff = odp_time_diff(cycles1, cycles2);
> +	CU_ASSERT(odp_time_cmp(diff, ODP_TIME_NULL) > 0);
>   }
>   
>   /* check that related conversions come back to the same value */
>   void time_test_odp_time_conversion(void)
>   {
> -	uint64_t ns1, ns2, cycles;
> +	uint64_t ns1, ns2;
> +	odp_time_t cycles;
>   	uint64_t upper_limit, lower_limit;
>   
>   	ns1 = 100;
> -	cycles = odp_time_ns_to_cycles(ns1);
> -	CU_ASSERT(cycles > 0);
> +	cycles = odp_time_local_from_ns(ns1);
> +	CU_ASSERT(odp_time_cmp(cycles, ODP_TIME_NULL) > 0);
>   
> -	ns2 = odp_time_cycles_to_ns(cycles);
> +	ns2 = odp_time_to_ns(cycles);
>   
>   	/* need to check within arithmetic tolerance that the same
>   	 * value in ns is returned after conversions */
> diff --git a/test/validation/timer/timer.c b/test/validation/timer/timer.c
> index 645dc58..dda5e4c 100644
> --- a/test/validation/timer/timer.c
> +++ b/test/validation/timer/timer.c
> @@ -145,9 +145,9 @@ void timer_test_odp_timer_cancel(void)
>   	if (pool == ODP_POOL_INVALID)
>   		CU_FAIL_FATAL("Timeout pool create failed");
>   
> -	tparam.res_ns     = 100 * ODP_TIME_MSEC;
> -	tparam.min_tmo    = 1   * ODP_TIME_SEC;
> -	tparam.max_tmo    = 10  * ODP_TIME_SEC;
> +	tparam.res_ns     = 100 * ODP_TIME_MSEC_IN_NS;
> +	tparam.min_tmo    = 1   * ODP_TIME_SEC_IN_NS;
> +	tparam.max_tmo    = 10  * ODP_TIME_SEC_IN_NS;
>   	tparam.num_timers = 1;
>   	tparam.priv       = 0;
>   	tparam.clk_src    = ODP_CLOCK_CPU;
> @@ -171,7 +171,7 @@ void timer_test_odp_timer_cancel(void)
>   	if (ev == ODP_EVENT_INVALID)
>   		CU_FAIL_FATAL("Failed to allocate timeout");
>   
> -	tick = odp_timer_ns_to_tick(tp, 2 * ODP_TIME_SEC);
> +	tick = odp_timer_ns_to_tick(tp, 2 * ODP_TIME_SEC_IN_NS);
>   
>   	rc = odp_timer_set_rel(tim, tick, &ev);
>   	if (rc != ODP_TIMER_SUCCESS)
> @@ -457,9 +457,9 @@ void timer_test_odp_timer_all(void)
>   		CU_FAIL_FATAL("Timeout pool create failed");
>   
>   #define NAME "timer_pool"
> -#define RES (10 * ODP_TIME_MSEC / 3)
> -#define MIN (10 * ODP_TIME_MSEC / 3)
> -#define MAX (1000000 * ODP_TIME_MSEC)
> +#define RES (10 * ODP_TIME_MSEC_IN_NS / 3)
> +#define MIN (10 * ODP_TIME_MSEC_IN_NS / 3)
> +#define MAX (1000000 * ODP_TIME_MSEC_IN_NS)
>   	/* Create a timer pool */
>   	tparam.res_ns = RES;
>   	tparam.min_tmo = MIN;
Ivan Khoronzhuk Nov. 10, 2015, 8:33 a.m. UTC | #2
On 10.11.15 10:06, Maxim Uvarov wrote:
> this patch refers to odp_time_t which is defined in patch 4.
>
> and I have that error:
> ../../include/odp/api/time.h:52:1: error: unknown type name 'odp_time_t'
>   odp_time_t odp_time_local(void);
>
> Hole patches looks good for me. But or you need merge 3 and 4 or move that defines from 4 to 3.
>
> Please send updated version.
>
> Maxim.

Maxim, I've split it intentionally as implementation side and app side.
There is no harm to merge it with commit message from the 3-d patch.

>
> On 11/06/2015 16:08, Ivan Khoronzhuk wrote:
>> Current time API supposes that frequency of counter is equal
>> to CPU frequency. But that's not always true, for instance,
>> in case if no access to CPU cycle counter, another hi-resolution
>> timer can be used, and it`s rate can be different from CPU
>> rate. There is no big difference in which cycles to measure
>> time, the better hi-resolution timer the better measurements.
>> So, unbind CPU cycle counter from time API by eliminating word
>> "cycle" as it's believed to be used with CPU.
>>
>> Also add new opaque type for time odp_time_t, as it asks user to use
>> API and abstracts time from units. New odp_time_t requires several
>> additional API functions to be added:
>>
>> odp_time_t odp_time_sum(odp_time_t t1, odp_time_t t2);
>> int odp_time_cmp(odp_time_t t1, odp_time_t t2);
>> uint64_t odp_time_to_u64(odp_time_t hdl);
>>
>> Also added new definition that represents 0 ticks for time -
>> ODP_TIME_NULL. It can be used instead of odp_time_from_ns(0) for
>> comparison and initialization.
>>
>> This patch changes only used time API, it doesn't change used var
>> names for simplicity.
>>
>> This time API can be implemented with local timer counter, so
>> shouldn't be used between threads.
>>
>> Signed-off-by: Ivan Khoronzhuk <ivan.khoronzhuk@linaro.org>
>> ---
>>   example/generator/odp_generator.c                  | 16 ++---
>>   example/timer/odp_timer_test.c                     | 10 +--
>>   include/odp/api/time.h                             | 77 +++++++++++++++++-----
>>   test/performance/odp_l2fwd.c                       |  2 +-
>>   test/performance/odp_pktio_perf.c                  | 55 +++++++++-------
>>   .../classification/odp_classification_test_pmr.c   | 20 +++---
>>   .../classification/odp_classification_tests.c      | 14 ++--
>>   test/validation/pktio/pktio.c                      | 31 ++++-----
>>   test/validation/scheduler/scheduler.c              |  5 +-
>>   test/validation/time/time.c                        | 27 ++++----
>>   test/validation/timer/timer.c                      | 14 ++--
>>   11 files changed, 162 insertions(+), 109 deletions(-)
>>
>> diff --git a/example/generator/odp_generator.c b/example/generator/odp_generator.c
>> index dd30403..d476240 100644
>> --- a/example/generator/odp_generator.c
>> +++ b/example/generator/odp_generator.c
>> @@ -586,7 +586,7 @@ static void *gen_recv_thread(void *arg)
>>    */
>>   static void print_global_stats(int num_workers)
>>   {
>> -    uint64_t start, wait, diff;
>> +    odp_time_t start, wait, diff;
>>       uint64_t pkts, pkts_prev = 0, pps, maximum_pps = 0;
>>       int verbose_interval = 20;
>>       odp_thrmask_t thrd_mask;
>> @@ -594,8 +594,8 @@ static void print_global_stats(int num_workers)
>>       while (odp_thrmask_worker(&thrd_mask) < num_workers)
>>           continue;
>> -    wait = odp_time_ns_to_cycles(verbose_interval * ODP_TIME_SEC);
>> -    start = odp_time_cycles();
>> +    wait = odp_time_local_from_ns(verbose_interval * ODP_TIME_SEC_IN_NS);
>> +    start = odp_time_local();
>>       while (odp_thrmask_worker(&thrd_mask) == num_workers) {
>>           if (args->appl.number != -1 &&
>> @@ -604,11 +604,11 @@ static void print_global_stats(int num_workers)
>>               break;
>>           }
>> -        diff = odp_time_diff_cycles(start, odp_time_cycles());
>> -        if (diff < wait)
>> +        diff = odp_time_diff(start, odp_time_local());
>> +        if (odp_time_cmp(wait, diff) > 0)
>>               continue;
>> -        start = odp_time_cycles();
>> +        start = odp_time_local();
>>           if (args->appl.mode == APPL_MODE_RCV) {
>>               pkts = odp_atomic_load_u64(&counters.udp);
>> @@ -730,9 +730,9 @@ int main(int argc, char *argv[])
>>       odp_pool_print(pool);
>>       /* Create timer pool */
>> -    tparams.res_ns = 1 * ODP_TIME_MSEC;
>> +    tparams.res_ns = 1 * ODP_TIME_MSEC_IN_NS;
>>       tparams.min_tmo = 0;
>> -    tparams.max_tmo = 10000 * ODP_TIME_SEC;
>> +    tparams.max_tmo = 10000 * ODP_TIME_SEC_IN_NS;
>>       tparams.num_timers = num_workers; /* One timer per worker */
>>       tparams.priv = 0; /* Shared */
>>       tparams.clk_src = ODP_CLOCK_CPU;
>> diff --git a/example/timer/odp_timer_test.c b/example/timer/odp_timer_test.c
>> index d3f2ca0..7d305cd 100644
>> --- a/example/timer/odp_timer_test.c
>> +++ b/example/timer/odp_timer_test.c
>> @@ -95,7 +95,7 @@ static void test_abs_timeouts(int thr, test_globals_t *gbls)
>>       queue = odp_queue_lookup("timer_queue");
>> -    period_ns = gbls->args.period_us*ODP_TIME_USEC;
>> +    period_ns = gbls->args.period_us * ODP_TIME_USEC_IN_NS;
>>       period    = odp_timer_ns_to_tick(gbls->tp, period_ns);
>>       EXAMPLE_DBG("  [%i] period %"PRIu64" ticks,  %"PRIu64" ns\n", thr,
>> @@ -408,9 +408,9 @@ int main(int argc, char *argv[])
>>           return -1;
>>       }
>> -    tparams.res_ns = gbls->args.resolution_us*ODP_TIME_USEC;
>> -    tparams.min_tmo = gbls->args.min_us*ODP_TIME_USEC;
>> -    tparams.max_tmo = gbls->args.max_us*ODP_TIME_USEC;
>> +    tparams.res_ns = gbls->args.resolution_us * ODP_TIME_USEC_IN_NS;
>> +    tparams.min_tmo = gbls->args.min_us * ODP_TIME_USEC_IN_NS;
>> +    tparams.max_tmo = gbls->args.max_us * ODP_TIME_USEC_IN_NS;
>>       tparams.num_timers = num_workers; /* One timer per worker */
>>       tparams.priv = 0; /* Shared */
>>       tparams.clk_src = ODP_CLOCK_CPU;
>> @@ -455,7 +455,7 @@ int main(int argc, char *argv[])
>>       printf("  %12" PRIu64 " ticks   ->  %12" PRIu64 " ns\n", tick,
>>              odp_timer_tick_to_ns(gbls->tp, tick));
>> -    for (ns = 1; ns <= 100*ODP_TIME_SEC; ns *= 10) {
>> +    for (ns = 1; ns <= 100 * ODP_TIME_SEC_IN_NS; ns *= 10) {
>>           tick = odp_timer_ns_to_tick(gbls->tp, ns);
>>           printf("  %12" PRIu64 " ns      ->  %12" PRIu64 " ticks\n", ns,
>> diff --git a/include/odp/api/time.h b/include/odp/api/time.h
>> index b0072fc..f119733 100644
>> --- a/include/odp/api/time.h
>> +++ b/include/odp/api/time.h
>> @@ -24,18 +24,32 @@ extern "C" {
>>    */
>>   /* Time in nanoseconds */
>> -#define ODP_TIME_USEC 1000ULL       /**< Microsecond in nsec */
>> -#define ODP_TIME_MSEC 1000000ULL    /**< Millisecond in nsec */
>> -#define ODP_TIME_SEC  1000000000ULL /**< Second in nsec */
>> +#define ODP_TIME_USEC_IN_NS    1000ULL       /**< Microsecond in nsec */
>> +#define ODP_TIME_MSEC_IN_NS    1000000ULL    /**< Millisecond in nsec */
>> +#define ODP_TIME_SEC_IN_NS    1000000000ULL /**< Second in nsec */
>> +/**
>> + * @typedef odp_time_t
>> + * ODP time stamp. Time stamp can represent a time stamp from local or global
>> + * time source. A local time stamp must not be shared between threads. API calls
>> + * work correctly only when all time stamps for input are from the same time
>> + * source.
>> + */
>>   /**
>> - * Current time in CPU cycles
>> - *
>> - * @return Current time in CPU cycles
>> + * @def ODP_TIME_NULL
>> + * Zero time stamp
>>    */
>> -uint64_t odp_time_cycles(void);
>> +/**
>> + * Current local time
>> + *
>> + * Returns current local time stamp value. The local time source provides high
>> + * resolution time.
>> + *
>> + * @return Local time stamp.
>> + */
>> +odp_time_t odp_time_local(void);
>>   /**
>>    * Time difference
>> @@ -43,29 +57,60 @@ uint64_t odp_time_cycles(void);
>>    * @param t1    First time stamp
>>    * @param t2    Second time stamp
>>    *
>> - * @return Difference of time stamps in CPU cycles
>> + * @return Difference of time stamps
>>    */
>> -uint64_t odp_time_diff_cycles(uint64_t t1, uint64_t t2);
>> +odp_time_t odp_time_diff(odp_time_t t1, odp_time_t t2);
>> +/**
>> + * Time sum
>> + *
>> + * @param t1    Time stamp
>> + * @param t2    Time stamp
>> + *
>> + * @return Sum of time stamps
>> + */
>> +odp_time_t odp_time_sum(odp_time_t t1, odp_time_t t2);
>>   /**
>> - * Convert CPU cycles to nanoseconds
>> + * Convert time to nanoseconds
>>    *
>> - * @param cycles  Time in CPU cycles
>> + * @param time  Time
>>    *
>>    * @return Time in nanoseconds
>>    */
>> -uint64_t odp_time_cycles_to_ns(uint64_t cycles);
>> +uint64_t odp_time_to_ns(odp_time_t time);
>> +/**
>> + * Convert nanoseconds to local time
>> + *
>> + * @param ns    Time in nanoseconds
>> + *
>> + * @return Local time stamp
>> + */
>> +odp_time_t odp_time_local_from_ns(uint64_t ns);
>> +
>> +/**
>> + * Compare two times
>> + *
>> + * @param t2    Second time
>> + * @param t1    First time
>> + *
>> + * @retval <0 if t2 < t1, >0 if t1 = t2, 1 if t2 > t1
>> + */
>> +int odp_time_cmp(odp_time_t t2, odp_time_t t1);
>>   /**
>> - * Convert nanoseconds to CPU cycles
>> + * Get printable value for an odp_time_t
>> + *
>> + * @param time time to be printed
>>    *
>> - * @param ns      Time in nanoseconds
>> + * @return uint64_t value that can be used to print/display this time
>>    *
>> - * @return Time in CPU cycles
>> + * @note This routine is intended to be used for diagnostic purposes
>> + * to enable applications to generate a printable value that represents
>> + * an odp_time_t time.
>>    */
>> -uint64_t odp_time_ns_to_cycles(uint64_t ns);
>> +uint64_t odp_time_to_u64(odp_time_t time);
>>   /**
>>    * @}
>> diff --git a/test/performance/odp_l2fwd.c b/test/performance/odp_l2fwd.c
>> index f7ccdce..d201186 100644
>> --- a/test/performance/odp_l2fwd.c
>> +++ b/test/performance/odp_l2fwd.c
>> @@ -157,7 +157,7 @@ static void *pktio_queue_thread(void *arg)
>>       printf("[%02i] QUEUE mode\n", thr);
>>       odp_barrier_wait(&barrier);
>> -    wait = odp_schedule_wait_time(ODP_TIME_MSEC * 100);
>> +    wait = odp_schedule_wait_time(ODP_TIME_MSEC_IN_NS * 100);
>>       /* Loop packets */
>>       while (!exit_threads) {
>> diff --git a/test/performance/odp_pktio_perf.c b/test/performance/odp_pktio_perf.c
>> index ae5b4c0..2d64b40 100644
>> --- a/test/performance/odp_pktio_perf.c
>> +++ b/test/performance/odp_pktio_perf.c
>> @@ -50,7 +50,7 @@
>>   /* Amount of time to wait, in nanoseconds, between the transmitter(s)
>>    * completing and the receiver(s) being shutdown. Any packets not
>>    * received by this time will be assumed to have been lost. */
>> -#define SHUTDOWN_DELAY_NS (ODP_TIME_MSEC*100)
>> +#define SHUTDOWN_DELAY_NS (ODP_TIME_MSEC_IN_NS * 100)
>>   #define VPRINT(fmt, ...) \
>>       do { \
>> @@ -106,7 +106,7 @@ struct tx_stats_s {
>>       uint64_t tx_cnt;    /* Packets transmitted */
>>       uint64_t alloc_failures;/* Packet allocation failures */
>>       uint64_t enq_failures;    /* Enqueue failures */
>> -    uint64_t idle_cycles;    /* Idle cycle count in TX loop */
>> +    odp_time_t idle_cycles;    /* Idle cycle count in TX loop */
>>   };
>>   typedef union tx_stats_u {
>> @@ -305,12 +305,12 @@ static void *run_thread_tx(void *arg)
>>       int thr_id;
>>       odp_queue_t outq;
>>       pkt_tx_stats_t *stats;
>> -    uint64_t burst_start_cycles, start_cycles, cur_cycles, send_duration;
>> -    uint64_t burst_gap_cycles;
>> +    odp_time_t start_cycles, cur_cycles, send_duration;
>> +    odp_time_t burst_start_cycles, burst_gap_cycles;
>>       uint32_t batch_len;
>>       int unsent_pkts = 0;
>>       odp_event_t  tx_event[BATCH_LEN_MAX];
>> -    uint64_t idle_start = 0;
>> +    odp_time_t idle_start = ODP_TIME_NULL;
>>       thread_args_t *targs = arg;
>> @@ -328,30 +328,34 @@ static void *run_thread_tx(void *arg)
>>       if (outq == ODP_QUEUE_INVALID)
>>           LOG_ABORT("Failed to get output queue for thread %d\n", thr_id);
>> -    burst_gap_cycles = odp_time_ns_to_cycles(
>> -                ODP_TIME_SEC / (targs->pps / targs->batch_len));
>> -    send_duration = odp_time_ns_to_cycles(targs->duration * ODP_TIME_SEC);
>> +    burst_gap_cycles = odp_time_local_from_ns(
>> +            ODP_TIME_SEC_IN_NS / (targs->pps / targs->batch_len));
>> +    send_duration =
>> +        odp_time_local_from_ns(targs->duration * ODP_TIME_SEC_IN_NS);
>>       odp_barrier_wait(&globals->tx_barrier);
>> -    cur_cycles     = odp_time_cycles();
>> +    cur_cycles     = odp_time_local();
>>       start_cycles   = cur_cycles;
>> -    burst_start_cycles = odp_time_diff_cycles(burst_gap_cycles, cur_cycles);
>> -    while (odp_time_diff_cycles(start_cycles, cur_cycles) < send_duration) {
>> +    burst_start_cycles = odp_time_diff(burst_gap_cycles, cur_cycles);
>> +    while (odp_time_diff(start_cycles, cur_cycles) < send_duration) {
>>           unsigned alloc_cnt = 0, tx_cnt;
>> -        if (odp_time_diff_cycles(burst_start_cycles, cur_cycles)
>> +        if (odp_time_diff(burst_start_cycles, cur_cycles)
>>                               < burst_gap_cycles) {
>> -            cur_cycles = odp_time_cycles();
>> -            if (idle_start == 0)
>> +            cur_cycles = odp_time_local();
>> +            if (!odp_time_cmp(idle_start, ODP_TIME_NULL))
>>                   idle_start = cur_cycles;
>>               continue;
>>           }
>> -        if (idle_start) {
>> -            stats->s.idle_cycles += odp_time_diff_cycles(
>> -                            idle_start, cur_cycles);
>> -            idle_start = 0;
>> +        if (odp_time_cmp(idle_start, ODP_TIME_NULL)) {
>> +            odp_time_t diff = odp_time_diff(idle_start, cur_cycles);
>> +
>> +            stats->s.idle_cycles =
>> +                odp_time_sum(diff, stats->s.idle_cycles);
>> +
>> +            idle_start = ODP_TIME_NULL;
>>           }
>>           burst_start_cycles += burst_gap_cycles;
>> @@ -365,14 +369,15 @@ static void *run_thread_tx(void *arg)
>>           stats->s.enq_failures += unsent_pkts;
>>           stats->s.tx_cnt += tx_cnt;
>> -        cur_cycles = odp_time_cycles();
>> +        cur_cycles = odp_time_local();
>>       }
>>       VPRINT(" %02d: TxPkts %-8"PRIu64" EnqFail %-6"PRIu64
>>              " AllocFail %-6"PRIu64" Idle %"PRIu64"ms\n",
>>              thr_id, stats->s.tx_cnt,
>>              stats->s.enq_failures, stats->s.alloc_failures,
>> -           odp_time_cycles_to_ns(stats->s.idle_cycles)/1000/1000);
>> +           odp_time_to_ns(stats->s.idle_cycles) /
>> +           (uint64_t)ODP_TIME_MSEC_IN_NS);
>>       return NULL;
>>   }
>> @@ -591,13 +596,13 @@ static int setup_txrx_masks(odp_cpumask_t *thd_mask_tx,
>>    */
>>   static void busy_loop_ns(uint64_t wait_ns)
>>   {
>> -    uint64_t diff;
>> -    uint64_t start_time = odp_time_cycles();
>> -    uint64_t wait = odp_time_ns_to_cycles(wait_ns);
>> +    odp_time_t diff;
>> +    odp_time_t start_time = odp_time_local();
>> +    odp_time_t wait = odp_time_local_from_ns(wait_ns);
>>       do {
>> -        diff = odp_time_diff_cycles(start_time, odp_time_cycles());
>> -    } while (diff < wait);
>> +        diff = odp_time_diff(start_time, odp_time_local());
>> +    } while (odp_time_cmp(wait, diff) > 0);
>>   }
>>   /*
>> diff --git a/test/validation/classification/odp_classification_test_pmr.c b/test/validation/classification/odp_classification_test_pmr.c
>> index 73ba6f5..3f49d4c 100644
>> --- a/test/validation/classification/odp_classification_test_pmr.c
>> +++ b/test/validation/classification/odp_classification_test_pmr.c
>> @@ -168,7 +168,7 @@ static void classification_test_pmr_term_tcp_dport(void)
>>       enqueue_pktio_interface(pkt, pktio);
>> -    pkt = receive_packet(&retqueue, ODP_TIME_SEC);
>> +    pkt = receive_packet(&retqueue, ODP_TIME_SEC_IN_NS);
>>       CU_ASSERT(pkt != ODP_PACKET_INVALID);
>>       CU_ASSERT(retqueue == queue);
>>       CU_ASSERT(seqno == cls_pkt_get_seq(pkt));
>> @@ -185,7 +185,7 @@ static void classification_test_pmr_term_tcp_dport(void)
>>       enqueue_pktio_interface(pkt, pktio);
>> -    pkt = receive_packet(&retqueue, ODP_TIME_SEC);
>> +    pkt = receive_packet(&retqueue, ODP_TIME_SEC_IN_NS);
>>       CU_ASSERT(pkt != ODP_PACKET_INVALID);
>>       CU_ASSERT(seqno == cls_pkt_get_seq(pkt));
>>       CU_ASSERT(retqueue == defqueue);
>> @@ -255,7 +255,7 @@ static void classification_test_pmr_term_tcp_sport(void)
>>       enqueue_pktio_interface(pkt, pktio);
>> -    pkt = receive_packet(&retqueue, ODP_TIME_SEC);
>> +    pkt = receive_packet(&retqueue, ODP_TIME_SEC_IN_NS);
>>       CU_ASSERT(pkt != ODP_PACKET_INVALID);
>>       CU_ASSERT(seqno == cls_pkt_get_seq(pkt));
>>       CU_ASSERT(retqueue == queue);
>> @@ -270,7 +270,7 @@ static void classification_test_pmr_term_tcp_sport(void)
>>       enqueue_pktio_interface(pkt, pktio);
>> -    pkt = receive_packet(&retqueue, ODP_TIME_SEC);
>> +    pkt = receive_packet(&retqueue, ODP_TIME_SEC_IN_NS);
>>       CU_ASSERT(pkt != ODP_PACKET_INVALID);
>>       CU_ASSERT(seqno == cls_pkt_get_seq(pkt));
>>       CU_ASSERT(retqueue == defqueue);
>> @@ -340,7 +340,7 @@ static void classification_test_pmr_term_udp_dport(void)
>>       enqueue_pktio_interface(pkt, pktio);
>> -    pkt = receive_packet(&retqueue, ODP_TIME_SEC);
>> +    pkt = receive_packet(&retqueue, ODP_TIME_SEC_IN_NS);
>>       CU_ASSERT(pkt != ODP_PACKET_INVALID);
>>       CU_ASSERT(seqno == cls_pkt_get_seq(pkt));
>>       CU_ASSERT(retqueue == queue);
>> @@ -356,7 +356,7 @@ static void classification_test_pmr_term_udp_dport(void)
>>       enqueue_pktio_interface(pkt, pktio);
>> -    pkt = receive_packet(&retqueue, ODP_TIME_SEC);
>> +    pkt = receive_packet(&retqueue, ODP_TIME_SEC_IN_NS);
>>       CU_ASSERT(pkt != ODP_PACKET_INVALID);
>>       CU_ASSERT(seqno == cls_pkt_get_seq(pkt));
>>       CU_ASSERT(retqueue == defqueue);
>> @@ -426,7 +426,7 @@ static void classification_test_pmr_term_udp_sport(void)
>>       enqueue_pktio_interface(pkt, pktio);
>> -    pkt = receive_packet(&retqueue, ODP_TIME_SEC);
>> +    pkt = receive_packet(&retqueue, ODP_TIME_SEC_IN_NS);
>>       CU_ASSERT(pkt != ODP_PACKET_INVALID);
>>       CU_ASSERT(seqno == cls_pkt_get_seq(pkt));
>>       CU_ASSERT(retqueue == queue);
>> @@ -441,7 +441,7 @@ static void classification_test_pmr_term_udp_sport(void)
>>       enqueue_pktio_interface(pkt, pktio);
>> -    pkt = receive_packet(&retqueue, ODP_TIME_SEC);
>> +    pkt = receive_packet(&retqueue, ODP_TIME_SEC_IN_NS);
>>       CU_ASSERT(pkt != ODP_PACKET_INVALID);
>>       CU_ASSERT(seqno == cls_pkt_get_seq(pkt));
>>       CU_ASSERT(retqueue == defqueue);
>> @@ -507,7 +507,7 @@ static void classification_test_pmr_term_ipproto(void)
>>       enqueue_pktio_interface(pkt, pktio);
>> -    pkt = receive_packet(&retqueue, ODP_TIME_SEC);
>> +    pkt = receive_packet(&retqueue, ODP_TIME_SEC_IN_NS);
>>       CU_ASSERT(pkt != ODP_PACKET_INVALID);
>>       CU_ASSERT(seqno == cls_pkt_get_seq(pkt));
>>       CU_ASSERT(retqueue == queue);
>> @@ -520,7 +520,7 @@ static void classification_test_pmr_term_ipproto(void)
>>       enqueue_pktio_interface(pkt, pktio);
>> -    pkt = receive_packet(&retqueue, ODP_TIME_SEC);
>> +    pkt = receive_packet(&retqueue, ODP_TIME_SEC_IN_NS);
>>       CU_ASSERT(pkt != ODP_PACKET_INVALID);
>>       CU_ASSERT(seqno == cls_pkt_get_seq(pkt));
>>       CU_ASSERT(retqueue == defqueue);
>> diff --git a/test/validation/classification/odp_classification_tests.c b/test/validation/classification/odp_classification_tests.c
>> index 823e30f..3944d94 100644
>> --- a/test/validation/classification/odp_classification_tests.c
>> +++ b/test/validation/classification/odp_classification_tests.c
>> @@ -225,7 +225,7 @@ void test_cls_pmr_chain(void)
>>       enqueue_pktio_interface(pkt, pktio_loop);
>> -    pkt = receive_packet(&queue, ODP_TIME_SEC);
>> +    pkt = receive_packet(&queue, ODP_TIME_SEC_IN_NS);
>>       CU_ASSERT(pkt != ODP_PACKET_INVALID);
>>       CU_ASSERT(queue == queue_list[CLS_PMR_CHAIN_DST]);
>>       CU_ASSERT(seqno == cls_pkt_get_seq(pkt));
>> @@ -242,7 +242,7 @@ void test_cls_pmr_chain(void)
>>       ip->chksum = odph_ipv4_csum_update(pkt);
>>       enqueue_pktio_interface(pkt, pktio_loop);
>> -    pkt = receive_packet(&queue, ODP_TIME_SEC);
>> +    pkt = receive_packet(&queue, ODP_TIME_SEC_IN_NS);
>>       CU_ASSERT(pkt != ODP_PACKET_INVALID);
>>       CU_ASSERT(queue == queue_list[CLS_PMR_CHAIN_SRC]);
>>       CU_ASSERT(seqno == cls_pkt_get_seq(pkt));
>> @@ -289,7 +289,7 @@ void test_pktio_default_cos(void)
>>       enqueue_pktio_interface(pkt, pktio_loop);
>> -    pkt = receive_packet(&queue, ODP_TIME_SEC);
>> +    pkt = receive_packet(&queue, ODP_TIME_SEC_IN_NS);
>>       CU_ASSERT(pkt != ODP_PACKET_INVALID);
>>       /* Default packet should be received in default queue */
>>       CU_ASSERT(queue == queue_list[CLS_DEFAULT]);
>> @@ -341,7 +341,7 @@ void test_pktio_error_cos(void)
>>       ip->chksum = 0;
>>       enqueue_pktio_interface(pkt, pktio_loop);
>> -    pkt = receive_packet(&queue, ODP_TIME_SEC);
>> +    pkt = receive_packet(&queue, ODP_TIME_SEC_IN_NS);
>>       CU_ASSERT(pkt != ODP_PACKET_INVALID);
>>       /* Error packet should be received in error queue */
>>       CU_ASSERT(queue == queue_list[CLS_ERROR]);
>> @@ -436,7 +436,7 @@ void test_cos_with_l2_priority(void)
>>           vlan = (odph_vlanhdr_t *)(&ethhdr->type);
>>           vlan->tci = odp_cpu_to_be_16(i << 13);
>>           enqueue_pktio_interface(pkt, pktio_loop);
>> -        pkt = receive_packet(&queue, ODP_TIME_SEC);
>> +        pkt = receive_packet(&queue, ODP_TIME_SEC_IN_NS);
>>           CU_ASSERT(pkt != ODP_PACKET_INVALID);
>>           CU_ASSERT(queue == queue_list[CLS_L2_QOS_0 + i]);
>>           CU_ASSERT(seqno == cls_pkt_get_seq(pkt));
>> @@ -501,7 +501,7 @@ void test_pmr_cos(void)
>>       udp = (odph_udphdr_t *)odp_packet_l4_ptr(pkt, NULL);
>>       udp->src_port = odp_cpu_to_be_16(CLS_PMR_SPORT);
>>       enqueue_pktio_interface(pkt, pktio_loop);
>> -    pkt = receive_packet(&queue, ODP_TIME_SEC);
>> +    pkt = receive_packet(&queue, ODP_TIME_SEC_IN_NS);
>>       CU_ASSERT(pkt != ODP_PACKET_INVALID);
>>       CU_ASSERT(queue == queue_list[CLS_PMR]);
>>       CU_ASSERT(seqno == cls_pkt_get_seq(pkt));
>> @@ -585,7 +585,7 @@ void test_pktio_pmr_match_set_cos(void)
>>       udp = (odph_udphdr_t *)odp_packet_l4_ptr(pkt, NULL);
>>       udp->src_port = odp_cpu_to_be_16(CLS_PMR_SET_SPORT);
>>       enqueue_pktio_interface(pkt, pktio_loop);
>> -    pkt = receive_packet(&queue, ODP_TIME_SEC);
>> +    pkt = receive_packet(&queue, ODP_TIME_SEC_IN_NS);
>>       CU_ASSERT(pkt != ODP_PACKET_INVALID);
>>       CU_ASSERT(queue == queue_list[CLS_PMR_SET]);
>>       CU_ASSERT(seqno == cls_pkt_get_seq(pkt));
>> diff --git a/test/validation/pktio/pktio.c b/test/validation/pktio/pktio.c
>> index b3738ce..9435a22 100644
>> --- a/test/validation/pktio/pktio.c
>> +++ b/test/validation/pktio/pktio.c
>> @@ -336,18 +336,18 @@ static int destroy_inq(odp_pktio_t pktio)
>>   static odp_event_t queue_deq_wait_time(odp_queue_t queue, uint64_t ns)
>>   {
>> -    uint64_t start, now, diff;
>> +    odp_time_t start, now, diff;
>>       odp_event_t ev;
>> -    start = odp_time_cycles();
>> +    start = odp_time_local();
>>       do {
>>           ev = odp_queue_deq(queue);
>>           if (ev != ODP_EVENT_INVALID)
>>               return ev;
>> -        now = odp_time_cycles();
>> -        diff = odp_time_diff_cycles(start, now);
>> -    } while (odp_time_cycles_to_ns(diff) < ns);
>> +        now = odp_time_local();
>> +        diff = odp_time_diff(start, now);
>> +    } while (odp_time_to_ns(diff) < ns);
>>       return ODP_EVENT_INVALID;
>>   }
>> @@ -355,12 +355,12 @@ static odp_event_t queue_deq_wait_time(odp_queue_t queue, uint64_t ns)
>>   static odp_packet_t wait_for_packet(pktio_info_t *pktio_rx,
>>                       uint32_t seq, uint64_t ns)
>>   {
>> -    uint64_t start, now, diff;
>> +    odp_time_t start, now, diff;
>>       odp_event_t ev;
>>       odp_packet_t pkt;
>>       uint64_t wait;
>> -    start = odp_time_cycles();
>> +    start = odp_time_local();
>>       wait = odp_schedule_wait_time(ns);
>>       do {
>> @@ -389,9 +389,9 @@ static odp_packet_t wait_for_packet(pktio_info_t *pktio_rx,
>>               odp_packet_free(pkt);
>>           }
>> -        now = odp_time_cycles();
>> -        diff = odp_time_diff_cycles(start, now);
>> -    } while (odp_time_cycles_to_ns(diff) < ns);
>> +        now = odp_time_local();
>> +        diff = odp_time_diff(start, now);
>> +    } while (odp_time_to_ns(diff) < ns);
>>       CU_FAIL("failed to receive transmitted packet");
>> @@ -450,7 +450,8 @@ static void pktio_txrx_multi(pktio_info_t *pktio_a, pktio_info_t *pktio_b,
>>       /* and wait for them to arrive back */
>>       for (i = 0; i < num_pkts; ++i) {
>> -        rx_pkt = wait_for_packet(pktio_b, tx_seq[i], ODP_TIME_SEC);
>> +        rx_pkt = wait_for_packet(pktio_b, tx_seq[i],
>> +                     ODP_TIME_SEC_IN_NS);
>>           if (rx_pkt == ODP_PACKET_INVALID)
>>               break;
>> @@ -627,7 +628,7 @@ void pktio_test_inq_remdef(void)
>>       CU_ASSERT(inq != ODP_QUEUE_INVALID);
>>       CU_ASSERT(odp_pktio_inq_remdef(pktio) == 0);
>> -    wait = odp_schedule_wait_time(ODP_TIME_MSEC);
>> +    wait = odp_schedule_wait_time(ODP_TIME_MSEC_IN_NS);
>>       for (i = 0; i < 100; i++) {
>>           ev = odp_schedule(NULL, wait);
>>           if (ev != ODP_EVENT_INVALID) {
>> @@ -703,7 +704,7 @@ static void pktio_test_start_stop(void)
>>       odp_event_t ev;
>>       int i, pkts, ret, alloc = 0;
>>       odp_queue_t outq;
>> -    uint64_t wait = odp_schedule_wait_time(ODP_TIME_MSEC);
>> +    uint64_t wait = odp_schedule_wait_time(ODP_TIME_MSEC_IN_NS);
>>       for (i = 0; i < num_ifaces; i++) {
>>           pktio[i] = create_pktio(i, ODP_PKTIN_MODE_SCHED);
>> @@ -918,8 +919,8 @@ static void pktio_test_send_failure(void)
>>           info_rx.in_mode = ODP_PKTIN_MODE_RECV;
>>           for (i = 0; i < ret; ++i) {
>> -            pkt_tbl[i] = wait_for_packet(&info_rx,
>> -                             pkt_seq[i], ODP_TIME_SEC);
>> +            pkt_tbl[i] = wait_for_packet(&info_rx, pkt_seq[i],
>> +                             ODP_TIME_SEC_IN_NS);
>>               if (pkt_tbl[i] == ODP_PACKET_INVALID)
>>                   break;
>>           }
>> diff --git a/test/validation/scheduler/scheduler.c b/test/validation/scheduler/scheduler.c
>> index 042d7b4..e813f82 100644
>> --- a/test/validation/scheduler/scheduler.c
>> +++ b/test/validation/scheduler/scheduler.c
>> @@ -514,10 +514,11 @@ static void *schedule_common_(void *arg)
>>               CU_ASSERT(from != ODP_QUEUE_INVALID);
>>               if (locked) {
>>                   int cnt;
>> -                uint64_t cycles = 0;
>> +                odp_time_t cycles = ODP_TIME_NULL;
>>                   /* Do some work here to keep the thread busy */
>>                   for (cnt = 0; cnt < 1000; cnt++)
>> -                    cycles += odp_time_cycles();
>> +                    cycles = odp_time_sum(cycles,
>> +                                  odp_time_local());
>>                   odp_spinlock_unlock(&globals->atomic_lock);
>>               }
>> diff --git a/test/validation/time/time.c b/test/validation/time/time.c
>> index 41db0e9..231f50e 100644
>> --- a/test/validation/time/time.c
>> +++ b/test/validation/time/time.c
>> @@ -16,43 +16,44 @@ void time_test_odp_cycles_diff(void)
>>   {
>>       /* volatile to stop optimization of busy loop */
>>       volatile int count = 0;
>> -    uint64_t diff, cycles1, cycles2;
>> +    odp_time_t diff, cycles1, cycles2;
>> -    cycles1 = odp_time_cycles();
>> +    cycles1 = odp_time_local();
>>       while (count < BUSY_LOOP_CNT) {
>>           count++;
>>       };
>> -    cycles2 = odp_time_cycles();
>> -    CU_ASSERT(cycles2 > cycles1);
>> +    cycles2 = odp_time_local();
>> +    CU_ASSERT((odp_time_cmp(cycles2, cycles1) > 0));
>> -    diff = odp_time_diff_cycles(cycles1, cycles2);
>> -    CU_ASSERT(diff > 0);
>> +    diff = odp_time_diff(cycles1, cycles2);
>> +    CU_ASSERT(odp_time_cmp(diff, ODP_TIME_NULL) > 0);
>>   }
>>   /* check that a negative cycles difference gives a reasonable result */
>>   void time_test_odp_cycles_negative_diff(void)
>>   {
>> -    uint64_t diff, cycles1, cycles2;
>> +    odp_time_t diff, cycles1, cycles2;
>>       cycles1 = 10;
>>       cycles2 = 5;
>> -    diff = odp_time_diff_cycles(cycles1, cycles2);
>> -    CU_ASSERT(diff > 0);
>> +    diff = odp_time_diff(cycles1, cycles2);
>> +    CU_ASSERT(odp_time_cmp(diff, ODP_TIME_NULL) > 0);
>>   }
>>   /* check that related conversions come back to the same value */
>>   void time_test_odp_time_conversion(void)
>>   {
>> -    uint64_t ns1, ns2, cycles;
>> +    uint64_t ns1, ns2;
>> +    odp_time_t cycles;
>>       uint64_t upper_limit, lower_limit;
>>       ns1 = 100;
>> -    cycles = odp_time_ns_to_cycles(ns1);
>> -    CU_ASSERT(cycles > 0);
>> +    cycles = odp_time_local_from_ns(ns1);
>> +    CU_ASSERT(odp_time_cmp(cycles, ODP_TIME_NULL) > 0);
>> -    ns2 = odp_time_cycles_to_ns(cycles);
>> +    ns2 = odp_time_to_ns(cycles);
>>       /* need to check within arithmetic tolerance that the same
>>        * value in ns is returned after conversions */
>> diff --git a/test/validation/timer/timer.c b/test/validation/timer/timer.c
>> index 645dc58..dda5e4c 100644
>> --- a/test/validation/timer/timer.c
>> +++ b/test/validation/timer/timer.c
>> @@ -145,9 +145,9 @@ void timer_test_odp_timer_cancel(void)
>>       if (pool == ODP_POOL_INVALID)
>>           CU_FAIL_FATAL("Timeout pool create failed");
>> -    tparam.res_ns     = 100 * ODP_TIME_MSEC;
>> -    tparam.min_tmo    = 1   * ODP_TIME_SEC;
>> -    tparam.max_tmo    = 10  * ODP_TIME_SEC;
>> +    tparam.res_ns     = 100 * ODP_TIME_MSEC_IN_NS;
>> +    tparam.min_tmo    = 1   * ODP_TIME_SEC_IN_NS;
>> +    tparam.max_tmo    = 10  * ODP_TIME_SEC_IN_NS;
>>       tparam.num_timers = 1;
>>       tparam.priv       = 0;
>>       tparam.clk_src    = ODP_CLOCK_CPU;
>> @@ -171,7 +171,7 @@ void timer_test_odp_timer_cancel(void)
>>       if (ev == ODP_EVENT_INVALID)
>>           CU_FAIL_FATAL("Failed to allocate timeout");
>> -    tick = odp_timer_ns_to_tick(tp, 2 * ODP_TIME_SEC);
>> +    tick = odp_timer_ns_to_tick(tp, 2 * ODP_TIME_SEC_IN_NS);
>>       rc = odp_timer_set_rel(tim, tick, &ev);
>>       if (rc != ODP_TIMER_SUCCESS)
>> @@ -457,9 +457,9 @@ void timer_test_odp_timer_all(void)
>>           CU_FAIL_FATAL("Timeout pool create failed");
>>   #define NAME "timer_pool"
>> -#define RES (10 * ODP_TIME_MSEC / 3)
>> -#define MIN (10 * ODP_TIME_MSEC / 3)
>> -#define MAX (1000000 * ODP_TIME_MSEC)
>> +#define RES (10 * ODP_TIME_MSEC_IN_NS / 3)
>> +#define MIN (10 * ODP_TIME_MSEC_IN_NS / 3)
>> +#define MAX (1000000 * ODP_TIME_MSEC_IN_NS)
>>       /* Create a timer pool */
>>       tparam.res_ns = RES;
>>       tparam.min_tmo = MIN;
>
> _______________________________________________
> lng-odp mailing list
> lng-odp@lists.linaro.org
> https://lists.linaro.org/mailman/listinfo/lng-odp
Ivan Khoronzhuk Nov. 10, 2015, 8:58 a.m. UTC | #3
On 10.11.15 10:45, Savolainen, Petri (Nokia - FI/Espoo) wrote:
>
>
>> -----Original Message-----
>> From: lng-odp [mailto:lng-odp-bounces@lists.linaro.org] On Behalf Of
>> EXT Ivan Khoronzhuk
>> Sent: Tuesday, November 10, 2015 10:34 AM
>> To: Maxim Uvarov; lng-odp@lists.linaro.org
>> Subject: Re: [lng-odp] [API-NEXT PATCH v8 3/6] api: time: unbind CPU
>> cycles from time API
>>
>>
>>
>> On 10.11.15 10:06, Maxim Uvarov wrote:
>>> this patch refers to odp_time_t which is defined in patch 4.
>>>
>>> and I have that error:
>>> ../../include/odp/api/time.h:52:1: error: unknown type name
>> 'odp_time_t'
>>>    odp_time_t odp_time_local(void);
>>>
>>> Hole patches looks good for me. But or you need merge 3 and 4 or move
>> that defines from 4 to 3.
>>>
>>> Please send updated version.
>>>
>>> Maxim.
>>
>> Maxim, I've split it intentionally as implementation side and app side.
>> There is no harm to merge it with commit message from the 3-d patch.
>>
>
> Every commit (patch) must build, pass validation tests and produce doxygen documentation without errors. Otherwise, it's hard to work with commits later on if there are commits in the repo which intentionally break the build.
>
> -Petri

Sure, and it concerns only linux-generic as base implementation.

>
>
>
>
>
>
Ivan Khoronzhuk Nov. 10, 2015, 9:17 a.m. UTC | #4
On 10.11.15 11:08, Savolainen, Petri (Nokia - FI/Espoo) wrote:
>
>
>> -----Original Message-----
>> From: EXT Ivan Khoronzhuk [mailto:ivan.khoronzhuk@linaro.org]
>> Sent: Tuesday, November 10, 2015 10:59 AM
>> To: Savolainen, Petri (Nokia - FI/Espoo); Maxim Uvarov; lng-
>> odp@lists.linaro.org
>> Subject: Re: [lng-odp] [API-NEXT PATCH v8 3/6] api: time: unbind CPU
>> cycles from time API
>>
>>
>>
>> On 10.11.15 10:45, Savolainen, Petri (Nokia - FI/Espoo) wrote:
>>>
>>>
>>>> -----Original Message-----
>>>> From: lng-odp [mailto:lng-odp-bounces@lists.linaro.org] On Behalf Of
>>>> EXT Ivan Khoronzhuk
>>>> Sent: Tuesday, November 10, 2015 10:34 AM
>>>> To: Maxim Uvarov; lng-odp@lists.linaro.org
>>>> Subject: Re: [lng-odp] [API-NEXT PATCH v8 3/6] api: time: unbind CPU
>>>> cycles from time API
>>>>
>>>>
>>>>
>>>> On 10.11.15 10:06, Maxim Uvarov wrote:
>>>>> this patch refers to odp_time_t which is defined in patch 4.
>>>>>
>>>>> and I have that error:
>>>>> ../../include/odp/api/time.h:52:1: error: unknown type name
>>>> 'odp_time_t'
>>>>>     odp_time_t odp_time_local(void);
>>>>>
>>>>> Hole patches looks good for me. But or you need merge 3 and 4 or
>> move
>>>> that defines from 4 to 3.
>>>>>
>>>>> Please send updated version.
>>>>>
>>>>> Maxim.
>>>>
>>>> Maxim, I've split it intentionally as implementation side and app
>> side.
>>>> There is no harm to merge it with commit message from the 3-d patch.
>>>>
>>>
>>> Every commit (patch) must build, pass validation tests and produce
>> doxygen documentation without errors. Otherwise, it's hard to work with
>> commits later on if there are commits in the repo which intentionally
>> break the build.
>>>
>>> -Petri
>>
>> Sure, and it concerns only linux-generic as base implementation.
>
> Linux-generic is our reference platform for API development. If patch 3 breaks our (reference)  build, you need to fix the patch set before it can be merged into repo.
>
> -Petri

As I sad, 3 and 4 can be squashed with commit from 3 while apply.
Maxim is OK, do you have some objection?

>
>
Maxim Uvarov Nov. 10, 2015, 9:19 a.m. UTC | #5
On 11/10/2015 12:17, Ivan Khoronzhuk wrote:
>
>
> On 10.11.15 11:08, Savolainen, Petri (Nokia - FI/Espoo) wrote:
>>
>>
>>> -----Original Message-----
>>> From: EXT Ivan Khoronzhuk [mailto:ivan.khoronzhuk@linaro.org]
>>> Sent: Tuesday, November 10, 2015 10:59 AM
>>> To: Savolainen, Petri (Nokia - FI/Espoo); Maxim Uvarov; lng-
>>> odp@lists.linaro.org
>>> Subject: Re: [lng-odp] [API-NEXT PATCH v8 3/6] api: time: unbind CPU
>>> cycles from time API
>>>
>>>
>>>
>>> On 10.11.15 10:45, Savolainen, Petri (Nokia - FI/Espoo) wrote:
>>>>
>>>>
>>>>> -----Original Message-----
>>>>> From: lng-odp [mailto:lng-odp-bounces@lists.linaro.org] On Behalf Of
>>>>> EXT Ivan Khoronzhuk
>>>>> Sent: Tuesday, November 10, 2015 10:34 AM
>>>>> To: Maxim Uvarov; lng-odp@lists.linaro.org
>>>>> Subject: Re: [lng-odp] [API-NEXT PATCH v8 3/6] api: time: unbind CPU
>>>>> cycles from time API
>>>>>
>>>>>
>>>>>
>>>>> On 10.11.15 10:06, Maxim Uvarov wrote:
>>>>>> this patch refers to odp_time_t which is defined in patch 4.
>>>>>>
>>>>>> and I have that error:
>>>>>> ../../include/odp/api/time.h:52:1: error: unknown type name
>>>>> 'odp_time_t'
>>>>>>     odp_time_t odp_time_local(void);
>>>>>>
>>>>>> Hole patches looks good for me. But or you need merge 3 and 4 or
>>> move
>>>>> that defines from 4 to 3.
>>>>>>
>>>>>> Please send updated version.
>>>>>>
>>>>>> Maxim.
>>>>>
>>>>> Maxim, I've split it intentionally as implementation side and app
>>> side.
>>>>> There is no harm to merge it with commit message from the 3-d patch.
>>>>>
>>>>
>>>> Every commit (patch) must build, pass validation tests and produce
>>> doxygen documentation without errors. Otherwise, it's hard to work with
>>> commits later on if there are commits in the repo which intentionally
>>> break the build.
>>>>
>>>> -Petri
>>>
>>> Sure, and it concerns only linux-generic as base implementation.
>>
>> Linux-generic is our reference platform for API development. If patch 
>> 3 breaks our (reference)  build, you need to fix the patch set before 
>> it can be merged into repo.
>>
>> -Petri
>
> As I sad, 3 and 4 can be squashed with commit from 3 while apply.
> Maxim is OK, do you have some objection?

I will squash 3 and 4.

Maxim.
>
>>
>>
>
diff mbox

Patch

diff --git a/example/generator/odp_generator.c b/example/generator/odp_generator.c
index dd30403..d476240 100644
--- a/example/generator/odp_generator.c
+++ b/example/generator/odp_generator.c
@@ -586,7 +586,7 @@  static void *gen_recv_thread(void *arg)
  */
 static void print_global_stats(int num_workers)
 {
-	uint64_t start, wait, diff;
+	odp_time_t start, wait, diff;
 	uint64_t pkts, pkts_prev = 0, pps, maximum_pps = 0;
 	int verbose_interval = 20;
 	odp_thrmask_t thrd_mask;
@@ -594,8 +594,8 @@  static void print_global_stats(int num_workers)
 	while (odp_thrmask_worker(&thrd_mask) < num_workers)
 		continue;
 
-	wait = odp_time_ns_to_cycles(verbose_interval * ODP_TIME_SEC);
-	start = odp_time_cycles();
+	wait = odp_time_local_from_ns(verbose_interval * ODP_TIME_SEC_IN_NS);
+	start = odp_time_local();
 
 	while (odp_thrmask_worker(&thrd_mask) == num_workers) {
 		if (args->appl.number != -1 &&
@@ -604,11 +604,11 @@  static void print_global_stats(int num_workers)
 			break;
 		}
 
-		diff = odp_time_diff_cycles(start, odp_time_cycles());
-		if (diff < wait)
+		diff = odp_time_diff(start, odp_time_local());
+		if (odp_time_cmp(wait, diff) > 0)
 			continue;
 
-		start = odp_time_cycles();
+		start = odp_time_local();
 
 		if (args->appl.mode == APPL_MODE_RCV) {
 			pkts = odp_atomic_load_u64(&counters.udp);
@@ -730,9 +730,9 @@  int main(int argc, char *argv[])
 	odp_pool_print(pool);
 
 	/* Create timer pool */
-	tparams.res_ns = 1 * ODP_TIME_MSEC;
+	tparams.res_ns = 1 * ODP_TIME_MSEC_IN_NS;
 	tparams.min_tmo = 0;
-	tparams.max_tmo = 10000 * ODP_TIME_SEC;
+	tparams.max_tmo = 10000 * ODP_TIME_SEC_IN_NS;
 	tparams.num_timers = num_workers; /* One timer per worker */
 	tparams.priv = 0; /* Shared */
 	tparams.clk_src = ODP_CLOCK_CPU;
diff --git a/example/timer/odp_timer_test.c b/example/timer/odp_timer_test.c
index d3f2ca0..7d305cd 100644
--- a/example/timer/odp_timer_test.c
+++ b/example/timer/odp_timer_test.c
@@ -95,7 +95,7 @@  static void test_abs_timeouts(int thr, test_globals_t *gbls)
 
 	queue = odp_queue_lookup("timer_queue");
 
-	period_ns = gbls->args.period_us*ODP_TIME_USEC;
+	period_ns = gbls->args.period_us * ODP_TIME_USEC_IN_NS;
 	period    = odp_timer_ns_to_tick(gbls->tp, period_ns);
 
 	EXAMPLE_DBG("  [%i] period %"PRIu64" ticks,  %"PRIu64" ns\n", thr,
@@ -408,9 +408,9 @@  int main(int argc, char *argv[])
 		return -1;
 	}
 
-	tparams.res_ns = gbls->args.resolution_us*ODP_TIME_USEC;
-	tparams.min_tmo = gbls->args.min_us*ODP_TIME_USEC;
-	tparams.max_tmo = gbls->args.max_us*ODP_TIME_USEC;
+	tparams.res_ns = gbls->args.resolution_us * ODP_TIME_USEC_IN_NS;
+	tparams.min_tmo = gbls->args.min_us * ODP_TIME_USEC_IN_NS;
+	tparams.max_tmo = gbls->args.max_us * ODP_TIME_USEC_IN_NS;
 	tparams.num_timers = num_workers; /* One timer per worker */
 	tparams.priv = 0; /* Shared */
 	tparams.clk_src = ODP_CLOCK_CPU;
@@ -455,7 +455,7 @@  int main(int argc, char *argv[])
 	printf("  %12" PRIu64 " ticks   ->  %12" PRIu64 " ns\n", tick,
 	       odp_timer_tick_to_ns(gbls->tp, tick));
 
-	for (ns = 1; ns <= 100*ODP_TIME_SEC; ns *= 10) {
+	for (ns = 1; ns <= 100 * ODP_TIME_SEC_IN_NS; ns *= 10) {
 		tick = odp_timer_ns_to_tick(gbls->tp, ns);
 
 		printf("  %12" PRIu64 " ns      ->  %12" PRIu64 " ticks\n", ns,
diff --git a/include/odp/api/time.h b/include/odp/api/time.h
index b0072fc..f119733 100644
--- a/include/odp/api/time.h
+++ b/include/odp/api/time.h
@@ -24,18 +24,32 @@  extern "C" {
  */
 
 /* Time in nanoseconds */
-#define ODP_TIME_USEC 1000ULL       /**< Microsecond in nsec */
-#define ODP_TIME_MSEC 1000000ULL    /**< Millisecond in nsec */
-#define ODP_TIME_SEC  1000000000ULL /**< Second in nsec */
+#define ODP_TIME_USEC_IN_NS	1000ULL       /**< Microsecond in nsec */
+#define ODP_TIME_MSEC_IN_NS	1000000ULL    /**< Millisecond in nsec */
+#define ODP_TIME_SEC_IN_NS	1000000000ULL /**< Second in nsec */
 
+/**
+ * @typedef odp_time_t
+ * ODP time stamp. Time stamp can represent a time stamp from local or global
+ * time source. A local time stamp must not be shared between threads. API calls
+ * work correctly only when all time stamps for input are from the same time
+ * source.
+ */
 
 /**
- * Current time in CPU cycles
- *
- * @return Current time in CPU cycles
+ * @def ODP_TIME_NULL
+ * Zero time stamp
  */
-uint64_t odp_time_cycles(void);
 
+/**
+ * Current local time
+ *
+ * Returns current local time stamp value. The local time source provides high
+ * resolution time.
+ *
+ * @return Local time stamp.
+ */
+odp_time_t odp_time_local(void);
 
 /**
  * Time difference
@@ -43,29 +57,60 @@  uint64_t odp_time_cycles(void);
  * @param t1    First time stamp
  * @param t2    Second time stamp
  *
- * @return Difference of time stamps in CPU cycles
+ * @return Difference of time stamps
  */
-uint64_t odp_time_diff_cycles(uint64_t t1, uint64_t t2);
+odp_time_t odp_time_diff(odp_time_t t1, odp_time_t t2);
 
+/**
+ * Time sum
+ *
+ * @param t1    Time stamp
+ * @param t2    Time stamp
+ *
+ * @return Sum of time stamps
+ */
+odp_time_t odp_time_sum(odp_time_t t1, odp_time_t t2);
 
 /**
- * Convert CPU cycles to nanoseconds
+ * Convert time to nanoseconds
  *
- * @param cycles  Time in CPU cycles
+ * @param time  Time
  *
  * @return Time in nanoseconds
  */
-uint64_t odp_time_cycles_to_ns(uint64_t cycles);
+uint64_t odp_time_to_ns(odp_time_t time);
 
+/**
+ * Convert nanoseconds to local time
+ *
+ * @param ns    Time in nanoseconds
+ *
+ * @return Local time stamp
+ */
+odp_time_t odp_time_local_from_ns(uint64_t ns);
+
+/**
+ * Compare two times
+ *
+ * @param t2    Second time
+ * @param t1    First time
+ *
+ * @retval <0 if t2 < t1, >0 if t1 = t2, 1 if t2 > t1
+ */
+int odp_time_cmp(odp_time_t t2, odp_time_t t1);
 
 /**
- * Convert nanoseconds to CPU cycles
+ * Get printable value for an odp_time_t
+ *
+ * @param time time to be printed
  *
- * @param ns      Time in nanoseconds
+ * @return uint64_t value that can be used to print/display this time
  *
- * @return Time in CPU cycles
+ * @note This routine is intended to be used for diagnostic purposes
+ * to enable applications to generate a printable value that represents
+ * an odp_time_t time.
  */
-uint64_t odp_time_ns_to_cycles(uint64_t ns);
+uint64_t odp_time_to_u64(odp_time_t time);
 
 /**
  * @}
diff --git a/test/performance/odp_l2fwd.c b/test/performance/odp_l2fwd.c
index f7ccdce..d201186 100644
--- a/test/performance/odp_l2fwd.c
+++ b/test/performance/odp_l2fwd.c
@@ -157,7 +157,7 @@  static void *pktio_queue_thread(void *arg)
 	printf("[%02i] QUEUE mode\n", thr);
 	odp_barrier_wait(&barrier);
 
-	wait = odp_schedule_wait_time(ODP_TIME_MSEC * 100);
+	wait = odp_schedule_wait_time(ODP_TIME_MSEC_IN_NS * 100);
 
 	/* Loop packets */
 	while (!exit_threads) {
diff --git a/test/performance/odp_pktio_perf.c b/test/performance/odp_pktio_perf.c
index ae5b4c0..2d64b40 100644
--- a/test/performance/odp_pktio_perf.c
+++ b/test/performance/odp_pktio_perf.c
@@ -50,7 +50,7 @@ 
 /* Amount of time to wait, in nanoseconds, between the transmitter(s)
  * completing and the receiver(s) being shutdown. Any packets not
  * received by this time will be assumed to have been lost. */
-#define SHUTDOWN_DELAY_NS (ODP_TIME_MSEC*100)
+#define SHUTDOWN_DELAY_NS (ODP_TIME_MSEC_IN_NS * 100)
 
 #define VPRINT(fmt, ...) \
 	do { \
@@ -106,7 +106,7 @@  struct tx_stats_s {
 	uint64_t tx_cnt;	/* Packets transmitted */
 	uint64_t alloc_failures;/* Packet allocation failures */
 	uint64_t enq_failures;	/* Enqueue failures */
-	uint64_t idle_cycles;	/* Idle cycle count in TX loop */
+	odp_time_t idle_cycles;	/* Idle cycle count in TX loop */
 };
 
 typedef union tx_stats_u {
@@ -305,12 +305,12 @@  static void *run_thread_tx(void *arg)
 	int thr_id;
 	odp_queue_t outq;
 	pkt_tx_stats_t *stats;
-	uint64_t burst_start_cycles, start_cycles, cur_cycles, send_duration;
-	uint64_t burst_gap_cycles;
+	odp_time_t start_cycles, cur_cycles, send_duration;
+	odp_time_t burst_start_cycles, burst_gap_cycles;
 	uint32_t batch_len;
 	int unsent_pkts = 0;
 	odp_event_t  tx_event[BATCH_LEN_MAX];
-	uint64_t idle_start = 0;
+	odp_time_t idle_start = ODP_TIME_NULL;
 
 	thread_args_t *targs = arg;
 
@@ -328,30 +328,34 @@  static void *run_thread_tx(void *arg)
 	if (outq == ODP_QUEUE_INVALID)
 		LOG_ABORT("Failed to get output queue for thread %d\n", thr_id);
 
-	burst_gap_cycles = odp_time_ns_to_cycles(
-				ODP_TIME_SEC / (targs->pps / targs->batch_len));
-	send_duration = odp_time_ns_to_cycles(targs->duration * ODP_TIME_SEC);
+	burst_gap_cycles = odp_time_local_from_ns(
+			ODP_TIME_SEC_IN_NS / (targs->pps / targs->batch_len));
+	send_duration =
+		odp_time_local_from_ns(targs->duration * ODP_TIME_SEC_IN_NS);
 
 	odp_barrier_wait(&globals->tx_barrier);
 
-	cur_cycles     = odp_time_cycles();
+	cur_cycles     = odp_time_local();
 	start_cycles   = cur_cycles;
-	burst_start_cycles = odp_time_diff_cycles(burst_gap_cycles, cur_cycles);
-	while (odp_time_diff_cycles(start_cycles, cur_cycles) < send_duration) {
+	burst_start_cycles = odp_time_diff(burst_gap_cycles, cur_cycles);
+	while (odp_time_diff(start_cycles, cur_cycles) < send_duration) {
 		unsigned alloc_cnt = 0, tx_cnt;
 
-		if (odp_time_diff_cycles(burst_start_cycles, cur_cycles)
+		if (odp_time_diff(burst_start_cycles, cur_cycles)
 							< burst_gap_cycles) {
-			cur_cycles = odp_time_cycles();
-			if (idle_start == 0)
+			cur_cycles = odp_time_local();
+			if (!odp_time_cmp(idle_start, ODP_TIME_NULL))
 				idle_start = cur_cycles;
 			continue;
 		}
 
-		if (idle_start) {
-			stats->s.idle_cycles += odp_time_diff_cycles(
-							idle_start, cur_cycles);
-			idle_start = 0;
+		if (odp_time_cmp(idle_start, ODP_TIME_NULL)) {
+			odp_time_t diff = odp_time_diff(idle_start, cur_cycles);
+
+			stats->s.idle_cycles =
+				odp_time_sum(diff, stats->s.idle_cycles);
+
+			idle_start = ODP_TIME_NULL;
 		}
 
 		burst_start_cycles += burst_gap_cycles;
@@ -365,14 +369,15 @@  static void *run_thread_tx(void *arg)
 		stats->s.enq_failures += unsent_pkts;
 		stats->s.tx_cnt += tx_cnt;
 
-		cur_cycles = odp_time_cycles();
+		cur_cycles = odp_time_local();
 	}
 
 	VPRINT(" %02d: TxPkts %-8"PRIu64" EnqFail %-6"PRIu64
 	       " AllocFail %-6"PRIu64" Idle %"PRIu64"ms\n",
 	       thr_id, stats->s.tx_cnt,
 	       stats->s.enq_failures, stats->s.alloc_failures,
-	       odp_time_cycles_to_ns(stats->s.idle_cycles)/1000/1000);
+	       odp_time_to_ns(stats->s.idle_cycles) /
+	       (uint64_t)ODP_TIME_MSEC_IN_NS);
 
 	return NULL;
 }
@@ -591,13 +596,13 @@  static int setup_txrx_masks(odp_cpumask_t *thd_mask_tx,
  */
 static void busy_loop_ns(uint64_t wait_ns)
 {
-	uint64_t diff;
-	uint64_t start_time = odp_time_cycles();
-	uint64_t wait = odp_time_ns_to_cycles(wait_ns);
+	odp_time_t diff;
+	odp_time_t start_time = odp_time_local();
+	odp_time_t wait = odp_time_local_from_ns(wait_ns);
 
 	do {
-		diff = odp_time_diff_cycles(start_time, odp_time_cycles());
-	} while (diff < wait);
+		diff = odp_time_diff(start_time, odp_time_local());
+	} while (odp_time_cmp(wait, diff) > 0);
 }
 
 /*
diff --git a/test/validation/classification/odp_classification_test_pmr.c b/test/validation/classification/odp_classification_test_pmr.c
index 73ba6f5..3f49d4c 100644
--- a/test/validation/classification/odp_classification_test_pmr.c
+++ b/test/validation/classification/odp_classification_test_pmr.c
@@ -168,7 +168,7 @@  static void classification_test_pmr_term_tcp_dport(void)
 
 	enqueue_pktio_interface(pkt, pktio);
 
-	pkt = receive_packet(&retqueue, ODP_TIME_SEC);
+	pkt = receive_packet(&retqueue, ODP_TIME_SEC_IN_NS);
 	CU_ASSERT(pkt != ODP_PACKET_INVALID);
 	CU_ASSERT(retqueue == queue);
 	CU_ASSERT(seqno == cls_pkt_get_seq(pkt));
@@ -185,7 +185,7 @@  static void classification_test_pmr_term_tcp_dport(void)
 
 	enqueue_pktio_interface(pkt, pktio);
 
-	pkt = receive_packet(&retqueue, ODP_TIME_SEC);
+	pkt = receive_packet(&retqueue, ODP_TIME_SEC_IN_NS);
 	CU_ASSERT(pkt != ODP_PACKET_INVALID);
 	CU_ASSERT(seqno == cls_pkt_get_seq(pkt));
 	CU_ASSERT(retqueue == defqueue);
@@ -255,7 +255,7 @@  static void classification_test_pmr_term_tcp_sport(void)
 
 	enqueue_pktio_interface(pkt, pktio);
 
-	pkt = receive_packet(&retqueue, ODP_TIME_SEC);
+	pkt = receive_packet(&retqueue, ODP_TIME_SEC_IN_NS);
 	CU_ASSERT(pkt != ODP_PACKET_INVALID);
 	CU_ASSERT(seqno == cls_pkt_get_seq(pkt));
 	CU_ASSERT(retqueue == queue);
@@ -270,7 +270,7 @@  static void classification_test_pmr_term_tcp_sport(void)
 
 	enqueue_pktio_interface(pkt, pktio);
 
-	pkt = receive_packet(&retqueue, ODP_TIME_SEC);
+	pkt = receive_packet(&retqueue, ODP_TIME_SEC_IN_NS);
 	CU_ASSERT(pkt != ODP_PACKET_INVALID);
 	CU_ASSERT(seqno == cls_pkt_get_seq(pkt));
 	CU_ASSERT(retqueue == defqueue);
@@ -340,7 +340,7 @@  static void classification_test_pmr_term_udp_dport(void)
 
 	enqueue_pktio_interface(pkt, pktio);
 
-	pkt = receive_packet(&retqueue, ODP_TIME_SEC);
+	pkt = receive_packet(&retqueue, ODP_TIME_SEC_IN_NS);
 	CU_ASSERT(pkt != ODP_PACKET_INVALID);
 	CU_ASSERT(seqno == cls_pkt_get_seq(pkt));
 	CU_ASSERT(retqueue == queue);
@@ -356,7 +356,7 @@  static void classification_test_pmr_term_udp_dport(void)
 
 	enqueue_pktio_interface(pkt, pktio);
 
-	pkt = receive_packet(&retqueue, ODP_TIME_SEC);
+	pkt = receive_packet(&retqueue, ODP_TIME_SEC_IN_NS);
 	CU_ASSERT(pkt != ODP_PACKET_INVALID);
 	CU_ASSERT(seqno == cls_pkt_get_seq(pkt));
 	CU_ASSERT(retqueue == defqueue);
@@ -426,7 +426,7 @@  static void classification_test_pmr_term_udp_sport(void)
 
 	enqueue_pktio_interface(pkt, pktio);
 
-	pkt = receive_packet(&retqueue, ODP_TIME_SEC);
+	pkt = receive_packet(&retqueue, ODP_TIME_SEC_IN_NS);
 	CU_ASSERT(pkt != ODP_PACKET_INVALID);
 	CU_ASSERT(seqno == cls_pkt_get_seq(pkt));
 	CU_ASSERT(retqueue == queue);
@@ -441,7 +441,7 @@  static void classification_test_pmr_term_udp_sport(void)
 
 	enqueue_pktio_interface(pkt, pktio);
 
-	pkt = receive_packet(&retqueue, ODP_TIME_SEC);
+	pkt = receive_packet(&retqueue, ODP_TIME_SEC_IN_NS);
 	CU_ASSERT(pkt != ODP_PACKET_INVALID);
 	CU_ASSERT(seqno == cls_pkt_get_seq(pkt));
 	CU_ASSERT(retqueue == defqueue);
@@ -507,7 +507,7 @@  static void classification_test_pmr_term_ipproto(void)
 
 	enqueue_pktio_interface(pkt, pktio);
 
-	pkt = receive_packet(&retqueue, ODP_TIME_SEC);
+	pkt = receive_packet(&retqueue, ODP_TIME_SEC_IN_NS);
 	CU_ASSERT(pkt != ODP_PACKET_INVALID);
 	CU_ASSERT(seqno == cls_pkt_get_seq(pkt));
 	CU_ASSERT(retqueue == queue);
@@ -520,7 +520,7 @@  static void classification_test_pmr_term_ipproto(void)
 
 	enqueue_pktio_interface(pkt, pktio);
 
-	pkt = receive_packet(&retqueue, ODP_TIME_SEC);
+	pkt = receive_packet(&retqueue, ODP_TIME_SEC_IN_NS);
 	CU_ASSERT(pkt != ODP_PACKET_INVALID);
 	CU_ASSERT(seqno == cls_pkt_get_seq(pkt));
 	CU_ASSERT(retqueue == defqueue);
diff --git a/test/validation/classification/odp_classification_tests.c b/test/validation/classification/odp_classification_tests.c
index 823e30f..3944d94 100644
--- a/test/validation/classification/odp_classification_tests.c
+++ b/test/validation/classification/odp_classification_tests.c
@@ -225,7 +225,7 @@  void test_cls_pmr_chain(void)
 
 	enqueue_pktio_interface(pkt, pktio_loop);
 
-	pkt = receive_packet(&queue, ODP_TIME_SEC);
+	pkt = receive_packet(&queue, ODP_TIME_SEC_IN_NS);
 	CU_ASSERT(pkt != ODP_PACKET_INVALID);
 	CU_ASSERT(queue == queue_list[CLS_PMR_CHAIN_DST]);
 	CU_ASSERT(seqno == cls_pkt_get_seq(pkt));
@@ -242,7 +242,7 @@  void test_cls_pmr_chain(void)
 	ip->chksum = odph_ipv4_csum_update(pkt);
 
 	enqueue_pktio_interface(pkt, pktio_loop);
-	pkt = receive_packet(&queue, ODP_TIME_SEC);
+	pkt = receive_packet(&queue, ODP_TIME_SEC_IN_NS);
 	CU_ASSERT(pkt != ODP_PACKET_INVALID);
 	CU_ASSERT(queue == queue_list[CLS_PMR_CHAIN_SRC]);
 	CU_ASSERT(seqno == cls_pkt_get_seq(pkt));
@@ -289,7 +289,7 @@  void test_pktio_default_cos(void)
 
 	enqueue_pktio_interface(pkt, pktio_loop);
 
-	pkt = receive_packet(&queue, ODP_TIME_SEC);
+	pkt = receive_packet(&queue, ODP_TIME_SEC_IN_NS);
 	CU_ASSERT(pkt != ODP_PACKET_INVALID);
 	/* Default packet should be received in default queue */
 	CU_ASSERT(queue == queue_list[CLS_DEFAULT]);
@@ -341,7 +341,7 @@  void test_pktio_error_cos(void)
 	ip->chksum = 0;
 	enqueue_pktio_interface(pkt, pktio_loop);
 
-	pkt = receive_packet(&queue, ODP_TIME_SEC);
+	pkt = receive_packet(&queue, ODP_TIME_SEC_IN_NS);
 	CU_ASSERT(pkt != ODP_PACKET_INVALID);
 	/* Error packet should be received in error queue */
 	CU_ASSERT(queue == queue_list[CLS_ERROR]);
@@ -436,7 +436,7 @@  void test_cos_with_l2_priority(void)
 		vlan = (odph_vlanhdr_t *)(&ethhdr->type);
 		vlan->tci = odp_cpu_to_be_16(i << 13);
 		enqueue_pktio_interface(pkt, pktio_loop);
-		pkt = receive_packet(&queue, ODP_TIME_SEC);
+		pkt = receive_packet(&queue, ODP_TIME_SEC_IN_NS);
 		CU_ASSERT(pkt != ODP_PACKET_INVALID);
 		CU_ASSERT(queue == queue_list[CLS_L2_QOS_0 + i]);
 		CU_ASSERT(seqno == cls_pkt_get_seq(pkt));
@@ -501,7 +501,7 @@  void test_pmr_cos(void)
 	udp = (odph_udphdr_t *)odp_packet_l4_ptr(pkt, NULL);
 	udp->src_port = odp_cpu_to_be_16(CLS_PMR_SPORT);
 	enqueue_pktio_interface(pkt, pktio_loop);
-	pkt = receive_packet(&queue, ODP_TIME_SEC);
+	pkt = receive_packet(&queue, ODP_TIME_SEC_IN_NS);
 	CU_ASSERT(pkt != ODP_PACKET_INVALID);
 	CU_ASSERT(queue == queue_list[CLS_PMR]);
 	CU_ASSERT(seqno == cls_pkt_get_seq(pkt));
@@ -585,7 +585,7 @@  void test_pktio_pmr_match_set_cos(void)
 	udp = (odph_udphdr_t *)odp_packet_l4_ptr(pkt, NULL);
 	udp->src_port = odp_cpu_to_be_16(CLS_PMR_SET_SPORT);
 	enqueue_pktio_interface(pkt, pktio_loop);
-	pkt = receive_packet(&queue, ODP_TIME_SEC);
+	pkt = receive_packet(&queue, ODP_TIME_SEC_IN_NS);
 	CU_ASSERT(pkt != ODP_PACKET_INVALID);
 	CU_ASSERT(queue == queue_list[CLS_PMR_SET]);
 	CU_ASSERT(seqno == cls_pkt_get_seq(pkt));
diff --git a/test/validation/pktio/pktio.c b/test/validation/pktio/pktio.c
index b3738ce..9435a22 100644
--- a/test/validation/pktio/pktio.c
+++ b/test/validation/pktio/pktio.c
@@ -336,18 +336,18 @@  static int destroy_inq(odp_pktio_t pktio)
 
 static odp_event_t queue_deq_wait_time(odp_queue_t queue, uint64_t ns)
 {
-	uint64_t start, now, diff;
+	odp_time_t start, now, diff;
 	odp_event_t ev;
 
-	start = odp_time_cycles();
+	start = odp_time_local();
 
 	do {
 		ev = odp_queue_deq(queue);
 		if (ev != ODP_EVENT_INVALID)
 			return ev;
-		now = odp_time_cycles();
-		diff = odp_time_diff_cycles(start, now);
-	} while (odp_time_cycles_to_ns(diff) < ns);
+		now = odp_time_local();
+		diff = odp_time_diff(start, now);
+	} while (odp_time_to_ns(diff) < ns);
 
 	return ODP_EVENT_INVALID;
 }
@@ -355,12 +355,12 @@  static odp_event_t queue_deq_wait_time(odp_queue_t queue, uint64_t ns)
 static odp_packet_t wait_for_packet(pktio_info_t *pktio_rx,
 				    uint32_t seq, uint64_t ns)
 {
-	uint64_t start, now, diff;
+	odp_time_t start, now, diff;
 	odp_event_t ev;
 	odp_packet_t pkt;
 	uint64_t wait;
 
-	start = odp_time_cycles();
+	start = odp_time_local();
 	wait = odp_schedule_wait_time(ns);
 
 	do {
@@ -389,9 +389,9 @@  static odp_packet_t wait_for_packet(pktio_info_t *pktio_rx,
 			odp_packet_free(pkt);
 		}
 
-		now = odp_time_cycles();
-		diff = odp_time_diff_cycles(start, now);
-	} while (odp_time_cycles_to_ns(diff) < ns);
+		now = odp_time_local();
+		diff = odp_time_diff(start, now);
+	} while (odp_time_to_ns(diff) < ns);
 
 	CU_FAIL("failed to receive transmitted packet");
 
@@ -450,7 +450,8 @@  static void pktio_txrx_multi(pktio_info_t *pktio_a, pktio_info_t *pktio_b,
 
 	/* and wait for them to arrive back */
 	for (i = 0; i < num_pkts; ++i) {
-		rx_pkt = wait_for_packet(pktio_b, tx_seq[i], ODP_TIME_SEC);
+		rx_pkt = wait_for_packet(pktio_b, tx_seq[i],
+					 ODP_TIME_SEC_IN_NS);
 
 		if (rx_pkt == ODP_PACKET_INVALID)
 			break;
@@ -627,7 +628,7 @@  void pktio_test_inq_remdef(void)
 	CU_ASSERT(inq != ODP_QUEUE_INVALID);
 	CU_ASSERT(odp_pktio_inq_remdef(pktio) == 0);
 
-	wait = odp_schedule_wait_time(ODP_TIME_MSEC);
+	wait = odp_schedule_wait_time(ODP_TIME_MSEC_IN_NS);
 	for (i = 0; i < 100; i++) {
 		ev = odp_schedule(NULL, wait);
 		if (ev != ODP_EVENT_INVALID) {
@@ -703,7 +704,7 @@  static void pktio_test_start_stop(void)
 	odp_event_t ev;
 	int i, pkts, ret, alloc = 0;
 	odp_queue_t outq;
-	uint64_t wait = odp_schedule_wait_time(ODP_TIME_MSEC);
+	uint64_t wait = odp_schedule_wait_time(ODP_TIME_MSEC_IN_NS);
 
 	for (i = 0; i < num_ifaces; i++) {
 		pktio[i] = create_pktio(i, ODP_PKTIN_MODE_SCHED);
@@ -918,8 +919,8 @@  static void pktio_test_send_failure(void)
 		info_rx.in_mode = ODP_PKTIN_MODE_RECV;
 
 		for (i = 0; i < ret; ++i) {
-			pkt_tbl[i] = wait_for_packet(&info_rx,
-						     pkt_seq[i], ODP_TIME_SEC);
+			pkt_tbl[i] = wait_for_packet(&info_rx, pkt_seq[i],
+						     ODP_TIME_SEC_IN_NS);
 			if (pkt_tbl[i] == ODP_PACKET_INVALID)
 				break;
 		}
diff --git a/test/validation/scheduler/scheduler.c b/test/validation/scheduler/scheduler.c
index 042d7b4..e813f82 100644
--- a/test/validation/scheduler/scheduler.c
+++ b/test/validation/scheduler/scheduler.c
@@ -514,10 +514,11 @@  static void *schedule_common_(void *arg)
 			CU_ASSERT(from != ODP_QUEUE_INVALID);
 			if (locked) {
 				int cnt;
-				uint64_t cycles = 0;
+				odp_time_t cycles = ODP_TIME_NULL;
 				/* Do some work here to keep the thread busy */
 				for (cnt = 0; cnt < 1000; cnt++)
-					cycles += odp_time_cycles();
+					cycles = odp_time_sum(cycles,
+							      odp_time_local());
 
 				odp_spinlock_unlock(&globals->atomic_lock);
 			}
diff --git a/test/validation/time/time.c b/test/validation/time/time.c
index 41db0e9..231f50e 100644
--- a/test/validation/time/time.c
+++ b/test/validation/time/time.c
@@ -16,43 +16,44 @@  void time_test_odp_cycles_diff(void)
 {
 	/* volatile to stop optimization of busy loop */
 	volatile int count = 0;
-	uint64_t diff, cycles1, cycles2;
+	odp_time_t diff, cycles1, cycles2;
 
-	cycles1 = odp_time_cycles();
+	cycles1 = odp_time_local();
 
 	while (count < BUSY_LOOP_CNT) {
 		count++;
 	};
 
-	cycles2 = odp_time_cycles();
-	CU_ASSERT(cycles2 > cycles1);
+	cycles2 = odp_time_local();
+	CU_ASSERT((odp_time_cmp(cycles2, cycles1) > 0));
 
-	diff = odp_time_diff_cycles(cycles1, cycles2);
-	CU_ASSERT(diff > 0);
+	diff = odp_time_diff(cycles1, cycles2);
+	CU_ASSERT(odp_time_cmp(diff, ODP_TIME_NULL) > 0);
 }
 
 /* check that a negative cycles difference gives a reasonable result */
 void time_test_odp_cycles_negative_diff(void)
 {
-	uint64_t diff, cycles1, cycles2;
+	odp_time_t diff, cycles1, cycles2;
 
 	cycles1 = 10;
 	cycles2 = 5;
-	diff = odp_time_diff_cycles(cycles1, cycles2);
-	CU_ASSERT(diff > 0);
+	diff = odp_time_diff(cycles1, cycles2);
+	CU_ASSERT(odp_time_cmp(diff, ODP_TIME_NULL) > 0);
 }
 
 /* check that related conversions come back to the same value */
 void time_test_odp_time_conversion(void)
 {
-	uint64_t ns1, ns2, cycles;
+	uint64_t ns1, ns2;
+	odp_time_t cycles;
 	uint64_t upper_limit, lower_limit;
 
 	ns1 = 100;
-	cycles = odp_time_ns_to_cycles(ns1);
-	CU_ASSERT(cycles > 0);
+	cycles = odp_time_local_from_ns(ns1);
+	CU_ASSERT(odp_time_cmp(cycles, ODP_TIME_NULL) > 0);
 
-	ns2 = odp_time_cycles_to_ns(cycles);
+	ns2 = odp_time_to_ns(cycles);
 
 	/* need to check within arithmetic tolerance that the same
 	 * value in ns is returned after conversions */
diff --git a/test/validation/timer/timer.c b/test/validation/timer/timer.c
index 645dc58..dda5e4c 100644
--- a/test/validation/timer/timer.c
+++ b/test/validation/timer/timer.c
@@ -145,9 +145,9 @@  void timer_test_odp_timer_cancel(void)
 	if (pool == ODP_POOL_INVALID)
 		CU_FAIL_FATAL("Timeout pool create failed");
 
-	tparam.res_ns     = 100 * ODP_TIME_MSEC;
-	tparam.min_tmo    = 1   * ODP_TIME_SEC;
-	tparam.max_tmo    = 10  * ODP_TIME_SEC;
+	tparam.res_ns     = 100 * ODP_TIME_MSEC_IN_NS;
+	tparam.min_tmo    = 1   * ODP_TIME_SEC_IN_NS;
+	tparam.max_tmo    = 10  * ODP_TIME_SEC_IN_NS;
 	tparam.num_timers = 1;
 	tparam.priv       = 0;
 	tparam.clk_src    = ODP_CLOCK_CPU;
@@ -171,7 +171,7 @@  void timer_test_odp_timer_cancel(void)
 	if (ev == ODP_EVENT_INVALID)
 		CU_FAIL_FATAL("Failed to allocate timeout");
 
-	tick = odp_timer_ns_to_tick(tp, 2 * ODP_TIME_SEC);
+	tick = odp_timer_ns_to_tick(tp, 2 * ODP_TIME_SEC_IN_NS);
 
 	rc = odp_timer_set_rel(tim, tick, &ev);
 	if (rc != ODP_TIMER_SUCCESS)
@@ -457,9 +457,9 @@  void timer_test_odp_timer_all(void)
 		CU_FAIL_FATAL("Timeout pool create failed");
 
 #define NAME "timer_pool"
-#define RES (10 * ODP_TIME_MSEC / 3)
-#define MIN (10 * ODP_TIME_MSEC / 3)
-#define MAX (1000000 * ODP_TIME_MSEC)
+#define RES (10 * ODP_TIME_MSEC_IN_NS / 3)
+#define MIN (10 * ODP_TIME_MSEC_IN_NS / 3)
+#define MAX (1000000 * ODP_TIME_MSEC_IN_NS)
 	/* Create a timer pool */
 	tparam.res_ns = RES;
 	tparam.min_tmo = MIN;