1 | // SPDX-License-Identifier: GPL-2.0-or-later |
2 | /* |
3 | * iteration_check_2.c: Check that deleting a tagged entry doesn't cause |
4 | * an RCU walker to finish early. |
5 | * Copyright (c) 2020 Oracle |
6 | * Author: Matthew Wilcox <willy@infradead.org> |
7 | */ |
8 | #include <pthread.h> |
9 | #include "test.h" |
10 | |
11 | static volatile bool test_complete; |
12 | |
13 | static void *iterator(void *arg) |
14 | { |
15 | XA_STATE(xas, arg, 0); |
16 | void *entry; |
17 | |
18 | rcu_register_thread(); |
19 | |
20 | while (!test_complete) { |
21 | xas_set(xas: &xas, index: 0); |
22 | rcu_read_lock(); |
23 | xas_for_each_marked(&xas, entry, ULONG_MAX, XA_MARK_0) |
24 | ; |
25 | rcu_read_unlock(); |
26 | assert(xas.xa_index >= 100); |
27 | } |
28 | |
29 | rcu_unregister_thread(); |
30 | return NULL; |
31 | } |
32 | |
33 | static void *throbber(void *arg) |
34 | { |
35 | struct xarray *xa = arg; |
36 | |
37 | rcu_register_thread(); |
38 | |
39 | while (!test_complete) { |
40 | int i; |
41 | |
42 | for (i = 0; i < 100; i++) { |
43 | xa_store(xa, index: i, entry: xa_mk_value(v: i), GFP_KERNEL); |
44 | xa_set_mark(xa, index: i, XA_MARK_0); |
45 | } |
46 | for (i = 0; i < 100; i++) |
47 | xa_erase(xa, index: i); |
48 | } |
49 | |
50 | rcu_unregister_thread(); |
51 | return NULL; |
52 | } |
53 | |
54 | void iteration_test2(unsigned test_duration) |
55 | { |
56 | pthread_t threads[2]; |
57 | DEFINE_XARRAY(array); |
58 | int i; |
59 | |
60 | printv(1, "Running iteration test 2 for %d seconds\n" , test_duration); |
61 | |
62 | test_complete = false; |
63 | |
64 | xa_store(&array, index: 100, entry: xa_mk_value(v: 100), GFP_KERNEL); |
65 | xa_set_mark(&array, index: 100, XA_MARK_0); |
66 | |
67 | if (pthread_create(&threads[0], NULL, iterator, &array)) { |
68 | perror("create iterator thread" ); |
69 | exit(1); |
70 | } |
71 | if (pthread_create(&threads[1], NULL, throbber, &array)) { |
72 | perror("create throbber thread" ); |
73 | exit(1); |
74 | } |
75 | |
76 | sleep(test_duration); |
77 | test_complete = true; |
78 | |
79 | for (i = 0; i < 2; i++) { |
80 | if (pthread_join(threads[i], NULL)) { |
81 | perror("pthread_join" ); |
82 | exit(1); |
83 | } |
84 | } |
85 | |
86 | xa_destroy(&array); |
87 | } |
88 | |