88 lines · c
1// SPDX-License-Identifier: GPL-2.0-or-later2/*3 * iteration_check_2.c: Check that deleting a tagged entry doesn't cause4 * an RCU walker to finish early.5 * Copyright (c) 2020 Oracle6 * Author: Matthew Wilcox <willy@infradead.org>7 */8#include <pthread.h>9#include "test.h"10 11static volatile bool test_complete;12 13static 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 33static 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 54void 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