From: Paul E. McKenney Date: Fri, 3 Jun 2011 16:49:21 +0000 (-0400) Subject: Document the new call_rcu() primitives. X-Git-Tag: v0.6.0~41 X-Git-Url: https://git.lttng.org/?p=urcu.git;a=commitdiff_plain;h=26ba798aa19e32441020728f2f5fd90df87d4175 Document the new call_rcu() primitives. Signed-off-by: Paul E. McKenney Signed-off-by: Mathieu Desnoyers --- diff --git a/API.txt b/API.txt new file mode 100644 index 0000000..162ca93 --- /dev/null +++ b/API.txt @@ -0,0 +1,120 @@ +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); + +struct call_rcu_data *create_call_rcu_data(unsigned long flags); + + 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. + +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. + +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. + +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. + +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 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. diff --git a/README b/README index 7d97f19..a6e29c8 100644 --- a/README +++ b/README @@ -139,6 +139,22 @@ Usage of liburcu-defer * Its API is currently experimental. It may change in future library releases. +Usage of urcu-call-rcu + + * Follow instructions for either liburcu, liburcu-qsbr, + liburcu-mb, liburcu-signal, or liburcu-bp above. + The urcu-call-rcu functionality is provided for each of + these library modules. + * Provides the call_rcu() primitive to enqueue delayed callbacks + in a manner similar to defer_rcu(), but without ever delaying + for a grace period. On the other hand, call_rcu()'s best-case + overhead is not quite as good as that of defer_rcu(). + * Provides call_rcu() to allow asynchronous handling of RCU + grace periods. A number of additional functions are provided + to manage the helper threads used by call_rcu(), but reasonable + defaults are used if these additional functions are not invoked. + See API.txt for more details. + Being careful with signals The liburcu library uses signals internally. The signal handler is