]> git.proxmox.com Git - mirror_frr.git/blame - lib/wheel.c
Merge pull request #12798 from donaldsharp/rib_match_multicast
[mirror_frr.git] / lib / wheel.c
CommitLineData
acddc0ed 1// SPDX-License-Identifier: GPL-2.0-or-later
cbea8737
DS
2/*
3 * Timer Wheel
4 * Copyright (C) 2016 Cumulus Networks, Inc.
5 * Donald Sharp
cbea8737
DS
6 */
7#include "zebra.h"
8#include "linklist.h"
9#include "thread.h"
10#include "memory.h"
11#include "wheel.h"
12#include "log.h"
13
bf8d3d6a
DL
14DEFINE_MTYPE_STATIC(LIB, TIMER_WHEEL, "Timer Wheel");
15DEFINE_MTYPE_STATIC(LIB, TIMER_WHEEL_LIST, "Timer Wheel Slot List");
cbea8737
DS
16
17static int debug_timer_wheel = 0;
18
cc9f21da 19static void wheel_timer_thread(struct thread *t);
c2cfa843 20
cc9f21da 21static void wheel_timer_thread_helper(struct thread *t)
cbea8737 22{
d62a17ae 23 struct listnode *node, *nextnode;
24 unsigned long long curr_slot;
25 unsigned int slots_to_skip = 1;
26 struct timer_wheel *wheel;
27 void *data;
cbea8737 28
d62a17ae 29 wheel = THREAD_ARG(t);
cbea8737 30
d62a17ae 31 wheel->curr_slot += wheel->slots_to_skip;
cbea8737 32
d62a17ae 33 curr_slot = wheel->curr_slot % wheel->slots;
cbea8737 34
d62a17ae 35 if (debug_timer_wheel)
5e81f5dd
DS
36 zlog_debug("%s: Wheel Slot: %lld(%lld) count: %d", __func__,
37 wheel->curr_slot, curr_slot,
d62a17ae 38 listcount(wheel->wheel_slot_lists[curr_slot]));
cbea8737 39
d62a17ae 40 for (ALL_LIST_ELEMENTS(wheel->wheel_slot_lists[curr_slot], node,
41 nextnode, data))
42 (*wheel->slot_run)(data);
cbea8737 43
d62a17ae 44 while (list_isempty(wheel->wheel_slot_lists[(curr_slot + slots_to_skip)
45 % wheel->slots])
46 && (curr_slot + slots_to_skip) % wheel->slots != curr_slot)
47 slots_to_skip++;
cbea8737 48
d62a17ae 49 wheel->slots_to_skip = slots_to_skip;
50 thread_add_timer_msec(wheel->master, wheel_timer_thread, wheel,
51 wheel->nexttime * slots_to_skip, &wheel->timer);
cbea8737
DS
52}
53
cc9f21da 54static void wheel_timer_thread(struct thread *t)
c2cfa843
DS
55{
56 struct timer_wheel *wheel;
57
58 wheel = THREAD_ARG(t);
59
60a3efec 60 thread_execute(wheel->master, wheel_timer_thread_helper, wheel, 0);
c2cfa843
DS
61}
62
d62a17ae 63struct timer_wheel *wheel_init(struct thread_master *master, int period,
d8b87afe 64 size_t slots, unsigned int (*slot_key)(const void *),
c2cfa843
DS
65 void (*slot_run)(void *),
66 const char *run_name)
cbea8737 67{
d62a17ae 68 struct timer_wheel *wheel;
69 size_t i;
cbea8737 70
d62a17ae 71 wheel = XCALLOC(MTYPE_TIMER_WHEEL, sizeof(struct timer_wheel));
cbea8737 72
c2cfa843 73 wheel->name = XSTRDUP(MTYPE_TIMER_WHEEL, run_name);
d62a17ae 74 wheel->slot_key = slot_key;
75 wheel->slot_run = slot_run;
cbea8737 76
d62a17ae 77 wheel->period = period;
78 wheel->slots = slots;
79 wheel->curr_slot = 0;
80 wheel->master = master;
81 wheel->nexttime = period / slots;
cbea8737 82
d62a17ae 83 wheel->wheel_slot_lists = XCALLOC(MTYPE_TIMER_WHEEL_LIST,
5e7d0337 84 slots * sizeof(struct list *));
d62a17ae 85 for (i = 0; i < slots; i++)
86 wheel->wheel_slot_lists[i] = list_new();
cbea8737 87
d62a17ae 88 thread_add_timer_msec(wheel->master, wheel_timer_thread, wheel,
89 wheel->nexttime, &wheel->timer);
cbea8737 90
d62a17ae 91 return wheel;
cbea8737
DS
92}
93
d62a17ae 94void wheel_delete(struct timer_wheel *wheel)
cbea8737 95{
d62a17ae 96 int i;
cbea8737 97
d62a17ae 98 for (i = 0; i < wheel->slots; i++) {
6a154c88 99 list_delete(&wheel->wheel_slot_lists[i]);
d62a17ae 100 }
cbea8737 101
d62a17ae 102 THREAD_OFF(wheel->timer);
103 XFREE(MTYPE_TIMER_WHEEL_LIST, wheel->wheel_slot_lists);
c2cfa843 104 XFREE(MTYPE_TIMER_WHEEL, wheel->name);
d62a17ae 105 XFREE(MTYPE_TIMER_WHEEL, wheel);
cbea8737
DS
106}
107
d62a17ae 108int wheel_add_item(struct timer_wheel *wheel, void *item)
cbea8737 109{
d62a17ae 110 long long slot;
cbea8737 111
d62a17ae 112 slot = (*wheel->slot_key)(item);
cbea8737 113
d62a17ae 114 if (debug_timer_wheel)
15569c58
DA
115 zlog_debug("%s: Inserting %p: %lld %lld", __func__, item, slot,
116 slot % wheel->slots);
d62a17ae 117 listnode_add(wheel->wheel_slot_lists[slot % wheel->slots], item);
cbea8737 118
d62a17ae 119 return 0;
cbea8737
DS
120}
121
d62a17ae 122int wheel_remove_item(struct timer_wheel *wheel, void *item)
cbea8737 123{
d62a17ae 124 long long slot;
cbea8737 125
d62a17ae 126 slot = (*wheel->slot_key)(item);
cbea8737 127
d62a17ae 128 if (debug_timer_wheel)
15569c58
DA
129 zlog_debug("%s: Removing %p: %lld %lld", __func__, item, slot,
130 slot % wheel->slots);
d62a17ae 131 listnode_delete(wheel->wheel_slot_lists[slot % wheel->slots], item);
cbea8737 132
d62a17ae 133 return 0;
cbea8737 134}