mirror of
https://git.proxmox.com/git/mirror_frr
synced 2025-05-23 22:37:58 +00:00
lib: Add Timer Wheel functionality
Signed-off-by: Donald Sharp <sharpd@cumulusnetworks.com>
This commit is contained in:
parent
d67f268e94
commit
1de1c5bed3
@ -24,7 +24,7 @@ libzebra_la_SOURCES = \
|
|||||||
sigevent.c pqueue.c jhash.c workqueue.c nexthop.c json.c \
|
sigevent.c pqueue.c jhash.c workqueue.c nexthop.c json.c \
|
||||||
ptm_lib.c csv.c bfd.c vrf.c systemd.c ns.c memory.c memory_vty.c \
|
ptm_lib.c csv.c bfd.c vrf.c systemd.c ns.c memory.c memory_vty.c \
|
||||||
imsg-buffer.c imsg.c skiplist.c \
|
imsg-buffer.c imsg.c skiplist.c \
|
||||||
qobj.c \
|
qobj.c wheel.c \
|
||||||
event_counter.c \
|
event_counter.c \
|
||||||
strlcpy.c \
|
strlcpy.c \
|
||||||
strlcat.c
|
strlcat.c
|
||||||
@ -45,7 +45,7 @@ pkginclude_HEADERS = \
|
|||||||
workqueue.h route_types.h libospf.h nexthop.h json.h \
|
workqueue.h route_types.h libospf.h nexthop.h json.h \
|
||||||
ptm_lib.h csv.h bfd.h vrf.h ns.h systemd.h bitfield.h \
|
ptm_lib.h csv.h bfd.h vrf.h ns.h systemd.h bitfield.h \
|
||||||
fifo.h memory_vty.h mpls.h imsg.h openbsd-queue.h openbsd-tree.h \
|
fifo.h memory_vty.h mpls.h imsg.h openbsd-queue.h openbsd-tree.h \
|
||||||
skiplist.h qobj.h \
|
skiplist.h qobj.h wheel.h \
|
||||||
event_counter.h
|
event_counter.h
|
||||||
|
|
||||||
noinst_HEADERS = \
|
noinst_HEADERS = \
|
||||||
|
164
lib/wheel.c
Normal file
164
lib/wheel.c
Normal file
@ -0,0 +1,164 @@
|
|||||||
|
/*
|
||||||
|
* Timer Wheel
|
||||||
|
* Copyright (C) 2016 Cumulus Networks, Inc.
|
||||||
|
* Donald Sharp
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful, but
|
||||||
|
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; see the file COPYING; if not, write to the
|
||||||
|
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
|
||||||
|
* MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
#include "zebra.h"
|
||||||
|
#include "linklist.h"
|
||||||
|
#include "thread.h"
|
||||||
|
#include "memory.h"
|
||||||
|
#include "wheel.h"
|
||||||
|
#include "log.h"
|
||||||
|
|
||||||
|
DEFINE_MTYPE_STATIC(LIB, TIMER_WHEEL, "Timer Wheel")
|
||||||
|
DEFINE_MTYPE_STATIC(LIB, TIMER_WHEEL_LIST, "Timer Wheel Slot List")
|
||||||
|
|
||||||
|
static int debug_timer_wheel = 1;
|
||||||
|
|
||||||
|
static int
|
||||||
|
wheel_timer_thread (struct thread *t)
|
||||||
|
{
|
||||||
|
struct listnode *node, *nextnode;
|
||||||
|
unsigned long long curr_slot;
|
||||||
|
unsigned int slots_to_skip = 1;
|
||||||
|
struct timer_wheel *wheel;
|
||||||
|
void *data;
|
||||||
|
|
||||||
|
wheel = THREAD_ARG(t);
|
||||||
|
THREAD_OFF(wheel->timer);
|
||||||
|
|
||||||
|
wheel->curr_slot += wheel->slots_to_skip;
|
||||||
|
|
||||||
|
curr_slot = wheel->curr_slot % wheel->slots;
|
||||||
|
|
||||||
|
if (debug_timer_wheel)
|
||||||
|
zlog_debug ("%s: Wheel Slot: %lld(%lld) count: %d",
|
||||||
|
__PRETTY_FUNCTION__,
|
||||||
|
wheel->curr_slot,
|
||||||
|
curr_slot, listcount(wheel->wheel_slot_lists[curr_slot]));
|
||||||
|
|
||||||
|
for (ALL_LIST_ELEMENTS (wheel->wheel_slot_lists[curr_slot], node, nextnode, data))
|
||||||
|
(*wheel->slot_run)(data);
|
||||||
|
|
||||||
|
while (list_isempty(wheel->wheel_slot_lists[(curr_slot + slots_to_skip) % wheel->slots]) &&
|
||||||
|
(curr_slot + slots_to_skip ) % wheel->slots != curr_slot)
|
||||||
|
slots_to_skip++;
|
||||||
|
|
||||||
|
wheel->slots_to_skip = slots_to_skip;
|
||||||
|
THREAD_TIMER_MSEC_ON (wheel->master, wheel->timer,
|
||||||
|
wheel_timer_thread, wheel,
|
||||||
|
wheel->nexttime * slots_to_skip);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct timer_wheel *
|
||||||
|
wheel_init (struct thread_master *master, int period, size_t slots,
|
||||||
|
unsigned int (*slot_key) (void *),
|
||||||
|
void (*slot_run) (void *))
|
||||||
|
{
|
||||||
|
struct timer_wheel *wheel;
|
||||||
|
size_t i;
|
||||||
|
|
||||||
|
wheel = XCALLOC(MTYPE_TIMER_WHEEL, sizeof (struct timer_wheel));
|
||||||
|
|
||||||
|
wheel->slot_key = slot_key;
|
||||||
|
wheel->slot_run = slot_run;
|
||||||
|
|
||||||
|
wheel->period = period;
|
||||||
|
wheel->slots = slots;
|
||||||
|
wheel->curr_slot = 0;
|
||||||
|
wheel->master = master;
|
||||||
|
wheel->nexttime = period / slots;
|
||||||
|
|
||||||
|
wheel->wheel_slot_lists = XCALLOC(MTYPE_TIMER_WHEEL_LIST,
|
||||||
|
slots * sizeof (struct listnode *));
|
||||||
|
for (i = 0; i < slots; i++)
|
||||||
|
wheel->wheel_slot_lists[i] = list_new ();
|
||||||
|
|
||||||
|
THREAD_TIMER_MSEC_ON (wheel->master, wheel->timer,
|
||||||
|
wheel_timer_thread, wheel,
|
||||||
|
wheel->nexttime);
|
||||||
|
|
||||||
|
return wheel;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
wheel_delete (struct timer_wheel *wheel)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i < wheel->slots; i++)
|
||||||
|
{
|
||||||
|
list_delete(wheel->wheel_slot_lists[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
THREAD_OFF(wheel->timer);
|
||||||
|
XFREE(MTYPE_TIMER_WHEEL_LIST, wheel->wheel_slot_lists);
|
||||||
|
XFREE(MTYPE_TIMER_WHEEL, wheel);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
wheel_stop (struct timer_wheel *wheel)
|
||||||
|
{
|
||||||
|
THREAD_OFF(wheel->timer);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
wheel_start (struct timer_wheel *wheel)
|
||||||
|
{
|
||||||
|
if (!wheel->timer)
|
||||||
|
THREAD_TIMER_MSEC_ON (wheel->master, wheel->timer,
|
||||||
|
wheel_timer_thread, wheel,
|
||||||
|
wheel->nexttime);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
wheel_add_item (struct timer_wheel *wheel, void *item)
|
||||||
|
{
|
||||||
|
long long slot;
|
||||||
|
|
||||||
|
slot = (*wheel->slot_key)(item);
|
||||||
|
|
||||||
|
if (debug_timer_wheel)
|
||||||
|
zlog_debug ("%s: Inserting %p: %lld %lld",
|
||||||
|
__PRETTY_FUNCTION__, item,
|
||||||
|
slot, slot % wheel->slots);
|
||||||
|
listnode_add (wheel->wheel_slot_lists[slot % wheel->slots], item);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
wheel_remove_item (struct timer_wheel *wheel, void *item)
|
||||||
|
{
|
||||||
|
long long slot;
|
||||||
|
|
||||||
|
slot = (*wheel->slot_key)(item);
|
||||||
|
|
||||||
|
if (debug_timer_wheel)
|
||||||
|
zlog_debug ("%s: Removing %p: %lld %lld",
|
||||||
|
__PRETTY_FUNCTION__, item,
|
||||||
|
slot, slot % wheel->slots);
|
||||||
|
listnode_delete (wheel->wheel_slot_lists[slot % wheel->slots], item);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
70
lib/wheel.h
Normal file
70
lib/wheel.h
Normal file
@ -0,0 +1,70 @@
|
|||||||
|
/*
|
||||||
|
* Timer Wheel
|
||||||
|
* Copyright (C) 2016 Cumulus Networks, Inc.
|
||||||
|
* Donald Sharp
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful, but
|
||||||
|
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; see the file COPYING; if not, write to the
|
||||||
|
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
|
||||||
|
* MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
#ifndef __WHEEL_H__
|
||||||
|
#define __WHEEL_H__
|
||||||
|
|
||||||
|
struct timer_wheel
|
||||||
|
{
|
||||||
|
struct thread_master *master;
|
||||||
|
int slots;
|
||||||
|
long long curr_slot;
|
||||||
|
unsigned int period;
|
||||||
|
unsigned int nexttime;
|
||||||
|
unsigned int slots_to_skip;
|
||||||
|
|
||||||
|
struct list **wheel_slot_lists;
|
||||||
|
struct thread *timer;
|
||||||
|
/*
|
||||||
|
* Key to determine what slot the item belongs in
|
||||||
|
*/
|
||||||
|
unsigned int (*slot_key) (void *);
|
||||||
|
|
||||||
|
void (*slot_run) (void *);
|
||||||
|
};
|
||||||
|
|
||||||
|
struct timer_wheel *wheel_init (struct thread_master *master, int period, size_t slots,
|
||||||
|
unsigned int (*slot_key) (void *),
|
||||||
|
void (*slot_run) (void *));
|
||||||
|
void wheel_delete (struct timer_wheel *);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Pause the Wheel from running
|
||||||
|
*/
|
||||||
|
int wheel_stop (struct timer_wheel *wheel);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Start the wheel from running again
|
||||||
|
*/
|
||||||
|
int wheel_start (struct timer_wheel *wheel);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Add item to a slot setup by the slot_key,
|
||||||
|
* possibly change next time pop.
|
||||||
|
*/
|
||||||
|
int wheel_add_item (struct timer_wheel *wheel, void *item);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Remove a item to a slot setup by the slot_key,
|
||||||
|
* possibly change next time pop.
|
||||||
|
*/
|
||||||
|
int wheel_remove_item (struct timer_wheel *wheel, void *item);
|
||||||
|
|
||||||
|
#endif
|
Loading…
Reference in New Issue
Block a user