@@ -230,13 +230,12 @@ static void uperftest(int nupdaters, int duration)
#define RCU_STRESS_PIPE_LEN 10
struct rcu_stress {
- int pipe_count;
+ int age; /* how many update cycles while not rcu_stress_current */
int mbtest;
};
struct rcu_stress rcu_stress_array[RCU_STRESS_PIPE_LEN] = { { 0 } };
struct rcu_stress *rcu_stress_current;
-int rcu_stress_idx;
int n_mberror;
/* Updates protected by counts_mutex */
@@ -261,7 +260,7 @@ static void *rcu_read_stress_test(void *arg)
while (goflag == GOFLAG_RUN) {
rcu_read_lock();
p = atomic_rcu_read(&rcu_stress_current);
- if (p->mbtest == 0) {
+ if (atomic_read(&p->mbtest) == 0) {
n_mberror++;
}
rcu_read_lock();
@@ -269,7 +268,7 @@ static void *rcu_read_stress_test(void *arg)
garbage++;
}
rcu_read_unlock();
- pc = p->pipe_count;
+ pc = atomic_read(&p->age);
rcu_read_unlock();
if ((pc > RCU_STRESS_PIPE_LEN) || (pc < 0)) {
pc = RCU_STRESS_PIPE_LEN;
@@ -288,32 +287,52 @@ static void *rcu_read_stress_test(void *arg)
return NULL;
}
+/*
+ * Stress Test Updater
+ *
+ * The updater cycles around updating rcu_stress_current to point at
+ * one of the rcu_stress_array_entries and resets it's age. It
+ * then increments the age of all the other entries. The age
+ * will be read under an rcu_read_lock() and distribution of values
+ * calculated. The final result gives an indication of how many
+ * previously current rcu_stress entries are in flight until the RCU
+ * cycle complete.
+ */
static void *rcu_update_stress_test(void *arg)
{
- int i;
- struct rcu_stress *p;
+ int i, rcu_stress_idx = 0;
+ struct rcu_stress *cp = atomic_read(&rcu_stress_current);
rcu_register_thread();
-
*(struct rcu_reader_data **)arg = &rcu_reader;
+
while (goflag == GOFLAG_INIT) {
g_usleep(1000);
}
+
while (goflag == GOFLAG_RUN) {
- i = rcu_stress_idx + 1;
- if (i >= RCU_STRESS_PIPE_LEN) {
- i = 0;
+ struct rcu_stress *p;
+ rcu_stress_idx++;
+ if (rcu_stress_idx >= RCU_STRESS_PIPE_LEN) {
+ rcu_stress_idx = 0;
}
- p = &rcu_stress_array[i];
- p->mbtest = 0;
+ p = &rcu_stress_array[rcu_stress_idx];
+ /* catching up with ourselves would be a bug */
+ assert(p != cp);
+ atomic_set(&p->mbtest, 0);
smp_mb();
- p->pipe_count = 0;
- p->mbtest = 1;
+ atomic_set(&p->age, 0);
+ atomic_set(&p->mbtest, 1);
atomic_rcu_set(&rcu_stress_current, p);
- rcu_stress_idx = i;
+ cp = p;
+ /*
+ * New RCU structure is now live, update pipe counts on old
+ * ones.
+ */
for (i = 0; i < RCU_STRESS_PIPE_LEN; i++) {
if (i != rcu_stress_idx) {
- rcu_stress_array[i].pipe_count++;
+ atomic_set(&rcu_stress_array[i].age,
+ rcu_stress_array[i].age + 1);
}
}
synchronize_rcu();
@@ -346,7 +365,7 @@ static void stresstest(int nreaders, int duration)
int i;
rcu_stress_current = &rcu_stress_array[0];
- rcu_stress_current->pipe_count = 0;
+ rcu_stress_current->age = 0;
rcu_stress_current->mbtest = 1;
for (i = 0; i < nreaders; i++) {
create_thread(rcu_read_stress_test);
@@ -376,7 +395,7 @@ static void gtest_stress(int nreaders, int duration)
int i;
rcu_stress_current = &rcu_stress_array[0];
- rcu_stress_current->pipe_count = 0;
+ rcu_stress_current->age = 0;
rcu_stress_current->mbtest = 1;
for (i = 0; i < nreaders; i++) {
create_thread(rcu_read_stress_test);