On 2022-12-16 22:56, Erik Gabriel Carrillo wrote:
Introduce an event timer adapter API which allows users to determine how
many adapter ticks remain until an event timer fires.

Signed-off-by: Erik Gabriel Carrillo <erik.g.carri...@intel.com>
---
  app/test/test_event_timer_adapter.c    | 68 ++++++++++++++++++++++++++
  lib/eventdev/event_timer_adapter_pmd.h |  7 +++
  lib/eventdev/rte_event_timer_adapter.c | 52 ++++++++++++++++++++
  lib/eventdev/rte_event_timer_adapter.h | 27 ++++++++++
  lib/eventdev/version.map               |  3 ++
  5 files changed, 157 insertions(+)

diff --git a/app/test/test_event_timer_adapter.c 
b/app/test/test_event_timer_adapter.c
index 1a440dfd10..6529b14ff9 100644
--- a/app/test/test_event_timer_adapter.c
+++ b/app/test/test_event_timer_adapter.c
@@ -1920,6 +1920,72 @@ adapter_create_max(void)
        return TEST_SUCCESS;
  }
+static inline int
+test_timer_ticks_remaining(void)
+{
+       uint64_t ticks_remaining = UINT64_MAX;
+       struct rte_event_timer *ev_tim;
+       struct rte_event ev;
+       int ret, i;
+       const struct rte_event_timer tim = {
+               .ev.op = RTE_EVENT_OP_NEW,
+               .ev.queue_id = 0,
+               .ev.sched_type = RTE_SCHED_TYPE_ATOMIC,
+               .ev.priority = RTE_EVENT_DEV_PRIORITY_NORMAL,
+               .ev.event_type =  RTE_EVENT_TYPE_TIMER,
+               .state = RTE_EVENT_TIMER_NOT_ARMED,
+       };
+
+       rte_mempool_get(eventdev_test_mempool, (void **)&ev_tim);
+       *ev_tim = tim;
+       ev_tim->ev.event_ptr = ev_tim;
+#define TEST_TICKS 5
+       ev_tim->timeout_ticks = CALC_TICKS(TEST_TICKS);
+
+       /* Test that unarmed timer returns error */
+       TEST_ASSERT_FAIL(rte_event_timer_ticks_remaining_get(timdev, ev_tim,
+                                                            &ticks_remaining),
+                        "Didn't fail to get ticks for unarmed event timer");
+
+       TEST_ASSERT_EQUAL(rte_event_timer_arm_burst(timdev, &ev_tim, 1), 1,
+                         "Failed to arm timer with proper timeout.");
+       TEST_ASSERT_EQUAL(ev_tim->state, RTE_EVENT_TIMER_ARMED,
+                         "Improper timer state set expected %d returned %d",
+                         RTE_EVENT_TIMER_ARMED, ev_tim->state);
+
+       for (i = 0; i < TEST_TICKS; i++) {
+               ret = rte_event_timer_ticks_remaining_get(timdev, ev_tim,
+                                                         &ticks_remaining);
+               if (ret < 0)
+                       return TEST_FAILED;
+
+               TEST_ASSERT_EQUAL((int)ticks_remaining, TEST_TICKS - i,
+                                 "Expected %d ticks remaining, got %"PRIu64"",
+                                 TEST_TICKS - i, ticks_remaining);
+
+               rte_delay_ms(100);
+       }
+
+       rte_delay_ms(100);
+
+       TEST_ASSERT_EQUAL(rte_event_dequeue_burst(evdev, 0, &ev, 1, 0), 1,
+                         "Armed timer failed to trigger.");
+       TEST_ASSERT_EQUAL(ev_tim->state, RTE_EVENT_TIMER_NOT_ARMED,
+                         "Improper timer state set expected %d returned %d",
+                         RTE_EVENT_TIMER_NOT_ARMED, ev_tim->state);
+
+       /* Test that timer that fired returns error */
+       TEST_ASSERT_FAIL(rte_event_timer_ticks_remaining_get(timdev, ev_tim,
+                                                          &ticks_remaining),
+                        "Didn't fail to get ticks for unarmed event timer");
+
+       rte_mempool_put(eventdev_test_mempool, (void *)ev_tim);
+
+#undef TEST_TICKS
+       return TEST_SUCCESS;
+}
+
+
  static struct unit_test_suite event_timer_adptr_functional_testsuite  = {
        .suite_name = "event timer functional test suite",
        .setup = testsuite_setup,
@@ -1982,6 +2048,8 @@ static struct unit_test_suite 
event_timer_adptr_functional_testsuite  = {
                TEST_CASE_ST(timdev_setup_msec, timdev_teardown,
                                adapter_tick_resolution),
                TEST_CASE(adapter_create_max),
+               TEST_CASE_ST(timdev_setup_msec, timdev_teardown,
+                               test_timer_ticks_remaining),
                TEST_CASES_END() /**< NULL terminate unit test array */
        }
  };
diff --git a/lib/eventdev/event_timer_adapter_pmd.h 
b/lib/eventdev/event_timer_adapter_pmd.h
index 189017b5c1..c19ff3576a 100644
--- a/lib/eventdev/event_timer_adapter_pmd.h
+++ b/lib/eventdev/event_timer_adapter_pmd.h
@@ -52,6 +52,11 @@ typedef int (*rte_event_timer_adapter_stats_get_t)(
  typedef int (*rte_event_timer_adapter_stats_reset_t)(
                const struct rte_event_timer_adapter *adapter);
  /**< @internal Reset statistics for event timer adapter */
+typedef int (*rte_event_timer_ticks_remaining_get_t)(
+               const struct rte_event_timer_adapter *adapter,
+               const struct rte_event_timer *evtim,
+               uint64_t *ticks_remaining);
+/**< @internal Get remaining ticks for event timer */
/**
   * @internal Structure containing the functions exported by an event timer
@@ -74,6 +79,8 @@ struct event_timer_adapter_ops {
        /**< Arm event timers with same expiration time */
        rte_event_timer_cancel_burst_t          cancel_burst;
        /**< Cancel one or more event timers */
+       rte_event_timer_ticks_remaining_get_t   ticks_remaining_get;
+       /**< Get remaining ticks for event timer */
  };
/**
diff --git a/lib/eventdev/rte_event_timer_adapter.c 
b/lib/eventdev/rte_event_timer_adapter.c
index a0f14bf861..e2542e985c 100644
--- a/lib/eventdev/rte_event_timer_adapter.c
+++ b/lib/eventdev/rte_event_timer_adapter.c
@@ -8,6 +8,7 @@
  #include <inttypes.h>
  #include <stdbool.h>
  #include <stdlib.h>
+#include <math.h>
#include <rte_memzone.h>
  #include <rte_errno.h>
@@ -458,6 +459,21 @@ rte_event_timer_adapter_stats_reset(struct 
rte_event_timer_adapter *adapter)
        return adapter->ops->stats_reset(adapter);
  }
+int
+rte_event_timer_ticks_remaining_get(

I think the general pattern is
<class>[<"sub-class">]_get_<attribute>

rte_event_timer_get_remaining_ticks()

+                       const struct rte_event_timer_adapter *adapter,
+                       const struct rte_event_timer *evtim,
+                       uint64_t *ticks_remaining)
+{
+       ADAPTER_VALID_OR_ERR_RET(adapter, -EINVAL);
+       FUNC_PTR_OR_ERR_RET(adapter->ops->ticks_remaining_get, -ENOTSUP);
+
+       if (ticks_remaining == NULL)
+               return -EINVAL;

Why is this not an RTE_ASSERT()?

Passing NULL is an API violation, likely due to a programming error.

+
+       return adapter->ops->ticks_remaining_get(adapter, evtim, 
ticks_remaining);
+}
+
  /*
   * Software event timer adapter buffer helper functions
   */
@@ -1072,6 +1088,41 @@ swtim_stats_reset(const struct rte_event_timer_adapter 
*adapter)
        return 0;
  }
+static int
+swtim_ticks_remaining_get(const struct rte_event_timer_adapter *adapter,
+                         const struct rte_event_timer *evtim,
+                         uint64_t *ticks_remaining)
+{
+       uint64_t nsecs_per_adapter_tick, opaque, cycles_remaining;
+       enum rte_event_timer_state n_state;
+       double nsecs_per_cycle;
+       struct rte_timer *tim;
+       uint64_t cur_cycles;
+
+       /* Check that timer is armed */
+       n_state = __atomic_load_n(&evtim->state, __ATOMIC_ACQUIRE);
+       if (n_state != RTE_EVENT_TIMER_ARMED)
+               return -EINVAL;
+
+       opaque = evtim->impl_opaque[0];
+       tim = (struct rte_timer *)(uintptr_t)opaque;
+
+       cur_cycles = rte_get_timer_cycles();
+       if (cur_cycles > tim->expire) {
+               *ticks_remaining = 0;
+               return 0;
+       }
+
+       cycles_remaining = tim->expire - cur_cycles;
+       nsecs_per_cycle = (double)NSECPERSEC / rte_get_timer_hz();
+       nsecs_per_adapter_tick = adapter->data->conf.timer_tick_ns;
+
+       *ticks_remaining = (uint64_t)ceil((cycles_remaining * nsecs_per_cycle) /
+                                         nsecs_per_adapter_tick);
+
+       return 0;
+}
+
  static uint16_t
  __swtim_arm_burst(const struct rte_event_timer_adapter *adapter,
                struct rte_event_timer **evtims,
@@ -1286,6 +1337,7 @@ static const struct event_timer_adapter_ops swtim_ops = {
        .arm_burst = swtim_arm_burst,
        .arm_tmo_tick_burst = swtim_arm_tmo_tick_burst,
        .cancel_burst = swtim_cancel_burst,
+       .ticks_remaining_get = swtim_ticks_remaining_get,
  };
static int
diff --git a/lib/eventdev/rte_event_timer_adapter.h 
b/lib/eventdev/rte_event_timer_adapter.h
index cd10db19e4..b05d9b400d 100644
--- a/lib/eventdev/rte_event_timer_adapter.h
+++ b/lib/eventdev/rte_event_timer_adapter.h
@@ -678,6 +678,33 @@ rte_event_timer_cancel_burst(const struct 
rte_event_timer_adapter *adapter,
        return adapter->cancel_burst(adapter, evtims, nb_evtims);
  }
+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change without prior notice
+ *
+ * Get the number of ticks remaining until an event timer fires.
+ *
+ * @param adapter
+ *   A pointer to an event timer adapter structure
+ * @param evtim
+ *   A pointer to an rte_event_timer structure
+ * @param[out] ticks_remaining
+ *   Pointer to variable into which to write the number of ticks remaining
+ *   until the event timer fires
+ *
+ * @return
+ *   - 0: Success
+ *   - -EINVAL Invalid timer adapter identifier, ticks_remaining pointer is
+ *   NULL, or the event timer is not in the armed state
+ *   - -ENOTSUP The timer adapter implementation does not support this API.
+ */
+__rte_experimental
+int
+rte_event_timer_ticks_remaining_get(
+                       const struct rte_event_timer_adapter *adapter,
+                       const struct rte_event_timer *evtim,
+                       uint64_t *ticks_remaining);
+
  #ifdef __cplusplus
  }
  #endif
diff --git a/lib/eventdev/version.map b/lib/eventdev/version.map
index dd63ec6f68..2a46fd27dc 100644
--- a/lib/eventdev/version.map
+++ b/lib/eventdev/version.map
@@ -118,6 +118,9 @@ EXPERIMENTAL {
        rte_event_eth_tx_adapter_instance_get;
        rte_event_eth_tx_adapter_queue_start;
        rte_event_eth_tx_adapter_queue_stop;
+
+       # added in 23.03
+       rte_event_timer_ticks_remaining_get;
  };
INTERNAL {

Reply via email to