Message ID | 20181216194836.1310998-1-arnd@arndb.de |
---|---|
State | Accepted |
Commit | 809c67059162e7ba85c61a83ad7547b4ffbb1e6e |
Headers | show |
Series | [v2] test_rhashtable: remove semaphore usage | expand |
On Sun, Dec 16, 2018 at 08:48:21PM +0100, Arnd Bergmann wrote: > This is one of only two files that initialize a semaphore to a negative > value. We don't really need the two semaphores here at all, but can do > the same thing in more conventional and more effient way, by using a > single waitqueue and an atomic thread counter. > > This gets us a little bit closer to eliminating classic semaphores from > the kernel. It also fixes a corner case where we fail to continue after > one of the threads fails to start up. > > An alternative would be to use a split kthread_create()+wake_up_process() > and completely eliminate the separate synchronization. > > Acked-by: Phil Sutter <phil@nwl.cc> > Signed-off-by: Arnd Bergmann <arnd@arndb.de> Acked-by: Herbert Xu <herbert@gondor.apana.org.au> -- Email: Herbert Xu <herbert@gondor.apana.org.au> Home Page: http://gondor.apana.org.au/~herbert/ PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt
From: Arnd Bergmann <arnd@arndb.de> Date: Sun, 16 Dec 2018 20:48:21 +0100 > This is one of only two files that initialize a semaphore to a negative > value. We don't really need the two semaphores here at all, but can do > the same thing in more conventional and more effient way, by using a > single waitqueue and an atomic thread counter. > > This gets us a little bit closer to eliminating classic semaphores from > the kernel. It also fixes a corner case where we fail to continue after > one of the threads fails to start up. > > An alternative would be to use a split kthread_create()+wake_up_process() > and completely eliminate the separate synchronization. > > Acked-by: Phil Sutter <phil@nwl.cc> > Signed-off-by: Arnd Bergmann <arnd@arndb.de> > --- > Changes from v1: > - rebase to mainline, > - fix pr_err() output > - bail out if interrupted Applied, thanks Arnd.
Hi Arnd, On Sun, Dec 16, 2018 at 8:50 PM Arnd Bergmann <arnd@arndb.de> wrote: > This is one of only two files that initialize a semaphore to a negative > value. We don't really need the two semaphores here at all, but can do > the same thing in more conventional and more effient way, by using a > single waitqueue and an atomic thread counter. > > This gets us a little bit closer to eliminating classic semaphores from > the kernel. It also fixes a corner case where we fail to continue after > one of the threads fails to start up. > > An alternative would be to use a split kthread_create()+wake_up_process() > and completely eliminate the separate synchronization. > > Acked-by: Phil Sutter <phil@nwl.cc> > Signed-off-by: Arnd Bergmann <arnd@arndb.de> > --- > Changes from v1: > - rebase to mainline, > - fix pr_err() output > - bail out if interrupted Now this is upstream as 809c67059162e7ba ("test_rhashtable: remove semaphore usage"), I gave test_rhashtable a try again on m68k/ARAnyM. And it succeeded, without my workaround from https://www.mail-archive.com/netdev@vger.kernel.org/msg134240.html Interestingly, it still succeeded without the workaround after reverting 809c67059162e7ba, so some other change during the last two years must have fixed this. I have no plans to bisect this, though. Gr{oetje,eeting}s, Geert -- Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert@linux-m68k.org In personal conversations with technical people, I call myself a hacker. But when I'm talking to journalists I just say "programmer" or something like that. -- Linus Torvalds
diff --git a/lib/test_rhashtable.c b/lib/test_rhashtable.c index 82ac39ce5310..6a8ac7626797 100644 --- a/lib/test_rhashtable.c +++ b/lib/test_rhashtable.c @@ -20,11 +20,11 @@ #include <linux/module.h> #include <linux/rcupdate.h> #include <linux/rhashtable.h> -#include <linux/semaphore.h> #include <linux/slab.h> #include <linux/sched.h> #include <linux/random.h> #include <linux/vmalloc.h> +#include <linux/wait.h> #define MAX_ENTRIES 1000000 #define TEST_INSERT_FAIL INT_MAX @@ -112,8 +112,8 @@ static struct rhashtable_params test_rht_params_dup = { .automatic_shrinking = false, }; -static struct semaphore prestart_sem; -static struct semaphore startup_sem = __SEMAPHORE_INITIALIZER(startup_sem, 0); +static atomic_t startup_count; +static DECLARE_WAIT_QUEUE_HEAD(startup_wait); static int insert_retry(struct rhashtable *ht, struct test_obj *obj, const struct rhashtable_params params) @@ -634,9 +634,12 @@ static int threadfunc(void *data) int i, step, err = 0, insert_retries = 0; struct thread_data *tdata = data; - up(&prestart_sem); - if (down_interruptible(&startup_sem)) - pr_err(" thread[%d]: down_interruptible failed\n", tdata->id); + if (atomic_dec_and_test(&startup_count)) + wake_up(&startup_wait); + if (wait_event_interruptible(startup_wait, atomic_read(&startup_count) == -1)) { + pr_err(" thread[%d]: interrupted\n", tdata->id); + goto out; + } for (i = 0; i < tdata->entries; i++) { tdata->objs[i].value.id = i; @@ -755,7 +758,7 @@ static int __init test_rht_init(void) pr_info("Testing concurrent rhashtable access from %d threads\n", tcount); - sema_init(&prestart_sem, 1 - tcount); + atomic_set(&startup_count, tcount); tdata = vzalloc(array_size(tcount, sizeof(struct thread_data))); if (!tdata) return -ENOMEM; @@ -781,15 +784,18 @@ static int __init test_rht_init(void) tdata[i].objs = objs + i * entries; tdata[i].task = kthread_run(threadfunc, &tdata[i], "rhashtable_thrad[%d]", i); - if (IS_ERR(tdata[i].task)) + if (IS_ERR(tdata[i].task)) { pr_err(" kthread_run failed for thread %d\n", i); - else + atomic_dec(&startup_count); + } else { started_threads++; + } } - if (down_interruptible(&prestart_sem)) - pr_err(" down interruptible failed\n"); - for (i = 0; i < tcount; i++) - up(&startup_sem); + if (wait_event_interruptible(startup_wait, atomic_read(&startup_count) == 0)) + pr_err(" wait_event interruptible failed\n"); + /* count is 0 now, set it to -1 and wake up all threads together */ + atomic_dec(&startup_count); + wake_up_all(&startup_wait); for (i = 0; i < tcount; i++) { if (IS_ERR(tdata[i].task)) continue;