Fix: use __noreturn__ for C11-compatibility
[urcu.git] / tests / regression / rcutorture.h
index 7de182f5db4025ad87effd3184c8b0d10bfdce55..bc394f9f8a048f9ba51575e3d9a1ac4952cf6bdb 100644 (file)
@@ -79,6 +79,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;
@@ -113,13 +119,13 @@ volatile int goflag __attribute__((__aligned__(CAA_CACHE_LINE_SIZE)))
 #endif
 
 #ifndef mark_rcu_quiescent_state
-#define mark_rcu_quiescent_state() do ; while (0)
+#define mark_rcu_quiescent_state() do {} while (0)
 #endif /* #ifdef mark_rcu_quiescent_state */
 
 #ifndef put_thread_offline
-#define put_thread_offline()           do ; while (0)
-#define put_thread_online()            do ; while (0)
-#define put_thread_online_delay()      do ; while (0)
+#define put_thread_offline()           do {} while (0)
+#define put_thread_online()            do {} while (0)
+#define put_thread_online_delay()      do {} while (0)
 #else /* #ifndef put_thread_offline */
 #define put_thread_online_delay()      synchronize_rcu()
 #endif /* #else #ifndef put_thread_offline */
@@ -128,6 +134,7 @@ volatile int goflag __attribute__((__aligned__(CAA_CACHE_LINE_SIZE)))
  * Performance test.
  */
 
+static
 void *rcu_read_perf_test(void *arg)
 {
        int i;
@@ -158,7 +165,8 @@ void *rcu_read_perf_test(void *arg)
        return (NULL);
 }
 
-void *rcu_update_perf_test(void *arg)
+static
+void *rcu_update_perf_test(void *arg __attribute__((unused)))
 {
        long long n_updates_local = 0;
 
@@ -189,6 +197,7 @@ void *rcu_update_perf_test(void *arg)
        return NULL;
 }
 
+static
 void perftestinit(void)
 {
        init_per_thread(n_reads_pt, 0LL);
@@ -196,6 +205,7 @@ void perftestinit(void)
        uatomic_set(&nthreadsrunning, 0);
 }
 
+static
 int perftestrun(int nthreads, int nreaders, int nupdaters)
 {
        int t;
@@ -229,6 +239,7 @@ int perftestrun(int nthreads, int nreaders, int nupdaters)
        return 0;
 }
 
+static
 int perftest(int nreaders, int cpustride)
 {
        int i;
@@ -244,6 +255,7 @@ int perftest(int nreaders, int cpustride)
        return perftestrun(i + 1, nreaders, 1);
 }
 
+static
 int rperftest(int nreaders, int cpustride)
 {
        int i;
@@ -258,6 +270,7 @@ int rperftest(int nreaders, int cpustride)
        return perftestrun(i, nreaders, 0);
 }
 
+static
 int uperftest(int nupdaters, int cpustride)
 {
        int i;
@@ -283,7 +296,7 @@ struct rcu_stress {
        int mbtest;
 };
 
-struct rcu_stress rcu_stress_array[RCU_STRESS_PIPE_LEN] = { { 0 } };
+struct rcu_stress rcu_stress_array[RCU_STRESS_PIPE_LEN] = { { 0, 0 } };
 struct rcu_stress *rcu_stress_current;
 int rcu_stress_idx = 0;
 
@@ -292,7 +305,8 @@ DEFINE_PER_THREAD(long long [RCU_STRESS_PIPE_LEN + 1], rcu_stress_count);
 
 int garbage = 0;
 
-void *rcu_read_stress_test(void *arg)
+static
+void *rcu_read_stress_test(void *arg __attribute__((unused)))
 {
        int i;
        int itercnt = 0;
@@ -335,7 +349,8 @@ void *rcu_read_stress_test(void *arg)
 static pthread_mutex_t call_rcu_test_mutex = PTHREAD_MUTEX_INITIALIZER;
 static pthread_cond_t call_rcu_test_cond = PTHREAD_COND_INITIALIZER;
 
-void rcu_update_stress_test_rcu(struct rcu_head *head)
+static
+void rcu_update_stress_test_rcu(struct rcu_head *head __attribute__((unused)))
 {
        int ret;
 
@@ -362,11 +377,29 @@ void rcu_update_stress_test_rcu(struct rcu_head *head)
        }
 }
 
-void *rcu_update_stress_test(void *arg)
+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;
+       }
+}
+
+static
+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;
 
        while (goflag == GOFLAG_INIT)
                (void) poll(NULL, 0, 1);
@@ -384,9 +417,12 @@ void *rcu_update_stress_test(void *arg)
                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 {
+                       break;
+               case WRITER_STATE_CALL_RCU:
+               {
                        int ret;
 
                        ret = pthread_mutex_lock(&call_rcu_test_mutex);
@@ -396,7 +432,23 @@ void *rcu_update_stress_test(void *arg)
                                        strerror(errno));
                                abort();
                        }
+                       rcu_register_thread();
                        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) {
@@ -412,13 +464,29 @@ void *rcu_update_stress_test(void *arg)
                                        strerror(errno));
                                abort();
                        }
+                       break;
+               }
+               case WRITER_STATE_POLL_RCU:
+               {
+                       struct urcu_gp_poll_state poll_state;
+
+                       rcu_register_thread();
+                       poll_state = start_poll_synchronize_rcu();
+                       rcu_unregister_thread();
+                       while (!poll_state_synchronize_rcu(poll_state))
+                               (void) poll(NULL, 0, 1);        /* Wait for 1ms */
+                       break;
+               }
                }
                n_updates++;
+               advance_writer_state(&writer_state);
        }
+
        return NULL;
 }
 
-void *rcu_fake_update_stress_test(void *arg)
+static
+void *rcu_fake_update_stress_test(void *arg __attribute__((unused)))
 {
        if (callrcu_type == CALLRCU_PERTHREAD) {
                struct call_rcu_data *crdp;
@@ -445,6 +513,7 @@ void *rcu_fake_update_stress_test(void *arg)
        return NULL;
 }
 
+static
 int stresstest(int nreaders)
 {
        int i;
@@ -502,7 +571,11 @@ int stresstest(int nreaders)
  * Mainprogram.
  */
 
-void usage(int argc, char *argv[])
+static
+void usage(char *argv[]) __attribute__((__noreturn__));
+
+static
+void usage(char *argv[])
 {
        diag("Usage: %s nreaders [ perf | rperf | uperf | stress ] [ stride ] [ callrcu_global | callrcu_percpu | callrcu_perthread ]\n", argv[0]);
        exit(-1);
@@ -527,11 +600,11 @@ int main(int argc, char *argv[])
                } else if (strcmp(callrcu_str, "callrcu_perthread") == 0) {
                        callrcu_type = CALLRCU_PERTHREAD;
                } else {
-                       usage(argc, argv);
+                       usage(argv);
                        goto end;
                }
        }
-       
+
        switch (callrcu_type) {
        case CALLRCU_GLOBAL:
                diag("Using global per-process call_rcu thread.");
@@ -557,7 +630,7 @@ int main(int argc, char *argv[])
        if (argc > 1) {
                if (strcmp(argv[1], "-h") == 0
                                || strcmp(argv[1], "--help") == 0) {
-                       usage(argc, argv);
+                       usage(argv);
                        goto end;
                }
                nreaders = strtoul(argv[1], NULL, 0);
@@ -586,9 +659,9 @@ int main(int argc, char *argv[])
                                "stresstest readers: %d, stride: %d",
                                nreaders, cpustride);
                else
-                       usage(argc, argv);
+                       usage(argv);
        } else {
-               usage(argc, argv);
+               usage(argv);
        }
 end:
        return exit_status();
This page took 0.025984 seconds and 4 git commands to generate.