From patchwork Fri Dec 16 21:56:15 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Carrillo, Erik G" X-Patchwork-Id: 120990 X-Patchwork-Delegate: jerinj@marvell.com Return-Path: X-Original-To: patchwork@inbox.dpdk.org Delivered-To: patchwork@inbox.dpdk.org Received: from mails.dpdk.org (mails.dpdk.org [217.70.189.124]) by inbox.dpdk.org (Postfix) with ESMTP id 892D9A0543; Fri, 16 Dec 2022 22:56:41 +0100 (CET) Received: from mails.dpdk.org (localhost [127.0.0.1]) by mails.dpdk.org (Postfix) with ESMTP id 2E22240695; Fri, 16 Dec 2022 22:56:41 +0100 (CET) Received: from mga12.intel.com (mga12.intel.com [192.55.52.136]) by mails.dpdk.org (Postfix) with ESMTP id 281AA4068E for ; Fri, 16 Dec 2022 22:56:38 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1671227799; x=1702763799; h=from:to:cc:subject:date:message-id:mime-version: content-transfer-encoding; bh=qBfsaL51CWi87lMmzOWYXX1Ph8kGoHqt2gh16drUIPw=; b=nzbRPx7GqPHwWFMf9ha/TMJmk2HlT3szioBorNIlNyDDdAs2s37mcSFA SAv+8gQBYjPRXPZFYGwr/mOVZoblelL6hzUuGuAaFrTZGqx3tW5ippoig 7qlhkNggrx08FAjRsdU5XVTiQm/5sQvcVSPxFoajmv6l25ijCnADD6DP3 ukRkHzJFqgZGnlcapUI1Q9FdYHE1eVJVTsqZDW5U/QnNVAzW0TBmGiY2j sFQRZvP4TsHovr/2m2Oz0Lsz+aM2QQmNaFU67kInNdwudh/iiG2qlKyr0 HZnHCdxllYt+GoltBBnBtsbEUyE5IwI97m/6NpzRrolDR7rL8mN9vpDUS A==; X-IronPort-AV: E=McAfee;i="6500,9779,10563"; a="298735255" X-IronPort-AV: E=Sophos;i="5.96,251,1665471600"; d="scan'208";a="298735255" Received: from orsmga002.jf.intel.com ([10.7.209.21]) by fmsmga106.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 16 Dec 2022 13:56:26 -0800 X-ExtLoop1: 1 X-IronPort-AV: E=McAfee;i="6500,9779,10563"; a="649951399" X-IronPort-AV: E=Sophos;i="5.96,251,1665471600"; d="scan'208";a="649951399" Received: from txandevlnx321.an.intel.com ([10.123.117.43]) by orsmga002.jf.intel.com with ESMTP; 16 Dec 2022 13:56:25 -0800 From: Erik Gabriel Carrillo To: jerinj@marvell.com Cc: s.v.naga.harish.k@intel.com, jay.jayatheerthan@intel.com, pbhagavatula@marvell.com, sthotton@marvell.com, dev@dpdk.org Subject: [PATCH] eventdev/timer: add API to get remaining ticks Date: Fri, 16 Dec 2022 15:56:15 -0600 Message-Id: <20221216215615.2158238-1-erik.g.carrillo@intel.com> X-Mailer: git-send-email 2.23.0 MIME-Version: 1.0 X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: DPDK patches and discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dev-bounces@dpdk.org 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 --- 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 #include #include +#include #include #include @@ -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( + 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; + + 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 {