#define NR_TRYLOCK_WRITERS 2
#define NR_READERS 4
#define NR_TRYLOCK_READERS 2
+
+/*
+ * 1 : test with thread and interrupt readers.
+ * 0 : test only with thread readers.
+ */
+#define TEST_INTERRUPTS 1
+
+#if (TEST_INTERRUPTS)
#define NR_INTERRUPT_READERS 1
#define NR_TRYLOCK_INTERRUPT_READERS 1
+#else
+#define NR_INTERRUPT_READERS 0
+#define NR_TRYLOCK_INTERRUPT_READERS 0
+#endif
/*
* Writer iteration delay, in us. 0 for busy loop. Caution : writers can
* starve readers.
*/
#define WRITER_DELAY 10
+#define TRYLOCK_WRITER_DELAY 1000
+
+/*
+ * Number of iterations after which a trylock writer fails.
+ * -1 for infinite loop.
+ */
+#define TRYLOCK_WRITERS_FAIL_ITER 100
+
+/* Thread and interrupt reader delay, in ms */
+#define THREAD_READER_DELAY 0 /* busy loop */
+#define INTERRUPT_READER_DELAY 100
static int var[NR_VARS];
static struct task_struct *reader_threads[NR_READERS];
static struct task_struct *trylock_reader_threads[NR_TRYLOCK_READERS];
static struct task_struct *writer_threads[NR_WRITERS];
static struct task_struct *trylock_writer_threads[NR_TRYLOCK_WRITERS];
-static struct task_struct *interrupt_reader;
-static struct task_struct *trylock_interrupt_reader;
+static struct task_struct *interrupt_reader[NR_INTERRUPT_READERS];
+static struct task_struct *trylock_interrupt_reader[NR_TRYLOCK_INTERRUPT_READERS];
static struct fair_rwlock frwlock = {
.value = ATOMIC_LONG_INIT(0),
}
fair_read_unlock(&frwlock);
preempt_enable(); /* for get_cycles accuracy */
- //msleep(100);
+ if (THREAD_READER_DELAY)
+ msleep(THREAD_READER_DELAY);
} while (!kthread_should_stop());
- delayavg /= iter;
- printk("reader_thread/%lu iterations : %lu, "
- "lock delay [min,avg,max] %llu,%llu,%llu cycles\n",
- (unsigned long)data, iter,
- calibrate_cycles(delaymin),
- calibrate_cycles(delayavg),
- calibrate_cycles(delaymax));
+ if (!iter) {
+ printk("reader_thread/%lu iterations : %lu",
+ (unsigned long)data, iter);
+ } else {
+ delayavg /= iter;
+ printk("reader_thread/%lu iterations : %lu, "
+ "lock delay [min,avg,max] %llu,%llu,%llu cycles\n",
+ (unsigned long)data, iter,
+ calibrate_cycles(delaymin),
+ calibrate_cycles(delayavg),
+ calibrate_cycles(delaymax));
+ }
return 0;
}
"in thread\n", cur, prev, i, iter);
}
fair_read_unlock(&frwlock);
- //msleep(100);
+ if (THREAD_READER_DELAY)
+ msleep(THREAD_READER_DELAY);
} while (!kthread_should_stop());
printk("trylock_reader_thread/%lu iterations : %lu, "
"successful iterations : %lu\n",
do {
iter++;
on_each_cpu(interrupt_reader_ipi, NULL, 0);
- msleep(100);
+ if (INTERRUPT_READER_DELAY)
+ msleep(INTERRUPT_READER_DELAY);
} while (!kthread_should_stop());
printk("interrupt_reader_thread/%lu iterations : %lu\n",
(unsigned long)data, iter);
for_each_online_cpu(i) {
+ if (!per_cpu(int_ipi_nr, i))
+ continue;
per_cpu(int_delayavg, i) /= per_cpu(int_ipi_nr, i);
printk("interrupt readers on CPU %i, "
"lock delay [min,avg,max] %llu,%llu,%llu cycles\n",
do {
iter++;
on_each_cpu(trylock_interrupt_reader_ipi, NULL, 0);
- msleep(100);
+ if (INTERRUPT_READER_DELAY)
+ msleep(INTERRUPT_READER_DELAY);
} while (!kthread_should_stop());
printk("trylock_interrupt_reader_thread/%lu iterations : %lu\n",
(unsigned long)data, iter);
time1 = get_cycles();
rdtsc_barrier();
+#if (TEST_INTERRUPTS)
fair_write_lock_irq(&frwlock);
- //fair_write_lock(&frwlock);
+#else
+ fair_write_lock(&frwlock);
+#endif
rdtsc_barrier();
time2 = get_cycles();
for (i = 0; i < NR_VARS; i++) {
var[i] = new;
}
- //fair_write_unlock(&frwlock);
+#if (TEST_INTERRUPTS)
fair_write_unlock_irq(&frwlock);
+#else
+ fair_write_unlock(&frwlock);
+#endif
preempt_enable(); /* for get_cycles accuracy */
if (WRITER_DELAY > 0)
udelay(WRITER_DELAY);
{
int i;
int new;
- unsigned long iter = 0, success = 0;
+ unsigned long iter = 0, success = 0, fail = 0;
printk("trylock_writer_thread/%lu runnning\n", (unsigned long)data);
do {
- fair_write_subscribe(&frwlock);
- while (!fair_write_trylock_subscribed_irq(&frwlock)) {
+ iter++;
+#if (TEST_INTERRUPTS)
+ if (fair_write_trylock_irq_else_subscribe(&frwlock))
+#else
+ if (fair_write_trylock_else_subscribe(&frwlock))
+#endif
+ goto locked;
+#if (TRYLOCK_WRITERS_FAIL_ITER == -1)
+ for (;;) {
iter++;
- continue;
+#if (TEST_INTERRUPTS)
+ if (fair_write_trylock_irq_subscribed(&frwlock))
+#else
+ if (fair_write_trylock_subscribed(&frwlock))
+#endif
+ goto locked;
}
+#else
+ for (i = 0; i < TRYLOCK_WRITERS_FAIL_ITER; i++) {
+ iter++;
+#if (TEST_INTERRUPTS)
+ if (fair_write_trylock_irq_subscribed(&frwlock))
+#else
+ if (fair_write_trylock_subscribed(&frwlock))
+#endif
+ goto locked;
+ }
+#endif
+ fail++;
+ fair_write_unsubscribe(&frwlock);
+ goto loop;
+locked:
success++;
- //fair_write_lock(&frwlock);
new = (int)get_cycles();
for (i = 0; i < NR_VARS; i++) {
var[i] = new;
}
- //fair_write_unlock(&frwlock);
+#if (TEST_INTERRUPTS)
fair_write_unlock_irq(&frwlock);
- if (WRITER_DELAY > 0)
- udelay(WRITER_DELAY);
+#else
+ fair_write_unlock(&frwlock);
+#endif
+loop:
+ if (TRYLOCK_WRITER_DELAY > 0)
+ udelay(TRYLOCK_WRITER_DELAY);
} while (!kthread_should_stop());
- printk("trylock_writer_thread/%lu iterations : %lu, "
- "successful iterations : %lu\n",
- (unsigned long)data, iter, success);
+ printk("trylock_writer_thread/%lu iterations : "
+ "[try,success,fail after %d try], "
+ "%lu,%lu,%lu\n",
+ (unsigned long)data, TRYLOCK_WRITERS_FAIL_ITER,
+ iter, success, fail);
return 0;
}
(void *)i, "frwlock_trylock_reader");
BUG_ON(!trylock_reader_threads[i]);
}
-
-
- printk("starting interrupt reader %lu\n", i);
- interrupt_reader = kthread_run(interrupt_reader_thread, NULL,
- "frwlock_interrupt_reader");
- printk("starting trylock interrupt reader %lu\n", i);
- trylock_interrupt_reader = kthread_run(trylock_interrupt_reader_thread,
- NULL, "frwlock_trylock_interrupt_reader");
-
+ for (i = 0; i < NR_INTERRUPT_READERS; i++) {
+ printk("starting interrupt reader %lu\n", i);
+ interrupt_reader[i] = kthread_run(interrupt_reader_thread,
+ (void *)i,
+ "frwlock_interrupt_reader");
+ }
+ for (i = 0; i < NR_TRYLOCK_INTERRUPT_READERS; i++) {
+ printk("starting trylock interrupt reader %lu\n", i);
+ trylock_interrupt_reader[i] =
+ kthread_run(trylock_interrupt_reader_thread,
+ (void *)i, "frwlock_trylock_interrupt_reader");
+ }
for (i = 0; i < NR_WRITERS; i++) {
printk("starting writer thread %lu\n", i);
writer_threads[i] = kthread_run(writer_thread, (void *)i,
kthread_stop(reader_threads[i]);
for (i = 0; i < NR_TRYLOCK_READERS; i++)
kthread_stop(trylock_reader_threads[i]);
- kthread_stop(interrupt_reader);
- kthread_stop(trylock_interrupt_reader);
+ for (i = 0; i < NR_INTERRUPT_READERS; i++)
+ kthread_stop(interrupt_reader[i]);
+ for (i = 0; i < NR_TRYLOCK_INTERRUPT_READERS; i++)
+ kthread_stop(trylock_interrupt_reader[i]);
}
ssleep(SINGLE_WRITER_TEST_DURATION);
kthread_stop(writer_threads[0]);
+ printk("** Single trylock writer test, no contention **\n");
+ trylock_writer_threads[0] = kthread_run(trylock_writer_thread,
+ (void *)0,
+ "trylock_frwlock_writer");
+ BUG_ON(!trylock_writer_threads[0]);
+ ssleep(SINGLE_WRITER_TEST_DURATION);
+ kthread_stop(trylock_writer_threads[0]);
+
printk("** Single reader test, no contention **\n");
reader_threads[0] = kthread_run(reader_thread, (void *)0,
"frwlock_reader");