X-Git-Url: https://git.liburcu.org/?a=blobdiff_plain;f=tests%2Fregression%2Frcutorture.h;h=f495cbd12259709721212a17b84a7e7744be905a;hb=c92c99041415698b57ca123e58a19b05189ae398;hp=639fcfc19cb2bfe33f765629dd233af04e35267d;hpb=153b081a9b007aad7bece415dc3bf1125edd2da3;p=urcu.git diff --git a/tests/regression/rcutorture.h b/tests/regression/rcutorture.h index 639fcfc..f495cbd 100644 --- a/tests/regression/rcutorture.h +++ b/tests/regression/rcutorture.h @@ -1,3 +1,7 @@ +// SPDX-FileCopyrightText: 2008 Paul E. McKenney, IBM Corporation. +// +// SPDX-License-Identifier: GPL-2.0-or-later + /* * rcutorture.h: simple user-level performance/stress test of RCU. * @@ -43,22 +47,6 @@ * line lists the number of readers observing progressively more stale * data. A correct RCU implementation will have all but the first two * numbers non-zero. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Copyright (c) 2008 Paul E. McKenney, IBM Corporation. */ /* @@ -68,6 +56,8 @@ #include #include "tap.h" +#include "urcu-wait.h" + #define NR_TESTS 1 DEFINE_PER_THREAD(long long, n_reads_pt); @@ -79,6 +69,12 @@ enum callrcu_type { CALLRCU_PERTHREAD, }; +enum writer_state { + WRITER_STATE_SYNC_RCU, + WRITER_STATE_CALL_RCU, + WRITER_STATE_POLL_RCU, +}; + static enum callrcu_type callrcu_type = CALLRCU_GLOBAL; long long n_reads = 0LL; @@ -340,34 +336,30 @@ void *rcu_read_stress_test(void *arg __attribute__((unused))) return (NULL); } -static pthread_mutex_t call_rcu_test_mutex = PTHREAD_MUTEX_INITIALIZER; -static pthread_cond_t call_rcu_test_cond = PTHREAD_COND_INITIALIZER; +static DEFINE_URCU_WAIT_QUEUE(call_rcu_waiters); static void rcu_update_stress_test_rcu(struct rcu_head *head __attribute__((unused))) { - int ret; + struct urcu_waiters waiters; - ret = pthread_mutex_lock(&call_rcu_test_mutex); - if (ret) { - errno = ret; - diag("pthread_mutex_lock: %s", - strerror(errno)); - abort(); - } - ret = pthread_cond_signal(&call_rcu_test_cond); - if (ret) { - errno = ret; - diag("pthread_cond_signal: %s", - strerror(errno)); - abort(); - } - ret = pthread_mutex_unlock(&call_rcu_test_mutex); - if (ret) { - errno = ret; - diag("pthread_mutex_unlock: %s", - strerror(errno)); - abort(); + urcu_move_waiters(&waiters, &call_rcu_waiters); + urcu_wake_all_waiters(&waiters); +} + +static +void advance_writer_state(enum writer_state *state) +{ + switch (*state) { + case WRITER_STATE_SYNC_RCU: + *state = WRITER_STATE_CALL_RCU; + break; + case WRITER_STATE_CALL_RCU: + *state = WRITER_STATE_POLL_RCU; + break; + case WRITER_STATE_POLL_RCU: + *state = WRITER_STATE_SYNC_RCU; + break; } } @@ -377,9 +369,16 @@ void *rcu_update_stress_test(void *arg __attribute__((unused))) int i; struct rcu_stress *p; struct rcu_head rh; + enum writer_state writer_state = WRITER_STATE_SYNC_RCU; + + rcu_register_thread(); + /* Offline for poll. */ + put_thread_offline(); while (goflag == GOFLAG_INIT) (void) poll(NULL, 0, 1); + put_thread_online(); + while (goflag == GOFLAG_RUN) { i = rcu_stress_idx + 1; if (i >= RCU_STRESS_PIPE_LEN) @@ -394,54 +393,44 @@ void *rcu_update_stress_test(void *arg __attribute__((unused))) for (i = 0; i < RCU_STRESS_PIPE_LEN; i++) if (i != rcu_stress_idx) rcu_stress_array[i].pipe_count++; - if (n_updates & 0x1) + switch (writer_state) { + case WRITER_STATE_SYNC_RCU: synchronize_rcu(); - else { - int ret; - - ret = pthread_mutex_lock(&call_rcu_test_mutex); - if (ret) { - errno = ret; - diag("pthread_mutex_lock: %s", - strerror(errno)); - abort(); - } - rcu_register_thread(); + break; + case WRITER_STATE_CALL_RCU: + { + DEFINE_URCU_WAIT_NODE(wait, URCU_WAIT_WAITING); + + urcu_wait_add(&call_rcu_waiters, &wait); + call_rcu(&rh, rcu_update_stress_test_rcu); - rcu_unregister_thread(); - /* - * Our MacOS X test machine with the following - * config: - * 15.6.0 Darwin Kernel Version 15.6.0 - * root:xnu-3248.60.10~1/RELEASE_X86_64 - * appears to have issues with liburcu-signal - * signal being delivered on top of - * pthread_cond_wait. It seems to make the - * thread continue, and therefore corrupt the - * rcu_head. Work around this issue by - * unregistering the RCU read-side thread - * immediately after call_rcu (call_rcu needs - * us to be registered RCU readers). - */ - ret = pthread_cond_wait(&call_rcu_test_cond, - &call_rcu_test_mutex); - if (ret) { - errno = ret; - diag("pthread_cond_signal: %s", - strerror(errno)); - abort(); - } - ret = pthread_mutex_unlock(&call_rcu_test_mutex); - if (ret) { - errno = ret; - diag("pthread_mutex_unlock: %s", - strerror(errno)); - abort(); - } + + /* Offline for busy-wait. */ + put_thread_offline(); + urcu_adaptative_busy_wait(&wait); + put_thread_online(); + break; + } + case WRITER_STATE_POLL_RCU: + { + struct urcu_gp_poll_state poll_state; + + poll_state = start_poll_synchronize_rcu(); + + /* Offline for poll. */ + put_thread_offline(); + while (!poll_state_synchronize_rcu(poll_state)) + (void) poll(NULL, 0, 1); /* Wait for 1ms */ + put_thread_online(); + break; + } } n_updates++; + advance_writer_state(&writer_state); } + rcu_unregister_thread(); + return NULL; } @@ -532,7 +521,7 @@ int stresstest(int nreaders) */ static -void usage(char *argv[]) __attribute__((noreturn)); +void usage(char *argv[]) __attribute__((__noreturn__)); static void usage(char *argv[])