timer: fix resource leak in finalize
[dpdk.git] / lib / librte_timer / rte_timer.c
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright(c) 2010-2014 Intel Corporation
3  */
4
5 #include <string.h>
6 #include <stdio.h>
7 #include <stdint.h>
8 #include <stdbool.h>
9 #include <inttypes.h>
10 #include <assert.h>
11 #include <sys/queue.h>
12
13 #include <rte_atomic.h>
14 #include <rte_common.h>
15 #include <rte_cycles.h>
16 #include <rte_eal_memconfig.h>
17 #include <rte_per_lcore.h>
18 #include <rte_memory.h>
19 #include <rte_launch.h>
20 #include <rte_eal.h>
21 #include <rte_lcore.h>
22 #include <rte_branch_prediction.h>
23 #include <rte_spinlock.h>
24 #include <rte_random.h>
25 #include <rte_pause.h>
26 #include <rte_memzone.h>
27 #include <rte_malloc.h>
28 #include <rte_compat.h>
29 #include <rte_errno.h>
30
31 #include "rte_timer.h"
32
33 /**
34  * Per-lcore info for timers.
35  */
36 struct priv_timer {
37         struct rte_timer pending_head;  /**< dummy timer instance to head up list */
38         rte_spinlock_t list_lock;       /**< lock to protect list access */
39
40         /** per-core variable that true if a timer was updated on this
41          *  core since last reset of the variable */
42         int updated;
43
44         /** track the current depth of the skiplist */
45         unsigned curr_skiplist_depth;
46
47         unsigned prev_lcore;              /**< used for lcore round robin */
48
49         /** running timer on this lcore now */
50         struct rte_timer *running_tim;
51
52 #ifdef RTE_LIBRTE_TIMER_DEBUG
53         /** per-lcore statistics */
54         struct rte_timer_debug_stats stats;
55 #endif
56 } __rte_cache_aligned;
57
58 #define FL_ALLOCATED    (1 << 0)
59 struct rte_timer_data {
60         struct priv_timer priv_timer[RTE_MAX_LCORE];
61         uint8_t internal_flags;
62 };
63
64 #define RTE_MAX_DATA_ELS 64
65 static const struct rte_memzone *rte_timer_data_mz;
66 static int *volatile rte_timer_mz_refcnt;
67 static struct rte_timer_data *rte_timer_data_arr;
68 static const uint32_t default_data_id;
69 static uint32_t rte_timer_subsystem_initialized;
70
71 /* For maintaining older interfaces for a period */
72 static struct rte_timer_data default_timer_data;
73
74 /* when debug is enabled, store some statistics */
75 #ifdef RTE_LIBRTE_TIMER_DEBUG
76 #define __TIMER_STAT_ADD(priv_timer, name, n) do {                      \
77                 unsigned __lcore_id = rte_lcore_id();                   \
78                 if (__lcore_id < RTE_MAX_LCORE)                         \
79                         priv_timer[__lcore_id].stats.name += (n);       \
80         } while(0)
81 #else
82 #define __TIMER_STAT_ADD(priv_timer, name, n) do {} while (0)
83 #endif
84
85 static inline int
86 timer_data_valid(uint32_t id)
87 {
88         return !!(rte_timer_data_arr[id].internal_flags & FL_ALLOCATED);
89 }
90
91 /* validate ID and retrieve timer data pointer, or return error value */
92 #define TIMER_DATA_VALID_GET_OR_ERR_RET(id, timer_data, retval) do {    \
93         if (id >= RTE_MAX_DATA_ELS || !timer_data_valid(id))            \
94                 return retval;                                          \
95         timer_data = &rte_timer_data_arr[id];                           \
96 } while (0)
97
98 int
99 rte_timer_data_alloc(uint32_t *id_ptr)
100 {
101         int i;
102         struct rte_timer_data *data;
103
104         if (!rte_timer_subsystem_initialized)
105                 return -ENOMEM;
106
107         for (i = 0; i < RTE_MAX_DATA_ELS; i++) {
108                 data = &rte_timer_data_arr[i];
109                 if (!(data->internal_flags & FL_ALLOCATED)) {
110                         data->internal_flags |= FL_ALLOCATED;
111
112                         if (id_ptr)
113                                 *id_ptr = i;
114
115                         return 0;
116                 }
117         }
118
119         return -ENOSPC;
120 }
121
122 int
123 rte_timer_data_dealloc(uint32_t id)
124 {
125         struct rte_timer_data *timer_data;
126         TIMER_DATA_VALID_GET_OR_ERR_RET(id, timer_data, -EINVAL);
127
128         timer_data->internal_flags &= ~(FL_ALLOCATED);
129
130         return 0;
131 }
132
133 void
134 rte_timer_subsystem_init_v20(void)
135 {
136         unsigned lcore_id;
137         struct priv_timer *priv_timer = default_timer_data.priv_timer;
138
139         /* since priv_timer is static, it's zeroed by default, so only init some
140          * fields.
141          */
142         for (lcore_id = 0; lcore_id < RTE_MAX_LCORE; lcore_id ++) {
143                 rte_spinlock_init(&priv_timer[lcore_id].list_lock);
144                 priv_timer[lcore_id].prev_lcore = lcore_id;
145         }
146 }
147 VERSION_SYMBOL(rte_timer_subsystem_init, _v20, 2.0);
148
149 /* Init the timer library. Allocate an array of timer data structs in shared
150  * memory, and allocate the zeroth entry for use with original timer
151  * APIs. Since the intersection of the sets of lcore ids in primary and
152  * secondary processes should be empty, the zeroth entry can be shared by
153  * multiple processes.
154  */
155 int
156 rte_timer_subsystem_init_v1905(void)
157 {
158         const struct rte_memzone *mz;
159         struct rte_timer_data *data;
160         int i, lcore_id;
161         static const char *mz_name = "rte_timer_mz";
162         const size_t data_arr_size =
163                         RTE_MAX_DATA_ELS * sizeof(*rte_timer_data_arr);
164         const size_t mem_size = data_arr_size + sizeof(*rte_timer_mz_refcnt);
165         bool do_full_init = true;
166
167         if (rte_timer_subsystem_initialized)
168                 return -EALREADY;
169
170         rte_mcfg_timer_lock();
171
172         mz = rte_memzone_lookup(mz_name);
173         if (mz == NULL) {
174                 mz = rte_memzone_reserve_aligned(mz_name, mem_size,
175                                 SOCKET_ID_ANY, 0, RTE_CACHE_LINE_SIZE);
176                 if (mz == NULL) {
177                         rte_mcfg_timer_unlock();
178                         return -ENOMEM;
179                 }
180                 do_full_init = true;
181         } else
182                 do_full_init = false;
183
184         rte_timer_data_mz = mz;
185         rte_timer_data_arr = mz->addr;
186         rte_timer_mz_refcnt = (void *)((char *)mz->addr + data_arr_size);
187
188         if (do_full_init) {
189                 for (i = 0; i < RTE_MAX_DATA_ELS; i++) {
190                         data = &rte_timer_data_arr[i];
191
192                         for (lcore_id = 0; lcore_id < RTE_MAX_LCORE;
193                              lcore_id++) {
194                                 rte_spinlock_init(
195                                         &data->priv_timer[lcore_id].list_lock);
196                                 data->priv_timer[lcore_id].prev_lcore =
197                                         lcore_id;
198                         }
199                 }
200         }
201
202         rte_timer_data_arr[default_data_id].internal_flags |= FL_ALLOCATED;
203         (*rte_timer_mz_refcnt)++;
204
205         rte_mcfg_timer_unlock();
206
207         rte_timer_subsystem_initialized = 1;
208
209         return 0;
210 }
211 MAP_STATIC_SYMBOL(int rte_timer_subsystem_init(void),
212                   rte_timer_subsystem_init_v1905);
213 BIND_DEFAULT_SYMBOL(rte_timer_subsystem_init, _v1905, 19.05);
214
215 void
216 rte_timer_subsystem_finalize(void)
217 {
218         if (!rte_timer_subsystem_initialized)
219                 return;
220
221         rte_mcfg_timer_lock();
222
223         if (--(*rte_timer_mz_refcnt) == 0)
224                 rte_memzone_free(rte_timer_data_mz);
225
226         rte_mcfg_timer_unlock();
227
228         rte_timer_subsystem_initialized = 0;
229 }
230
231 /* Initialize the timer handle tim for use */
232 void
233 rte_timer_init(struct rte_timer *tim)
234 {
235         union rte_timer_status status;
236
237         status.state = RTE_TIMER_STOP;
238         status.owner = RTE_TIMER_NO_OWNER;
239         tim->status.u32 = status.u32;
240 }
241
242 /*
243  * if timer is pending or stopped (or running on the same core than
244  * us), mark timer as configuring, and on success return the previous
245  * status of the timer
246  */
247 static int
248 timer_set_config_state(struct rte_timer *tim,
249                        union rte_timer_status *ret_prev_status,
250                        struct priv_timer *priv_timer)
251 {
252         union rte_timer_status prev_status, status;
253         int success = 0;
254         unsigned lcore_id;
255
256         lcore_id = rte_lcore_id();
257
258         /* wait that the timer is in correct status before update,
259          * and mark it as being configured */
260         while (success == 0) {
261                 prev_status.u32 = tim->status.u32;
262
263                 /* timer is running on another core
264                  * or ready to run on local core, exit
265                  */
266                 if (prev_status.state == RTE_TIMER_RUNNING &&
267                     (prev_status.owner != (uint16_t)lcore_id ||
268                      tim != priv_timer[lcore_id].running_tim))
269                         return -1;
270
271                 /* timer is being configured on another core */
272                 if (prev_status.state == RTE_TIMER_CONFIG)
273                         return -1;
274
275                 /* here, we know that timer is stopped or pending,
276                  * mark it atomically as being configured */
277                 status.state = RTE_TIMER_CONFIG;
278                 status.owner = (int16_t)lcore_id;
279                 success = rte_atomic32_cmpset(&tim->status.u32,
280                                               prev_status.u32,
281                                               status.u32);
282         }
283
284         ret_prev_status->u32 = prev_status.u32;
285         return 0;
286 }
287
288 /*
289  * if timer is pending, mark timer as running
290  */
291 static int
292 timer_set_running_state(struct rte_timer *tim)
293 {
294         union rte_timer_status prev_status, status;
295         unsigned lcore_id = rte_lcore_id();
296         int success = 0;
297
298         /* wait that the timer is in correct status before update,
299          * and mark it as running */
300         while (success == 0) {
301                 prev_status.u32 = tim->status.u32;
302
303                 /* timer is not pending anymore */
304                 if (prev_status.state != RTE_TIMER_PENDING)
305                         return -1;
306
307                 /* here, we know that timer is stopped or pending,
308                  * mark it atomically as being configured */
309                 status.state = RTE_TIMER_RUNNING;
310                 status.owner = (int16_t)lcore_id;
311                 success = rte_atomic32_cmpset(&tim->status.u32,
312                                               prev_status.u32,
313                                               status.u32);
314         }
315
316         return 0;
317 }
318
319 /*
320  * Return a skiplist level for a new entry.
321  * This probabilistically gives a level with p=1/4 that an entry at level n
322  * will also appear at level n+1.
323  */
324 static uint32_t
325 timer_get_skiplist_level(unsigned curr_depth)
326 {
327 #ifdef RTE_LIBRTE_TIMER_DEBUG
328         static uint32_t i, count = 0;
329         static uint32_t levels[MAX_SKIPLIST_DEPTH] = {0};
330 #endif
331
332         /* probability value is 1/4, i.e. all at level 0, 1 in 4 is at level 1,
333          * 1 in 16 at level 2, 1 in 64 at level 3, etc. Calculated using lowest
334          * bit position of a (pseudo)random number.
335          */
336         uint32_t rand = rte_rand() & (UINT32_MAX - 1);
337         uint32_t level = rand == 0 ? MAX_SKIPLIST_DEPTH : (rte_bsf32(rand)-1) / 2;
338
339         /* limit the levels used to one above our current level, so we don't,
340          * for instance, have a level 0 and a level 7 without anything between
341          */
342         if (level > curr_depth)
343                 level = curr_depth;
344         if (level >= MAX_SKIPLIST_DEPTH)
345                 level = MAX_SKIPLIST_DEPTH-1;
346 #ifdef RTE_LIBRTE_TIMER_DEBUG
347         count ++;
348         levels[level]++;
349         if (count % 10000 == 0)
350                 for (i = 0; i < MAX_SKIPLIST_DEPTH; i++)
351                         printf("Level %u: %u\n", (unsigned)i, (unsigned)levels[i]);
352 #endif
353         return level;
354 }
355
356 /*
357  * For a given time value, get the entries at each level which
358  * are <= that time value.
359  */
360 static void
361 timer_get_prev_entries(uint64_t time_val, unsigned tim_lcore,
362                        struct rte_timer **prev, struct priv_timer *priv_timer)
363 {
364         unsigned lvl = priv_timer[tim_lcore].curr_skiplist_depth;
365         prev[lvl] = &priv_timer[tim_lcore].pending_head;
366         while(lvl != 0) {
367                 lvl--;
368                 prev[lvl] = prev[lvl+1];
369                 while (prev[lvl]->sl_next[lvl] &&
370                                 prev[lvl]->sl_next[lvl]->expire <= time_val)
371                         prev[lvl] = prev[lvl]->sl_next[lvl];
372         }
373 }
374
375 /*
376  * Given a timer node in the skiplist, find the previous entries for it at
377  * all skiplist levels.
378  */
379 static void
380 timer_get_prev_entries_for_node(struct rte_timer *tim, unsigned tim_lcore,
381                                 struct rte_timer **prev,
382                                 struct priv_timer *priv_timer)
383 {
384         int i;
385
386         /* to get a specific entry in the list, look for just lower than the time
387          * values, and then increment on each level individually if necessary
388          */
389         timer_get_prev_entries(tim->expire - 1, tim_lcore, prev, priv_timer);
390         for (i = priv_timer[tim_lcore].curr_skiplist_depth - 1; i >= 0; i--) {
391                 while (prev[i]->sl_next[i] != NULL &&
392                                 prev[i]->sl_next[i] != tim &&
393                                 prev[i]->sl_next[i]->expire <= tim->expire)
394                         prev[i] = prev[i]->sl_next[i];
395         }
396 }
397
398 /* call with lock held as necessary
399  * add in list
400  * timer must be in config state
401  * timer must not be in a list
402  */
403 static void
404 timer_add(struct rte_timer *tim, unsigned int tim_lcore,
405           struct priv_timer *priv_timer)
406 {
407         unsigned lvl;
408         struct rte_timer *prev[MAX_SKIPLIST_DEPTH+1];
409
410         /* find where exactly this element goes in the list of elements
411          * for each depth. */
412         timer_get_prev_entries(tim->expire, tim_lcore, prev, priv_timer);
413
414         /* now assign it a new level and add at that level */
415         const unsigned tim_level = timer_get_skiplist_level(
416                         priv_timer[tim_lcore].curr_skiplist_depth);
417         if (tim_level == priv_timer[tim_lcore].curr_skiplist_depth)
418                 priv_timer[tim_lcore].curr_skiplist_depth++;
419
420         lvl = tim_level;
421         while (lvl > 0) {
422                 tim->sl_next[lvl] = prev[lvl]->sl_next[lvl];
423                 prev[lvl]->sl_next[lvl] = tim;
424                 lvl--;
425         }
426         tim->sl_next[0] = prev[0]->sl_next[0];
427         prev[0]->sl_next[0] = tim;
428
429         /* save the lowest list entry into the expire field of the dummy hdr
430          * NOTE: this is not atomic on 32-bit*/
431         priv_timer[tim_lcore].pending_head.expire = priv_timer[tim_lcore].\
432                         pending_head.sl_next[0]->expire;
433 }
434
435 /*
436  * del from list, lock if needed
437  * timer must be in config state
438  * timer must be in a list
439  */
440 static void
441 timer_del(struct rte_timer *tim, union rte_timer_status prev_status,
442           int local_is_locked, struct priv_timer *priv_timer)
443 {
444         unsigned lcore_id = rte_lcore_id();
445         unsigned prev_owner = prev_status.owner;
446         int i;
447         struct rte_timer *prev[MAX_SKIPLIST_DEPTH+1];
448
449         /* if timer needs is pending another core, we need to lock the
450          * list; if it is on local core, we need to lock if we are not
451          * called from rte_timer_manage() */
452         if (prev_owner != lcore_id || !local_is_locked)
453                 rte_spinlock_lock(&priv_timer[prev_owner].list_lock);
454
455         /* save the lowest list entry into the expire field of the dummy hdr.
456          * NOTE: this is not atomic on 32-bit */
457         if (tim == priv_timer[prev_owner].pending_head.sl_next[0])
458                 priv_timer[prev_owner].pending_head.expire =
459                                 ((tim->sl_next[0] == NULL) ? 0 : tim->sl_next[0]->expire);
460
461         /* adjust pointers from previous entries to point past this */
462         timer_get_prev_entries_for_node(tim, prev_owner, prev, priv_timer);
463         for (i = priv_timer[prev_owner].curr_skiplist_depth - 1; i >= 0; i--) {
464                 if (prev[i]->sl_next[i] == tim)
465                         prev[i]->sl_next[i] = tim->sl_next[i];
466         }
467
468         /* in case we deleted last entry at a level, adjust down max level */
469         for (i = priv_timer[prev_owner].curr_skiplist_depth - 1; i >= 0; i--)
470                 if (priv_timer[prev_owner].pending_head.sl_next[i] == NULL)
471                         priv_timer[prev_owner].curr_skiplist_depth --;
472                 else
473                         break;
474
475         if (prev_owner != lcore_id || !local_is_locked)
476                 rte_spinlock_unlock(&priv_timer[prev_owner].list_lock);
477 }
478
479 /* Reset and start the timer associated with the timer handle (private func) */
480 static int
481 __rte_timer_reset(struct rte_timer *tim, uint64_t expire,
482                   uint64_t period, unsigned tim_lcore,
483                   rte_timer_cb_t fct, void *arg,
484                   int local_is_locked,
485                   struct rte_timer_data *timer_data)
486 {
487         union rte_timer_status prev_status, status;
488         int ret;
489         unsigned lcore_id = rte_lcore_id();
490         struct priv_timer *priv_timer = timer_data->priv_timer;
491
492         /* round robin for tim_lcore */
493         if (tim_lcore == (unsigned)LCORE_ID_ANY) {
494                 if (lcore_id < RTE_MAX_LCORE) {
495                         /* EAL thread with valid lcore_id */
496                         tim_lcore = rte_get_next_lcore(
497                                 priv_timer[lcore_id].prev_lcore,
498                                 0, 1);
499                         priv_timer[lcore_id].prev_lcore = tim_lcore;
500                 } else
501                         /* non-EAL thread do not run rte_timer_manage(),
502                          * so schedule the timer on the first enabled lcore. */
503                         tim_lcore = rte_get_next_lcore(LCORE_ID_ANY, 0, 1);
504         }
505
506         /* wait that the timer is in correct status before update,
507          * and mark it as being configured */
508         ret = timer_set_config_state(tim, &prev_status, priv_timer);
509         if (ret < 0)
510                 return -1;
511
512         __TIMER_STAT_ADD(priv_timer, reset, 1);
513         if (prev_status.state == RTE_TIMER_RUNNING &&
514             lcore_id < RTE_MAX_LCORE) {
515                 priv_timer[lcore_id].updated = 1;
516         }
517
518         /* remove it from list */
519         if (prev_status.state == RTE_TIMER_PENDING) {
520                 timer_del(tim, prev_status, local_is_locked, priv_timer);
521                 __TIMER_STAT_ADD(priv_timer, pending, -1);
522         }
523
524         tim->period = period;
525         tim->expire = expire;
526         tim->f = fct;
527         tim->arg = arg;
528
529         /* if timer needs to be scheduled on another core, we need to
530          * lock the destination list; if it is on local core, we need to lock if
531          * we are not called from rte_timer_manage()
532          */
533         if (tim_lcore != lcore_id || !local_is_locked)
534                 rte_spinlock_lock(&priv_timer[tim_lcore].list_lock);
535
536         __TIMER_STAT_ADD(priv_timer, pending, 1);
537         timer_add(tim, tim_lcore, priv_timer);
538
539         /* update state: as we are in CONFIG state, only us can modify
540          * the state so we don't need to use cmpset() here */
541         rte_wmb();
542         status.state = RTE_TIMER_PENDING;
543         status.owner = (int16_t)tim_lcore;
544         tim->status.u32 = status.u32;
545
546         if (tim_lcore != lcore_id || !local_is_locked)
547                 rte_spinlock_unlock(&priv_timer[tim_lcore].list_lock);
548
549         return 0;
550 }
551
552 /* Reset and start the timer associated with the timer handle tim */
553 int
554 rte_timer_reset_v20(struct rte_timer *tim, uint64_t ticks,
555                     enum rte_timer_type type, unsigned int tim_lcore,
556                     rte_timer_cb_t fct, void *arg)
557 {
558         uint64_t cur_time = rte_get_timer_cycles();
559         uint64_t period;
560
561         if (unlikely((tim_lcore != (unsigned)LCORE_ID_ANY) &&
562                         !(rte_lcore_is_enabled(tim_lcore) ||
563                           rte_lcore_has_role(tim_lcore, ROLE_SERVICE))))
564                 return -1;
565
566         if (type == PERIODICAL)
567                 period = ticks;
568         else
569                 period = 0;
570
571         return __rte_timer_reset(tim,  cur_time + ticks, period, tim_lcore,
572                           fct, arg, 0, &default_timer_data);
573 }
574 VERSION_SYMBOL(rte_timer_reset, _v20, 2.0);
575
576 int
577 rte_timer_reset_v1905(struct rte_timer *tim, uint64_t ticks,
578                       enum rte_timer_type type, unsigned int tim_lcore,
579                       rte_timer_cb_t fct, void *arg)
580 {
581         return rte_timer_alt_reset(default_data_id, tim, ticks, type,
582                                    tim_lcore, fct, arg);
583 }
584 MAP_STATIC_SYMBOL(int rte_timer_reset(struct rte_timer *tim, uint64_t ticks,
585                                       enum rte_timer_type type,
586                                       unsigned int tim_lcore,
587                                       rte_timer_cb_t fct, void *arg),
588                   rte_timer_reset_v1905);
589 BIND_DEFAULT_SYMBOL(rte_timer_reset, _v1905, 19.05);
590
591 int
592 rte_timer_alt_reset(uint32_t timer_data_id, struct rte_timer *tim,
593                     uint64_t ticks, enum rte_timer_type type,
594                     unsigned int tim_lcore, rte_timer_cb_t fct, void *arg)
595 {
596         uint64_t cur_time = rte_get_timer_cycles();
597         uint64_t period;
598         struct rte_timer_data *timer_data;
599
600         TIMER_DATA_VALID_GET_OR_ERR_RET(timer_data_id, timer_data, -EINVAL);
601
602         if (type == PERIODICAL)
603                 period = ticks;
604         else
605                 period = 0;
606
607         return __rte_timer_reset(tim,  cur_time + ticks, period, tim_lcore,
608                                  fct, arg, 0, timer_data);
609 }
610
611 /* loop until rte_timer_reset() succeed */
612 void
613 rte_timer_reset_sync(struct rte_timer *tim, uint64_t ticks,
614                      enum rte_timer_type type, unsigned tim_lcore,
615                      rte_timer_cb_t fct, void *arg)
616 {
617         while (rte_timer_reset(tim, ticks, type, tim_lcore,
618                                fct, arg) != 0)
619                 rte_pause();
620 }
621
622 static int
623 __rte_timer_stop(struct rte_timer *tim, int local_is_locked,
624                  struct rte_timer_data *timer_data)
625 {
626         union rte_timer_status prev_status, status;
627         unsigned lcore_id = rte_lcore_id();
628         int ret;
629         struct priv_timer *priv_timer = timer_data->priv_timer;
630
631         /* wait that the timer is in correct status before update,
632          * and mark it as being configured */
633         ret = timer_set_config_state(tim, &prev_status, priv_timer);
634         if (ret < 0)
635                 return -1;
636
637         __TIMER_STAT_ADD(priv_timer, stop, 1);
638         if (prev_status.state == RTE_TIMER_RUNNING &&
639             lcore_id < RTE_MAX_LCORE) {
640                 priv_timer[lcore_id].updated = 1;
641         }
642
643         /* remove it from list */
644         if (prev_status.state == RTE_TIMER_PENDING) {
645                 timer_del(tim, prev_status, local_is_locked, priv_timer);
646                 __TIMER_STAT_ADD(priv_timer, pending, -1);
647         }
648
649         /* mark timer as stopped */
650         rte_wmb();
651         status.state = RTE_TIMER_STOP;
652         status.owner = RTE_TIMER_NO_OWNER;
653         tim->status.u32 = status.u32;
654
655         return 0;
656 }
657
658 /* Stop the timer associated with the timer handle tim */
659 int
660 rte_timer_stop_v20(struct rte_timer *tim)
661 {
662         return __rte_timer_stop(tim, 0, &default_timer_data);
663 }
664 VERSION_SYMBOL(rte_timer_stop, _v20, 2.0);
665
666 int
667 rte_timer_stop_v1905(struct rte_timer *tim)
668 {
669         return rte_timer_alt_stop(default_data_id, tim);
670 }
671 MAP_STATIC_SYMBOL(int rte_timer_stop(struct rte_timer *tim),
672                   rte_timer_stop_v1905);
673 BIND_DEFAULT_SYMBOL(rte_timer_stop, _v1905, 19.05);
674
675 int
676 rte_timer_alt_stop(uint32_t timer_data_id, struct rte_timer *tim)
677 {
678         struct rte_timer_data *timer_data;
679
680         TIMER_DATA_VALID_GET_OR_ERR_RET(timer_data_id, timer_data, -EINVAL);
681
682         return __rte_timer_stop(tim, 0, timer_data);
683 }
684
685 /* loop until rte_timer_stop() succeed */
686 void
687 rte_timer_stop_sync(struct rte_timer *tim)
688 {
689         while (rte_timer_stop(tim) != 0)
690                 rte_pause();
691 }
692
693 /* Test the PENDING status of the timer handle tim */
694 int
695 rte_timer_pending(struct rte_timer *tim)
696 {
697         return tim->status.state == RTE_TIMER_PENDING;
698 }
699
700 /* must be called periodically, run all timer that expired */
701 static void
702 __rte_timer_manage(struct rte_timer_data *timer_data)
703 {
704         union rte_timer_status status;
705         struct rte_timer *tim, *next_tim;
706         struct rte_timer *run_first_tim, **pprev;
707         unsigned lcore_id = rte_lcore_id();
708         struct rte_timer *prev[MAX_SKIPLIST_DEPTH + 1];
709         uint64_t cur_time;
710         int i, ret;
711         struct priv_timer *priv_timer = timer_data->priv_timer;
712
713         /* timer manager only runs on EAL thread with valid lcore_id */
714         assert(lcore_id < RTE_MAX_LCORE);
715
716         __TIMER_STAT_ADD(priv_timer, manage, 1);
717         /* optimize for the case where per-cpu list is empty */
718         if (priv_timer[lcore_id].pending_head.sl_next[0] == NULL)
719                 return;
720         cur_time = rte_get_timer_cycles();
721
722 #ifdef RTE_ARCH_64
723         /* on 64-bit the value cached in the pending_head.expired will be
724          * updated atomically, so we can consult that for a quick check here
725          * outside the lock */
726         if (likely(priv_timer[lcore_id].pending_head.expire > cur_time))
727                 return;
728 #endif
729
730         /* browse ordered list, add expired timers in 'expired' list */
731         rte_spinlock_lock(&priv_timer[lcore_id].list_lock);
732
733         /* if nothing to do just unlock and return */
734         if (priv_timer[lcore_id].pending_head.sl_next[0] == NULL ||
735             priv_timer[lcore_id].pending_head.sl_next[0]->expire > cur_time) {
736                 rte_spinlock_unlock(&priv_timer[lcore_id].list_lock);
737                 return;
738         }
739
740         /* save start of list of expired timers */
741         tim = priv_timer[lcore_id].pending_head.sl_next[0];
742
743         /* break the existing list at current time point */
744         timer_get_prev_entries(cur_time, lcore_id, prev, priv_timer);
745         for (i = priv_timer[lcore_id].curr_skiplist_depth -1; i >= 0; i--) {
746                 if (prev[i] == &priv_timer[lcore_id].pending_head)
747                         continue;
748                 priv_timer[lcore_id].pending_head.sl_next[i] =
749                     prev[i]->sl_next[i];
750                 if (prev[i]->sl_next[i] == NULL)
751                         priv_timer[lcore_id].curr_skiplist_depth--;
752                 prev[i] ->sl_next[i] = NULL;
753         }
754
755         /* transition run-list from PENDING to RUNNING */
756         run_first_tim = tim;
757         pprev = &run_first_tim;
758
759         for ( ; tim != NULL; tim = next_tim) {
760                 next_tim = tim->sl_next[0];
761
762                 ret = timer_set_running_state(tim);
763                 if (likely(ret == 0)) {
764                         pprev = &tim->sl_next[0];
765                 } else {
766                         /* another core is trying to re-config this one,
767                          * remove it from local expired list
768                          */
769                         *pprev = next_tim;
770                 }
771         }
772
773         /* update the next to expire timer value */
774         priv_timer[lcore_id].pending_head.expire =
775             (priv_timer[lcore_id].pending_head.sl_next[0] == NULL) ? 0 :
776                 priv_timer[lcore_id].pending_head.sl_next[0]->expire;
777
778         rte_spinlock_unlock(&priv_timer[lcore_id].list_lock);
779
780         /* now scan expired list and call callbacks */
781         for (tim = run_first_tim; tim != NULL; tim = next_tim) {
782                 next_tim = tim->sl_next[0];
783                 priv_timer[lcore_id].updated = 0;
784                 priv_timer[lcore_id].running_tim = tim;
785
786                 /* execute callback function with list unlocked */
787                 tim->f(tim, tim->arg);
788
789                 __TIMER_STAT_ADD(priv_timer, pending, -1);
790                 /* the timer was stopped or reloaded by the callback
791                  * function, we have nothing to do here */
792                 if (priv_timer[lcore_id].updated == 1)
793                         continue;
794
795                 if (tim->period == 0) {
796                         /* remove from done list and mark timer as stopped */
797                         status.state = RTE_TIMER_STOP;
798                         status.owner = RTE_TIMER_NO_OWNER;
799                         rte_wmb();
800                         tim->status.u32 = status.u32;
801                 }
802                 else {
803                         /* keep it in list and mark timer as pending */
804                         rte_spinlock_lock(&priv_timer[lcore_id].list_lock);
805                         status.state = RTE_TIMER_PENDING;
806                         __TIMER_STAT_ADD(priv_timer, pending, 1);
807                         status.owner = (int16_t)lcore_id;
808                         rte_wmb();
809                         tim->status.u32 = status.u32;
810                         __rte_timer_reset(tim, tim->expire + tim->period,
811                                 tim->period, lcore_id, tim->f, tim->arg, 1,
812                                 timer_data);
813                         rte_spinlock_unlock(&priv_timer[lcore_id].list_lock);
814                 }
815         }
816         priv_timer[lcore_id].running_tim = NULL;
817 }
818
819 void
820 rte_timer_manage_v20(void)
821 {
822         __rte_timer_manage(&default_timer_data);
823 }
824 VERSION_SYMBOL(rte_timer_manage, _v20, 2.0);
825
826 int
827 rte_timer_manage_v1905(void)
828 {
829         struct rte_timer_data *timer_data;
830
831         TIMER_DATA_VALID_GET_OR_ERR_RET(default_data_id, timer_data, -EINVAL);
832
833         __rte_timer_manage(timer_data);
834
835         return 0;
836 }
837 MAP_STATIC_SYMBOL(int rte_timer_manage(void), rte_timer_manage_v1905);
838 BIND_DEFAULT_SYMBOL(rte_timer_manage, _v1905, 19.05);
839
840 int
841 rte_timer_alt_manage(uint32_t timer_data_id,
842                      unsigned int *poll_lcores,
843                      int nb_poll_lcores,
844                      rte_timer_alt_manage_cb_t f)
845 {
846         unsigned int default_poll_lcores[] = {rte_lcore_id()};
847         union rte_timer_status status;
848         struct rte_timer *tim, *next_tim, **pprev;
849         struct rte_timer *run_first_tims[RTE_MAX_LCORE];
850         unsigned int this_lcore = rte_lcore_id();
851         struct rte_timer *prev[MAX_SKIPLIST_DEPTH + 1];
852         uint64_t cur_time;
853         int i, j, ret;
854         int nb_runlists = 0;
855         struct rte_timer_data *data;
856         struct priv_timer *privp;
857         uint32_t poll_lcore;
858
859         TIMER_DATA_VALID_GET_OR_ERR_RET(timer_data_id, data, -EINVAL);
860
861         /* timer manager only runs on EAL thread with valid lcore_id */
862         assert(this_lcore < RTE_MAX_LCORE);
863
864         __TIMER_STAT_ADD(data->priv_timer, manage, 1);
865
866         if (poll_lcores == NULL) {
867                 poll_lcores = default_poll_lcores;
868                 nb_poll_lcores = RTE_DIM(default_poll_lcores);
869         }
870
871         for (i = 0; i < nb_poll_lcores; i++) {
872                 poll_lcore = poll_lcores[i];
873                 privp = &data->priv_timer[poll_lcore];
874
875                 /* optimize for the case where per-cpu list is empty */
876                 if (privp->pending_head.sl_next[0] == NULL)
877                         continue;
878                 cur_time = rte_get_timer_cycles();
879
880 #ifdef RTE_ARCH_64
881                 /* on 64-bit the value cached in the pending_head.expired will
882                  * be updated atomically, so we can consult that for a quick
883                  * check here outside the lock
884                  */
885                 if (likely(privp->pending_head.expire > cur_time))
886                         continue;
887 #endif
888
889                 /* browse ordered list, add expired timers in 'expired' list */
890                 rte_spinlock_lock(&privp->list_lock);
891
892                 /* if nothing to do just unlock and return */
893                 if (privp->pending_head.sl_next[0] == NULL ||
894                     privp->pending_head.sl_next[0]->expire > cur_time) {
895                         rte_spinlock_unlock(&privp->list_lock);
896                         continue;
897                 }
898
899                 /* save start of list of expired timers */
900                 tim = privp->pending_head.sl_next[0];
901
902                 /* break the existing list at current time point */
903                 timer_get_prev_entries(cur_time, poll_lcore, prev,
904                                        data->priv_timer);
905                 for (j = privp->curr_skiplist_depth - 1; j >= 0; j--) {
906                         if (prev[j] == &privp->pending_head)
907                                 continue;
908                         privp->pending_head.sl_next[j] =
909                                 prev[j]->sl_next[j];
910                         if (prev[j]->sl_next[j] == NULL)
911                                 privp->curr_skiplist_depth--;
912
913                         prev[j]->sl_next[j] = NULL;
914                 }
915
916                 /* transition run-list from PENDING to RUNNING */
917                 run_first_tims[nb_runlists] = tim;
918                 pprev = &run_first_tims[nb_runlists];
919                 nb_runlists++;
920
921                 for ( ; tim != NULL; tim = next_tim) {
922                         next_tim = tim->sl_next[0];
923
924                         ret = timer_set_running_state(tim);
925                         if (likely(ret == 0)) {
926                                 pprev = &tim->sl_next[0];
927                         } else {
928                                 /* another core is trying to re-config this one,
929                                  * remove it from local expired list
930                                  */
931                                 *pprev = next_tim;
932                         }
933                 }
934
935                 /* update the next to expire timer value */
936                 privp->pending_head.expire =
937                     (privp->pending_head.sl_next[0] == NULL) ? 0 :
938                         privp->pending_head.sl_next[0]->expire;
939
940                 rte_spinlock_unlock(&privp->list_lock);
941         }
942
943         /* Now process the run lists */
944         while (1) {
945                 bool done = true;
946                 uint64_t min_expire = UINT64_MAX;
947                 int min_idx = 0;
948
949                 /* Find the next oldest timer to process */
950                 for (i = 0; i < nb_runlists; i++) {
951                         tim = run_first_tims[i];
952
953                         if (tim != NULL && tim->expire < min_expire) {
954                                 min_expire = tim->expire;
955                                 min_idx = i;
956                                 done = false;
957                         }
958                 }
959
960                 if (done)
961                         break;
962
963                 tim = run_first_tims[min_idx];
964
965                 /* Move down the runlist from which we picked a timer to
966                  * execute
967                  */
968                 run_first_tims[min_idx] = run_first_tims[min_idx]->sl_next[0];
969
970                 data->priv_timer[this_lcore].updated = 0;
971                 data->priv_timer[this_lcore].running_tim = tim;
972
973                 /* Call the provided callback function */
974                 f(tim);
975
976                 __TIMER_STAT_ADD(data->priv_timer, pending, -1);
977
978                 /* the timer was stopped or reloaded by the callback
979                  * function, we have nothing to do here
980                  */
981                 if (data->priv_timer[this_lcore].updated == 1)
982                         continue;
983
984                 if (tim->period == 0) {
985                         /* remove from done list and mark timer as stopped */
986                         status.state = RTE_TIMER_STOP;
987                         status.owner = RTE_TIMER_NO_OWNER;
988                         rte_wmb();
989                         tim->status.u32 = status.u32;
990                 } else {
991                         /* keep it in list and mark timer as pending */
992                         rte_spinlock_lock(
993                                 &data->priv_timer[this_lcore].list_lock);
994                         status.state = RTE_TIMER_PENDING;
995                         __TIMER_STAT_ADD(data->priv_timer, pending, 1);
996                         status.owner = (int16_t)this_lcore;
997                         rte_wmb();
998                         tim->status.u32 = status.u32;
999                         __rte_timer_reset(tim, tim->expire + tim->period,
1000                                 tim->period, this_lcore, tim->f, tim->arg, 1,
1001                                 data);
1002                         rte_spinlock_unlock(
1003                                 &data->priv_timer[this_lcore].list_lock);
1004                 }
1005
1006                 data->priv_timer[this_lcore].running_tim = NULL;
1007         }
1008
1009         return 0;
1010 }
1011
1012 /* Walk pending lists, stopping timers and calling user-specified function */
1013 int
1014 rte_timer_stop_all(uint32_t timer_data_id, unsigned int *walk_lcores,
1015                    int nb_walk_lcores,
1016                    rte_timer_stop_all_cb_t f, void *f_arg)
1017 {
1018         int i;
1019         struct priv_timer *priv_timer;
1020         uint32_t walk_lcore;
1021         struct rte_timer *tim, *next_tim;
1022         struct rte_timer_data *timer_data;
1023
1024         TIMER_DATA_VALID_GET_OR_ERR_RET(timer_data_id, timer_data, -EINVAL);
1025
1026         for (i = 0; i < nb_walk_lcores; i++) {
1027                 walk_lcore = walk_lcores[i];
1028                 priv_timer = &timer_data->priv_timer[walk_lcore];
1029
1030                 rte_spinlock_lock(&priv_timer->list_lock);
1031
1032                 for (tim = priv_timer->pending_head.sl_next[0];
1033                      tim != NULL;
1034                      tim = next_tim) {
1035                         next_tim = tim->sl_next[0];
1036
1037                         /* Call timer_stop with lock held */
1038                         __rte_timer_stop(tim, 1, timer_data);
1039
1040                         if (f)
1041                                 f(tim, f_arg);
1042                 }
1043
1044                 rte_spinlock_unlock(&priv_timer->list_lock);
1045         }
1046
1047         return 0;
1048 }
1049
1050 /* dump statistics about timers */
1051 static void
1052 __rte_timer_dump_stats(struct rte_timer_data *timer_data __rte_unused, FILE *f)
1053 {
1054 #ifdef RTE_LIBRTE_TIMER_DEBUG
1055         struct rte_timer_debug_stats sum;
1056         unsigned lcore_id;
1057         struct priv_timer *priv_timer = timer_data->priv_timer;
1058
1059         memset(&sum, 0, sizeof(sum));
1060         for (lcore_id = 0; lcore_id < RTE_MAX_LCORE; lcore_id++) {
1061                 sum.reset += priv_timer[lcore_id].stats.reset;
1062                 sum.stop += priv_timer[lcore_id].stats.stop;
1063                 sum.manage += priv_timer[lcore_id].stats.manage;
1064                 sum.pending += priv_timer[lcore_id].stats.pending;
1065         }
1066         fprintf(f, "Timer statistics:\n");
1067         fprintf(f, "  reset = %"PRIu64"\n", sum.reset);
1068         fprintf(f, "  stop = %"PRIu64"\n", sum.stop);
1069         fprintf(f, "  manage = %"PRIu64"\n", sum.manage);
1070         fprintf(f, "  pending = %"PRIu64"\n", sum.pending);
1071 #else
1072         fprintf(f, "No timer statistics, RTE_LIBRTE_TIMER_DEBUG is disabled\n");
1073 #endif
1074 }
1075
1076 void
1077 rte_timer_dump_stats_v20(FILE *f)
1078 {
1079         __rte_timer_dump_stats(&default_timer_data, f);
1080 }
1081 VERSION_SYMBOL(rte_timer_dump_stats, _v20, 2.0);
1082
1083 int
1084 rte_timer_dump_stats_v1905(FILE *f)
1085 {
1086         return rte_timer_alt_dump_stats(default_data_id, f);
1087 }
1088 MAP_STATIC_SYMBOL(int rte_timer_dump_stats(FILE *f),
1089                   rte_timer_dump_stats_v1905);
1090 BIND_DEFAULT_SYMBOL(rte_timer_dump_stats, _v1905, 19.05);
1091
1092 int
1093 rte_timer_alt_dump_stats(uint32_t timer_data_id __rte_unused, FILE *f)
1094 {
1095         struct rte_timer_data *timer_data;
1096
1097         TIMER_DATA_VALID_GET_OR_ERR_RET(timer_data_id, timer_data, -EINVAL);
1098
1099         __rte_timer_dump_stats(timer_data, f);
1100
1101         return 0;
1102 }