From ec8e44cf2ba50dcb421af40b67e74650bb5057f6 Mon Sep 17 00:00:00 2001 From: Mathieu Desnoyers Date: Fri, 23 Oct 2009 08:17:29 -0400 Subject: [PATCH] Add defer_rcu_ratelimit() Signed-off-by: Mathieu Desnoyers --- README | 3 +++ urcu-defer.c | 16 +++++++++++----- urcu-defer.h | 5 +++-- 3 files changed, 17 insertions(+), 7 deletions(-) diff --git a/README b/README index ecdda63..e1ce893 100644 --- a/README +++ b/README @@ -104,6 +104,9 @@ Usage of liburcu-defer callbacks are executed in batch periodically after a grace period. Do _not_ use defer_rcu() within a read-side critical section, because it may call synchronize_rcu() if the thread queue is full. + * Provides defer_rcu_ratelimit() primitive, which acts just like + defer_rcu(), but takes an additional rate limiter callback forcing + synchronized callback execution of the limiter returns non-zero. Being careful with signals diff --git a/urcu-defer.c b/urcu-defer.c index dd57071..3cc1a0c 100644 --- a/urcu-defer.c +++ b/urcu-defer.c @@ -232,9 +232,15 @@ end: /* * _defer_rcu - Queue a RCU callback. */ -void _defer_rcu(void (*fct)(void *p), void *p) +void _defer_rcu_ratelimit(void (*fct)(void *p), void *p, int (*rl)(void *p)) { unsigned long head, tail; + int sync; + + /* + * Verify if we reached the rate limiter threshold. + */ + sync = rl ? rl(p) : 0; /* * Head is only modified by ourself. Tail can be modified by reclamation @@ -244,10 +250,10 @@ void _defer_rcu(void (*fct)(void *p), void *p) tail = LOAD_SHARED(defer_queue.tail); /* - * If queue is full, empty it ourself. + * If queue is full, or reached threshold. Empty queue ourself. * Worse-case: must allow 2 supplementary entries for fct pointer. */ - if (unlikely(head - tail >= DEFER_QUEUE_SIZE - 2)) { + if (unlikely(sync || (head - tail >= DEFER_QUEUE_SIZE - 2))) { assert(head - tail <= DEFER_QUEUE_SIZE); rcu_defer_barrier_thread(); assert(head - LOAD_SHARED(defer_queue.tail) == 0); @@ -315,9 +321,9 @@ void *thr_defer(void *args) * library wrappers to be used by non-LGPL compatible source code. */ -void defer_rcu(void (*fct)(void *p), void *p) +void defer_rcu_ratelimit(void (*fct)(void *p), void *p, int (*rl)(void *p)) { - _defer_rcu(fct, p); + _defer_rcu_ratelimit(fct, p, rl); } static void start_defer_thread(void) diff --git a/urcu-defer.h b/urcu-defer.h index 9fdaf18..75b6005 100644 --- a/urcu-defer.h +++ b/urcu-defer.h @@ -43,9 +43,10 @@ * primitive need to call synchronize_rcu() if the thread queue is full. */ -#define rcu_reclaim_queue(p) defer_rcu(free, p) +#define defer_rcu(fct, p) defer_rcu_ratelimit(fct, p, NULL) -extern void defer_rcu(void (*fct)(void *p), void *p); +extern void defer_rcu_ratelimit(void (*fct)(void *p), void *p, + int (*rl)(void *p)); /* * Thread registration for reclamation. -- 2.34.1