X-Git-Url: https://git.lttng.org/?a=blobdiff_plain;f=trunk%2Ftests%2Fkernel%2Ftest-wbias-rwlock.c;h=3b16f5feb0c934ab161d6efb0d449aaa2227fd97;hb=27828bc1b0010ee87c2f68e31fb77fd4ae39fa6b;hp=6cfac1f5514267781be5ef657f56616fff2447ce;hpb=ca935c46fd44acf883554b4a9da04f0d2c188b61;p=lttv.git diff --git a/trunk/tests/kernel/test-wbias-rwlock.c b/trunk/tests/kernel/test-wbias-rwlock.c index 6cfac1f5..3b16f5fe 100644 --- a/trunk/tests/kernel/test-wbias-rwlock.c +++ b/trunk/tests/kernel/test-wbias-rwlock.c @@ -6,7 +6,6 @@ #include #include #include -#include #include #include #include @@ -14,6 +13,7 @@ #include #include #include +#include /* Test with no contention duration, in seconds */ #define SINGLE_WRITER_TEST_DURATION 10 @@ -26,7 +26,7 @@ #define NR_VARS 100 #define NR_WRITERS 2 #define NR_TRYLOCK_WRITERS 1 -#define NR_READERS 4 +#define NR_NPREADERS 2 #define NR_TRYLOCK_READERS 1 /* @@ -49,6 +49,19 @@ #define NR_TRYLOCK_INTERRUPT_READERS 0 #endif +/* + * 1 : test with thread preemption readers. + * 0 : test only with non-preemptable thread readers. + */ +#define TEST_PREEMPT 1 + +#if (TEST_PREEMPT) +#define NR_PREADERS 2 +#else +#define NR_PREADERS 0 +#endif + + /* * Writer iteration delay, in us. 0 for busy loop. Caution : writers can * starve readers. @@ -66,8 +79,15 @@ #define THREAD_READER_DELAY 0 /* busy loop */ #define INTERRUPT_READER_DELAY 100 +#ifdef CONFIG_PREEMPT +#define yield_in_non_preempt() +#else +#define yield_in_non_preempt() yield() +#endif + static int var[NR_VARS]; -static struct task_struct *reader_threads[NR_READERS]; +static struct task_struct *preader_threads[NR_PREADERS]; +static struct task_struct *npreader_threads[NR_NPREADERS]; 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]; @@ -82,9 +102,11 @@ static DEFINE_RWLOCK(std_rw_lock); #define wrap_read_trylock() read_trylock(&std_rw_lock) #define wrap_read_unlock() read_unlock(&std_rw_lock) +#define wrap_read_lock_inatomic() read_lock(&std_rw_lock) +#define wrap_read_trylock_inatomic() read_trylock(&std_rw_lock) + #define wrap_read_lock_irq() read_lock(&std_rw_lock) #define wrap_read_trylock_irq() read_trylock(&std_rw_lock) -#define wrap_read_unlock_irq() read_unlock(&std_rw_lock) #if (TEST_INTERRUPTS) #define wrap_write_lock() write_lock_irq(&std_rw_lock) @@ -94,25 +116,54 @@ static DEFINE_RWLOCK(std_rw_lock); #define wrap_write_unlock() write_unlock(&std_rw_lock) #endif +#define wrap_write_trylock() write_trylock(&std_rw_lock) + #else -static DEFINE_WBIAS_RWLOCK(wbiasrwlock); +#if (TEST_INTERRUPTS) +#if (TEST_PREEMPT) +#define WBIASRWLOCKWCTX WB_PRIO_P +#define WBIASRWLOCKRCTX (WB_RIRQ | WB_RNPTHREAD | WB_RPTHREAD) +#else +#define WBIASRWLOCKWCTX WB_PRIO_NP +#define WBIASRWLOCKRCTX (WB_RIRQ | WB_RNPTHREAD) +#endif +#else +#if (TEST_PREEMPT) +#define WBIASRWLOCKWCTX WB_PRIO_P +#define WBIASRWLOCKRCTX (WB_RNPTHREAD | WB_RPTHREAD) +#else +#define WBIASRWLOCKWCTX WB_PRIO_NP +#define WBIASRWLOCKRCTX (WB_RNPTHREAD) +#endif +#endif + +static DEFINE_WBIAS_RWLOCK(wbiasrwlock, WBIASRWLOCKWCTX, WBIASRWLOCKRCTX); +CHECK_WBIAS_RWLOCK_MAP(wbiasrwlock, WBIASRWLOCKWCTX, WBIASRWLOCKRCTX); + +#if (TEST_PREEMPT) #define wrap_read_lock() wbias_read_lock(&wbiasrwlock) #define wrap_read_trylock() wbias_read_trylock(&wbiasrwlock) +#else +#define wrap_read_lock() wbias_read_lock_inatomic(&wbiasrwlock) +#define wrap_read_trylock() wbias_read_trylock_inatomic(&wbiasrwlock) +#endif #define wrap_read_unlock() wbias_read_unlock(&wbiasrwlock) +#define wrap_read_lock_inatomic() wbias_read_lock_inatomic(&wbiasrwlock) +#define wrap_read_trylock_inatomic() \ + wbias_read_trylock_inatomic(&wbiasrwlock) + #define wrap_read_lock_irq() wbias_read_lock_irq(&wbiasrwlock) #define wrap_read_trylock_irq() wbias_read_trylock_irq(&wbiasrwlock) -#define wrap_read_unlock_irq() wbias_read_unlock_irq(&wbiasrwlock) -#if (TEST_INTERRUPTS) -#define wrap_write_lock() wbias_write_lock_irq(&wbiasrwlock) -#define wrap_write_unlock() wbias_write_unlock_irq(&wbiasrwlock) -#else -#define wrap_write_lock() wbias_write_lock(&wbiasrwlock) -#define wrap_write_unlock() wbias_write_unlock(&wbiasrwlock) -#endif +#define wrap_write_lock() \ + wbias_write_lock(&wbiasrwlock, WBIASRWLOCKWCTX, WBIASRWLOCKRCTX) +#define wrap_write_unlock() \ + wbias_write_unlock(&wbiasrwlock, WBIASRWLOCKWCTX, WBIASRWLOCKRCTX) +#define wrap_write_trylock() \ + wbias_write_trylock(&wbiasrwlock, WBIASRWLOCKWCTX, WBIASRWLOCKRCTX) #endif @@ -127,61 +178,103 @@ static inline cycles_t calibrate_cycles(cycles_t cycles) struct proc_dir_entry *pentry = NULL; -static int reader_thread(void *data) +static int p_or_np_reader_thread(const char *typename, + void *data, int preemptable) { int i; int prev, cur; unsigned long iter = 0; - cycles_t time1, time2, delay, delaymax = 0, delaymin = ULLONG_MAX, - delayavg = 0; + cycles_t time1, time2, delay; + cycles_t ldelaymax = 0, ldelaymin = ULLONG_MAX, ldelayavg = 0; + cycles_t udelaymax = 0, udelaymin = ULLONG_MAX, udelayavg = 0; - printk("reader_thread/%lu runnning\n", (unsigned long)data); + printk("%s/%lu runnning\n", typename, (unsigned long)data); do { iter++; - preempt_disable(); /* for get_cycles accuracy */ + if (!preemptable) + preempt_disable(); rdtsc_barrier(); time1 = get_cycles(); rdtsc_barrier(); - wrap_read_lock(); + if (!preemptable) + wrap_read_lock_inatomic(); + else + wrap_read_lock(); rdtsc_barrier(); time2 = get_cycles(); rdtsc_barrier(); delay = time2 - time1; - delaymax = max(delaymax, delay); - delaymin = min(delaymin, delay); - delayavg += delay; + ldelaymax = max(ldelaymax, delay); + ldelaymin = min(ldelaymin, delay); + ldelayavg += delay; prev = var[0]; for (i = 1; i < NR_VARS; i++) { cur = var[i]; - if (cur != prev) + if (cur != prev) { printk(KERN_ALERT "Unequal cur %d/prev %d at i %d, iter %lu " - "in thread\n", cur, prev, i, iter); + "in reader thread\n", + cur, prev, i, iter); + } } + rdtsc_barrier(); + time1 = get_cycles(); + rdtsc_barrier(); + wrap_read_unlock(); - preempt_enable(); /* for get_cycles accuracy */ + rdtsc_barrier(); + time2 = get_cycles(); + rdtsc_barrier(); + delay = time2 - time1; + udelaymax = max(udelaymax, delay); + udelaymin = min(udelaymin, delay); + udelayavg += delay; + + if (!preemptable) + preempt_enable(); + if (THREAD_READER_DELAY) msleep(THREAD_READER_DELAY); + yield_in_non_preempt(); } while (!kthread_should_stop()); if (!iter) { - printk("reader_thread/%lu iterations : %lu", + printk("%s/%lu iterations : %lu", typename, (unsigned long)data, iter); } else { - delayavg /= iter; - printk("reader_thread/%lu iterations : %lu, " + ldelayavg /= iter; + udelayavg /= iter; + printk("%s/%lu iterations : %lu, " "lock delay [min,avg,max] %llu,%llu,%llu cycles\n", + typename, + (unsigned long)data, iter, + calibrate_cycles(ldelaymin), + calibrate_cycles(ldelayavg), + calibrate_cycles(ldelaymax)); + printk("%s/%lu iterations : %lu, " + "unlock delay [min,avg,max] %llu,%llu,%llu cycles\n", + typename, (unsigned long)data, iter, - calibrate_cycles(delaymin), - calibrate_cycles(delayavg), - calibrate_cycles(delaymax)); + calibrate_cycles(udelaymin), + calibrate_cycles(udelayavg), + calibrate_cycles(udelaymax)); } return 0; } +static int preader_thread(void *data) +{ + return p_or_np_reader_thread("preader_thread", data, 1); +} + +static int npreader_thread(void *data) +{ + return p_or_np_reader_thread("npreader_thread", data, 0); +} + static int trylock_reader_thread(void *data) { int i; @@ -190,30 +283,44 @@ static int trylock_reader_thread(void *data) printk("trylock_reader_thread/%lu runnning\n", (unsigned long)data); do { - while (!wrap_read_trylock()) +#if (!TEST_PREEMPT) + preempt_disable(); +#endif + while (!wrap_read_trylock()) { + cpu_relax(); iter++; + } success_iter++; prev = var[0]; for (i = 1; i < NR_VARS; i++) { cur = var[i]; - if (cur != prev) + if (cur != prev) { printk(KERN_ALERT "Unequal cur %d/prev %d at i %d, iter %lu " - "in thread\n", cur, prev, i, iter); + "in trylock reader thread\n", + cur, prev, i, iter); + } } wrap_read_unlock(); +#if (!TEST_PREEMPT) + preempt_enable(); +#endif if (THREAD_READER_DELAY) msleep(THREAD_READER_DELAY); + yield_in_non_preempt(); } while (!kthread_should_stop()); printk("trylock_reader_thread/%lu iterations : %lu, " "successful iterations : %lu\n", - (unsigned long)data, iter, success_iter); + (unsigned long)data, iter + success_iter, success_iter); return 0; } -DEFINE_PER_CPU(cycles_t, int_delaymin); -DEFINE_PER_CPU(cycles_t, int_delayavg); -DEFINE_PER_CPU(cycles_t, int_delaymax); +DEFINE_PER_CPU(cycles_t, int_ldelaymin); +DEFINE_PER_CPU(cycles_t, int_ldelayavg); +DEFINE_PER_CPU(cycles_t, int_ldelaymax); +DEFINE_PER_CPU(cycles_t, int_udelaymin); +DEFINE_PER_CPU(cycles_t, int_udelayavg); +DEFINE_PER_CPU(cycles_t, int_udelaymax); DEFINE_PER_CPU(cycles_t, int_ipi_nr); static void interrupt_reader_ipi(void *data) @@ -221,7 +328,8 @@ static void interrupt_reader_ipi(void *data) int i; int prev, cur; cycles_t time1, time2; - cycles_t *delaymax, *delaymin, *delayavg, *ipi_nr, delay; + cycles_t *ldelaymax, *ldelaymin, *ldelayavg, *ipi_nr, delay; + cycles_t *udelaymax, *udelaymin, *udelayavg; /* * Skip the ipi caller, not in irq context. @@ -229,9 +337,12 @@ static void interrupt_reader_ipi(void *data) if (!in_irq()) return; - delaymax = &per_cpu(int_delaymax, smp_processor_id()); - delaymin = &per_cpu(int_delaymin, smp_processor_id()); - delayavg = &per_cpu(int_delayavg, smp_processor_id()); + ldelaymax = &per_cpu(int_ldelaymax, smp_processor_id()); + ldelaymin = &per_cpu(int_ldelaymin, smp_processor_id()); + ldelayavg = &per_cpu(int_ldelayavg, smp_processor_id()); + udelaymax = &per_cpu(int_udelaymax, smp_processor_id()); + udelaymin = &per_cpu(int_udelaymin, smp_processor_id()); + udelayavg = &per_cpu(int_udelayavg, smp_processor_id()); ipi_nr = &per_cpu(int_ipi_nr, smp_processor_id()); rdtsc_barrier(); @@ -244,9 +355,9 @@ static void interrupt_reader_ipi(void *data) time2 = get_cycles(); rdtsc_barrier(); delay = time2 - time1; - *delaymax = max(*delaymax, delay); - *delaymin = min(*delaymin, delay); - *delayavg += delay; + *ldelaymax = max(*ldelaymax, delay); + *ldelaymin = min(*ldelaymin, delay); + *ldelayavg += delay; (*ipi_nr)++; prev = var[0]; for (i = 1; i < NR_VARS; i++) { @@ -256,7 +367,16 @@ static void interrupt_reader_ipi(void *data) "Unequal cur %d/prev %d at i %d in interrupt\n", cur, prev, i); } - wrap_read_unlock_irq(); + rdtsc_barrier(); + time1 = get_cycles(); + rdtsc_barrier(); + wrap_read_unlock(); + time2 = get_cycles(); + rdtsc_barrier(); + delay = time2 - time1; + *udelaymax = max(*udelaymax, delay); + *udelaymin = min(*udelaymin, delay); + *udelayavg += delay; } DEFINE_PER_CPU(unsigned long, trylock_int_iter); @@ -285,7 +405,7 @@ static void trylock_interrupt_reader_ipi(void *data) "Unequal cur %d/prev %d at i %d in interrupt\n", cur, prev, i); } - wrap_read_unlock_irq(); + wrap_read_unlock(); } @@ -295,9 +415,12 @@ static int interrupt_reader_thread(void *data) int i; for_each_online_cpu(i) { - per_cpu(int_delaymax, i) = 0; - per_cpu(int_delaymin, i) = ULLONG_MAX; - per_cpu(int_delayavg, i) = 0; + per_cpu(int_ldelaymax, i) = 0; + per_cpu(int_ldelaymin, i) = ULLONG_MAX; + per_cpu(int_ldelayavg, i) = 0; + per_cpu(int_udelaymax, i) = 0; + per_cpu(int_udelaymin, i) = ULLONG_MAX; + per_cpu(int_udelayavg, i) = 0; per_cpu(int_ipi_nr, i) = 0; } do { @@ -305,19 +428,27 @@ static int interrupt_reader_thread(void *data) on_each_cpu(interrupt_reader_ipi, NULL, 0); if (INTERRUPT_READER_DELAY) msleep(INTERRUPT_READER_DELAY); + yield_in_non_preempt(); } 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); + per_cpu(int_ldelayavg, i) /= per_cpu(int_ipi_nr, i); + per_cpu(int_udelayavg, i) /= per_cpu(int_ipi_nr, i); printk("interrupt readers on CPU %i, " "lock delay [min,avg,max] %llu,%llu,%llu cycles\n", i, - calibrate_cycles(per_cpu(int_delaymin, i)), - calibrate_cycles(per_cpu(int_delayavg, i)), - calibrate_cycles(per_cpu(int_delaymax, i))); + calibrate_cycles(per_cpu(int_ldelaymin, i)), + calibrate_cycles(per_cpu(int_ldelayavg, i)), + calibrate_cycles(per_cpu(int_ldelaymax, i))); + printk("interrupt readers on CPU %i, " + "unlock delay [min,avg,max] %llu,%llu,%llu cycles\n", + i, + calibrate_cycles(per_cpu(int_udelaymin, i)), + calibrate_cycles(per_cpu(int_udelayavg, i)), + calibrate_cycles(per_cpu(int_udelaymax, i))); } return 0; } @@ -332,6 +463,7 @@ static int trylock_interrupt_reader_thread(void *data) on_each_cpu(trylock_interrupt_reader_ipi, NULL, 0); if (INTERRUPT_READER_DELAY) msleep(INTERRUPT_READER_DELAY); + yield_in_non_preempt(); } while (!kthread_should_stop()); printk("trylock_interrupt_reader_thread/%lu iterations : %lu\n", (unsigned long)data, iter); @@ -350,15 +482,18 @@ static int trylock_interrupt_reader_thread(void *data) static int writer_thread(void *data) { int i; - int new; + int new, prev, cur; unsigned long iter = 0; - cycles_t time1, time2, delay, delaymax = 0, delaymin = ULLONG_MAX, - delayavg = 0; + cycles_t time1, time2, delay; + cycles_t ldelaymax = 0, ldelaymin = ULLONG_MAX, ldelayavg = 0; + cycles_t udelaymax = 0, udelaymin = ULLONG_MAX, udelayavg = 0; printk("writer_thread/%lu runnning\n", (unsigned long)data); do { iter++; - preempt_disable(); /* for get_cycles accuracy */ +#if (!TEST_PREEMPT) + preempt_disable(); +#endif rdtsc_barrier(); time1 = get_cycles(); rdtsc_barrier(); @@ -369,31 +504,69 @@ static int writer_thread(void *data) time2 = get_cycles(); rdtsc_barrier(); delay = time2 - time1; - delaymax = max(delaymax, delay); - delaymin = min(delaymin, delay); - delayavg += delay; + ldelaymax = max(ldelaymax, delay); + ldelaymin = min(ldelaymin, delay); + ldelayavg += delay; + /* + * Read the previous values, check that they are coherent. + */ + prev = var[0]; + for (i = 1; i < NR_VARS; i++) { + cur = var[i]; + if (cur != prev) + printk(KERN_ALERT + "Unequal cur %d/prev %d at i %d, iter %lu " + "in writer thread\n", + cur, prev, i, iter); + } new = (int)get_cycles(); for (i = 0; i < NR_VARS; i++) { var[i] = new; } + rdtsc_barrier(); + time1 = get_cycles(); + rdtsc_barrier(); + wrap_write_unlock(); - preempt_enable(); /* for get_cycles accuracy */ + rdtsc_barrier(); + time2 = get_cycles(); + rdtsc_barrier(); + delay = time2 - time1; + udelaymax = max(udelaymax, delay); + udelaymin = min(udelaymin, delay); + udelayavg += delay; + +#if (!TEST_PREEMPT) + preempt_enable(); +#endif if (WRITER_DELAY > 0) udelay(WRITER_DELAY); + cpu_relax(); /* + * make sure we don't busy-loop faster than + * the lock busy-loop, it would cause reader and + * writer starvation. + */ + yield_in_non_preempt(); } while (!kthread_should_stop()); - delayavg /= iter; + ldelayavg /= iter; + udelayavg /= iter; printk("writer_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)); + calibrate_cycles(ldelaymin), + calibrate_cycles(ldelayavg), + calibrate_cycles(ldelaymax)); + printk("writer_thread/%lu iterations : %lu, " + "unlock delay [min,avg,max] %llu,%llu,%llu cycles\n", + (unsigned long)data, iter, + calibrate_cycles(udelaymin), + calibrate_cycles(udelayavg), + calibrate_cycles(udelaymax)); return 0; } -#if (TEST_STD_RWLOCK) static int trylock_writer_thread(void *data) { int i; @@ -402,7 +575,11 @@ static int trylock_writer_thread(void *data) printk("trylock_writer_thread/%lu runnning\n", (unsigned long)data); do { -#if (TEST_INTERRUPTS) +#if ((!TEST_PREEMPT) && (!TEST_STD_RWLOCK)) + preempt_disable(); +#endif + +#if (TEST_STD_RWLOCK && TEST_INTERRUPTS) /* std write trylock cannot disable interrupts. */ local_irq_disable(); #endif @@ -410,85 +587,27 @@ static int trylock_writer_thread(void *data) #if (TRYLOCK_WRITERS_FAIL_ITER == -1) for (;;) { iter++; - if (write_trylock(&std_rw_lock)) + if (wrap_write_trylock()) goto locked; + cpu_relax(); } #else for (i = 0; i < TRYLOCK_WRITERS_FAIL_ITER; i++) { iter++; - if (write_trylock(&std_rw_lock)) + if (wrap_write_trylock()) goto locked; + cpu_relax(); } #endif fail++; -#if (TEST_INTERRUPTS) - local_irq_enable(); -#endif - goto loop; -locked: - success++; - new = (int)get_cycles(); - for (i = 0; i < NR_VARS; i++) { - var[i] = new; - } -#if (TEST_INTERRUPTS) - write_unlock_irq(&std_rw_lock); -#else - write_unlock(&std_rw_lock); -#endif -loop: - if (TRYLOCK_WRITER_DELAY > 0) - udelay(TRYLOCK_WRITER_DELAY); - } while (!kthread_should_stop()); - 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; -} - -#else /* !TEST_STD_RWLOCK */ -static int trylock_writer_thread(void *data) -{ - int i; - int new; - unsigned long iter = 0, success = 0, fail = 0; - - printk("trylock_writer_thread/%lu runnning\n", (unsigned long)data); - do { - iter++; -#if (TEST_INTERRUPTS) - if (wbias_write_trylock_irq_else_subscribe(&wbiasrwlock)) -#else - if (wbias_write_trylock_else_subscribe(&wbiasrwlock)) +#if (TEST_STD_RWLOCK && TEST_INTERRUPTS) + local_irq_enable(); #endif - goto locked; -#if (TRYLOCK_WRITERS_FAIL_ITER == -1) - for (;;) { - iter++; -#if (TEST_INTERRUPTS) - if (wbias_write_trylock_irq_subscribed(&wbiasrwlock)) -#else - if (wbias_write_trylock_subscribed(&wbiasrwlock)) -#endif - goto locked; - } -#else - for (i = 0; i < TRYLOCK_WRITERS_FAIL_ITER - 1; i++) { - iter++; -#if (TEST_INTERRUPTS) - if (wbias_write_trylock_irq_subscribed(&wbiasrwlock)) -#else - if (wbias_write_trylock_subscribed(&wbiasrwlock)) -#endif - goto locked; - } +#if ((!TEST_PREEMPT) && (!TEST_STD_RWLOCK)) + preempt_enable(); #endif - fail++; - wbias_write_unsubscribe(&wbiasrwlock); goto loop; locked: success++; @@ -496,14 +615,19 @@ locked: for (i = 0; i < NR_VARS; i++) { var[i] = new; } -#if (TEST_INTERRUPTS) - wbias_write_unlock_irq(&wbiasrwlock); -#else - wbias_write_unlock(&wbiasrwlock); + wrap_write_unlock(); +#if ((!TEST_PREEMPT) && (!TEST_STD_RWLOCK)) + preempt_enable(); #endif loop: if (TRYLOCK_WRITER_DELAY > 0) udelay(TRYLOCK_WRITER_DELAY); + cpu_relax(); /* + * make sure we don't busy-loop faster than + * the lock busy-loop, it would cause reader and + * writer starvation. + */ + yield_in_non_preempt(); } while (!kthread_should_stop()); printk("trylock_writer_thread/%lu iterations : " "[try,success,fail after %d try], " @@ -513,17 +637,22 @@ loop: return 0; } -#endif /* TEST_STD_RWLOCK */ - static void wbias_rwlock_create(void) { unsigned long i; - for (i = 0; i < NR_READERS; i++) { - printk("starting reader thread %lu\n", i); - reader_threads[i] = kthread_run(reader_thread, (void *)i, - "wbiasrwlock_reader"); - BUG_ON(!reader_threads[i]); + for (i = 0; i < NR_PREADERS; i++) { + printk("starting preemptable reader thread %lu\n", i); + preader_threads[i] = kthread_run(preader_thread, (void *)i, + "wbiasrwlock_preader"); + BUG_ON(!preader_threads[i]); + } + + for (i = 0; i < NR_NPREADERS; i++) { + printk("starting non-preemptable reader thread %lu\n", i); + npreader_threads[i] = kthread_run(npreader_thread, (void *)i, + "wbiasrwlock_npreader"); + BUG_ON(!npreader_threads[i]); } for (i = 0; i < NR_TRYLOCK_READERS; i++) { @@ -566,8 +695,10 @@ static void wbias_rwlock_stop(void) kthread_stop(writer_threads[i]); for (i = 0; i < NR_TRYLOCK_WRITERS; i++) kthread_stop(trylock_writer_threads[i]); - for (i = 0; i < NR_READERS; i++) - kthread_stop(reader_threads[i]); + for (i = 0; i < NR_NPREADERS; i++) + kthread_stop(npreader_threads[i]); + for (i = 0; i < NR_PREADERS; i++) + kthread_stop(preader_threads[i]); for (i = 0; i < NR_TRYLOCK_READERS; i++) kthread_stop(trylock_reader_threads[i]); for (i = 0; i < NR_INTERRUPT_READERS; i++) @@ -614,44 +745,93 @@ static int my_open(struct inode *inode, struct file *file) cycles_calibration_min, cycles_calibration_avg, cycles_calibration_max); + printk("\n"); +#if (NR_WRITERS) printk("** Single writer test, no contention **\n"); + wbias_rwlock_profile_latency_reset(); writer_threads[0] = kthread_run(writer_thread, (void *)0, "wbiasrwlock_writer"); BUG_ON(!writer_threads[0]); ssleep(SINGLE_WRITER_TEST_DURATION); kthread_stop(writer_threads[0]); + printk("\n"); + wbias_rwlock_profile_latency_print(); +#endif + +#if (NR_TRYLOCK_WRITERS) printk("** Single trylock writer test, no contention **\n"); + wbias_rwlock_profile_latency_reset(); trylock_writer_threads[0] = kthread_run(trylock_writer_thread, (void *)0, "trylock_wbiasrwlock_writer"); BUG_ON(!trylock_writer_threads[0]); ssleep(SINGLE_WRITER_TEST_DURATION); kthread_stop(trylock_writer_threads[0]); + printk("\n"); - printk("** Single reader test, no contention **\n"); - reader_threads[0] = kthread_run(reader_thread, (void *)0, - "wbiasrwlock_reader"); - BUG_ON(!reader_threads[0]); + wbias_rwlock_profile_latency_print(); +#endif + +#if (TEST_PREEMPT) + printk("** Single preemptable reader test, no contention **\n"); + wbias_rwlock_profile_latency_reset(); + preader_threads[0] = kthread_run(preader_thread, (void *)0, + "wbiasrwlock_preader"); + BUG_ON(!preader_threads[0]); + ssleep(SINGLE_READER_TEST_DURATION); + kthread_stop(preader_threads[0]); + printk("\n"); + + wbias_rwlock_profile_latency_print(); +#endif + + printk("** Single non-preemptable reader test, no contention **\n"); + wbias_rwlock_profile_latency_reset(); + npreader_threads[0] = kthread_run(npreader_thread, (void *)0, + "wbiasrwlock_npreader"); + BUG_ON(!npreader_threads[0]); ssleep(SINGLE_READER_TEST_DURATION); - kthread_stop(reader_threads[0]); - - printk("** Multiple readers test, no contention **\n"); - for (i = 0; i < NR_READERS; i++) { - printk("starting reader thread %lu\n", i); - reader_threads[i] = kthread_run(reader_thread, (void *)i, - "wbiasrwlock_reader"); - BUG_ON(!reader_threads[i]); + kthread_stop(npreader_threads[0]); + printk("\n"); + + wbias_rwlock_profile_latency_print(); + + printk("** Multiple p/non-p readers test, no contention **\n"); + wbias_rwlock_profile_latency_reset(); +#if (TEST_PREEMPT) + for (i = 0; i < NR_PREADERS; i++) { + printk("starting preader thread %lu\n", i); + preader_threads[i] = kthread_run(preader_thread, (void *)i, + "wbiasrwlock_preader"); + BUG_ON(!preader_threads[i]); + } +#endif + for (i = 0; i < NR_NPREADERS; i++) { + printk("starting npreader thread %lu\n", i); + npreader_threads[i] = kthread_run(npreader_thread, (void *)i, + "wbiasrwlock_npreader"); + BUG_ON(!npreader_threads[i]); } ssleep(SINGLE_READER_TEST_DURATION); - for (i = 0; i < NR_READERS; i++) - kthread_stop(reader_threads[i]); + for (i = 0; i < NR_NPREADERS; i++) + kthread_stop(npreader_threads[i]); +#if (TEST_PREEMPT) + for (i = 0; i < NR_PREADERS; i++) + kthread_stop(preader_threads[i]); +#endif + printk("\n"); + + wbias_rwlock_profile_latency_print(); printk("** High contention test **\n"); + wbias_rwlock_profile_latency_reset(); perform_test("wbias-rwlock-create", wbias_rwlock_create); ssleep(TEST_DURATION); perform_test("wbias-rwlock-stop", wbias_rwlock_stop); + printk("\n"); + wbias_rwlock_profile_latency_print(); return -EPERM; } @@ -667,18 +847,20 @@ int init_module(void) if (pentry) pentry->proc_fops = &my_operations; - printk("pow2cpus : %lu\n", pow2cpus); - printk("THREAD_ROFFSET : %lX\n", THREAD_ROFFSET); - printk("THREAD_RMASK : %lX\n", THREAD_RMASK); - printk("SOFTIRQ_ROFFSET : %lX\n", SOFTIRQ_ROFFSET); - printk("SOFTIRQ_RMASK : %lX\n", SOFTIRQ_RMASK); - printk("HARDIRQ_ROFFSET : %lX\n", HARDIRQ_ROFFSET); - printk("HARDIRQ_RMASK : %lX\n", HARDIRQ_RMASK); - printk("SUBSCRIBERS_WOFFSET : %lX\n", SUBSCRIBERS_WOFFSET); - printk("SUBSCRIBERS_WMASK : %lX\n", SUBSCRIBERS_WMASK); - printk("WRITER_MUTEX : %lX\n", WRITER_MUTEX); - printk("SOFTIRQ_WMASK : %lX\n", SOFTIRQ_WMASK); - printk("HARDIRQ_WMASK : %lX\n", HARDIRQ_WMASK); + printk("UC_READER_MASK : %08X\n", UC_READER_MASK); + printk("UC_HARDIRQ_R_MASK: %08X\n", UC_HARDIRQ_READER_MASK); + printk("UC_SOFTIRQ_R_MASK: %08X\n", UC_SOFTIRQ_READER_MASK); + printk("UC_NPTHREA_R_MASK: %08X\n", UC_NPTHREAD_READER_MASK); + printk("UC_PTHREAD_R_MASK: %08X\n", UC_PTHREAD_READER_MASK); + printk("UC_WRITER : %08X\n", UC_WRITER); + printk("UC_SLOW_WRITER : %08X\n", UC_SLOW_WRITER); + printk("UC_WQ_ACTIVE : %08X\n", UC_WQ_ACTIVE); + printk("WS_MASK : %08X\n", WS_MASK); + printk("WS_WQ_MUTEX : %08X\n", WS_WQ_MUTEX); + printk("WS_COUNT_MUTEX : %08X\n", WS_COUNT_MUTEX); + printk("WS_LOCK_MUTEX : %08X\n", WS_LOCK_MUTEX); + printk("CTX_RMASK : %016lX\n", CTX_RMASK); + printk("CTX_WMASK : %016lX\n", CTX_WMASK); return 0; }