-void rcu_lfq_enqueue(struct rcu_lfq_queue *q, struct rcu_lfq_node *node)
-{
- urcu_ref_get(&node->ref);
-
- /*
- * uatomic_cmpxchg() implicit memory barrier orders earlier stores to
- * node before publication.
- */
-
- for (;;) {
- struct rcu_lfq_node *tail, *next;
-
- rcu_read_lock();
- tail = rcu_dereference(q->tail);
- /*
- * Typically expect tail->next to be NULL.
- */
- next = uatomic_cmpxchg(&tail->next, NULL, node);
- if (next == NULL) {
- /*
- * Tail was at the end of queue, we successfully
- * appended to it.
- * Now move tail (another enqueue might beat
- * us to it, that's fine).
- */
- uatomic_cmpxchg(&q->tail, tail, node);
- rcu_read_unlock();
- return;
- } else {
- /*
- * Failure to append to current tail. Help moving tail
- * further and retry.
- */
- uatomic_cmpxchg(&q->tail, tail, next);
- rcu_read_unlock();
- continue;
- }
- }
-}
+#define cds_lfq_node_init_rcu _cds_lfq_node_init_rcu
+#define cds_lfq_init_rcu _cds_lfq_init_rcu
+#define cds_lfq_destroy_rcu _cds_lfq_destroy_rcu
+#define cds_lfq_enqueue_rcu _cds_lfq_enqueue_rcu
+#define cds_lfq_dequeue_rcu _cds_lfq_dequeue_rcu
+
+#else /* !_LGPL_SOURCE */
+
+extern void cds_lfq_node_init_rcu(struct cds_lfq_node_rcu *node);
+extern void cds_lfq_init_rcu(struct cds_lfq_queue_rcu *q,
+ void queue_call_rcu(struct rcu_head *head,
+ void (*func)(struct rcu_head *head)));
+/*
+ * The queue should be emptied before calling destroy.
+ *
+ * Return 0 on success, -EPERM if queue is not empty.
+ */
+extern int cds_lfq_destroy_rcu(struct cds_lfq_queue_rcu *q);