* API change * for all liburcu-cds* flavors.
Signed-off-by: Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
_cds_lfq_node_init_rcu(node);
}
-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)))
+void cds_lfq_init_rcu(struct cds_lfq_queue_rcu *q)
{
- _cds_lfq_init_rcu(q, queue_call_rcu);
+ _cds_lfq_init_rcu(q);
}
int cds_lfq_destroy_rcu(struct cds_lfq_queue_rcu *q)
if (!node)
goto fail;
cds_lfq_node_init_rcu(node);
- rcu_read_lock();
cds_lfq_enqueue_rcu(&q, node);
- rcu_read_unlock();
nr_successful_enqueues++;
if (unlikely(wdelay))
for (;;) {
struct cds_lfq_node_rcu *node;
- rcu_read_lock();
node = cds_lfq_dequeue_rcu(&q);
- rcu_read_unlock();
-
if (node) {
defer_rcu(free, node);
nr_successful_dequeues++;
struct cds_lfq_node_rcu *node;
do {
- rcu_read_lock();
node = cds_lfq_dequeue_rcu(q);
- rcu_read_unlock();
if (node) {
free(node); /* no more concurrent access */
(*nr_dequeues)++;
tid_dequeuer = malloc(sizeof(*tid_dequeuer) * nr_dequeuers);
count_enqueuer = malloc(2 * sizeof(*count_enqueuer) * nr_enqueuers);
count_dequeuer = malloc(2 * sizeof(*count_dequeuer) * nr_dequeuers);
- cds_lfq_init_rcu(&q, call_rcu);
+ cds_lfq_init_rcu(&q);
next_aff = 0;
for (;;) {
struct cds_lfs_node_rcu *node;
- rcu_read_lock();
node = cds_lfs_pop_rcu(&s);
- rcu_read_unlock();
if (node) {
defer_rcu(free, node);
nr_successful_dequeues++;
struct cds_lfq_queue_rcu {
struct cds_lfq_node_rcu *head, *tail;
- void (*queue_call_rcu)(struct rcu_head *head,
- void (*func)(struct rcu_head *head));
};
#ifdef _LGPL_SOURCE
#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)));
+extern void cds_lfq_init_rcu(struct cds_lfq_queue_rcu *q);
/*
* The queue should be emptied before calling destroy.
*
extern int cds_lfq_destroy_rcu(struct cds_lfq_queue_rcu *q);
/*
- * Should be called under rcu read lock critical section.
+ * Acts as a RCU reader.
*/
extern void cds_lfq_enqueue_rcu(struct cds_lfq_queue_rcu *q,
struct cds_lfq_node_rcu *node);
/*
- * Should be called under rcu read lock critical section.
+ * Acts as a RCU reader.
*
* The caller must wait for a grace period to pass before freeing the returned
* node or modifying the cds_lfq_node_rcu structure.
extern void cds_lfs_push_rcu(struct cds_lfs_stack_rcu *s, struct cds_lfs_node_rcu *node);
/*
- * Should be called under rcu read lock critical section.
+ * Acts as a RCU reader.
*
* The caller must wait for a grace period to pass before freeing the returned
* node or modifying the cds_lfs_node_rcu structure.
assert(node->dummy);
dummy = caa_container_of(node, struct cds_lfq_node_rcu_dummy, parent);
- dummy->q->queue_call_rcu(&dummy->head, free_dummy_cb);
+ call_rcu(&dummy->head, free_dummy_cb);
}
static inline
}
static inline
-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)))
+void _cds_lfq_init_rcu(struct cds_lfq_queue_rcu *q)
{
q->tail = make_dummy(q, NULL);
q->head = q->tail;
- q->queue_call_rcu = queue_call_rcu;
}
/*
}
/*
- * Should be called under rcu read lock critical section.
+ * Acts as a RCU reader.
*/
static inline
void _cds_lfq_enqueue_rcu(struct cds_lfq_queue_rcu *q,
for (;;) {
struct cds_lfq_node_rcu *tail, *next;
+ rcu_read_lock();
tail = rcu_dereference(q->tail);
next = uatomic_cmpxchg(&tail->next, NULL, node);
if (next == NULL) {
* enqueue might beat us to it, that's fine).
*/
(void) uatomic_cmpxchg(&q->tail, tail, node);
+ rcu_read_unlock();
return;
} else {
/*
* Help moving tail further and retry.
*/
(void) uatomic_cmpxchg(&q->tail, tail, next);
+ rcu_read_unlock();
continue;
}
}
}
/*
- * Should be called under rcu read lock critical section.
+ * Acts as a RCU reader.
*
* The caller must wait for a grace period to pass before freeing the returned
* node or modifying the cds_lfq_node_rcu structure.
for (;;) {
struct cds_lfq_node_rcu *head, *next;
+ rcu_read_lock();
head = rcu_dereference(q->head);
next = rcu_dereference(head->next);
- if (head->dummy && next == NULL)
+ if (head->dummy && next == NULL) {
+ rcu_read_unlock();
return NULL; /* empty */
+ }
/*
* We never, ever allow dequeue to get to a state where
* the queue is empty (we need at least one node in the
enqueue_dummy(q);
next = rcu_dereference(head->next);
}
- if (uatomic_cmpxchg(&q->head, head, next) != head)
+ if (uatomic_cmpxchg(&q->head, head, next) != head) {
+ rcu_read_unlock();
continue; /* Concurrently pushed. */
+ }
if (head->dummy) {
/* Free dummy after grace period. */
rcu_free_dummy(head);
+ rcu_read_unlock();
continue; /* try again */
}
+ rcu_read_unlock();
return head;
}
}
}
/*
- * Should be called under rcu read-side lock.
+ * Acts as a RCU reader.
*
* The caller must wait for a grace period to pass before freeing the returned
* node or modifying the cds_lfs_node_rcu structure.
for (;;) {
struct cds_lfs_node_rcu *head;
+ rcu_read_lock();
head = rcu_dereference(s->head);
if (head) {
struct cds_lfs_node_rcu *next = rcu_dereference(head->next);
if (uatomic_cmpxchg(&s->head, head, next) == head) {
+ rcu_read_unlock();
return head;
} else {
/* Concurrent modification. Retry. */
+ rcu_read_unlock();
continue;
}
} else {
/* Empty stack */
+ rcu_read_unlock();
return NULL;
}
}