From patchwork Thu Nov 29 23:35:13 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Carrillo, Erik G" X-Patchwork-Id: 48427 X-Patchwork-Delegate: jerinj@marvell.com Return-Path: X-Original-To: patchwork@dpdk.org Delivered-To: patchwork@dpdk.org Received: from [92.243.14.124] (localhost [127.0.0.1]) by dpdk.org (Postfix) with ESMTP id 985F21B52B; Fri, 30 Nov 2018 00:35:32 +0100 (CET) Received: from mga14.intel.com (mga14.intel.com [192.55.52.115]) by dpdk.org (Postfix) with ESMTP id D6EDF1B523 for ; Fri, 30 Nov 2018 00:35:30 +0100 (CET) X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from fmsmga001.fm.intel.com ([10.253.24.23]) by fmsmga103.fm.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 29 Nov 2018 15:35:30 -0800 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.56,296,1539673200"; d="scan'208";a="119277011" Received: from wcpqa1.an.intel.com ([10.123.72.207]) by fmsmga001.fm.intel.com with ESMTP; 29 Nov 2018 15:35:30 -0800 From: Erik Gabriel Carrillo To: pbhagavatula@caviumnetworks.com, jerin.jacob@caviumnetworks.com, rsanford@akamai.com Cc: dev@dpdk.org Date: Thu, 29 Nov 2018 17:35:13 -0600 Message-Id: <1543534514-183766-3-git-send-email-erik.g.carrillo@intel.com> X-Mailer: git-send-email 1.7.10 In-Reply-To: <1543534514-183766-1-git-send-email-erik.g.carrillo@intel.com> References: <1543534514-183766-1-git-send-email-erik.g.carrillo@intel.com> Subject: [dpdk-dev] [PATCH 2/3] timer: add function to stop all timers in a list X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: DPDK patches and discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dev-bounces@dpdk.org Sender: "dev" Add a function to the timer API that allows a caller to traverse a specified set of timer lists, stopping each timer in each list, and invoking a callback function. Signed-off-by: Erik Gabriel Carrillo --- lib/librte_timer/rte_timer.c | 81 +++++++++++++++++++++++++++------- lib/librte_timer/rte_timer.h | 32 ++++++++++++++ lib/librte_timer/rte_timer_version.map | 1 + 3 files changed, 97 insertions(+), 17 deletions(-) diff --git a/lib/librte_timer/rte_timer.c b/lib/librte_timer/rte_timer.c index a76be8b..1eaf755 100644 --- a/lib/librte_timer/rte_timer.c +++ b/lib/librte_timer/rte_timer.c @@ -559,39 +559,30 @@ rte_timer_reset_sync(struct rte_timer *tim, uint64_t ticks, rte_pause(); } -/* Stop the timer associated with the timer handle tim */ -int -rte_timer_stop(struct rte_timer *tim) -{ - return rte_timer_alt_stop(default_data_id, tim); -} - -int __rte_experimental -rte_timer_alt_stop(uint32_t timer_data_id, struct rte_timer *tim) +static int +__rte_timer_stop(struct rte_timer *tim, int local_is_locked, + struct rte_timer_data *data) { union rte_timer_status prev_status, status; unsigned lcore_id = rte_lcore_id(); int ret; - struct rte_timer_data *timer_data; - - TIMER_DATA_VALID_GET_OR_ERR_RET(timer_data_id, timer_data, -EINVAL); /* wait that the timer is in correct status before update, * and mark it as being configured */ - ret = timer_set_config_state(tim, &prev_status, timer_data); + ret = timer_set_config_state(tim, &prev_status, data); if (ret < 0) return -1; - __TIMER_STAT_ADD(timer_data, stop, 1); + __TIMER_STAT_ADD(data, stop, 1); if (prev_status.state == RTE_TIMER_RUNNING && lcore_id < RTE_MAX_LCORE) { - timer_data->priv_timer[lcore_id].updated = 1; + data->priv_timer[lcore_id].updated = 1; } /* remove it from list */ if (prev_status.state == RTE_TIMER_PENDING) { - timer_del(tim, prev_status, 0, timer_data); - __TIMER_STAT_ADD(timer_data, pending, -1); + timer_del(tim, prev_status, local_is_locked, data); + __TIMER_STAT_ADD(data, pending, -1); } /* mark timer as stopped */ @@ -603,6 +594,23 @@ rte_timer_alt_stop(uint32_t timer_data_id, struct rte_timer *tim) return 0; } +/* Stop the timer associated with the timer handle tim */ +int +rte_timer_stop(struct rte_timer *tim) +{ + return rte_timer_alt_stop(default_data_id, tim); +} + +int __rte_experimental +rte_timer_alt_stop(uint32_t timer_data_id, struct rte_timer *tim) +{ + struct rte_timer_data *timer_data; + + TIMER_DATA_VALID_GET_OR_ERR_RET(timer_data_id, timer_data, -EINVAL); + + return __rte_timer_stop(tim, 0, timer_data); +} + /* loop until rte_timer_stop() succeed */ void rte_timer_stop_sync(struct rte_timer *tim) @@ -912,6 +920,45 @@ rte_timer_alt_manage(uint32_t timer_data_id, return 0; } +/* Walk pending lists, stopping timers and calling user-specified function */ +int __rte_experimental +rte_timer_stop_all(uint32_t timer_data_id, unsigned int *walk_lcores, + int nb_walk_lcores, + rte_timer_stop_all_cb_t f, void *f_arg) +{ + int i; + struct priv_timer *priv_timer; + uint32_t walk_lcore; + struct rte_timer *tim, *next_tim; + struct rte_timer_data *timer_data; + + TIMER_DATA_VALID_GET_OR_ERR_RET(timer_data_id, timer_data, -EINVAL); + + for (i = 0, walk_lcore = walk_lcores[i]; + i < nb_walk_lcores; + walk_lcore = walk_lcores[++i]) { + priv_timer = &timer_data->priv_timer[walk_lcore]; + + rte_spinlock_lock(&priv_timer->list_lock); + + for (tim = priv_timer->pending_head.sl_next[0]; + tim != NULL; + tim = next_tim) { + next_tim = tim->sl_next[0]; + + /* Call timer_stop with lock held */ + __rte_timer_stop(tim, 1, timer_data); + + if (f) + f(tim, f_arg); + } + + rte_spinlock_unlock(&priv_timer->list_lock); + } + + return 0; +} + /* dump statistics about timers */ void rte_timer_dump_stats(FILE *f) { diff --git a/lib/librte_timer/rte_timer.h b/lib/librte_timer/rte_timer.h index 9daa334..27b1ebd 100644 --- a/lib/librte_timer/rte_timer.h +++ b/lib/librte_timer/rte_timer.h @@ -446,6 +446,38 @@ rte_timer_alt_manage(uint32_t timer_data_id, unsigned int *poll_lcores, int n_poll_lcores, rte_timer_alt_manage_cb_t f); /** + * Callback function type for rte_timer_stop_all(). + */ +typedef void (*rte_timer_stop_all_cb_t)(struct rte_timer *tim, void *arg); + +/** + * @warning + * @b EXPERIMENTAL: this API may change without prior notice + * + * Walk the pending timer lists for the specified lcore IDs, and for each timer + * that is encountered, stop it and call the specified callback function to + * process it further. + * + * @param timer_data_id + * An identifier indicating which instance of timer data should be used for + * this operation. + * @param walk_lcores + * An array of lcore ids identifying the timer lists that should be processed. + * @param nb_walk_lcores + * The size of the walk_lcores array. + * @param f + * The callback function which should be called for each timers. Can be NULL. + * @param f_arg + * An arbitrary argument that will be passed to f, if it is called. + * @return + * - 0: success + * - EINVAL: invalid timer_data_id + */ +int __rte_experimental +rte_timer_stop_all(uint32_t timer_data_id, unsigned int *walk_lcores, + int nb_walk_lcores, rte_timer_stop_all_cb_t f, void *f_arg); + +/** * @warning * @b EXPERIMENTAL: this API may change without prior notice * diff --git a/lib/librte_timer/rte_timer_version.map b/lib/librte_timer/rte_timer_version.map index 1e6b70d..0fab845 100644 --- a/lib/librte_timer/rte_timer_version.map +++ b/lib/librte_timer/rte_timer_version.map @@ -28,5 +28,6 @@ EXPERIMENTAL { rte_timer_alt_stop; rte_timer_data_alloc; rte_timer_data_dealloc; + rte_timer_stop_all; rte_timer_subsystem_finalize; };