+ /* Now process the run lists */
+ while (1) {
+ bool done = true;
+ uint64_t min_expire = UINT64_MAX;
+ int min_idx = 0;
+
+ /* Find the next oldest timer to process */
+ for (i = 0; i < nb_runlists; i++) {
+ tim = run_first_tims[i];
+
+ if (tim != NULL && tim->expire < min_expire) {
+ min_expire = tim->expire;
+ min_idx = i;
+ done = false;
+ }
+ }
+
+ if (done)
+ break;
+
+ tim = run_first_tims[min_idx];
+
+ /* Move down the runlist from which we picked a timer to
+ * execute
+ */
+ run_first_tims[min_idx] = run_first_tims[min_idx]->sl_next[0];
+
+ data->priv_timer[this_lcore].updated = 0;
+ data->priv_timer[this_lcore].running_tim = tim;
+
+ /* Call the provided callback function */
+ f(tim);
+
+ __TIMER_STAT_ADD(data->priv_timer, pending, -1);
+
+ /* the timer was stopped or reloaded by the callback
+ * function, we have nothing to do here
+ */
+ if (data->priv_timer[this_lcore].updated == 1)
+ continue;
+
+ if (tim->period == 0) {
+ /* remove from done list and mark timer as stopped */
+ status.state = RTE_TIMER_STOP;
+ status.owner = RTE_TIMER_NO_OWNER;
+ rte_wmb();
+ tim->status.u32 = status.u32;
+ } else {
+ /* keep it in list and mark timer as pending */
+ rte_spinlock_lock(
+ &data->priv_timer[this_lcore].list_lock);
+ status.state = RTE_TIMER_PENDING;
+ __TIMER_STAT_ADD(data->priv_timer, pending, 1);
+ status.owner = (int16_t)this_lcore;
+ rte_wmb();
+ tim->status.u32 = status.u32;
+ __rte_timer_reset(tim, tim->expire + tim->period,
+ tim->period, this_lcore, tim->f, tim->arg, 1,
+ data);
+ rte_spinlock_unlock(
+ &data->priv_timer[this_lcore].list_lock);
+ }
+
+ data->priv_timer[this_lcore].running_tim = NULL;
+ }
+
+ return 0;
+}
+
+/* Walk pending lists, stopping timers and calling user-specified function */
+int
+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; i < nb_walk_lcores; i++) {
+ 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;