diff mbox series

[ovs-dev,v2,3/8] tests: Add RCU postpone test

Message ID 9a79d2906cac9fe5b6f58e49e27e2bdb625450cf.1621517561.git.grive@u256.net
State New
Headers show
Series RCU: Add blocking mode for debugging | expand

Commit Message

Gaetan Rivet May 20, 2021, 1:35 p.m. UTC
Add a simple postponing test verifying RCU callbacks have executed and
RCU exits in order. Add as part of library unit-tests.

Signed-off-by: Gaetan Rivet <grive@u256.net>
---
 tests/library.at |  8 ++++++-
 tests/test-rcu.c | 61 ++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 68 insertions(+), 1 deletion(-)
diff mbox series

Patch

diff --git a/tests/library.at b/tests/library.at
index e572c22e3..6e8a154e5 100644
--- a/tests/library.at
+++ b/tests/library.at
@@ -251,10 +251,16 @@  AT_KEYWORDS([barrier])
 AT_CHECK([ovstest test-barrier], [0], [])
 AT_CLEANUP
 
-AT_SETUP([rcu])
+AT_SETUP([rcu quiescing])
+AT_KEYWORDS([rcu])
 AT_CHECK([ovstest test-rcu-quiesce], [0], [])
 AT_CLEANUP
 
+AT_SETUP([rcu postponing])
+AT_KEYWORDS([rcu])
+AT_CHECK([ovstest test-rcu], [0], [])
+AT_CLEANUP
+
 AT_SETUP([stopwatch module])
 AT_CHECK([ovstest test-stopwatch], [0], [......
 ], [ignore])
diff --git a/tests/test-rcu.c b/tests/test-rcu.c
index 965f3c49f..38e1cbb6f 100644
--- a/tests/test-rcu.c
+++ b/tests/test-rcu.c
@@ -49,3 +49,64 @@  test_rcu_quiesce(int argc OVS_UNUSED, char *argv[] OVS_UNUSED)
 }
 
 OVSTEST_REGISTER("test-rcu-quiesce", test_rcu_quiesce);
+
+struct rcu_user_aux {
+    bool done;
+};
+
+static void
+rcu_user_deferred(struct rcu_user_aux *aux)
+{
+    aux->done = true;
+}
+
+static void *
+rcu_user_main(void *aux_)
+{
+    struct rcu_user_aux *aux = aux_;
+
+    ovsrcu_quiesce();
+
+    aux->done = false;
+    ovsrcu_postpone(rcu_user_deferred, aux);
+
+    ovsrcu_quiesce();
+
+    return NULL;
+}
+
+#define N_THREAD 4
+
+static void
+test_rcu(int argc OVS_UNUSED, char *argv[] OVS_UNUSED)
+{
+    struct rcu_user_aux main_aux = {0};
+    struct rcu_user_aux aux[N_THREAD];
+    pthread_t users[N_THREAD];
+    size_t i;
+
+    memset(aux, 0, sizeof aux);
+
+    for (i = 0; i < ARRAY_SIZE(users); i++) {
+        users[i] = ovs_thread_create("user", rcu_user_main, &aux[i]);
+    }
+
+    for (i = 0; i < ARRAY_SIZE(users); i++) {
+        xpthread_join(users[i], NULL);
+    }
+
+    /* Register a last callback and verify that it will be properly executed
+     * even if the RCU lib is exited without this thread quiescing.
+     */
+    ovsrcu_postpone(rcu_user_deferred, &main_aux);
+
+    ovsrcu_exit();
+
+    ovs_assert(main_aux.done);
+
+    for (i = 0; i < ARRAY_SIZE(users); i++) {
+        ovs_assert(aux[i].done);
+    }
+}
+
+OVSTEST_REGISTER("test-rcu", test_rcu);