hc
2024-12-19 9370bb92b2d16684ee45cf24e879c93c509162da
kernel/lib/test_rhashtable.c
....@@ -1,12 +1,9 @@
1
+// SPDX-License-Identifier: GPL-2.0-only
12 /*
23 * Resizable, Scalable, Concurrent Hash Table
34 *
45 * Copyright (c) 2014-2015 Thomas Graf <tgraf@suug.ch>
56 * Copyright (c) 2008-2014 Patrick McHardy <kaber@trash.net>
6
- *
7
- * This program is free software; you can redistribute it and/or modify
8
- * it under the terms of the GNU General Public License version 2 as
9
- * published by the Free Software Foundation.
107 */
118
129 /**************************************************************************
....@@ -20,11 +17,11 @@
2017 #include <linux/module.h>
2118 #include <linux/rcupdate.h>
2219 #include <linux/rhashtable.h>
23
-#include <linux/semaphore.h>
2420 #include <linux/slab.h>
2521 #include <linux/sched.h>
2622 #include <linux/random.h>
2723 #include <linux/vmalloc.h>
24
+#include <linux/wait.h>
2825
2926 #define MAX_ENTRIES 1000000
3027 #define TEST_INSERT_FAIL INT_MAX
....@@ -112,8 +109,8 @@
112109 .automatic_shrinking = false,
113110 };
114111
115
-static struct semaphore prestart_sem;
116
-static struct semaphore startup_sem = __SEMAPHORE_INITIALIZER(startup_sem, 0);
112
+static atomic_t startup_count;
113
+static DECLARE_WAIT_QUEUE_HEAD(startup_wait);
117114
118115 static int insert_retry(struct rhashtable *ht, struct test_obj *obj,
119116 const struct rhashtable_params params)
....@@ -177,16 +174,11 @@
177174
178175 static void test_bucket_stats(struct rhashtable *ht, unsigned int entries)
179176 {
180
- unsigned int err, total = 0, chain_len = 0;
177
+ unsigned int total = 0, chain_len = 0;
181178 struct rhashtable_iter hti;
182179 struct rhash_head *pos;
183180
184
- err = rhashtable_walk_init(ht, &hti, GFP_KERNEL);
185
- if (err) {
186
- pr_warn("Test failed: allocation error");
187
- return;
188
- }
189
-
181
+ rhashtable_walk_enter(ht, &hti);
190182 rhashtable_walk_start(&hti);
191183
192184 while ((pos = rhashtable_walk_next(&hti))) {
....@@ -395,7 +387,7 @@
395387 if (WARN(err, "cannot remove element at slot %d", i))
396388 continue;
397389 } else {
398
- if (WARN(err != -ENOENT, "removed non-existant element %d, error %d not %d",
390
+ if (WARN(err != -ENOENT, "removed non-existent element %d, error %d not %d",
399391 i, err, -ENOENT))
400392 continue;
401393 }
....@@ -440,9 +432,9 @@
440432 if (WARN(err, "cannot remove element at slot %d", i))
441433 continue;
442434 } else {
443
- if (WARN(err != -ENOENT, "removed non-existant element, error %d not %d",
435
+ if (WARN(err != -ENOENT, "removed non-existent element, error %d not %d",
444436 err, -ENOENT))
445
- continue;
437
+ continue;
446438 }
447439 }
448440
....@@ -505,7 +497,7 @@
505497 struct rhash_head *pos, *next;
506498 struct test_obj_rhl *p;
507499
508
- pos = rht_dereference(tbl->buckets[i], ht);
500
+ pos = rht_ptr_exclusive(tbl->buckets + i);
509501 next = !rht_is_a_nulls(pos) ? rht_dereference(pos->next, ht) : NULL;
510502
511503 if (!rht_is_a_nulls(pos)) {
....@@ -641,9 +633,12 @@
641633 int i, step, err = 0, insert_retries = 0;
642634 struct thread_data *tdata = data;
643635
644
- up(&prestart_sem);
645
- if (down_interruptible(&startup_sem))
646
- pr_err(" thread[%d]: down_interruptible failed\n", tdata->id);
636
+ if (atomic_dec_and_test(&startup_count))
637
+ wake_up(&startup_wait);
638
+ if (wait_event_interruptible(startup_wait, atomic_read(&startup_count) == -1)) {
639
+ pr_err(" thread[%d]: interrupted\n", tdata->id);
640
+ goto out;
641
+ }
647642
648643 for (i = 0; i < tdata->entries; i++) {
649644 tdata->objs[i].value.id = i;
....@@ -762,7 +757,7 @@
762757
763758 pr_info("Testing concurrent rhashtable access from %d threads\n",
764759 tcount);
765
- sema_init(&prestart_sem, 1 - tcount);
760
+ atomic_set(&startup_count, tcount);
766761 tdata = vzalloc(array_size(tcount, sizeof(struct thread_data)));
767762 if (!tdata)
768763 return -ENOMEM;
....@@ -788,15 +783,18 @@
788783 tdata[i].objs = objs + i * entries;
789784 tdata[i].task = kthread_run(threadfunc, &tdata[i],
790785 "rhashtable_thrad[%d]", i);
791
- if (IS_ERR(tdata[i].task))
786
+ if (IS_ERR(tdata[i].task)) {
792787 pr_err(" kthread_run failed for thread %d\n", i);
793
- else
788
+ atomic_dec(&startup_count);
789
+ } else {
794790 started_threads++;
791
+ }
795792 }
796
- if (down_interruptible(&prestart_sem))
797
- pr_err(" down interruptible failed\n");
798
- for (i = 0; i < tcount; i++)
799
- up(&startup_sem);
793
+ if (wait_event_interruptible(startup_wait, atomic_read(&startup_count) == 0))
794
+ pr_err(" wait_event interruptible failed\n");
795
+ /* count is 0 now, set it to -1 and wake up all threads together */
796
+ atomic_dec(&startup_count);
797
+ wake_up_all(&startup_wait);
800798 for (i = 0; i < tcount; i++) {
801799 if (IS_ERR(tdata[i].task))
802800 continue;