mirror of
https://gitlab.nic.cz/labs/bird.git
synced 2024-12-22 17:51:53 +00:00
84c298465f
On large configurations, too many threads would spawn with one thread per loop. Therefore, threads may now run multiple loops at once. The thread count is configurable and may be changed during run. All threads are spawned on startup. This change helps with memory bloating. BIRD filters need large temporary memory blocks to store their stack and also memory management keeps its hot page storage per-thread. Known bugs: * Thread autobalancing is not yet implemented. * Low latency loops are executed together with standard loops.
80 lines
1.8 KiB
C
80 lines
1.8 KiB
C
/*
|
|
* BIRD Library -- Read-Copy-Update Basic Operations
|
|
*
|
|
* (c) 2021 Maria Matejka <mq@jmq.cz>
|
|
* (c) 2021 CZ.NIC z.s.p.o.
|
|
*
|
|
* Can be freely distributed and used under the terms of the GNU GPL.
|
|
* Note: all the relevant patents shall be expired.
|
|
*
|
|
* Using the Supplementary Material for User-Level Implementations of Read-Copy-Update
|
|
* by Matthieu Desnoyers, Paul E. McKenney, Alan S. Stern, Michel R. Dagenais and Jonathan Walpole
|
|
* obtained from https://www.efficios.com/pub/rcu/urcu-supp-accepted.pdf
|
|
*/
|
|
|
|
#include "lib/rcu.h"
|
|
#include "lib/io-loop.h"
|
|
#include "lib/locking.h"
|
|
|
|
_Atomic uint rcu_gp_ctl = RCU_NEST_CNT;
|
|
_Thread_local struct rcu_thread *this_rcu_thread = NULL;
|
|
|
|
static list rcu_thread_list;
|
|
|
|
static struct rcu_thread main_rcu_thread;
|
|
|
|
DEFINE_DOMAIN(resource);
|
|
static DOMAIN(resource) rcu_domain;
|
|
|
|
static int
|
|
rcu_gp_ongoing(_Atomic uint *ctl)
|
|
{
|
|
uint val = atomic_load(ctl);
|
|
return (val & RCU_NEST_CNT) && ((val ^ rcu_gp_ctl) & RCU_GP_PHASE);
|
|
}
|
|
|
|
static void
|
|
update_counter_and_wait(void)
|
|
{
|
|
atomic_fetch_xor(&rcu_gp_ctl, RCU_GP_PHASE);
|
|
struct rcu_thread *rc;
|
|
WALK_LIST(rc, rcu_thread_list)
|
|
while (rcu_gp_ongoing(&rc->ctl))
|
|
birdloop_yield();
|
|
}
|
|
|
|
void
|
|
synchronize_rcu(void)
|
|
{
|
|
LOCK_DOMAIN(resource, rcu_domain);
|
|
update_counter_and_wait();
|
|
update_counter_and_wait();
|
|
UNLOCK_DOMAIN(resource, rcu_domain);
|
|
}
|
|
|
|
void
|
|
rcu_thread_start(struct rcu_thread *rc)
|
|
{
|
|
LOCK_DOMAIN(resource, rcu_domain);
|
|
add_tail(&rcu_thread_list, &rc->n);
|
|
this_rcu_thread = rc;
|
|
UNLOCK_DOMAIN(resource, rcu_domain);
|
|
}
|
|
|
|
void
|
|
rcu_thread_stop(struct rcu_thread *rc)
|
|
{
|
|
LOCK_DOMAIN(resource, rcu_domain);
|
|
this_rcu_thread = NULL;
|
|
rem_node(&rc->n);
|
|
UNLOCK_DOMAIN(resource, rcu_domain);
|
|
}
|
|
|
|
void
|
|
rcu_init(void)
|
|
{
|
|
rcu_domain = DOMAIN_NEW(resource, "Read-Copy-Update");
|
|
init_list(&rcu_thread_list);
|
|
rcu_thread_start(&main_rcu_thread);
|
|
}
|