summary |
shortlog |
log |
commit | commitdiff |
tree
raw |
patch |
inline | side by side (from parent 1:
4a0b347)
* API change * for all liburcu-cds* flavors.
Signed-off-by: Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
_cds_lfq_node_init_rcu(node);
}
_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);
}
int cds_lfq_destroy_rcu(struct cds_lfq_queue_rcu *q)
}
int cds_lfq_destroy_rcu(struct cds_lfq_queue_rcu *q)
if (!node)
goto fail;
cds_lfq_node_init_rcu(node);
if (!node)
goto fail;
cds_lfq_node_init_rcu(node);
cds_lfq_enqueue_rcu(&q, node);
cds_lfq_enqueue_rcu(&q, node);
nr_successful_enqueues++;
if (unlikely(wdelay))
nr_successful_enqueues++;
if (unlikely(wdelay))
for (;;) {
struct cds_lfq_node_rcu *node;
for (;;) {
struct cds_lfq_node_rcu *node;
node = cds_lfq_dequeue_rcu(&q);
node = cds_lfq_dequeue_rcu(&q);
if (node) {
defer_rcu(free, node);
nr_successful_dequeues++;
if (node) {
defer_rcu(free, node);
nr_successful_dequeues++;
struct cds_lfq_node_rcu *node;
do {
struct cds_lfq_node_rcu *node;
do {
node = cds_lfq_dequeue_rcu(q);
node = cds_lfq_dequeue_rcu(q);
if (node) {
free(node); /* no more concurrent access */
(*nr_dequeues)++;
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);
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);
for (;;) {
struct cds_lfs_node_rcu *node;
for (;;) {
struct cds_lfs_node_rcu *node;
node = cds_lfs_pop_rcu(&s);
node = cds_lfs_pop_rcu(&s);
if (node) {
defer_rcu(free, node);
nr_successful_dequeues++;
if (node) {
defer_rcu(free, node);
nr_successful_dequeues++;
struct cds_lfq_queue_rcu {
struct cds_lfq_node_rcu *head, *tail;
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));
#else /* !_LGPL_SOURCE */
extern void cds_lfq_node_init_rcu(struct cds_lfq_node_rcu *node);
#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.
*
/*
* The queue should be emptied before calling destroy.
*
extern int cds_lfq_destroy_rcu(struct cds_lfq_queue_rcu *q);
/*
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);
/*
*/
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.
*
* 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);
/*
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.
*
* 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);
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);
-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->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,
*/
static inline
void _cds_lfq_enqueue_rcu(struct cds_lfq_queue_rcu *q,
for (;;) {
struct cds_lfq_node_rcu *tail, *next;
for (;;) {
struct cds_lfq_node_rcu *tail, *next;
tail = rcu_dereference(q->tail);
next = uatomic_cmpxchg(&tail->next, NULL, node);
if (next == NULL) {
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);
* enqueue might beat us to it, that's fine).
*/
(void) uatomic_cmpxchg(&q->tail, tail, node);
* Help moving tail further and retry.
*/
(void) uatomic_cmpxchg(&q->tail, tail, next);
* Help moving tail further and retry.
*/
(void) uatomic_cmpxchg(&q->tail, tail, next);
- * 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.
*
* 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;
for (;;) {
struct cds_lfq_node_rcu *head, *next;
head = rcu_dereference(q->head);
next = rcu_dereference(head->next);
head = rcu_dereference(q->head);
next = rcu_dereference(head->next);
- if (head->dummy && next == NULL)
+ if (head->dummy && next == NULL) {
+ rcu_read_unlock();
/*
* We never, ever allow dequeue to get to a state where
* the queue is empty (we need at least one node in the
/*
* 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);
}
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. */
continue; /* Concurrently pushed. */
if (head->dummy) {
/* Free dummy after grace period. */
rcu_free_dummy(head);
if (head->dummy) {
/* Free dummy after grace period. */
rcu_free_dummy(head);
continue; /* try again */
}
continue; /* try again */
}
- * 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.
*
* 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;
for (;;) {
struct cds_lfs_node_rcu *head;
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) {
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) {
return head;
} else {
/* Concurrent modification. Retry. */
return head;
} else {
/* Concurrent modification. Retry. */
continue;
}
} else {
/* Empty stack */
continue;
}
} else {
/* Empty stack */