Fix: change order of _cds_lfht_new_with_alloc parameters The "flavor" parameter should come before the "alloc" parameter to match the order of cds_lfht_new_with_flavor_alloc() parameters. Signed-off-by: Mathieu Desnoyers <mathieu.desnoyers@efficios.com> Change-Id: Ia704a0fd9cb90af966464e25e6202fed1a952eed
Add support for custom memory allocators for rculfhash The current implementation of rculfhash relies on calloc() to allocate memory for its buckets. This can in some cases lead to latency spikes when accessing the hash table, which can be avoided by using an optimized custom memory allocator. However, there is currently no way of replacing the default allocator with a custom one. This commit allows custom allocators to be used during the table initialization. The default behavior of the hash table remains unaffected, by using the stdlib calloc() and free(), if no custom allocator is given. Signed-off-by: Xenofon Foukas <fon1989@gmail.com> Signed-off-by: Mathieu Desnoyers <mathieu.desnoyers@efficios.com> Change-Id: Id9a405e5dc42e5564ff8623394c86056a4d1ff48
Public headers: use SPDX identifiers The SPDX identifiers [1] are a legally binding shorthand, which can be used instead of the full boiler plate text. This is another step towards implementing the full REUSE spec [2] to help with copyright and licensing audits and compliance. This will reduce a lot a manual work required for the licensing audit required in Debian on each update. For files that lacked copyright and licensing information, I used the following guidelines. Use the author from the git history and the main project license 'LGPL-2.1-or-later'. [1] https://spdx.org/ids-how [2] https://reuse.software/tutorial/ Change-Id: I31928c81be4821cca29b905d8a0a06de9bd0e1ec Signed-off-by: Michael Jeanson <mjeanson@efficios.com> Signed-off-by: Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
rculfhash: Use caa_container_of_check_null in cds_lfht_entry Use caa_container_of_check_null in cds_lfht_entry to allow removing caa_unqual_scalar_typeof, which requires C11. Signed-off-by: Mathieu Desnoyers <mathieu.desnoyers@efficios.com> Change-Id: Ifd8b05e666b8f1618a823b96a934a2357edb6b36
Avoid calling caa_container_of on NULL pointer in cds_lfht macros The cds_lfht_for_each_entry and cds_lfht_for_each_entry_duplicate macros would call caa_container_of() macro on NULL pointer. This is not a problem under normal circumstances as the check in the for loop fails and the loop-statement is not called with invalid (pos) value. However AddressSanitizer doesn't like that and complains about this: runtime error: applying non-zero offset 18446744073709551056 to null pointer Move the cds_lfht_iter_get_node(iter) != NULL from the cond-expression of the for loop into both init-clause and iteration-expression as conditional operator and check for (pos) value in the cond-expression instead. Introduce the cds_lfht_entry() macro to eliminate code duplication. Reported-by: Ondřej Surý <ondrej@sury.org> Signed-off-by: Mathieu Desnoyers <mathieu.desnoyers@efficios.com> Change-Id: I9969c1e0bc0eefc8c90c0d8f17b2927f6a4feb2a
Fix: auto-resize hash table destroy deadlock Fix a deadlock for auto-resize hash tables when cds_lfht_destroy is called with RCU read-side lock held. Example stack track of a hang: Thread 2 (Thread 0x7f21ba876700 (LWP 26114)): #0 syscall () at ../sysdeps/unix/sysv/linux/x86_64/syscall.S:38 #1 0x00007f21beba7aa0 in futex (val3=0, uaddr2=0x0, timeout=0x0, val=-1, op=0, uaddr=0x7f21bedac308 <urcu_memb_gp+8>) at ../include/urcu/futex.h:81 #2 futex_noasync (timeout=0x0, uaddr2=0x0, val3=0, val=-1, op=0, uaddr=0x7f21bedac308 <urcu_memb_gp+8>) at ../include/urcu/futex.h:90 #3 wait_gp () at urcu.c:265 #4 wait_for_readers (input_readers=input_readers@entry=0x7f21ba8751b0, cur_snap_readers=cur_snap_readers@entry=0x0, qsreaders=qsreaders@entry=0x7f21ba8751c0) at urcu.c:357 #5 0x00007f21beba8339 in urcu_memb_synchronize_rcu () at urcu.c:498 #6 0x00007f21be99f93f in fini_table (last_order=<optimized out>, first_order=13, ht=0x5651cec75400) at rculfhash.c:1489 #7 _do_cds_lfht_shrink (new_size=<optimized out>, old_size=<optimized out>, ht=0x5651cec75400) at rculfhash.c:2001 #8 _do_cds_lfht_resize (ht=ht@entry=0x5651cec75400) at rculfhash.c:2023 #9 0x00007f21be99fa26 in do_resize_cb (work=0x5651e20621a0) at rculfhash.c:2063 #10 0x00007f21be99dbfd in workqueue_thread (arg=0x5651cec74a00) at workqueue.c:234 #11 0x00007f21bd7c06db in start_thread (arg=0x7f21ba876700) at pthread_create.c:463 #12 0x00007f21bd4e961f in clone () at ../sysdeps/unix/sysv/linux/x86_64/clone.S:95 Thread 1 (Thread 0x7f21bf285300 (LWP 26098)): #0 syscall () at ../sysdeps/unix/sysv/linux/x86_64/syscall.S:38 #1 0x00007f21be99d8b7 in futex (val3=0, uaddr2=0x0, timeout=0x0, val=-1, op=0, uaddr=0x5651d8b38584) at ../include/urcu/futex.h:81 #2 futex_async (timeout=0x0, uaddr2=0x0, val3=0, val=-1, op=0, uaddr=0x5651d8b38584) at ../include/urcu/futex.h:113 #3 futex_wait (futex=futex@entry=0x5651d8b38584) at workqueue.c:135 #4 0x00007f21be99e2c8 in urcu_workqueue_wait_completion (completion=completion@entry=0x5651d8b38580) at workqueue.c:423 #5 0x00007f21be99e3f9 in urcu_workqueue_flush_queued_work (workqueue=0x5651cec74a00) at workqueue.c:452 #6 0x00007f21be9a0c83 in cds_lfht_destroy (ht=0x5651d8b2fcf0, attr=attr@entry=0x0) at rculfhash.c:1906 This deadlock is easy to reproduce when rapidly adding a large number of entries in the cds_lfht, removing them, and calling cds_lfht_destroy(). The deadlock will occur if the call to cds_lfht_destroy() takes place while a resize of the hash table is ongoing. Fix this by moving the teardown of the lfht worker thread to libcds library destructor, so it does not have to wait on synchronize_rcu from a resize callback from within a read-side critical section. As a consequence, the atfork callbacks are left registered within each urcu flavor for which a resizeable hash table is created until the end of the executable lifetime. The other part of the fix is to move the hash table destruction to the worker thread for auto-resize hash tables. This prevents having to wait for resize callbacks from RCU read-side critical section. This is guaranteed by the fact that the worker thread serializes previously queued resize callbacks before the destroy callback. Signed-off-by: Mathieu Desnoyers <mathieu.desnoyers@efficios.com> Change-Id: If8b1c3c8063dc7b9846dc5c3fc452efd917eab4d
rculfhash: introduce cds_lfht_node_init_deleted Allow initializing lfht node to "removed" state to allow querying whether the node is published in a hash table before it is added to the hash table and after it has been removed from the hash table. Signed-off-by: Mathieu Desnoyers <mathieu.desnoyers@efficios.com> Change-Id: I6e364a3ea076f33e34b4c63c7b23be22b35e9bb1
cleanup: explicitly mark unused parameters (-Wunused-parameter) Add the 'unused' attribute to function parameters that are unused to allow turning on -Wunused-parameter and distinguish unused parameters that are actual errors. Change-Id: Ie585e37f9d38718543a31aee2e7ab3428cdfd0a5 Signed-off-by: Michael Jeanson <mjeanson@efficios.com> Signed-off-by: Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
cds_lfht_is_node_deleted parameter can be marked const Mark the cds_lfht_node pointer parameter of cds_lfht_is_node_deleted as const. The fact that this parameter is mutable makes it harder to use liburcu in const-correct code. Signed-off-by: Jérémie Galarneau <jeremie.galarneau@efficios.com> Signed-off-by: Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
rculfhash: implement iterator debugging config option Building liburcu with --enable-cds-lfht-iter-debug and rebuilding application to match the ABI change allows finding cases where the hash table iterator is re-purposed to be used on a different hash table while still being used to iterate on a hash table. This is a common programming mistake that happens often enough to justify creating a debugging mode to track this automatically. Signed-off-by: Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
Use workqueue in rculfhash The RCU lock-free hash table currently requires that the destroy function should not be called from within RCU read-side critical sections. This is caused by the lazy resize, which uses the call_rcu worker thread, even though all it really needs is a workqueue/worker thread scheme. Use the new internal workqueue API instead of call_rcu in rculfhash to overcome this limitation. Signed-off-by: Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
Cleanup: Re-organise source dir Re-organise the sources, add a top level "src" and "include" dir and move relevant files. Disable autotools automated includes and define them manually. This fixes problems with collision of header names with system headers. Include the autoconf config.h in the default includes and remove it where it's explicitely included. Remove _GNU_SOURCE defines since it's detected at configure for platforms that requires it and added to the config.h. Signed-off-by: Michael Jeanson <mjeanson@efficios.com> Signed-off-by: Mathieu Desnoyers <mathieu.desnoyers@efficios.com>