From patchwork Fri Jan 13 19:50:21 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Carrillo, Erik G" X-Patchwork-Id: 122047 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 C1277423C7; Fri, 13 Jan 2023 20:50:29 +0100 (CET) Received: from mails.dpdk.org (localhost [127.0.0.1]) by mails.dpdk.org (Postfix) with ESMTP id AB16540E0F; Fri, 13 Jan 2023 20:50:29 +0100 (CET) Received: from mga07.intel.com (mga07.intel.com [134.134.136.100]) by mails.dpdk.org (Postfix) with ESMTP id C9E5E40042 for ; Fri, 13 Jan 2023 20:50:27 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1673639428; x=1705175428; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=ChsRl3cVaAE7Z2Ri9ZY39su3oHIZhX8hwySTRxQEqyM=; b=jDR3x0tX9cRRUQ4a4Hcq70N3SFPed6IFkBm+YFYFmjKVxSwFqTPmrQ6m kzX4istLIq6Mp0RhcAH8AA8iZbNU/6TlFlDh0EUzex1IHrNeTPevKo5t2 +TttuTV/3AhcYjAI76voKmONJRhSFmKxRF++oYbvBM+AX9UQ4I0KpA/f/ RF0RvpXUWWiDZuBHenA1QDF1WPCMH1LLhWW/QWYWoisAhXAUoSHdVoX62 6/ZSoS32k4dV8Gy2uGXYow8NH5BUTnPO99itIEOo2BpuFBvw0Jcbwjbrv JwKJ6tQMH3dRV0OmLhPZM5V00+3mKx1Pe3wYWRkS86Su8a/u/dPkXTvGn A==; X-IronPort-AV: E=McAfee;i="6500,9779,10589"; a="388580650" X-IronPort-AV: E=Sophos;i="5.97,214,1669104000"; d="scan'208";a="388580650" Received: from orsmga006.jf.intel.com ([10.7.209.51]) by orsmga105.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 13 Jan 2023 11:50:26 -0800 X-ExtLoop1: 1 X-IronPort-AV: E=McAfee;i="6500,9779,10589"; a="635880974" X-IronPort-AV: E=Sophos;i="5.97,214,1669104000"; d="scan'208";a="635880974" Received: from txandevlnx321.an.intel.com ([10.123.117.43]) by orsmga006.jf.intel.com with ESMTP; 13 Jan 2023 11:50:25 -0800 From: Erik Gabriel Carrillo To: jerinj@marvell.com Cc: dev@dpdk.org, hofors@lysator.liu.se, jay.jayatheerthan@intel.com, pbhagavatula@marvell.com, s.v.naga.harish.k@intel.com, sthotton@marvell.com, erik.g.carrillo@intel.com Subject: [PATCH v4] eventdev/timer: add API to get remaining ticks Date: Fri, 13 Jan 2023 13:50:21 -0600 Message-Id: <20230113195021.1747261-1-erik.g.carrillo@intel.com> X-Mailer: git-send-email 2.23.0 In-Reply-To: <20221219211135.2399687-1-erik.g.carrillo@intel.com> References: <20221219211135.2399687-1-erik.g.carrillo@intel.com> 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 expires. Signed-off-by: Erik Gabriel Carrillo Acked-by: Jerin Jacob --- v4: * Rename API to rte_event_timer_remaining_ticks_get * Return error if API out param is NULL instead asserting it is non-NULL * Update documentation v3: * Handle ENOTSUP case in unit test v2: * Rename API to rte_event_timer_get_remaining_ticks * Assert that API out param is non-NULL instead of checking and returning error app/test/test_event_timer_adapter.c | 75 ++++++++++++++++++++++++++ lib/eventdev/event_timer_adapter_pmd.h | 7 +++ lib/eventdev/rte_event_timer_adapter.c | 53 ++++++++++++++++++ lib/eventdev/rte_event_timer_adapter.h | 27 ++++++++++ lib/eventdev/version.map | 3 ++ 5 files changed, 165 insertions(+) diff --git a/app/test/test_event_timer_adapter.c b/app/test/test_event_timer_adapter.c index 1a440dfd10..5e7feec1c7 100644 --- a/app/test/test_event_timer_adapter.c +++ b/app/test/test_event_timer_adapter.c @@ -1920,6 +1920,79 @@ 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); + + ret = rte_event_timer_remaining_ticks_get(timdev, ev_tim, + &ticks_remaining); + if (ret == -ENOTSUP) { + rte_mempool_put(eventdev_test_mempool, (void *)ev_tim); + printf("API not supported, skipping test\n"); + return TEST_SKIPPED; + } + + /* Test that unarmed timer returns error */ + TEST_ASSERT_FAIL(ret, + "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_remaining_ticks_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_remaining_ticks_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 +2055,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..c7d4a4f0f6 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_remaining_ticks_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_remaining_ticks_get_t remaining_ticks_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..cae75c9945 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,22 @@ rte_event_timer_adapter_stats_reset(struct rte_event_timer_adapter *adapter) return adapter->ops->stats_reset(adapter); } +int +rte_event_timer_remaining_ticks_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->remaining_ticks_get, -ENOTSUP); + + if (ticks_remaining == NULL) + return -EINVAL; + + return adapter->ops->remaining_ticks_get(adapter, evtim, + ticks_remaining); +} + /* * Software event timer adapter buffer helper functions */ @@ -1072,6 +1089,41 @@ swtim_stats_reset(const struct rte_event_timer_adapter *adapter) return 0; } +static int +swtim_remaining_ticks_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 +1338,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, + .remaining_ticks_get = swtim_remaining_ticks_get, }; static int diff --git a/lib/eventdev/rte_event_timer_adapter.h b/lib/eventdev/rte_event_timer_adapter.h index cd10db19e4..c6f27fb604 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 event timer expiry. + * + * @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 event timer expiry + * + * @return + * - 0: Success + * - -EINVAL Invalid timer adapter identifier or the event timer is not in + * the armed state or ticks_remaining is NULL + * - -ENOTSUP The timer adapter implementation does not support this API. + */ +__rte_experimental +int +rte_event_timer_remaining_ticks_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..4405cd38eb 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_remaining_ticks_get; }; INTERNAL {