X-Git-Url: http://git.lttng.org./?a=blobdiff_plain;f=trunk%2Ftests%2Fkernel%2Ftest-fair-rwlock.c;h=14ca57c2722a05a0ff73fc697684d4fa8b713f05;hb=f36c41126df61fdc24eebcb2b865a6509d9f555c;hp=ec751a10f66884cb8f5aa5c7f2c7fe9a98c1b185;hpb=f0a36bb1de4aff951669733fac825e2a8d74ef92;p=lttv.git diff --git a/trunk/tests/kernel/test-fair-rwlock.c b/trunk/tests/kernel/test-fair-rwlock.c index ec751a10..14ca57c2 100644 --- a/trunk/tests/kernel/test-fair-rwlock.c +++ b/trunk/tests/kernel/test-fair-rwlock.c @@ -11,12 +11,16 @@ #include #include #include +#include #include -#if (NR_CPUS > 512 && (BITS_PER_LONG == 32 || NR_CPUS > 1048576)) +#if (NR_CPUS > 64 && (BITS_PER_LONG == 32 || NR_CPUS > 32768)) #error "fair rwlock needs more bits per long to deal with that many CPUs" #endif +/* Test duration, in seconds */ +#define TEST_DURATION 60 + #define THREAD_ROFFSET 1UL #define THREAD_RMASK ((NR_CPUS - 1) * THREAD_ROFFSET) #define SOFTIRQ_ROFFSET (THREAD_RMASK + 1) @@ -24,16 +28,25 @@ #define HARDIRQ_ROFFSET ((SOFTIRQ_RMASK | THREAD_RMASK) + 1) #define HARDIRQ_RMASK ((NR_CPUS - 1) * HARDIRQ_ROFFSET) -#define THREAD_WMASK (1UL << (BITS_PER_LONG - 3)) -#define SOFTIRQ_WMASK (1UL << (BITS_PER_LONG - 2)) -#define HARDIRQ_WMASK (1UL << (BITS_PER_LONG - 1)) - +#define SUBSCRIBERS_WOFFSET \ + ((HARDIRQ_RMASK | SOFTIRQ_RMASK | THREAD_RMASK) + 1) +#define SUBSCRIBERS_WMASK \ + ((NR_CPUS - 1) * SUBSCRIBERS_WOFFSET) +#define WRITER_MUTEX \ + ((SUBSCRIBERS_WMASK | HARDIRQ_RMASK | SOFTIRQ_RMASK | THREAD_RMASK) + 1) +#define SOFTIRQ_WMASK (WRITER_MUTEX << 1) +#define SOFTIRQ_WOFFSET SOFTIRQ_WMASK +#define HARDIRQ_WMASK (SOFTIRQ_WMASK << 1) +#define HARDIRQ_WOFFSET HARDIRQ_WMASK #define NR_VARS 100 #define NR_WRITERS 3 #define NR_READERS 6 #define NR_INTERRUPT_READERS 2 +/* Writer iteration delay, in ms. 0 for busy loop. */ +#define WRITER_DELAY 0 + static int var[NR_VARS]; static struct task_struct *reader_threads[NR_READERS]; static struct task_struct *writer_threads[NR_WRITERS]; @@ -41,7 +54,6 @@ static struct task_struct *interrupt_reader; static struct fair_rwlock frwlock = { .value = ATOMIC_LONG_INIT(0), - .wlock = __SPIN_LOCK_UNLOCKED(&frwlock.wlock), }; struct proc_dir_entry *pentry = NULL; @@ -51,11 +63,16 @@ static int reader_thread(void *data) int i; int prev, cur; unsigned long iter = 0; + cycles_t time1, time2, delaymax = 0; printk("reader_thread/%lu runnning\n", (unsigned long)data); do { iter++; + preempt_disable(); /* for get_cycles accuracy */ + time1 = get_cycles(); fair_read_lock(&frwlock); + time2 = get_cycles(); + delaymax = max(delaymax, time2 - time1); prev = var[0]; for (i = 1; i < NR_VARS; i++) { cur = var[i]; @@ -65,19 +82,35 @@ static int reader_thread(void *data) "in thread\n", cur, prev, i, iter); } fair_read_unlock(&frwlock); + preempt_enable(); /* for get_cycles accuracy */ //msleep(100); } while (!kthread_should_stop()); - printk("reader_thread/%lu iterations : %lu\n", - (unsigned long)data, iter); + printk("reader_thread/%lu iterations : %lu, " + "max contention %llu cycles\n", + (unsigned long)data, iter, delaymax); return 0; } +DEFINE_PER_CPU(cycles_t, int_delaymax); + static void interrupt_reader_ipi(void *data) { int i; int prev, cur; + cycles_t time1, time2; + cycles_t *delaymax; + + /* + * Skip the ipi caller, not in irq context. + */ + if (!in_irq()) + return; + delaymax = &per_cpu(int_delaymax, smp_processor_id()); + time1 = get_cycles(); fair_read_lock(&frwlock); + time2 = get_cycles(); + *delaymax = max(*delaymax, time2 - time1); prev = var[0]; for (i = 1; i < NR_VARS; i++) { cur = var[i]; @@ -92,6 +125,8 @@ static void interrupt_reader_ipi(void *data) static int interrupt_reader_thread(void *data) { unsigned long iter = 0; + int i; + do { iter++; on_each_cpu(interrupt_reader_ipi, NULL, 0); @@ -99,6 +134,11 @@ static int interrupt_reader_thread(void *data) } while (!kthread_should_stop()); printk("interrupt_reader_thread/%lu iterations : %lu\n", (unsigned long)data, iter); + for_each_online_cpu(i) { + printk("interrupt readers on CPU %i, " + "max contention : %llu cycles\n", + i, per_cpu(int_delaymax, i)); + } return 0; } @@ -107,22 +147,30 @@ static int writer_thread(void *data) int i; int new; unsigned long iter = 0; + cycles_t time1, time2, delaymax = 0; printk("writer_thread/%lu runnning\n", (unsigned long)data); do { iter++; + preempt_disable(); /* for get_cycles accuracy */ + time1 = get_cycles(); fair_write_lock_irq(&frwlock); //fair_write_lock(&frwlock); + time2 = get_cycles(); + delaymax = max(delaymax, time2 - time1); new = (int)get_cycles(); for (i = 0; i < NR_VARS; i++) { var[i] = new; } //fair_write_unlock(&frwlock); fair_write_unlock_irq(&frwlock); - //msleep(100); + preempt_enable(); /* for get_cycles accuracy */ + if (WRITER_DELAY > 0) + msleep(WRITER_DELAY); } while (!kthread_should_stop()); - printk("writer_thread/%lu iterations : %lu\n", - (unsigned long)data, iter); + printk("writer_thread/%lu iterations : %lu, " + "max contention %llu cycles\n", + (unsigned long)data, iter, delaymax); return 0; } @@ -153,15 +201,15 @@ static void fair_rwlock_stop(void) { unsigned long i; + for (i = 0; i < NR_WRITERS; i++) { + kthread_stop(writer_threads[i]); + } + for (i = 0; i < NR_READERS; i++) { kthread_stop(reader_threads[i]); } - //kthread_stop(interrupt_reader); - - for (i = 0; i < NR_WRITERS; i++) { - kthread_stop(writer_threads[i]); - } + kthread_stop(interrupt_reader); } @@ -174,7 +222,7 @@ static void perform_test(const char *name, void (*callback)(void)) static int my_open(struct inode *inode, struct file *file) { perform_test("fair-rwlock-create", fair_rwlock_create); - ssleep(30); + ssleep(TEST_DURATION); perform_test("fair-rwlock-stop", fair_rwlock_stop); return -EPERM; @@ -194,12 +242,14 @@ int init_module(void) printk("NR_CPUS : %d\n", NR_CPUS); printk("THREAD_ROFFSET : %lX\n", THREAD_ROFFSET); printk("THREAD_RMASK : %lX\n", THREAD_RMASK); - printk("THREAD_WMASK : %lX\n", THREAD_WMASK); printk("SOFTIRQ_ROFFSET : %lX\n", SOFTIRQ_ROFFSET); printk("SOFTIRQ_RMASK : %lX\n", SOFTIRQ_RMASK); - printk("SOFTIRQ_WMASK : %lX\n", SOFTIRQ_WMASK); 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); return 0;