1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171
|
Userspace RCU API
by Mathieu Desnoyers and Paul E. McKenney
void rcu_init(void);
This must be called before any of the following functions
are invoked.
void rcu_read_lock(void);
Begin an RCU read-side critical section. These critical
sections may be nested.
void rcu_read_unlock(void);
End an RCU read-side critical section.
void rcu_register_thread(void);
Each thread must invoke this function before its first call to
rcu_read_lock(). Threads that never call rcu_read_lock() need
not invoke this function. In addition, rcu-bp ("bullet proof"
RCU) does not require any thread to invoke rcu_register_thread().
void rcu_unregister_thread(void);
Each thread that invokes rcu_register_thread() must invoke
rcu_unregister_thread() before invoking pthread_exit()
or before returning from its top-level function.
void synchronize_rcu(void);
Wait until every pre-existing RCU read-side critical section
has completed. Note that this primitive will not necessarily
wait for RCU read-side critical sections that have not yet
started: this is not a reader-writer lock. The duration
actually waited is called an RCU grace period.
void call_rcu(struct rcu_head *head,
void (*func)(struct rcu_head *head));
Registers the callback indicated by "head". This means
that "func" will be invoked after the end of a future
RCU grace period. The rcu_head structure referenced
by "head" will normally be a field in a larger RCU-protected
structure. A typical implementation of "func" is as
follows:
void func(struct rcu_head *head)
{
struct foo *p = container_of(head, struct foo, rcu);
free(p);
}
This RCU callback function can be registered as follows
given a pointer "p" to the enclosing structure:
call_rcu(&p->rcu, func);
call_rcu should be called from registered RCU read-side threads.
For the QSBR flavor, the caller should be online.
struct call_rcu_data *create_call_rcu_data(unsigned long flags,
int cpu_affinity);
Returns a handle that can be passed to the following
primitives. The "flags" argument can be zero, or can be
URCU_CALL_RCU_RT if the worker threads associated with the
new helper thread are to get real-time response. The argument
"cpu_affinity" specifies a cpu on which the call_rcu thread should
be affined to. It is ignored if negative.
struct call_rcu_data *get_default_call_rcu_data(void);
Returns the handle of the default call_rcu() helper thread.
struct call_rcu_data *get_call_rcu_data(void);
Returns the handle of the current thread's call_rcu() helper
thread, which might well be the default helper thread.
get_call_rcu_data should be called from registered RCU read-side
threads. For the QSBR flavor, the caller should be online.
void call_rcu_data_free(struct call_rcu_data *crdp);
Terminates a call_rcu() helper thread and frees its associated
data. The caller must have ensured that this thread is no longer
in use, for example, by passing NULL to set_thread_call_rcu_data()
and set_cpu_call_rcu_data() as required.
struct call_rcu_data *get_default_call_rcu_data(void);
Returns the handle for the default call_rcu() helper thread.
Creates it if necessary.
struct call_rcu_data *get_cpu_call_rcu_data(int cpu);
Returns the handle for the current cpu's call_rcu() helper
thread, or NULL if the current CPU has no helper thread
currently assigned. The call to this function and use of the
returned call_rcu_data should be protected by RCU read-side
lock.
struct call_rcu_data *get_thread_call_rcu_data(void);
Returns the handle for the current thread's hard-assigned
call_rcu() helper thread, or NULL if the current thread is
instead using a per-CPU or the default helper thread.
struct call_rcu_data *get_call_rcu_data(void);
Returns the handle for the current thread's call_rcu() helper
thread, which is either, in increasing order of preference:
per-thread hard-assigned helper thread, per-cpu helper thread,
or default helper thread.
pthread_t get_call_rcu_thread(struct call_rcu_data *crdp);
Returns the helper thread's pthread identifier linked to a call
rcu helper thread data.
void set_thread_call_rcu_data(struct call_rcu_data *crdp);
Sets the current thread's hard-assigned call_rcu() helper to the
handle specified by "crdp". Note that "crdp" can be NULL to
disassociate this thread from its helper. Once a thread is
disassociated from its helper, further call_rcu() invocations
use the current CPU's helper if there is one and the default
helper otherwise.
int set_cpu_call_rcu_data(int cpu, struct call_rcu_data *crdp);
Sets the specified CPU's call_rcu() helper to the handle
specified by "crdp". Again, "crdp" can be NULL to disassociate
this CPU from its helper thread. Once a CPU has been
disassociated from its helper, further call_rcu() invocations
that would otherwise have used this CPU's helper will instead
use the default helper. The caller must wait for a grace-period
to pass between return from set_cpu_call_rcu_data() and call to
call_rcu_data_free() passing the previous call rcu data as
argument.
int create_all_cpu_call_rcu_data(unsigned long flags)
Creates a separate call_rcu() helper thread for each CPU.
After this primitive is invoked, the global default call_rcu()
helper thread will not be called.
The set_thread_call_rcu_data(), set_cpu_call_rcu_data(), and
create_all_cpu_call_rcu_data() functions may be combined to set up
pretty much any desired association between worker and call_rcu()
helper threads. If a given executable calls only call_rcu(),
then that executable will have only the single global default
call_rcu() helper thread. This will suffice in most cases.
void free_all_cpu_call_rcu_data(void);
Clean up all the per-CPU call_rcu threads. Should be paired with
create_all_cpu_call_rcu_data() to perform teardown. Note that
this function invokes synchronize_rcu() internally, so the
caller should be careful not to hold mutexes (or mutexes within a
dependency chain) that are also taken within a RCU read-side
critical section, or in a section where QSBR threads are online.
void call_rcu_after_fork_child(void);
Should be used as pthread_atfork() handler for programs using
call_rcu and performing fork() or clone() without a following
exec().
|