[2/3] timer: add function to stop all timers in a list

Message ID 1543534514-183766-3-git-send-email-erik.g.carrillo@intel.com (mailing list archive)
State Superseded, archived
Delegated to: Jerin Jacob
Headers
Series new software event timer adapter |

Checks

Context Check Description
ci/Intel-compilation fail Compilation issues
ci/checkpatch success coding style OK

Commit Message

Carrillo, Erik G Nov. 29, 2018, 11:35 p.m. UTC
  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 <erik.g.carrillo@intel.com>
---
 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(-)
  

Patch

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;
 };