eal: add helpers for time conversions
authorDaniel Mrzyglod <danielx.t.mrzyglod@intel.com>
Fri, 13 Nov 2015 16:09:08 +0000 (16:09 +0000)
committerThomas Monjalon <thomas.monjalon@6wind.com>
Fri, 13 Nov 2015 16:44:34 +0000 (17:44 +0100)
Add common functions and structures to handle time, and cycle counts
which will be used for PTP processing.

Signed-off-by: Daniel Mrzyglod <danielx.t.mrzyglod@intel.com>
Signed-off-by: Pablo de Lara <pablo.de.lara.guarch@intel.com>
Reviewed-by: John McNamara <john.mcnamara@intel.com>
lib/librte_eal/common/Makefile
lib/librte_eal/common/include/rte_time.h [new file with mode: 0644]

index 0c43d6a..8508473 100644 (file)
@@ -40,7 +40,7 @@ INC += rte_string_fns.h rte_version.h
 INC += rte_eal_memconfig.h rte_malloc_heap.h
 INC += rte_hexdump.h rte_devargs.h rte_dev.h
 INC += rte_pci_dev_feature_defs.h rte_pci_dev_features.h
-INC += rte_malloc.h
+INC += rte_malloc.h rte_time.h
 
 ifeq ($(CONFIG_RTE_INSECURE_FUNCTION_WARNING),y)
 INC += rte_warnings.h
diff --git a/lib/librte_eal/common/include/rte_time.h b/lib/librte_eal/common/include/rte_time.h
new file mode 100644 (file)
index 0000000..4b13b9c
--- /dev/null
@@ -0,0 +1,122 @@
+/*-
+ *   BSD LICENSE
+ *
+ *   Copyright(c) 2015 Intel Corporation. All rights reserved.
+ *   All rights reserved.
+ *
+ *   Redistribution and use in source and binary forms, with or without
+ *   modification, are permitted provided that the following conditions
+ *   are met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in
+ *       the documentation and/or other materials provided with the
+ *       distribution.
+ *     * Neither the name of Intel Corporation nor the names of its
+ *       contributors may be used to endorse or promote products derived
+ *       from this software without specific prior written permission.
+ *
+ *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#define NSEC_PER_SEC             1000000000L
+
+/**
+ * Structure to hold the parameters of a running cycle counter to assist
+ * in converting cycles to nanoseconds.
+ */
+struct rte_timecounter {
+       /** Last cycle counter value read. */
+       uint64_t cycle_last;
+       /** Nanoseconds count. */
+       uint64_t nsec;
+       /** Bitmask separating nanosecond and sub-nanoseconds. */
+       uint64_t nsec_mask;
+       /** Sub-nanoseconds count. */
+       uint64_t nsec_frac;
+       /** Bitmask for two's complement substraction of non-64 bit counters. */
+       uint64_t cc_mask;
+       /** Cycle to nanosecond divisor (power of two). */
+       uint32_t cc_shift;
+};
+
+/**
+ * Converts cyclecounter cycles to nanoseconds.
+ */
+static inline uint64_t
+rte_cyclecounter_cycles_to_ns(struct rte_timecounter *tc, uint64_t cycles)
+{
+       uint64_t ns;
+
+       /* Add fractional nanoseconds. */
+       ns = cycles + tc->nsec_frac;
+       tc->nsec_frac = ns & tc->nsec_mask;
+
+       /* Shift to get only nanoseconds. */
+       return ns >> tc->cc_shift;
+}
+
+/**
+ * Update the internal nanosecond count in the structure.
+ */
+static inline uint64_t
+rte_timecounter_update(struct rte_timecounter *tc, uint64_t cycle_now)
+{
+       uint64_t cycle_delta, ns_offset;
+
+       /* Calculate the delta since the last call. */
+       if (tc->cycle_last <= cycle_now)
+               cycle_delta = (cycle_now - tc->cycle_last) & tc->cc_mask;
+       else
+               /* Handle cycle counts that have wrapped around . */
+               cycle_delta = (~(tc->cycle_last - cycle_now) & tc->cc_mask) + 1;
+
+       /* Convert to nanoseconds. */
+       ns_offset = rte_cyclecounter_cycles_to_ns(tc, cycle_delta);
+
+       /* Store current cycle counter for next call. */
+       tc->cycle_last = cycle_now;
+
+       /* Update the nanosecond count. */
+       tc->nsec += ns_offset;
+
+       return tc->nsec;
+}
+
+/**
+ * Convert from timespec structure into nanosecond units.
+ */
+static inline uint64_t
+rte_timespec_to_ns(const struct timespec *ts)
+{
+       return ((uint64_t) ts->tv_sec * NSEC_PER_SEC) + ts->tv_nsec;
+}
+
+/**
+ * Convert from nanosecond units into timespec structure.
+ */
+static inline struct timespec
+rte_ns_to_timespec(uint64_t nsec)
+{
+       struct timespec ts = {0, 0};
+
+       if (nsec == 0)
+               return ts;
+
+       ts.tv_sec = nsec / NSEC_PER_SEC;
+       ts.tv_nsec = nsec % NSEC_PER_SEC;
+
+       return ts;
+}