+void *rcu_xchg_pointer_sym(void **p, void *v)
+{
+ wmb();
+ return uatomic_xchg(p, v);
+}
+
+void *rcu_cmpxchg_pointer_sym(void **p, void *old, void *_new)
+{
+ wmb();
+ return uatomic_cmpxchg(p, old, _new);
+}
+
+void *rcu_publish_content_sym(void **p, void *v)
+{
+ void *oldptr;
+
+ oldptr = _rcu_xchg_pointer(p, v);
+ synchronize_rcu();
+ return oldptr;
+}
+
+void rcu_register_thread(void)
+{
+ urcu_reader.tid = pthread_self();
+ assert(urcu_reader.need_mb == 0);
+ assert(urcu_reader.ctr == 0);
+
+ internal_urcu_lock();
+ urcu_init(); /* In case gcc does not support constructor attribute */
+ list_add(&urcu_reader.head, ®istry);
+ internal_urcu_unlock();
+}
+
+void rcu_unregister_thread(void)
+{
+ internal_urcu_lock();
+ list_del(&urcu_reader.head);
+ internal_urcu_unlock();
+}
+
+#ifndef URCU_MB
+static void sigurcu_handler(int signo, siginfo_t *siginfo, void *context)
+{
+ /*
+ * Executing this smp_mb() is the only purpose of this signal handler.
+ * It punctually promotes barrier() into smp_mb() on every thread it is
+ * executed on.
+ */
+ smp_mb();
+ urcu_reader.need_mb = 0;
+ smp_mb();
+}
+
+/*
+ * urcu_init constructor. Called when the library is linked, but also when
+ * reader threads are calling rcu_register_thread().
+ * Should only be called by a single thread at a given time. This is ensured by
+ * holing the internal_urcu_lock() from rcu_register_thread() or by running at
+ * library load time, which should not be executed by multiple threads nor
+ * concurrently with rcu_register_thread() anyway.
+ */
+void urcu_init(void)