> -----Original Message-----
> From: EXT Ivan Khoronzhuk [mailto:ivan.khoronz...@linaro.org]
> Sent: Thursday, October 22, 2015 3:02 PM
> To: lng-odp@lists.linaro.org; Savolainen, Petri (Nokia - FI/Espoo)
> Cc: Ivan Khoronzhuk
> Subject: [lng-odp] [API-NEXT PATCH v5 3/5] api: time: unbind CPU cycles
> from time API
> 
> 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.khoronz...@linaro.org>
> ---
>  example/generator/odp_generator.c     | 12 +++----
>  include/odp/api/time.h                | 68 ++++++++++++++++++++++++++++---
> ----
>  test/performance/odp_pktio_perf.c     | 49 +++++++++++++------------
>  test/validation/pktio/pktio.c         | 20 +++++------
>  test/validation/scheduler/scheduler.c |  5 +--
>  test/validation/time/time.c           | 27 +++++++-------
>  6 files changed, 114 insertions(+), 67 deletions(-)
> 
> diff --git a/example/generator/odp_generator.c
> b/example/generator/odp_generator.c
> index be9597b..f84adc4 100644
> --- a/example/generator/odp_generator.c
> +++ b/example/generator/odp_generator.c
> @@ -585,7 +585,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;
> @@ -593,8 +593,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_from_ns(verbose_interval * ODP_TIME_SEC);
> +     start = odp_time();
> 
>       while (odp_thrmask_worker(&thrd_mask) == num_workers) {
>               if (args->appl.number != -1 &&
> @@ -603,11 +603,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());
> +             if (odp_time_cmp(diff, wait) > 0)
>                       continue;
> 
> -             start = odp_time_cycles();
> +             start = odp_time();
> 
>               if (args->appl.mode == APPL_MODE_RCV) {
>                       pkts = odp_atomic_load_u64(&counters.udp);
> diff --git a/include/odp/api/time.h b/include/odp/api/time.h
> index b0072fc..7ed4734 100644
> --- a/include/odp/api/time.h
> +++ b/include/odp/api/time.h
> @@ -28,14 +28,25 @@ extern "C" {
>  #define ODP_TIME_MSEC 1000000ULL    /**< Millisecond in nsec */
>  #define ODP_TIME_SEC  1000000000ULL /**< Second in nsec */


New name for these could be XXX_IN_NS
ODP_TIME_SEC_IN_NS  1000000000ULL /**< Second in nsec */


> 
> +/**
> + * @typedef odp_time_t
> + * ODP time stamp. Time stamp can be local, so shouldn't be shared between
> + * threads.
> + */


It's OK to implement local time first, but I'd define it so that global time is 
easy to add later.

/**
 * @typedef odp_time_t
 * ODP time stamp. Time stamp can be 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.
 */

In case of 64 bit time stamps, implementation can either define odp_time_t as a 
small struct or use couple of MSB bits for flags (e.g. time stamp would wrap in 
290 years instead of 580 years)


> 
>  /**
> - * 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 time stamp.
> + *
> + * It should be hi-resolution time.
> + *
> + * @return Time stamp.
> + */
> +odp_time_t odp_time(void);


This is then renamed to be the local time source.

/**
 * Current local time
 *
 * Returns current thread local time stamp value. The local time
 * source provides high resolution but may wrap between two time
 * stamp calls. Local time should be used only for short time
 * range calculations or comparisons.
 *
 * @return Local time stamp
 */
odp_time_t odp_time_local(void);


We can add later a call to query the local time stamp wrap around time (max 
range).

All other calls can remain as is.

-Petri

> 
>  /**
>   * Time difference
> @@ -43,29 +54,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 CPU cycles
> + * Convert nanoseconds to time
>   *
>   * @param ns      Time in nanoseconds
>   *
> - * @return Time in CPU cycles
> + * @return Time stamp
> + */
> +odp_time_t odp_time_from_ns(uint64_t ns);
> +
> +/**
> + * Compare two times as absolute ranges
> + *
> + * @param t1    First time
> + * @param t2    Second time
> + *
> + * @retval -1 if t2 < t1, 0 if t1 = t2, 1 if t2 > t1
> + */
> +int odp_time_cmp(odp_time_t t1, odp_time_t t2);
> +
> +/**
> + * Get printable value for an odp_time_t
> + *
> + * @param time time to be printed
> + * @return     uint64_t value that can be used to print/display this
> + *             time
> + *
> + * @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);
> 
_______________________________________________
lng-odp mailing list
lng-odp@lists.linaro.org
https://lists.linaro.org/mailman/listinfo/lng-odp

Reply via email to