>From 52f5d218442eb64f2798335d56a1838f90d96d5f Mon Sep 17 00:00:00 2001 From: Akira Yokosawa <akiyks@xxxxxxxxx> Date: Mon, 30 Dec 2018 22:54:43 +0900 Subject: [PATCH] EXP hashtorture.h: Avoid sporadic SIGSEGV in hash_bkt_rcu Commit 4e22bdc905ff ("Wait at end of test for call_rcu() to finish") added a couple of synchronize_rcu()s in perftest_update() and zoo_reader(). However, there still remains sporadic SIGSEGV in $ ./hash_bkt_rcu --perftest --nupdaters 3 On the other hand, $ ./hash_bkt_rcu --schroedinger --nupdaters 3 does not show such issue. Just moving synchronize_rcu()s in zoo_reader() to zoo_updater() does not resolve the SIGSEGV. This commit defines rcu_barrier() if not available, and puts them at both before and after the final loop of perftest_updater() and zoo_updater(). It looks like this change can fix the above mentioned SIGSEGV in "--perftest". [Tested on Ubuntu Xenial with liburcu-dev/xenial,now 0.9.1-3 and liburcu4/xenial,now 0.9.1-3 installed.] NOTE: $ ./hash_resize --schroedinger --resizemult 2 --duration 20 still fails with SIGSEGV frequently in zoo_del(). GDB says: (gdb) where #0 0x0000000000402b27 in cds_list_del_rcu (elem=0x7ff8fc0138f0) at /usr/include/urcu/rculist.h:71 #1 hashtab_del (htep=0x7ff8fc0138d0, htp_master=<optimized out>) at hash_resize.c:261 #2 zoo_del (zhep=0x7ff8fc0138d0) at hashtorture.h:1007 #3 zoo_updater (arg=0x1e8b298) at hashtorture.h:1153 #4 0x00007ff9057d16ba in start_thread (arg=0x7ff903fed700) at pthread_create.c:333 #5 0x00007ff9050f741d in clone () at ../sysdeps/unix/sysv/linux/x86_64/clone.S:109 Signed-off-by: Akira Yokosawa <akiyks@xxxxxxxxx> --- Hi Paul, This is a partial fix, but it resolves SIGSEGV in "--perftest" of hash_bkt_rcu and hash_resize. "--schroedinger" of hash_resize with resizing enabled still seg faults as mentioned in the commit log. By the way, what version of liburcu are you using? Thanks, Akira -- CodeSamples/datastruct/hash/hashtorture.h | 24 ++++++++++++++++-------- 1 file changed, 16 insertions(+), 8 deletions(-) diff --git a/CodeSamples/datastruct/hash/hashtorture.h b/CodeSamples/datastruct/hash/hashtorture.h index 0e90220..9ae3dfa 100644 --- a/CodeSamples/datastruct/hash/hashtorture.h +++ b/CodeSamples/datastruct/hash/hashtorture.h @@ -55,6 +55,15 @@ void (*defer_del_done)(struct ht_elem *htep) = NULL; #ifndef quiescent_state #define quiescent_state() do ; while (0) #define synchronize_rcu() do ; while (0) +#define rcu_barrier() do ; while (0) +#else +#ifndef rcu_barrier +#define rcu_barrier() do { \ + synchronize_rcu(); \ + poll(NULL, 0, 100); \ + synchronize_rcu(); \ + } while (0) +#endif /* #ifndef rcu_barrier */ #endif /* #ifndef quiescent_state */ /* @@ -765,6 +774,7 @@ void *perftest_reader(void *arg) if (i >= ne) i = i % ne + offset; } + pap->nlookups = nlookups; pap->nlookupfails = nlookupfails; hash_unregister_thread(); @@ -839,6 +849,7 @@ void *perftest_updater(void *arg) quiescent_state(); } + rcu_barrier(); /* Test over, so remove all our elements from the hash table. */ for (i = 0; i < elperupdater; i++) { if (thep[i].in_table != 1) @@ -846,10 +857,7 @@ void *perftest_updater(void *arg) BUG_ON(!perftest_lookup(thep[i].data)); perftest_del(&thep[i]); } - /* Really want rcu_barrier(), but missing from old liburcu versions. */ - synchronize_rcu(); - poll(NULL, 0, 100); - synchronize_rcu(); + rcu_barrier(); hash_unregister_thread(); free(thep); @@ -1048,10 +1056,6 @@ void *zoo_reader(void *arg) if (i >= ne) i = i % ne + offset; } - /* Really want rcu_barrier(), but missing from old liburcu versions. */ - synchronize_rcu(); - poll(NULL, 0, 100); - synchronize_rcu(); pap->nlookups = nlookups; pap->nlookupfails = nlookupfails; @@ -1136,15 +1140,19 @@ void *zoo_updater(void *arg) quiescent_state(); } + rcu_barrier(); /* Test over, so remove all our elements from the hash table. */ for (i = 0; i < elperupdater; i++) { if (!zheplist[i]) continue; zoo_del(zheplist[i]); } + rcu_barrier(); + hash_unregister_thread(); pap->nadds = nadds; pap->ndels = ndels; + free(zheplist); return NULL; } -- 2.7.4