[ltt-dev] [RFC] Lock-free RCU stack for userspace RCU library
Mathieu Desnoyers
mathieu.desnoyers at efficios.com
Mon Jul 12 11:50:44 EDT 2010
Hi,
I just did the lock-free stack, which end up being much simpler than the queue
because there is no need for dummy head pointer. Comments are welcome.
Even though I did not do formal verification of the queue and stack, I feel
sufficiently confident to push them in urcu mainline. I'll wait for feedback
before cutting a release though. I also created test_urcu_lfq and test_urcu_lfs
which will also be in the tree. They perform heavy enqueue/dequeue and push/pop
to stress-test the algorithms. They check if the number of operations (e.g. push
vs pop) balance.
Thanks,
Mathieu
/*
* rculfstack.h
*
* Userspace RCU library - Lock-Free RCU Stack
*
* Copyright 2010 - Mathieu Desnoyers <mathieu.desnoyers at efficios.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
struct rcu_lfs_node {
struct rcu_lfs_node *next;
};
struct rcu_lfs_stack {
struct rcu_lfs_node *head;
};
void rcu_lfs_node_init(struct rcu_lfs_node *node)
{
}
void rcu_lfs_init(struct rcu_lfs_stack *s)
{
s->head = NULL;
}
void rcu_lfs_push(struct rcu_lfs_stack *s, struct rcu_lfs_node *node)
{
rcu_read_lock();
for (;;) {
struct rcu_lfs_node *head = rcu_dereference(s->head);
node->next = head;
/*
* uatomic_cmpxchg() implicit memory barrier orders earlier
* stores to node before publication.
*/
if (uatomic_cmpxchg(&s->head, head, node) == head) {
rcu_read_unlock();
return;
} else {
/* Failure to prepend. Retry. */
continue;
}
}
}
struct rcu_lfs_node *
rcu_lfs_pop(struct rcu_lfs_stack *s)
{
rcu_read_lock();
for (;;) {
struct rcu_lfs_node *head = rcu_dereference(s->head);
if (head) {
struct rcu_lfs_node *next = rcu_dereference(head->next);
if (uatomic_cmpxchg(&s->head, head, next) == head) {
rcu_read_unlock();
return head;
} else {
/* Concurrent modification. Retry. */
continue;
}
} else {
/* Empty stack */
rcu_read_unlock();
return NULL;
}
}
}
--
Mathieu Desnoyers
Operating System Efficiency R&D Consultant
EfficiOS Inc.
http://www.efficios.com
More information about the lttng-dev
mailing list