2021-11-12 21:58:40 +00:00
|
|
|
/*
|
|
|
|
* 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.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#ifndef _BIRD_RCU_H_
|
|
|
|
#define _BIRD_RCU_H_
|
|
|
|
|
|
|
|
#include "lib/birdlib.h"
|
|
|
|
#include "lib/lists.h"
|
|
|
|
#include <stdatomic.h>
|
|
|
|
|
2024-05-31 18:43:15 +00:00
|
|
|
#define RCU_GP_PHASE 0x100
|
|
|
|
#define RCU_NEST_MASK (RCU_GP_PHASE-1)
|
|
|
|
#define RCU_NEST_CNT 1
|
2021-11-12 21:58:40 +00:00
|
|
|
|
2024-05-31 18:43:15 +00:00
|
|
|
extern _Atomic u64 rcu_global_phase;
|
2021-11-12 21:58:40 +00:00
|
|
|
|
2023-01-19 09:49:47 +00:00
|
|
|
struct rcu_thread {
|
2024-05-31 18:43:15 +00:00
|
|
|
struct rcu_thread * _Atomic next;
|
2024-06-20 20:57:52 +00:00
|
|
|
u64 local_ctl;
|
2024-05-31 18:43:15 +00:00
|
|
|
_Atomic u64 ctl;
|
2021-11-12 21:58:40 +00:00
|
|
|
};
|
|
|
|
|
2024-05-31 18:43:15 +00:00
|
|
|
extern _Thread_local struct rcu_thread this_rcu_thread;
|
2024-05-16 08:22:19 +00:00
|
|
|
extern _Thread_local uint rcu_blocked;
|
2021-11-12 21:58:40 +00:00
|
|
|
|
|
|
|
static inline void rcu_read_lock(void)
|
|
|
|
{
|
2024-05-31 18:43:15 +00:00
|
|
|
/* Increment the nesting counter */
|
2024-06-20 20:57:52 +00:00
|
|
|
atomic_store_explicit(&this_rcu_thread.ctl, (this_rcu_thread.local_ctl += RCU_NEST_CNT), memory_order_release);
|
2021-11-12 21:58:40 +00:00
|
|
|
|
2024-06-20 20:57:52 +00:00
|
|
|
/* Just nested */
|
|
|
|
u64 local_nest = this_rcu_thread.local_ctl & RCU_NEST_MASK;
|
|
|
|
if (local_nest > RCU_NEST_CNT)
|
2024-05-31 18:43:15 +00:00
|
|
|
return;
|
|
|
|
|
2024-06-20 20:57:52 +00:00
|
|
|
ASSUME(local_nest == RCU_NEST_CNT);
|
|
|
|
|
2024-05-31 18:43:15 +00:00
|
|
|
/* Update the phase */
|
2024-06-20 20:57:52 +00:00
|
|
|
u64 new = atomic_load_explicit(&rcu_global_phase, memory_order_acquire) + RCU_NEST_CNT;
|
|
|
|
atomic_store_explicit(&this_rcu_thread.ctl, new, memory_order_release);
|
|
|
|
this_rcu_thread.local_ctl = new;
|
2021-11-12 21:58:40 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static inline void rcu_read_unlock(void)
|
|
|
|
{
|
2024-05-31 18:43:15 +00:00
|
|
|
/* Just decrement the nesting counter; when unlocked, nobody cares */
|
2024-06-05 11:12:12 +00:00
|
|
|
atomic_fetch_sub_explicit(&this_rcu_thread.ctl, RCU_NEST_CNT, memory_order_acq_rel);
|
2024-06-20 20:57:52 +00:00
|
|
|
this_rcu_thread.local_ctl--;
|
2021-11-12 21:58:40 +00:00
|
|
|
}
|
|
|
|
|
2024-05-16 08:22:19 +00:00
|
|
|
static inline _Bool rcu_read_active(void)
|
|
|
|
{
|
2024-06-20 20:57:52 +00:00
|
|
|
return !!(this_rcu_thread.local_ctl & RCU_NEST_MASK);
|
2024-05-16 08:22:19 +00:00
|
|
|
}
|
|
|
|
|
2021-11-12 21:58:40 +00:00
|
|
|
void synchronize_rcu(void);
|
|
|
|
|
|
|
|
/* Registering and unregistering a birdloop. To be called from birdloop implementation */
|
2024-05-31 18:43:15 +00:00
|
|
|
void rcu_thread_start(void);
|
|
|
|
void rcu_thread_stop(void);
|
2021-11-12 21:58:40 +00:00
|
|
|
|
|
|
|
/* Run this from resource init */
|
|
|
|
void rcu_init(void);
|
|
|
|
|
|
|
|
#endif
|