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, 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, i, xa_mk_value(i), GFP_KERNEL); 44 xa_set_mark(xa, i, XA_MARK_0); 45 } 46 for (i = 0; i < 100; i++) 47 xa_erase(xa, 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, 100, xa_mk_value(100), GFP_KERNEL); 65 xa_set_mark(&array, 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