lttng-dev.lists.lttng.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v2 1/4] userspace-rcu: Add lock-free singly linked list rculflist
       [not found] <1564407331-25820-1-git-send-email-junchangwang@gmail.com>
@ 2019-07-29 13:35 ` Junchang Wang
  2019-07-29 13:35 ` [PATCH v2 2/4] userspace-rcu: Add sample code of rculflist Junchang Wang
                   ` (5 subsequent siblings)
  6 siblings, 0 replies; 9+ messages in thread
From: Junchang Wang @ 2019-07-29 13:35 UTC (permalink / raw)
  To: mathieu.desnoyers, lttng-dev; +Cc: paulmck

Signed-off-by: Junchang Wang <junchangwang@gmail.com>
---
 include/urcu/rculflist.h | 284 +++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 284 insertions(+)
 create mode 100644 include/urcu/rculflist.h

diff --git a/include/urcu/rculflist.h b/include/urcu/rculflist.h
new file mode 100644
index 0000000..35c08aa
--- /dev/null
+++ b/include/urcu/rculflist.h
@@ -0,0 +1,284 @@
+/*
+ * rculflist.c
+ *
+ * Userspace RCU library - Lock-Free and ordered singly-linked list
+ *
+ * Copyright (c) 2019 Junchang Wang
+ * Copyright (c) 2019 Paul E. McKenney
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, you can access it online at
+ * http://www.gnu.org/licenses/gpl-2.0.html.
+ *
+ *
+ * Based on the following research paper:
+ * - Maged M. Michael. High performance dynamic lock-free hash tables
+ *   and list-based sets. In Proceedings of the fourteenth annual ACM
+ *   symposium on Parallel algorithms and architectures, ACM Press,
+ *   (2002), 73-82.
+ *
+ * Some specificities of this Lock-free linked list implementation:
+ * - The original algorithm prevents the ABA problem by adding a tag field
+ *   in each hash-table node, whereas this implementation addresses this
+ *   issue by using the RCU mechanism.
+ */
+
+#ifndef _URCU_RCULFLIST_H
+#define _URCU_RCULFLIST_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <errno.h>
+#include <urcu/uatomic.h>
+#include <urcu-pointer.h>
+#include <urcu-call-rcu.h>
+
+#define ACCESS_ONCE(x) (*(volatile typeof(x) *)&(x))
+#define READ_ONCE(x) \
+            ({ typeof(x) ___x = ACCESS_ONCE(x); ___x; })
+#define WRITE_ONCE(x, val) ({ ACCESS_ONCE(x) = (val); })
+
+/*
+ * lflist reserves the least-significant 2 bits to record control information.
+ * Currently, it only uses the least-significant 1 bit to indicate if a node
+ * has been logically removed.
+ */
+#define RESERVED_BITS_LEN (2)
+#define REMOVED_FLAG 	(1UL << 0)
+#define FLAGS_MASK 	((1UL << RESERVED_BITS_LEN) - 1)
+
+/*
+ * Define the structure of list node and related functions.
+ */
+struct cds_lflist_node {
+	struct rcu_head rcu_head;
+	unsigned long key;
+	struct cds_lflist_node *next; /* (pointer | xxx_FLAG) */
+} __attribute__((aligned(CAA_CACHE_LINE_SIZE)));
+
+static
+unsigned long get_flag(struct cds_lflist_node *ptr)
+{
+	return (unsigned long)((uintptr_t)ptr & FLAGS_MASK);
+}
+
+static
+struct cds_lflist_node * get_ptr(struct cds_lflist_node *ptr)
+{
+	return (struct cds_lflist_node *)((uintptr_t)ptr & ~FLAGS_MASK);
+}
+
+static
+struct cds_lflist_node * set_flag(struct cds_lflist_node *ptr,
+                                      unsigned long mask)
+{
+	return (struct cds_lflist_node *)
+                    (((uintptr_t)ptr & ~FLAGS_MASK) | mask);
+}
+
+static
+int is_removed(struct cds_lflist_node *ptr)
+{
+	return ((uintptr_t)ptr & FLAGS_MASK) != 0;
+}
+
+void cds_lflist_node_init_rcu(struct cds_lflist_node *node)
+{
+	node->next = NULL;
+	node->key = 0UL;
+}
+
+void cds_lflist_node_set_key(struct cds_lflist_node *node, unsigned long key)
+{
+	node->key = key;
+}
+
+/*
+ * Struct cds_lflist_snapshot and its helper functions.
+ * Before invoking cds_lflist_find_rcu, the caller must first allocates
+ * an instance of struct cds_lflist_snapshot and passs the pointer
+ * to cds_lflist_find_rcu. By its completion, cds_lflist_find_rcu
+ * guarantees that (1) cur points to the node that contains the
+ * lowest key value that is greater than or equal to the input key
+ * and (2) prev is the predecessor pointer of cur.
+ */
+struct cds_lflist_snapshot {
+	struct cds_lflist_node **prev;
+	struct cds_lflist_node *cur;
+	struct cds_lflist_node *next;
+};
+
+static inline
+void set_snapshot(struct cds_lflist_snapshot *ssp,struct cds_lflist_node **prev,
+		     struct cds_lflist_node *cur, struct cds_lflist_node *next)
+{
+	ssp->prev = prev;
+	ssp->cur = get_ptr(cur);
+	ssp->next = get_ptr(next);
+}
+
+/*
+ * Define the struct of lock-free list and its helper functions.
+ */
+struct cds_lflist_rcu {
+	struct cds_lflist_node *head;
+	void (*delete_node)(struct cds_lflist_node *);
+};
+
+int cds_lflist_init_rcu(struct cds_lflist_rcu *list,
+		        void (*node_free)(struct cds_lflist_node *))
+{
+	list->head = NULL;
+	list->delete_node = node_free;
+	return 0;
+}
+
+/*
+ * Function cds_lflist_find_rcu() returns success(0) if the node with
+ * a matching key was found in the list, or returns failure(-Exxx) otherwise.
+ * No matter if find_rcu() returns success or failure, by its completion,
+ * it guarantees that *ssp* points to the snapshot of a segment of the list.
+ * Within the snapshot, field *cur* points to the node that contains
+ * the lowest key value greater than or equal to the input key,
+ * and *prev* is the predecessor pointer of *cur*.
+ */
+int cds_lflist_find_rcu(struct cds_lflist_rcu *list, unsigned long key,
+                            struct cds_lflist_snapshot *ssp)
+{
+	/* Local variables to record the snapshot */
+	struct cds_lflist_node **prev, *cur, *next;
+
+	struct cds_lflist_node *cur_ptr;
+	struct cds_lflist_node *next_ptr;
+	unsigned long cur_key;
+
+try_again:
+	prev = &list->head;
+	cur = rcu_dereference(*prev);
+	cur_ptr = get_ptr(cur);
+
+	for (;;) {
+		if (cur_ptr == NULL) {
+			/* Have reached the end of the list. */
+			set_snapshot(ssp, prev, NULL, NULL);
+			return -ENOENT;
+		}
+		cur_key = cur_ptr->key;
+		next = cur_ptr->next;
+		next_ptr = get_ptr(next);
+
+		/* If a new node has been added before cur, go to retry. */
+		if (READ_ONCE(*prev) != cur_ptr)
+			goto try_again;
+		if (!is_removed(next)) {
+			if (cur_key >= key) {
+				/* The key value of node cur_ptr is equal to
+				 * or larger than the input key value. */
+				set_snapshot(ssp, prev, cur_ptr, next);
+				if (cur_key == key)
+					return 0;
+				else
+					return -ENOENT;
+			}
+			prev = &cur_ptr->next;
+		} else {
+			/* If the node cur_ptr has been logically deleted,
+			 * try to physically delete it. */
+			if (uatomic_cmpxchg(prev, cur_ptr, next_ptr) == cur_ptr){
+				/* Some applications (e.g., hashtorture) manages
+				 * (destroy) nodes by themselves. For these cases,
+				 * list->delete_node is initialized to NULL.  */
+				if(list->delete_node)
+					list->delete_node(cur_ptr);
+			} else {
+				/* One of other threads has physically delete
+				 * the node. Retry. */
+				goto try_again;
+			}
+		}
+		cur = rcu_dereference(next);
+		cur_ptr = get_ptr(cur);
+	}
+}
+
+/*
+ * Function cds_lflist_insert_rcu returns -EINVAL if a node with a matching key
+ * is found in the list. Otherwise, this function inserts the new node before
+ * the node ss.cur and returns 0.
+ */
+int cds_lflist_insert_rcu(struct cds_lflist_rcu *list,
+                              struct cds_lflist_node *node)
+{
+	unsigned long key = node->key;
+	struct cds_lflist_snapshot ss;
+
+	for (;;) {
+		if (!cds_lflist_find_rcu(list, key, &ss))
+			return -EINVAL;
+		rcu_assign_pointer(node->next, set_flag(ss.cur, get_flag(node->next)));
+		if (uatomic_cmpxchg(ss.prev, set_flag(ss.cur, 0UL),
+				set_flag(node,0UL)) == set_flag(ss.cur, 0UL)) {
+			return 0;
+		}
+	}
+}
+
+/*
+ * Function cds_lflist_delete_rcu returns -EINVAL if the key is not found.
+ * Otherwise, the key value of the node pointed to by ss.cur must be equal to
+ * the input key. The function deletes the node by (1) marking the node pointed
+ * to by ss.cur as deleted, and (2) swinging prev->next to point to next.
+ */
+int cds_lflist_delete_rcu(struct cds_lflist_rcu *list, unsigned long key,
+		              struct cds_lflist_snapshot *ss)
+{
+	/* Local variables to record the snapshot */
+	struct cds_lflist_node *cur, *next;
+
+	for (;;) {
+		if (cds_lflist_find_rcu(list, key, ss))
+			return -EINVAL;
+		cur = READ_ONCE(ss->cur);
+		next = READ_ONCE(ss->next);
+
+		/* The node to be deleted is pointed to by ss->cur.
+		 * We first logically deleted it by setting its REMOVED_FLAG.
+		 */
+		if (uatomic_cmpxchg(&cur->next, set_flag(next, 0UL),
+				set_flag(next, REMOVED_FLAG)) != set_flag(next, 0UL))
+			continue;
+		/* If node pointed to by ss->cur has been logically deleted,
+		 * try to physically delete it.
+		 */
+		if (uatomic_cmpxchg(ss->prev, set_flag(cur, 0UL),
+				set_flag(next, 0UL)) == set_flag(cur, 0UL)) {
+			/* Some applications (e.g., hashtorture) manages
+			 * (destroy) nodes by themselves. For these cases,
+			 * list->delete_node is initialized to NULL.  */
+			if (list->delete_node)
+				list->delete_node(cur);
+		} else {
+			/* Physical deletion failed. Retry.  */
+			cds_lflist_find_rcu(list, key, ss);
+		}
+		return 0;
+	}
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /*_URCU_RCULFLIST_H */
-- 
1.8.3.1

^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [PATCH v2 2/4] userspace-rcu: Add sample code of rculflist
       [not found] <1564407331-25820-1-git-send-email-junchangwang@gmail.com>
  2019-07-29 13:35 ` [PATCH v2 1/4] userspace-rcu: Add lock-free singly linked list rculflist Junchang Wang
@ 2019-07-29 13:35 ` Junchang Wang
  2019-07-29 13:35 ` [PATCH v2 3/4] userspace-rcu: Update Makefile.am to include rculflist into the project Junchang Wang
                   ` (4 subsequent siblings)
  6 siblings, 0 replies; 9+ messages in thread
From: Junchang Wang @ 2019-07-29 13:35 UTC (permalink / raw)
  To: mathieu.desnoyers, lttng-dev; +Cc: paulmck

Signed-off-by: Junchang Wang <junchangwang@gmail.com>
---
 doc/examples/rculflist/Makefile                    |  24 +++++
 .../rculflist/Makefile.cds_lflist_delete_rcu       |  21 +++++
 .../rculflist/Makefile.cds_lflist_find_rcu         |  21 +++++
 .../rculflist/Makefile.cds_lflist_insert_rcu       |  21 +++++
 doc/examples/rculflist/cds_lflist_delete_rcu.c     | 101 +++++++++++++++++++++
 doc/examples/rculflist/cds_lflist_find_rcu.c       |  96 ++++++++++++++++++++
 doc/examples/rculflist/cds_lflist_insert_rcu.c     |  69 ++++++++++++++
 7 files changed, 353 insertions(+)
 create mode 100644 doc/examples/rculflist/Makefile
 create mode 100644 doc/examples/rculflist/Makefile.cds_lflist_delete_rcu
 create mode 100644 doc/examples/rculflist/Makefile.cds_lflist_find_rcu
 create mode 100644 doc/examples/rculflist/Makefile.cds_lflist_insert_rcu
 create mode 100644 doc/examples/rculflist/cds_lflist_delete_rcu.c
 create mode 100644 doc/examples/rculflist/cds_lflist_find_rcu.c
 create mode 100644 doc/examples/rculflist/cds_lflist_insert_rcu.c

diff --git a/doc/examples/rculflist/Makefile b/doc/examples/rculflist/Makefile
new file mode 100644
index 0000000..b804b13
--- /dev/null
+++ b/doc/examples/rculflist/Makefile
@@ -0,0 +1,24 @@
+# Copyright (C) 2013  Junchang Wang <junchangwang@gmail.com>
+#
+# THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED
+# OR IMPLIED.  ANY USE IS AT YOUR OWN RISK.
+#
+# Permission is hereby granted to use or copy this program for any
+# purpose,  provided the above notices are retained on all copies.
+# Permission to modify the code and to distribute modified code is
+# granted, provided the above notices are retained, and a notice that
+# the code was modified is included with the above copyright notice.
+#
+# This makefile is purposefully kept simple to support GNU and BSD make.
+
+all:
+	$(AM_V_at)$(MAKE) -f Makefile.cds_lflist_insert_rcu
+	$(AM_V_at)$(MAKE) -f Makefile.cds_lflist_delete_rcu
+	$(AM_V_at)$(MAKE) -f Makefile.cds_lflist_find_rcu
+
+.PHONY: clean
+clean:
+	$(AM_V_at)$(MAKE) -f Makefile.cds_lflist_insert_rcu clean
+	$(AM_V_at)$(MAKE) -f Makefile.cds_lflist_delete_rcu clean
+	$(AM_V_at)$(MAKE) -f Makefile.cds_lflist_find_rcu clean
+
diff --git a/doc/examples/rculflist/Makefile.cds_lflist_delete_rcu b/doc/examples/rculflist/Makefile.cds_lflist_delete_rcu
new file mode 100644
index 0000000..09d1a55
--- /dev/null
+++ b/doc/examples/rculflist/Makefile.cds_lflist_delete_rcu
@@ -0,0 +1,21 @@
+# Copyright (C) 2013  Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
+#
+# THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED
+# OR IMPLIED.  ANY USE IS AT YOUR OWN RISK.
+#
+# Permission is hereby granted to use or copy this program for any
+# purpose,  provided the above notices are retained on all copies.
+# Permission to modify the code and to distribute modified code is
+# granted, provided the above notices are retained, and a notice that
+# the code was modified is included with the above copyright notice.
+#
+# This makefile is purposefully kept simple to support GNU and BSD make.
+
+EXAMPLE_NAME = cds_lflist_delete_rcu
+
+SOURCES = $(EXAMPLE_NAME).c
+OBJECTS = $(EXAMPLE_NAME).o
+BINARY = $(EXAMPLE_NAME)
+LIBS = -lurcu
+
+include ../Makefile.examples.template
diff --git a/doc/examples/rculflist/Makefile.cds_lflist_find_rcu b/doc/examples/rculflist/Makefile.cds_lflist_find_rcu
new file mode 100644
index 0000000..77ad9b4
--- /dev/null
+++ b/doc/examples/rculflist/Makefile.cds_lflist_find_rcu
@@ -0,0 +1,21 @@
+# Copyright (C) 2013  Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
+#
+# THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED
+# OR IMPLIED.  ANY USE IS AT YOUR OWN RISK.
+#
+# Permission is hereby granted to use or copy this program for any
+# purpose,  provided the above notices are retained on all copies.
+# Permission to modify the code and to distribute modified code is
+# granted, provided the above notices are retained, and a notice that
+# the code was modified is included with the above copyright notice.
+#
+# This makefile is purposefully kept simple to support GNU and BSD make.
+
+EXAMPLE_NAME = cds_lflist_find_rcu
+
+SOURCES = $(EXAMPLE_NAME).c
+OBJECTS = $(EXAMPLE_NAME).o
+BINARY = $(EXAMPLE_NAME)
+LIBS = -lurcu
+
+include ../Makefile.examples.template
diff --git a/doc/examples/rculflist/Makefile.cds_lflist_insert_rcu b/doc/examples/rculflist/Makefile.cds_lflist_insert_rcu
new file mode 100644
index 0000000..cdde123
--- /dev/null
+++ b/doc/examples/rculflist/Makefile.cds_lflist_insert_rcu
@@ -0,0 +1,21 @@
+# Copyright (C) 2013  Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
+#
+# THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED
+# OR IMPLIED.  ANY USE IS AT YOUR OWN RISK.
+#
+# Permission is hereby granted to use or copy this program for any
+# purpose,  provided the above notices are retained on all copies.
+# Permission to modify the code and to distribute modified code is
+# granted, provided the above notices are retained, and a notice that
+# the code was modified is included with the above copyright notice.
+#
+# This makefile is purposefully kept simple to support GNU and BSD make.
+
+EXAMPLE_NAME = cds_lflist_insert_rcu
+
+SOURCES = $(EXAMPLE_NAME).c
+OBJECTS = $(EXAMPLE_NAME).o
+BINARY = $(EXAMPLE_NAME)
+LIBS = -lurcu
+
+include ../Makefile.examples.template
diff --git a/doc/examples/rculflist/cds_lflist_delete_rcu.c b/doc/examples/rculflist/cds_lflist_delete_rcu.c
new file mode 100644
index 0000000..d5b1327
--- /dev/null
+++ b/doc/examples/rculflist/cds_lflist_delete_rcu.c
@@ -0,0 +1,101 @@
+/*
+ * Copyright (C) 2019 Junchang Wang
+ *
+ * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED
+ * OR IMPLIED.  ANY USE IS AT YOUR OWN RISK.
+ *
+ * Permission is hereby granted to use or copy this program for any
+ * purpose,  provided the above notices are retained on all copies.
+ * Permission to modify the code and to distribute modified code is
+ * granted, provided the above notices are retained, and a notice that
+ * the code was modified is included with the above copyright notice.
+ *
+ * This example shows how to delete a node from a linked-list safely against
+ * concurrent RCU traversals.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <urcu/urcu-memb.h>	/* RCU flavor */
+#include <urcu/rculflist.h>	/* RCU lock-free linked list */
+#include <urcu/compiler.h>	/* For CAA_ARRAY_SIZE */
+
+static void free_node(struct rcu_head *head)
+{
+        struct cds_lflist_node *node =
+                caa_container_of(head, struct cds_lflist_node, rcu_head);
+
+        free(node);
+}
+
+int main(int argc, char **argv)
+{
+	int values[] = { -5, 42, 36, 24, };
+	struct cds_lflist_node * nodes[CAA_ARRAY_SIZE(values)];
+
+	struct cds_lflist_rcu mylist;	/* List */
+	unsigned int i;
+	int ret = 0;
+
+	/*
+	 * Each thread using RCU read-side needs to be explicitly
+	 * registered.
+	 */
+	urcu_memb_register_thread();
+
+	cds_lflist_init_rcu(&mylist, NULL);
+
+	/*
+	 * Insert nodes.
+	 */
+	printf("Insert content:");
+	for (i = 0; i < CAA_ARRAY_SIZE(values); i++) {
+		struct cds_lflist_node *node;
+
+		node = malloc(sizeof(*node));
+		if (!node) {
+			ret = -1;
+			goto end;
+		}
+
+		nodes[i] = node;
+		cds_lflist_node_init_rcu(node);
+		cds_lflist_node_set_key(node, values[i]);
+		/*
+		 * Both insert and delete need to be called within RCU
+		 * read-side critical section.
+		 */
+		urcu_memb_read_lock();
+		assert(!cds_lflist_insert_rcu(&mylist, node));
+		urcu_memb_read_unlock();
+		printf(" %ld", node->key);
+	}
+	printf("\n");
+
+	/*
+	 * Delete each node from the queue.
+	 */
+	printf("Delete content:");
+	struct cds_lflist_snapshot ss;
+	for (i = 0; i < CAA_ARRAY_SIZE(values); i++) {
+		struct cds_lflist_node *node = nodes[i];
+
+		/*
+		 * Both insert and delete need to be called within RCU
+		 * read-side critical section.
+		 */
+		urcu_memb_read_lock();
+		assert(!cds_lflist_delete_rcu(&mylist, node->key, &ss));
+		urcu_memb_read_unlock();
+
+		printf(" %ld", node->key);
+		urcu_memb_call_rcu(&node->rcu_head, free_node);
+	}
+	printf("\n");
+
+end:
+	urcu_memb_unregister_thread();
+	return ret;
+}
+
diff --git a/doc/examples/rculflist/cds_lflist_find_rcu.c b/doc/examples/rculflist/cds_lflist_find_rcu.c
new file mode 100644
index 0000000..bb465c1
--- /dev/null
+++ b/doc/examples/rculflist/cds_lflist_find_rcu.c
@@ -0,0 +1,96 @@
+/*
+ * Copyright (C) 2019 Junchang Wang
+ *
+ * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED
+ * OR IMPLIED.  ANY USE IS AT YOUR OWN RISK.
+ *
+ * Permission is hereby granted to use or copy this program for any
+ * purpose,  provided the above notices are retained on all copies.
+ * Permission to modify the code and to distribute modified code is
+ * granted, provided the above notices are retained, and a notice that
+ * the code was modified is included with the above copyright notice.
+ *
+ * This example shows how to safely search a key in the linked list.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <urcu/urcu-memb.h>	/* RCU flavor */
+#include <urcu/rculflist.h>	/* RCU lock-free linked list */
+#include <urcu/compiler.h>	/* For CAA_ARRAY_SIZE */
+
+int main(int argc, char **argv)
+{
+	int values[] = { -5, 42, 36, 24, };
+	struct cds_lflist_node * nodes[CAA_ARRAY_SIZE(values)];
+
+	struct cds_lflist_rcu mylist;	/* List */
+	unsigned int i;
+	int ret = 0;
+
+	/*
+	 * Each thread using RCU read-side need to be explicitly
+	 * registered.
+	 */
+	urcu_memb_register_thread();
+
+	cds_lflist_init_rcu(&mylist, NULL);
+
+	/*
+	 * Insert nodes.
+	 */
+	printf("Insert content:");
+	for (i = 0; i < CAA_ARRAY_SIZE(values); i++) {
+		struct cds_lflist_node *node;
+
+		node = malloc(sizeof(*node));
+		if (!node) {
+			ret = -1;
+			goto end;
+		}
+
+		nodes[i] = node;
+		cds_lflist_node_init_rcu(node);
+		cds_lflist_node_set_key(node, values[i]);
+		/*
+		 * Both insert and delete need to be called within RCU
+		 * read-side critical section.
+		 */
+		urcu_memb_read_lock();
+		assert(!cds_lflist_insert_rcu(&mylist, node));
+		urcu_memb_read_unlock();
+		printf(" %ld", node->key);
+	}
+	printf("\n");
+
+	/*
+	 * Search each node from the queue.
+	 */
+	struct cds_lflist_snapshot ss;
+	long invalid_key = 0;
+	for (i = 0; i < CAA_ARRAY_SIZE(values); i++) {
+		struct cds_lflist_node *node = nodes[i];
+
+		/*
+		 * Function find needs to be called within RCU
+		 * read-side critical section.
+		 */
+		urcu_memb_read_lock();
+		assert(!cds_lflist_find_rcu(&mylist, node->key, &ss));
+		urcu_memb_read_unlock();
+
+		invalid_key += node->key;
+		printf("Find content: %ld\n", node->key);
+	}
+
+	urcu_memb_read_lock();
+	assert(cds_lflist_find_rcu(&mylist, invalid_key, &ss) == -ENOENT);
+	urcu_memb_read_unlock();
+	printf("Can't find content: %ld\n", invalid_key);
+
+end:
+	urcu_memb_unregister_thread();
+	return ret;
+}
+
diff --git a/doc/examples/rculflist/cds_lflist_insert_rcu.c b/doc/examples/rculflist/cds_lflist_insert_rcu.c
new file mode 100644
index 0000000..252a25c
--- /dev/null
+++ b/doc/examples/rculflist/cds_lflist_insert_rcu.c
@@ -0,0 +1,69 @@
+/*
+ * Copyright (C) 2019 Junchang Wang
+ *
+ * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED
+ * OR IMPLIED.  ANY USE IS AT YOUR OWN RISK.
+ *
+ * Permission is hereby granted to use or copy this program for any
+ * purpose,  provided the above notices are retained on all copies.
+ * Permission to modify the code and to distribute modified code is
+ * granted, provided the above notices are retained, and a notice that
+ * the code was modified is included with the above copyright notice.
+ *
+ * This example shows how to add into a linked-list safely against
+ * concurrent RCU traversals.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <urcu/urcu-memb.h>	/* RCU flavor */
+#include <urcu/rculflist.h>	/* RCU lock-free linked list */
+#include <urcu/compiler.h>	/* For CAA_ARRAY_SIZE */
+
+int main(int argc, char **argv)
+{
+	int values[] = { -5, 42, 36, 24, };
+	struct cds_lflist_rcu mylist;	/* List */
+	unsigned int i;
+	int ret = 0;
+
+	/*
+	 * Each thread using RCU read-side needs to be explicitly
+	 * registered.
+	 */
+	urcu_memb_register_thread();
+
+	cds_lflist_init_rcu(&mylist, NULL);
+
+	/*
+	 * Insert nodes.
+	 */
+	printf("Insert content:");
+	for (i = 0; i < CAA_ARRAY_SIZE(values); i++) {
+		struct cds_lflist_node *node;
+
+		node = malloc(sizeof(*node));
+		if (!node) {
+			ret = -1;
+			goto end;
+		}
+
+		cds_lflist_node_init_rcu(node);
+		cds_lflist_node_set_key(node, values[i]);
+		/*
+		 * Both insert and delete need to be called within RCU
+		 * read-side critical section.
+		 */
+		urcu_memb_read_lock();
+		assert(!cds_lflist_insert_rcu(&mylist, node));
+		urcu_memb_read_unlock();
+		printf(" %ld", node->key);
+	}
+	printf("\n");
+
+end:
+	urcu_memb_unregister_thread();
+	return ret;
+}
+
-- 
1.8.3.1

^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [PATCH v2 3/4] userspace-rcu: Update Makefile.am to include rculflist into the project
       [not found] <1564407331-25820-1-git-send-email-junchangwang@gmail.com>
  2019-07-29 13:35 ` [PATCH v2 1/4] userspace-rcu: Add lock-free singly linked list rculflist Junchang Wang
  2019-07-29 13:35 ` [PATCH v2 2/4] userspace-rcu: Add sample code of rculflist Junchang Wang
@ 2019-07-29 13:35 ` Junchang Wang
  2019-07-29 13:35 ` [PATCH v2 4/4] userspace-rcu: Add a brief description of rculflist in cds-api.md Junchang Wang
                   ` (3 subsequent siblings)
  6 siblings, 0 replies; 9+ messages in thread
From: Junchang Wang @ 2019-07-29 13:35 UTC (permalink / raw)
  To: mathieu.desnoyers, lttng-dev; +Cc: paulmck

Signed-off-by: Junchang Wang <junchangwang@gmail.com>
---
 include/Makefile.am | 1 +
 include/urcu/cds.h  | 1 +
 2 files changed, 2 insertions(+)

diff --git a/include/Makefile.am b/include/Makefile.am
index 34812d4..c4de329 100644
--- a/include/Makefile.am
+++ b/include/Makefile.am
@@ -2,6 +2,7 @@ nobase_dist_include_HEADERS = urcu/compiler.h urcu/hlist.h urcu/list.h \
 		urcu/rculist.h urcu/rcuhlist.h urcu/system.h urcu/futex.h \
 		urcu/uatomic/generic.h urcu/arch/generic.h urcu/wfstack.h \
 		urcu/wfqueue.h urcu/rculfstack.h urcu/rculfqueue.h \
+		urcu/rculflist.h \
 		urcu/ref.h urcu/cds.h urcu/urcu_ref.h urcu/urcu-futex.h \
 		urcu/uatomic_arch.h urcu/rculfhash.h urcu/wfcqueue.h \
 		urcu/lfstack.h urcu/syscall-compat.h \
diff --git a/include/urcu/cds.h b/include/urcu/cds.h
index 78534bb..faa31ab 100644
--- a/include/urcu/cds.h
+++ b/include/urcu/cds.h
@@ -30,6 +30,7 @@
 #include <urcu/rculfqueue.h>
 #include <urcu/rculfstack.h>
 #include <urcu/rculfhash.h>
+#include <urcu/rculflist.h>
 #include <urcu/wfqueue.h>
 #include <urcu/wfcqueue.h>
 #include <urcu/wfstack.h>
-- 
1.8.3.1

^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [PATCH v2 4/4] userspace-rcu: Add a brief description of rculflist in cds-api.md
       [not found] <1564407331-25820-1-git-send-email-junchangwang@gmail.com>
                   ` (2 preceding siblings ...)
  2019-07-29 13:35 ` [PATCH v2 3/4] userspace-rcu: Update Makefile.am to include rculflist into the project Junchang Wang
@ 2019-07-29 13:35 ` Junchang Wang
       [not found] ` <1564407331-25820-2-git-send-email-junchangwang@gmail.com>
                   ` (2 subsequent siblings)
  6 siblings, 0 replies; 9+ messages in thread
From: Junchang Wang @ 2019-07-29 13:35 UTC (permalink / raw)
  To: mathieu.desnoyers, lttng-dev; +Cc: paulmck

Signed-off-by: Junchang Wang <junchangwang@gmail.com>
---
 doc/cds-api.md | 7 +++++++
 1 file changed, 7 insertions(+)

diff --git a/doc/cds-api.md b/doc/cds-api.md
index 49a3c7c..577126a 100644
--- a/doc/cds-api.md
+++ b/doc/cds-api.md
@@ -82,3 +82,10 @@ are supported. Provides "uniquify add" and "replace add"
 operations, along with associated read-side traversal uniqueness
 guarantees. Automatic hash table resize based on number of
 elements is supported. See the API for more details.
+
+
+### `urcu/rculflist.h`
+
+Ordered singly linked list with lock-free insert, delete and find operations.
+This list relies on RCU for existence guarantees and ABA-problem prevention.
+It is useful for implementing hash tables.
-- 
1.8.3.1

^ permalink raw reply related	[flat|nested] 9+ messages in thread

* Re: [PATCH v2 1/4] userspace-rcu: Add lock-free singly linked list rculflist
       [not found] ` <1564407331-25820-2-git-send-email-junchangwang@gmail.com>
@ 2019-07-29 13:45   ` Mathieu Desnoyers
  0 siblings, 0 replies; 9+ messages in thread
From: Mathieu Desnoyers @ 2019-07-29 13:45 UTC (permalink / raw)
  To: Junchang Wang; +Cc: lttng-dev, paulmck

----- On Jul 29, 2019, at 9:35 AM, Junchang Wang junchangwang@gmail.com wrote:

> Signed-off-by: Junchang Wang <junchangwang@gmail.com>

Hi Junchang,

Thanks for submitting this! I've been on vacation for the past two weeks,
hence the delay in reply.

A few points:

I think we should move the implementation of find/insert/delete to a .c
file (rather than headers) because at least two of those functions are
larger than 10 lines, and therefore don't fall under the "trivial"
category.

I also notice that the implementation you propose is GPLv2+. Would you
be willing to re-license your contribution under LGPLv2.1 or LGPLv2.1+ ?
This is the license we use for the entire Userspace RCU library. liburcu
is meant to be used by non-GPL/LGPL programs as well.

I'll wait until I get an answer from you on those points before digging
further into the code.

Thanks,

Mathieu

-- 
Mathieu Desnoyers
EfficiOS Inc.
http://www.efficios.com

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH v2 0/4] userspace-rcu: Add lock-free, ordered singly linked list
       [not found] <1564407331-25820-1-git-send-email-junchangwang@gmail.com>
                   ` (4 preceding siblings ...)
       [not found] ` <1564407331-25820-2-git-send-email-junchangwang@gmail.com>
@ 2019-07-29 13:55 ` Mathieu Desnoyers
       [not found] ` <1759632476.1182.1564408558415.JavaMail.zimbra@efficios.com>
  6 siblings, 0 replies; 9+ messages in thread
From: Mathieu Desnoyers @ 2019-07-29 13:55 UTC (permalink / raw)
  To: Junchang Wang; +Cc: lttng-dev, paulmck

----- On Jul 29, 2019, at 9:35 AM, Junchang Wang junchangwang@gmail.com wrote:

> Hi Mathieu and the list,
> 
> I'm recently using userspace-rcu to build lock-free data structures. Thanks for
> sharing this excellent project!
> 
> In building a hash table, I am looking for an ordered singly linked list
> that is lock-free. It seems such a list is missing in userspace-rcu. I
> discussed this with Paul in the mailing list of perfbook, and he kindly
> suggested me to submit my implementation to userspace-rcu. So here is the
> RFC. Any comments and suggestions are warmly welcome.

One point worth mentioning: the rculfhash data structure (rcu lock-free hash
table) already implements such list internally. You might want to have a look
at it, and perhaps just lift out its implementation into a separate .c file
and header file so we can expose its implementation publicly ?

Items are linked through the struct cds_lfht_node next field.

The struct cds_lfht_iter is used as a iterator on the list.

struct cds_lfht tbl_oder, tbl_chunk and tbl_mmap contain the
linked lists heads for each memory allocation scheme.

I'm wondering why you need to re-implement a hash table though. What is
missing from rculfhash to suit your needs ?

Thanks,

Mathieu


> 
> This singly linked list is based on the following research paper:
> - Maged M. Michael. High performance dynamic lock-free hash tables
>   and list-based sets. In Proceedings of the fourteenth annual ACM
>   symposium on Parallel algorithms and architectures, ACM Press,
>   (2002), 73-82.
> 
> And we made the following two major improvements:
> (1) Insert, Delete, and Find operations are protected by RCU read_lock,
>     such that the existence guarantees are provided by the RCU mechanism,
>     and that no special memory management schemes (e.g., hazard pointers)
>     is required anymore.
> (2) The use of the RCU mechanism can naturally prevent the ABA problem,
>     such that no flag field is required in this implementation. Hence,
>     we save a variable of 8 bytes (typically sizeof(long)) for each node.
> 
> In the past two weeks, I found some bugs in the first version of the
> list in building a lock-free hash table on top it. So this is the second
> version which fixes the known issues. Please review this version, if
> possible. The major changes are as follows. Sorry for the inconvenience.
> Any suggestions and comments are warmly welcome.
> 
> v1 -> v2:
>  - Functions insert(), delete(), and find() return 0 in success, and
>    return -Exxx otherwise.
>  - Fix a bug in function is_removed().
> 
> Cheers,
> --Junchang
> 
> Junchang Wang (4):
>  userspace-rcu: Add lock-free singly linked list rculflist
>  userspace-rcu: Add sample code of rculflist
>  userspace-rcu: Update Makefile.am to include rculflist into the
>    project
>  userspace-rcu: Add a brief description of rculflist in cds-api.md
> 
> doc/cds-api.md                                     |   7 +
> doc/examples/rculflist/Makefile                    |  24 ++
> .../rculflist/Makefile.cds_lflist_delete_rcu       |  21 ++
> .../rculflist/Makefile.cds_lflist_find_rcu         |  21 ++
> .../rculflist/Makefile.cds_lflist_insert_rcu       |  21 ++
> doc/examples/rculflist/cds_lflist_delete_rcu.c     | 101 ++++++++
> doc/examples/rculflist/cds_lflist_find_rcu.c       |  96 +++++++
> doc/examples/rculflist/cds_lflist_insert_rcu.c     |  69 +++++
> include/Makefile.am                                |   1 +
> include/urcu/cds.h                                 |   1 +
> include/urcu/rculflist.h                           | 284 +++++++++++++++++++++
> 11 files changed, 646 insertions(+)
> create mode 100644 doc/examples/rculflist/Makefile
> create mode 100644 doc/examples/rculflist/Makefile.cds_lflist_delete_rcu
> create mode 100644 doc/examples/rculflist/Makefile.cds_lflist_find_rcu
> create mode 100644 doc/examples/rculflist/Makefile.cds_lflist_insert_rcu
> create mode 100644 doc/examples/rculflist/cds_lflist_delete_rcu.c
> create mode 100644 doc/examples/rculflist/cds_lflist_find_rcu.c
> create mode 100644 doc/examples/rculflist/cds_lflist_insert_rcu.c
> create mode 100644 include/urcu/rculflist.h
> 
> --
> 1.8.3.1
> 
> _______________________________________________
> lttng-dev mailing list
> lttng-dev@lists.lttng.org
> https://lists.lttng.org/cgi-bin/mailman/listinfo/lttng-dev

-- 
Mathieu Desnoyers
EfficiOS Inc.
http://www.efficios.com

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH v2 0/4] userspace-rcu: Add lock-free, ordered singly linked list
       [not found] ` <1759632476.1182.1564408558415.JavaMail.zimbra@efficios.com>
@ 2019-07-30 13:34   ` Junchang Wang
       [not found]   ` <CABoNC821qnePU4Enrs8mSseVq-_Hp3Cehh93DO0+s=cKtDTZXQ@mail.gmail.com>
  1 sibling, 0 replies; 9+ messages in thread
From: Junchang Wang @ 2019-07-30 13:34 UTC (permalink / raw)
  To: Mathieu Desnoyers; +Cc: lttng-dev, paulmck

On Mon, Jul 29, 2019 at 9:55 PM Mathieu Desnoyers
<mathieu.desnoyers@efficios.com> wrote:
>
> ----- On Jul 29, 2019, at 9:35 AM, Junchang Wang junchangwang@gmail.com wrote:
>
> > Hi Mathieu and the list,
> >
> > I'm recently using userspace-rcu to build lock-free data structures. Thanks for
> > sharing this excellent project!
> >
> > In building a hash table, I am looking for an ordered singly linked list
> > that is lock-free. It seems such a list is missing in userspace-rcu. I
> > discussed this with Paul in the mailing list of perfbook, and he kindly
> > suggested me to submit my implementation to userspace-rcu. So here is the
> > RFC. Any comments and suggestions are warmly welcome.
>
> One point worth mentioning: the rculfhash data structure (rcu lock-free hash
> table) already implements such list internally. You might want to have a look
> at it, and perhaps just lift out its implementation into a separate .c file
> and header file so we can expose its implementation publicly ?
>
> Items are linked through the struct cds_lfht_node next field.
>
> The struct cds_lfht_iter is used as a iterator on the list.
>
> struct cds_lfht tbl_oder, tbl_chunk and tbl_mmap contain the
> linked lists heads for each memory allocation scheme.

Hi Mathieu,

Thanks for the note. I checked rculfhash today, and the list
implementation within rculfhash is indeed quite similar to the one I'm
working on. I will check to see if we can merge the two versions and
provide an independent rculflist.

>
> I'm wondering why you need to re-implement a hash table though. What is
> missing from rculfhash to suit your needs ?
>

The major reason is that I want a hash table that can change its hash
function on-the-fly. Split-ordered list is not adequate because it can
only increase/decrease the number of buckets. Besides, I doubt the
reverse operation is always efficient on platforms where hardware
cannot help reverse bit strings. Hence I'm working on the new hash
table algorithm, which, of course, is built on top of the linked list
we are working on :-).

Thanks,
--Junchang

> Thanks,
>
> Mathieu
>
>
> >
> > This singly linked list is based on the following research paper:
> > - Maged M. Michael. High performance dynamic lock-free hash tables
> >   and list-based sets. In Proceedings of the fourteenth annual ACM
> >   symposium on Parallel algorithms and architectures, ACM Press,
> >   (2002), 73-82.
> >
> > And we made the following two major improvements:
> > (1) Insert, Delete, and Find operations are protected by RCU read_lock,
> >     such that the existence guarantees are provided by the RCU mechanism,
> >     and that no special memory management schemes (e.g., hazard pointers)
> >     is required anymore.
> > (2) The use of the RCU mechanism can naturally prevent the ABA problem,
> >     such that no flag field is required in this implementation. Hence,
> >     we save a variable of 8 bytes (typically sizeof(long)) for each node.
> >
> > In the past two weeks, I found some bugs in the first version of the
> > list in building a lock-free hash table on top it. So this is the second
> > version which fixes the known issues. Please review this version, if
> > possible. The major changes are as follows. Sorry for the inconvenience.
> > Any suggestions and comments are warmly welcome.
> >
> > v1 -> v2:
> >  - Functions insert(), delete(), and find() return 0 in success, and
> >    return -Exxx otherwise.
> >  - Fix a bug in function is_removed().
> >
> > Cheers,
> > --Junchang
> >
> > Junchang Wang (4):
> >  userspace-rcu: Add lock-free singly linked list rculflist
> >  userspace-rcu: Add sample code of rculflist
> >  userspace-rcu: Update Makefile.am to include rculflist into the
> >    project
> >  userspace-rcu: Add a brief description of rculflist in cds-api.md
> >
> > doc/cds-api.md                                     |   7 +
> > doc/examples/rculflist/Makefile                    |  24 ++
> > .../rculflist/Makefile.cds_lflist_delete_rcu       |  21 ++
> > .../rculflist/Makefile.cds_lflist_find_rcu         |  21 ++
> > .../rculflist/Makefile.cds_lflist_insert_rcu       |  21 ++
> > doc/examples/rculflist/cds_lflist_delete_rcu.c     | 101 ++++++++
> > doc/examples/rculflist/cds_lflist_find_rcu.c       |  96 +++++++
> > doc/examples/rculflist/cds_lflist_insert_rcu.c     |  69 +++++
> > include/Makefile.am                                |   1 +
> > include/urcu/cds.h                                 |   1 +
> > include/urcu/rculflist.h                           | 284 +++++++++++++++++++++
> > 11 files changed, 646 insertions(+)
> > create mode 100644 doc/examples/rculflist/Makefile
> > create mode 100644 doc/examples/rculflist/Makefile.cds_lflist_delete_rcu
> > create mode 100644 doc/examples/rculflist/Makefile.cds_lflist_find_rcu
> > create mode 100644 doc/examples/rculflist/Makefile.cds_lflist_insert_rcu
> > create mode 100644 doc/examples/rculflist/cds_lflist_delete_rcu.c
> > create mode 100644 doc/examples/rculflist/cds_lflist_find_rcu.c
> > create mode 100644 doc/examples/rculflist/cds_lflist_insert_rcu.c
> > create mode 100644 include/urcu/rculflist.h
> >
> > --
> > 1.8.3.1
> >
> > _______________________________________________
> > lttng-dev mailing list
> > lttng-dev@lists.lttng.org
> > https://lists.lttng.org/cgi-bin/mailman/listinfo/lttng-dev
>
> --
> Mathieu Desnoyers
> EfficiOS Inc.
> http://www.efficios.com

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH v2 0/4] userspace-rcu: Add lock-free, ordered singly linked list
       [not found]   ` <CABoNC821qnePU4Enrs8mSseVq-_Hp3Cehh93DO0+s=cKtDTZXQ@mail.gmail.com>
@ 2019-07-30 15:15     ` Mathieu Desnoyers
       [not found]     ` <2090901729.4706.1564499733170.JavaMail.zimbra@efficios.com>
  1 sibling, 0 replies; 9+ messages in thread
From: Mathieu Desnoyers @ 2019-07-30 15:15 UTC (permalink / raw)
  To: Junchang Wang; +Cc: lttng-dev, paulmck

----- On Jul 30, 2019, at 9:34 AM, Junchang Wang junchangwang@gmail.com wrote:

> On Mon, Jul 29, 2019 at 9:55 PM Mathieu Desnoyers
> <mathieu.desnoyers@efficios.com> wrote:
>>
>> ----- On Jul 29, 2019, at 9:35 AM, Junchang Wang junchangwang@gmail.com wrote:
>>
>> > Hi Mathieu and the list,
>> >
>> > I'm recently using userspace-rcu to build lock-free data structures. Thanks for
>> > sharing this excellent project!
>> >
>> > In building a hash table, I am looking for an ordered singly linked list
>> > that is lock-free. It seems such a list is missing in userspace-rcu. I
>> > discussed this with Paul in the mailing list of perfbook, and he kindly
>> > suggested me to submit my implementation to userspace-rcu. So here is the
>> > RFC. Any comments and suggestions are warmly welcome.
>>
>> One point worth mentioning: the rculfhash data structure (rcu lock-free hash
>> table) already implements such list internally. You might want to have a look
>> at it, and perhaps just lift out its implementation into a separate .c file
>> and header file so we can expose its implementation publicly ?
>>
>> Items are linked through the struct cds_lfht_node next field.
>>
>> The struct cds_lfht_iter is used as a iterator on the list.
>>
>> struct cds_lfht tbl_oder, tbl_chunk and tbl_mmap contain the
>> linked lists heads for each memory allocation scheme.
> 
> Hi Mathieu,
> 
> Thanks for the note. I checked rculfhash today, and the list
> implementation within rculfhash is indeed quite similar to the one I'm
> working on. I will check to see if we can merge the two versions and
> provide an independent rculflist.

Great!

> 
>>
>> I'm wondering why you need to re-implement a hash table though. What is
>> missing from rculfhash to suit your needs ?
>>
> 
> The major reason is that I want a hash table that can change its hash
> function on-the-fly. Split-ordered list is not adequate because it can
> only increase/decrease the number of buckets. Besides, I doubt the
> reverse operation is always efficient on platforms where hardware
> cannot help reverse bit strings. Hence I'm working on the new hash
> table algorithm, which, of course, is built on top of the linked list
> we are working on :-).

That makes a lot of sense. Re-hasing is indeed the main feature missing
from rculfhash. I have ideas on how it could be introduced within the
current split-ordered implementation with only small changes.

One possibility would be to create two lists (rather than one): the
current list, and a second list that would be used when a re-hasing
is performed. The old list would be used by readers while re-hashing
is in progress, and add/del would take care of both lists when done
concurrently with re-hashing. After re-hasing is complete, the old
list would not be used anymore after a grace period has passed.

The cost of this approach is to have two next pointers per node (rather
than one).

An alternative would be to add a temporary layer of indirection when the
re-hasing is performed. The "next" pointer would actually point to an
intermediate object which contains the chaining information for both the
old and the new lists. This would save the cost of the additional next
pointer within each node, at the expense of doing extra temporary memory
allocation when doing the re-hashing.

I'd also be curious to see benchmarks of the bit-reversal compared to the
rest of the operations needed for lookup, addition, and removal in a
lock-free hash table for the main architectures that matter today.
What architectures do you care about ?

I'm also curious to see what new hash table algorithm you have in mind!

Thanks,

Mathieu


> 
> Thanks,
> --Junchang
> 
>> Thanks,
>>
>> Mathieu
>>
>>
>> >
>> > This singly linked list is based on the following research paper:
>> > - Maged M. Michael. High performance dynamic lock-free hash tables
>> >   and list-based sets. In Proceedings of the fourteenth annual ACM
>> >   symposium on Parallel algorithms and architectures, ACM Press,
>> >   (2002), 73-82.
>> >
>> > And we made the following two major improvements:
>> > (1) Insert, Delete, and Find operations are protected by RCU read_lock,
>> >     such that the existence guarantees are provided by the RCU mechanism,
>> >     and that no special memory management schemes (e.g., hazard pointers)
>> >     is required anymore.
>> > (2) The use of the RCU mechanism can naturally prevent the ABA problem,
>> >     such that no flag field is required in this implementation. Hence,
>> >     we save a variable of 8 bytes (typically sizeof(long)) for each node.
>> >
>> > In the past two weeks, I found some bugs in the first version of the
>> > list in building a lock-free hash table on top it. So this is the second
>> > version which fixes the known issues. Please review this version, if
>> > possible. The major changes are as follows. Sorry for the inconvenience.
>> > Any suggestions and comments are warmly welcome.
>> >
>> > v1 -> v2:
>> >  - Functions insert(), delete(), and find() return 0 in success, and
>> >    return -Exxx otherwise.
>> >  - Fix a bug in function is_removed().
>> >
>> > Cheers,
>> > --Junchang
>> >
>> > Junchang Wang (4):
>> >  userspace-rcu: Add lock-free singly linked list rculflist
>> >  userspace-rcu: Add sample code of rculflist
>> >  userspace-rcu: Update Makefile.am to include rculflist into the
>> >    project
>> >  userspace-rcu: Add a brief description of rculflist in cds-api.md
>> >
>> > doc/cds-api.md                                     |   7 +
>> > doc/examples/rculflist/Makefile                    |  24 ++
>> > .../rculflist/Makefile.cds_lflist_delete_rcu       |  21 ++
>> > .../rculflist/Makefile.cds_lflist_find_rcu         |  21 ++
>> > .../rculflist/Makefile.cds_lflist_insert_rcu       |  21 ++
>> > doc/examples/rculflist/cds_lflist_delete_rcu.c     | 101 ++++++++
>> > doc/examples/rculflist/cds_lflist_find_rcu.c       |  96 +++++++
>> > doc/examples/rculflist/cds_lflist_insert_rcu.c     |  69 +++++
>> > include/Makefile.am                                |   1 +
>> > include/urcu/cds.h                                 |   1 +
>> > include/urcu/rculflist.h                           | 284 +++++++++++++++++++++
>> > 11 files changed, 646 insertions(+)
>> > create mode 100644 doc/examples/rculflist/Makefile
>> > create mode 100644 doc/examples/rculflist/Makefile.cds_lflist_delete_rcu
>> > create mode 100644 doc/examples/rculflist/Makefile.cds_lflist_find_rcu
>> > create mode 100644 doc/examples/rculflist/Makefile.cds_lflist_insert_rcu
>> > create mode 100644 doc/examples/rculflist/cds_lflist_delete_rcu.c
>> > create mode 100644 doc/examples/rculflist/cds_lflist_find_rcu.c
>> > create mode 100644 doc/examples/rculflist/cds_lflist_insert_rcu.c
>> > create mode 100644 include/urcu/rculflist.h
>> >
>> > --
>> > 1.8.3.1
>> >
>> > _______________________________________________
>> > lttng-dev mailing list
>> > lttng-dev@lists.lttng.org
>> > https://lists.lttng.org/cgi-bin/mailman/listinfo/lttng-dev
>>
>> --
>> Mathieu Desnoyers
>> EfficiOS Inc.
>> http://www.efficios.com
> _______________________________________________
> lttng-dev mailing list
> lttng-dev@lists.lttng.org
> https://lists.lttng.org/cgi-bin/mailman/listinfo/lttng-dev

-- 
Mathieu Desnoyers
EfficiOS Inc.
http://www.efficios.com

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH v2 0/4] userspace-rcu: Add lock-free, ordered singly linked list
       [not found]     ` <2090901729.4706.1564499733170.JavaMail.zimbra@efficios.com>
@ 2019-08-01 10:51       ` Junchang Wang
  0 siblings, 0 replies; 9+ messages in thread
From: Junchang Wang @ 2019-08-01 10:51 UTC (permalink / raw)
  To: Mathieu Desnoyers; +Cc: lttng-dev, paulmck


[-- Attachment #1.1: Type: text/plain, Size: 8799 bytes --]

Hi Mathieu,

Thanks a lot for the feedback. Please see below,

On Tue, Jul 30, 2019 at 11:15 PM Mathieu Desnoyers <
mathieu.desnoyers@efficios.com> wrote:
>
> ----- On Jul 30, 2019, at 9:34 AM, Junchang Wang junchangwang@gmail.com
wrote:
>
> > On Mon, Jul 29, 2019 at 9:55 PM Mathieu Desnoyers
> > <mathieu.desnoyers@efficios.com> wrote:
> >>
> >> ----- On Jul 29, 2019, at 9:35 AM, Junchang Wang junchangwang@gmail.com
wrote:
> >>
> >> > Hi Mathieu and the list,
> >> >
> >> > I'm recently using userspace-rcu to build lock-free data structures.
Thanks for
> >> > sharing this excellent project!
> >> >
> >> > In building a hash table, I am looking for an ordered singly linked
list
> >> > that is lock-free. It seems such a list is missing in userspace-rcu.
I
> >> > discussed this with Paul in the mailing list of perfbook, and he
kindly
> >> > suggested me to submit my implementation to userspace-rcu. So here
is the
> >> > RFC. Any comments and suggestions are warmly welcome.
> >>
> >> One point worth mentioning: the rculfhash data structure (rcu
lock-free hash
> >> table) already implements such list internally. You might want to have
a look
> >> at it, and perhaps just lift out its implementation into a separate .c
file
> >> and header file so we can expose its implementation publicly ?
> >>
> >> Items are linked through the struct cds_lfht_node next field.
> >>
> >> The struct cds_lfht_iter is used as a iterator on the list.
> >>
> >> struct cds_lfht tbl_oder, tbl_chunk and tbl_mmap contain the
> >> linked lists heads for each memory allocation scheme.
> >
> > Hi Mathieu,
> >
> > Thanks for the note. I checked rculfhash today, and the list
> > implementation within rculfhash is indeed quite similar to the one I'm
> > working on. I will check to see if we can merge the two versions and
> > provide an independent rculflist.
>
> Great!
>
> >
> >>
> >> I'm wondering why you need to re-implement a hash table though. What is
> >> missing from rculfhash to suit your needs ?
> >>
> >
> > The major reason is that I want a hash table that can change its hash
> > function on-the-fly. Split-ordered list is not adequate because it can
> > only increase/decrease the number of buckets. Besides, I doubt the
> > reverse operation is always efficient on platforms where hardware
> > cannot help reverse bit strings. Hence I'm working on the new hash
> > table algorithm, which, of course, is built on top of the linked list
> > we are working on :-).
>
> That makes a lot of sense. Re-hasing is indeed the main feature missing
> from rculfhash. I have ideas on how it could be introduced within the
> current split-ordered implementation with only small changes.
>
> One possibility would be to create two lists (rather than one): the
> current list, and a second list that would be used when a re-hasing
> is performed. The old list would be used by readers while re-hashing
> is in progress, and add/del would take care of both lists when done
> concurrently with re-hashing. After re-hasing is complete, the old
> list would not be used anymore after a grace period has passed.
>
> The cost of this approach is to have two next pointers per node (rather
> than one).

Agree. And we need to customize a linked list to allow each node to contain
two next pointers, before the hash table algorithm can use the list.

>
> An alternative would be to add a temporary layer of indirection when the
> re-hasing is performed. The "next" pointer would actually point to an
> intermediate object which contains the chaining information for both the
> old and the new lists. This would save the cost of the additional next
> pointer within each node, at the expense of doing extra temporary memory
> allocation when doing the re-hashing.
>

Great suggestion! One benefit is that we may reuse a lock-free linked list
without any modifications. If I understand correctly, the overall memory
consumption with this approach is slightly larger than that of the previous
one, because, in rehashing, each node has one intermediate node followed.
Is that right?

> I'd also be curious to see benchmarks of the bit-reversal compared to the
> rest of the operations needed for lookup, addition, and removal in a
> lock-free hash table for the main architectures that matter today.
> What architectures do you care about ?
>

Would be very happy to take a look at this and let you know the results
soon. BTW, I was thinking that some architectures (e.g., x86) could have
special instructions to help us accelerate the bit-reversal. Unfortunately,
I searched on google today and can't find the exact instruction to do this.
The most related instructions I found was at
https://en.wikipedia.org/wiki/Bit_Manipulation_Instruction_Sets . Do you
know the x86 instructions that can reverse bit strings? Thanks.

> I'm also curious to see what new hash table algorithm you have in mind!
>

I will write down the algorithm and send it to you soon.


Thanks,
--Junchang

> Thanks,
>
> Mathieu
>
>
> >
> > Thanks,
> > --Junchang
> >
> >> Thanks,
> >>
> >> Mathieu
> >>
> >>
> >> >
> >> > This singly linked list is based on the following research paper:
> >> > - Maged M. Michael. High performance dynamic lock-free hash tables
> >> >   and list-based sets. In Proceedings of the fourteenth annual ACM
> >> >   symposium on Parallel algorithms and architectures, ACM Press,
> >> >   (2002), 73-82.
> >> >
> >> > And we made the following two major improvements:
> >> > (1) Insert, Delete, and Find operations are protected by RCU
read_lock,
> >> >     such that the existence guarantees are provided by the RCU
mechanism,
> >> >     and that no special memory management schemes (e.g., hazard
pointers)
> >> >     is required anymore.
> >> > (2) The use of the RCU mechanism can naturally prevent the ABA
problem,
> >> >     such that no flag field is required in this implementation.
Hence,
> >> >     we save a variable of 8 bytes (typically sizeof(long)) for each
node.
> >> >
> >> > In the past two weeks, I found some bugs in the first version of the
> >> > list in building a lock-free hash table on top it. So this is the
second
> >> > version which fixes the known issues. Please review this version, if
> >> > possible. The major changes are as follows. Sorry for the
inconvenience.
> >> > Any suggestions and comments are warmly welcome.
> >> >
> >> > v1 -> v2:
> >> >  - Functions insert(), delete(), and find() return 0 in success, and
> >> >    return -Exxx otherwise.
> >> >  - Fix a bug in function is_removed().
> >> >
> >> > Cheers,
> >> > --Junchang
> >> >
> >> > Junchang Wang (4):
> >> >  userspace-rcu: Add lock-free singly linked list rculflist
> >> >  userspace-rcu: Add sample code of rculflist
> >> >  userspace-rcu: Update Makefile.am to include rculflist into the
> >> >    project
> >> >  userspace-rcu: Add a brief description of rculflist in cds-api.md
> >> >
> >> > doc/cds-api.md                                     |   7 +
> >> > doc/examples/rculflist/Makefile                    |  24 ++
> >> > .../rculflist/Makefile.cds_lflist_delete_rcu       |  21 ++
> >> > .../rculflist/Makefile.cds_lflist_find_rcu         |  21 ++
> >> > .../rculflist/Makefile.cds_lflist_insert_rcu       |  21 ++
> >> > doc/examples/rculflist/cds_lflist_delete_rcu.c     | 101 ++++++++
> >> > doc/examples/rculflist/cds_lflist_find_rcu.c       |  96 +++++++
> >> > doc/examples/rculflist/cds_lflist_insert_rcu.c     |  69 +++++
> >> > include/Makefile.am                                |   1 +
> >> > include/urcu/cds.h                                 |   1 +
> >> > include/urcu/rculflist.h                           | 284
+++++++++++++++++++++
> >> > 11 files changed, 646 insertions(+)
> >> > create mode 100644 doc/examples/rculflist/Makefile
> >> > create mode 100644
doc/examples/rculflist/Makefile.cds_lflist_delete_rcu
> >> > create mode 100644
doc/examples/rculflist/Makefile.cds_lflist_find_rcu
> >> > create mode 100644
doc/examples/rculflist/Makefile.cds_lflist_insert_rcu
> >> > create mode 100644 doc/examples/rculflist/cds_lflist_delete_rcu.c
> >> > create mode 100644 doc/examples/rculflist/cds_lflist_find_rcu.c
> >> > create mode 100644 doc/examples/rculflist/cds_lflist_insert_rcu.c
> >> > create mode 100644 include/urcu/rculflist.h
> >> >
> >> > --
> >> > 1.8.3.1
> >> >
> >> > _______________________________________________
> >> > lttng-dev mailing list
> >> > lttng-dev@lists.lttng.org
> >> > https://lists.lttng.org/cgi-bin/mailman/listinfo/lttng-dev
> >>
> >> --
> >> Mathieu Desnoyers
> >> EfficiOS Inc.
> >> http://www.efficios.com
> > _______________________________________________
> > lttng-dev mailing list
> > lttng-dev@lists.lttng.org
> > https://lists.lttng.org/cgi-bin/mailman/listinfo/lttng-dev
>
> --
> Mathieu Desnoyers
> EfficiOS Inc.
> http://www.efficios.com

[-- Attachment #1.2: Type: text/html, Size: 11680 bytes --]

[-- Attachment #2: Type: text/plain, Size: 156 bytes --]

_______________________________________________
lttng-dev mailing list
lttng-dev@lists.lttng.org
https://lists.lttng.org/cgi-bin/mailman/listinfo/lttng-dev

^ permalink raw reply	[flat|nested] 9+ messages in thread

end of thread, other threads:[~2019-08-01 10:51 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
     [not found] <1564407331-25820-1-git-send-email-junchangwang@gmail.com>
2019-07-29 13:35 ` [PATCH v2 1/4] userspace-rcu: Add lock-free singly linked list rculflist Junchang Wang
2019-07-29 13:35 ` [PATCH v2 2/4] userspace-rcu: Add sample code of rculflist Junchang Wang
2019-07-29 13:35 ` [PATCH v2 3/4] userspace-rcu: Update Makefile.am to include rculflist into the project Junchang Wang
2019-07-29 13:35 ` [PATCH v2 4/4] userspace-rcu: Add a brief description of rculflist in cds-api.md Junchang Wang
     [not found] ` <1564407331-25820-2-git-send-email-junchangwang@gmail.com>
2019-07-29 13:45   ` [PATCH v2 1/4] userspace-rcu: Add lock-free singly linked list rculflist Mathieu Desnoyers
2019-07-29 13:55 ` [PATCH v2 0/4] userspace-rcu: Add lock-free, ordered singly linked list Mathieu Desnoyers
     [not found] ` <1759632476.1182.1564408558415.JavaMail.zimbra@efficios.com>
2019-07-30 13:34   ` Junchang Wang
     [not found]   ` <CABoNC821qnePU4Enrs8mSseVq-_Hp3Cehh93DO0+s=cKtDTZXQ@mail.gmail.com>
2019-07-30 15:15     ` Mathieu Desnoyers
     [not found]     ` <2090901729.4706.1564499733170.JavaMail.zimbra@efficios.com>
2019-08-01 10:51       ` Junchang Wang

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).