update test
[lttv.git] / trunk / tests / kernel / test-wbias-rwlock.c
CommitLineData
0e0fdeb6 1/* test-wbias-rwlock.c
f0a36bb1 2 *
3 */
4
5#include <linux/module.h>
6#include <linux/proc_fs.h>
7#include <linux/sched.h>
8#include <linux/timex.h>
f0a36bb1 9#include <linux/kthread.h>
10#include <linux/delay.h>
11#include <linux/hardirq.h>
12#include <linux/module.h>
7f563886 13#include <linux/percpu.h>
cd7cf33d 14#include <linux/spinlock.h>
f0a36bb1 15#include <asm/ptrace.h>
992fbe0f 16#include <linux/wbias-rwlock.h>
f0a36bb1 17
68f25f81 18/* Test with no contention duration, in seconds */
19#define SINGLE_WRITER_TEST_DURATION 10
20#define SINGLE_READER_TEST_DURATION 10
21#define MULTIPLE_READERS_TEST_DURATION 10
22
89889f86 23/* Test duration, in seconds */
f36c4112 24#define TEST_DURATION 60
89889f86 25
f0a36bb1 26#define NR_VARS 100
1c21e42c 27#define NR_WRITERS 2
ca935c46 28#define NR_TRYLOCK_WRITERS 1
1f5845d5 29#define NR_NPREADERS 2
ca935c46 30#define NR_TRYLOCK_READERS 1
cd7cf33d 31
32/*
33 * 1 : test standard rwlock
0e0fdeb6 34 * 0 : test wbiasrwlock
cd7cf33d 35 */
36#define TEST_STD_RWLOCK 0
4fd25765 37
38/*
39 * 1 : test with thread and interrupt readers.
40 * 0 : test only with thread readers.
41 */
42#define TEST_INTERRUPTS 1
43
44#if (TEST_INTERRUPTS)
1c21e42c 45#define NR_INTERRUPT_READERS 1
46#define NR_TRYLOCK_INTERRUPT_READERS 1
4fd25765 47#else
48#define NR_INTERRUPT_READERS 0
49#define NR_TRYLOCK_INTERRUPT_READERS 0
50#endif
f0a36bb1 51
992fbe0f 52/*
53 * 1 : test with thread preemption readers.
54 * 0 : test only with non-preemptable thread readers.
55 */
56#define TEST_PREEMPT 1
57
58#if (TEST_PREEMPT)
59#define NR_PREADERS 2
60#else
61#define NR_PREADERS 0
62#endif
63
64
4d1751f9 65/*
66 * Writer iteration delay, in us. 0 for busy loop. Caution : writers can
67 * starve readers.
68 */
cd7cf33d 69#define WRITER_DELAY 100
4fd25765 70#define TRYLOCK_WRITER_DELAY 1000
71
72/*
73 * Number of iterations after which a trylock writer fails.
74 * -1 for infinite loop.
75 */
76#define TRYLOCK_WRITERS_FAIL_ITER 100
77
78/* Thread and interrupt reader delay, in ms */
79#define THREAD_READER_DELAY 0 /* busy loop */
80#define INTERRUPT_READER_DELAY 100
89889f86 81
f0a36bb1 82static int var[NR_VARS];
1f5845d5 83static struct task_struct *preader_threads[NR_PREADERS];
84static struct task_struct *npreader_threads[NR_NPREADERS];
1c21e42c 85static struct task_struct *trylock_reader_threads[NR_TRYLOCK_READERS];
f0a36bb1 86static struct task_struct *writer_threads[NR_WRITERS];
1c21e42c 87static struct task_struct *trylock_writer_threads[NR_TRYLOCK_WRITERS];
4fd25765 88static struct task_struct *interrupt_reader[NR_INTERRUPT_READERS];
89static struct task_struct *trylock_interrupt_reader[NR_TRYLOCK_INTERRUPT_READERS];
f0a36bb1 90
cd7cf33d 91#if (TEST_STD_RWLOCK)
92
93static DEFINE_RWLOCK(std_rw_lock);
94
95#define wrap_read_lock() read_lock(&std_rw_lock)
96#define wrap_read_trylock() read_trylock(&std_rw_lock)
97#define wrap_read_unlock() read_unlock(&std_rw_lock)
98
1f5845d5 99#define wrap_read_lock_inatomic() read_lock(&std_rw_lock)
100#define wrap_read_trylock_inatomic() read_trylock(&std_rw_lock)
101#define wrap_read_unlock_inatomic() read_unlock(&std_rw_lock)
102
cd7cf33d 103#define wrap_read_lock_irq() read_lock(&std_rw_lock)
104#define wrap_read_trylock_irq() read_trylock(&std_rw_lock)
105#define wrap_read_unlock_irq() read_unlock(&std_rw_lock)
106
107#if (TEST_INTERRUPTS)
108#define wrap_write_lock() write_lock_irq(&std_rw_lock)
109#define wrap_write_unlock() write_unlock_irq(&std_rw_lock)
110#else
111#define wrap_write_lock() write_lock(&std_rw_lock)
112#define wrap_write_unlock() write_unlock(&std_rw_lock)
113#endif
114
115#else
116
0e0fdeb6 117static DEFINE_WBIAS_RWLOCK(wbiasrwlock);
f0a36bb1 118
0e0fdeb6 119#define wrap_read_lock() wbias_read_lock(&wbiasrwlock)
120#define wrap_read_trylock() wbias_read_trylock(&wbiasrwlock)
121#define wrap_read_unlock() wbias_read_unlock(&wbiasrwlock)
cd7cf33d 122
1f5845d5 123#define wrap_read_lock_inatomic() wbias_read_lock_inatomic(&wbiasrwlock)
124#define wrap_read_trylock_inatomic() \
125 wbias_read_trylock_inatomic(&wbiasrwlock)
126#define wrap_read_unlock_inatomic() \
127 wbias_read_unlock_inatomic(&wbiasrwlock)
128
0e0fdeb6 129#define wrap_read_lock_irq() wbias_read_lock_irq(&wbiasrwlock)
130#define wrap_read_trylock_irq() wbias_read_trylock_irq(&wbiasrwlock)
131#define wrap_read_unlock_irq() wbias_read_unlock_irq(&wbiasrwlock)
cd7cf33d 132
133#if (TEST_INTERRUPTS)
0e0fdeb6 134#define wrap_write_lock() wbias_write_lock_irq(&wbiasrwlock)
135#define wrap_write_unlock() wbias_write_unlock_irq(&wbiasrwlock)
992fbe0f 136#define wrap_write_trylock_else_subscribe() \
137 wbias_write_trylock_irq_else_subscribe(&wbiasrwlock)
138#define wrap_write_trylock_subscribed() \
139 wbias_write_trylock_irq_subscribed(&wbiasrwlock)
cd7cf33d 140#else
992fbe0f 141#if (TEST_PREEMPT)
0e0fdeb6 142#define wrap_write_lock() wbias_write_lock(&wbiasrwlock)
143#define wrap_write_unlock() wbias_write_unlock(&wbiasrwlock)
992fbe0f 144#define wrap_write_trylock_else_subscribe() \
145 wbias_write_trylock_else_subscribe(&wbiasrwlock)
146#define wrap_write_trylock_subscribed() \
147 wbias_write_trylock_subscribed(&wbiasrwlock)
148#else
992fbe0f 149#define wrap_write_lock() wbias_write_lock_atomic(&wbiasrwlock)
150#define wrap_write_unlock() wbias_write_unlock_atomic(&wbiasrwlock)
151#define wrap_write_trylock_else_subscribe() \
152 wbias_write_trylock_atomic_else_subscribe(&wbiasrwlock)
153#define wrap_write_trylock_subscribed() \
154 wbias_write_trylock_atomic_subscribed(&wbiasrwlock)
155#endif
cd7cf33d 156#endif
157
158#endif
159
68f25f81 160static cycles_t cycles_calibration_min,
161 cycles_calibration_avg,
162 cycles_calibration_max;
163
164static inline cycles_t calibrate_cycles(cycles_t cycles)
165{
166 return cycles - cycles_calibration_avg;
167}
168
f0a36bb1 169struct proc_dir_entry *pentry = NULL;
170
b37c9208 171static int p_or_np_reader_thread(const char *typename,
172 void *data, int preemptable)
f0a36bb1 173{
174 int i;
175 int prev, cur;
176 unsigned long iter = 0;
68f25f81 177 cycles_t time1, time2, delay, delaymax = 0, delaymin = ULLONG_MAX,
178 delayavg = 0;
f0a36bb1 179
b37c9208 180 printk("%s/%lu runnning\n", typename, (unsigned long)data);
f0a36bb1 181 do {
182 iter++;
1f5845d5 183 if (!preemptable)
184 preempt_disable();
68f25f81 185 rdtsc_barrier();
7f563886 186 time1 = get_cycles();
68f25f81 187 rdtsc_barrier();
188
1f5845d5 189 if (!preemptable)
190 wrap_read_lock_inatomic();
191 else
192 wrap_read_lock();
68f25f81 193
194 rdtsc_barrier();
7f563886 195 time2 = get_cycles();
68f25f81 196 rdtsc_barrier();
197 delay = time2 - time1;
198 delaymax = max(delaymax, delay);
199 delaymin = min(delaymin, delay);
200 delayavg += delay;
f0a36bb1 201 prev = var[0];
202 for (i = 1; i < NR_VARS; i++) {
203 cur = var[i];
204 if (cur != prev)
205 printk(KERN_ALERT
206 "Unequal cur %d/prev %d at i %d, iter %lu "
207 "in thread\n", cur, prev, i, iter);
208 }
cd7cf33d 209
1f5845d5 210 if (!preemptable)
211 wrap_read_unlock_inatomic();
212 else
213 wrap_read_unlock();
214 if (!preemptable)
215 preempt_enable();
4fd25765 216 if (THREAD_READER_DELAY)
217 msleep(THREAD_READER_DELAY);
f0a36bb1 218 } while (!kthread_should_stop());
4fd25765 219 if (!iter) {
b37c9208 220 printk("%s/%lu iterations : %lu", typename,
4fd25765 221 (unsigned long)data, iter);
222 } else {
223 delayavg /= iter;
b37c9208 224 printk("%s/%lu iterations : %lu, "
4fd25765 225 "lock delay [min,avg,max] %llu,%llu,%llu cycles\n",
b37c9208 226 typename,
4fd25765 227 (unsigned long)data, iter,
228 calibrate_cycles(delaymin),
229 calibrate_cycles(delayavg),
230 calibrate_cycles(delaymax));
231 }
f0a36bb1 232 return 0;
233}
234
1f5845d5 235static int preader_thread(void *data)
236{
b37c9208 237 return p_or_np_reader_thread("preader_thread", data, 1);
1f5845d5 238}
239
240static int npreader_thread(void *data)
241{
b37c9208 242 return p_or_np_reader_thread("npreader_thread", data, 0);
1f5845d5 243}
244
1c21e42c 245static int trylock_reader_thread(void *data)
246{
247 int i;
248 int prev, cur;
249 unsigned long iter = 0, success_iter = 0;
250
251 printk("trylock_reader_thread/%lu runnning\n", (unsigned long)data);
252 do {
cd7cf33d 253 while (!wrap_read_trylock())
1c21e42c 254 iter++;
255 success_iter++;
256 prev = var[0];
257 for (i = 1; i < NR_VARS; i++) {
258 cur = var[i];
259 if (cur != prev)
260 printk(KERN_ALERT
261 "Unequal cur %d/prev %d at i %d, iter %lu "
262 "in thread\n", cur, prev, i, iter);
263 }
cd7cf33d 264 wrap_read_unlock();
4fd25765 265 if (THREAD_READER_DELAY)
266 msleep(THREAD_READER_DELAY);
1c21e42c 267 } while (!kthread_should_stop());
268 printk("trylock_reader_thread/%lu iterations : %lu, "
269 "successful iterations : %lu\n",
270 (unsigned long)data, iter, success_iter);
271 return 0;
272}
273
68f25f81 274DEFINE_PER_CPU(cycles_t, int_delaymin);
275DEFINE_PER_CPU(cycles_t, int_delayavg);
7f563886 276DEFINE_PER_CPU(cycles_t, int_delaymax);
68f25f81 277DEFINE_PER_CPU(cycles_t, int_ipi_nr);
7f563886 278
f0a36bb1 279static void interrupt_reader_ipi(void *data)
280{
281 int i;
282 int prev, cur;
7f563886 283 cycles_t time1, time2;
68f25f81 284 cycles_t *delaymax, *delaymin, *delayavg, *ipi_nr, delay;
7f563886 285
286 /*
287 * Skip the ipi caller, not in irq context.
288 */
289 if (!in_irq())
290 return;
f0a36bb1 291
7f563886 292 delaymax = &per_cpu(int_delaymax, smp_processor_id());
68f25f81 293 delaymin = &per_cpu(int_delaymin, smp_processor_id());
294 delayavg = &per_cpu(int_delayavg, smp_processor_id());
295 ipi_nr = &per_cpu(int_ipi_nr, smp_processor_id());
296
297 rdtsc_barrier();
7f563886 298 time1 = get_cycles();
68f25f81 299 rdtsc_barrier();
300
cd7cf33d 301 wrap_read_lock_irq();
68f25f81 302
303 rdtsc_barrier();
7f563886 304 time2 = get_cycles();
68f25f81 305 rdtsc_barrier();
306 delay = time2 - time1;
307 *delaymax = max(*delaymax, delay);
308 *delaymin = min(*delaymin, delay);
309 *delayavg += delay;
310 (*ipi_nr)++;
f0a36bb1 311 prev = var[0];
312 for (i = 1; i < NR_VARS; i++) {
313 cur = var[i];
314 if (cur != prev)
315 printk(KERN_ALERT
316 "Unequal cur %d/prev %d at i %d in interrupt\n",
317 cur, prev, i);
318 }
cd7cf33d 319 wrap_read_unlock_irq();
f0a36bb1 320}
321
1c21e42c 322DEFINE_PER_CPU(unsigned long, trylock_int_iter);
323DEFINE_PER_CPU(unsigned long, trylock_int_success);
324
325static void trylock_interrupt_reader_ipi(void *data)
326{
327 int i;
328 int prev, cur;
329
330 /*
331 * Skip the ipi caller, not in irq context.
332 */
333 if (!in_irq())
334 return;
335
336 per_cpu(trylock_int_iter, smp_processor_id())++;
cd7cf33d 337 while (!wrap_read_trylock_irq())
1c21e42c 338 per_cpu(trylock_int_iter, smp_processor_id())++;
339 per_cpu(trylock_int_success, smp_processor_id())++;
340 prev = var[0];
341 for (i = 1; i < NR_VARS; i++) {
342 cur = var[i];
343 if (cur != prev)
344 printk(KERN_ALERT
345 "Unequal cur %d/prev %d at i %d in interrupt\n",
346 cur, prev, i);
347 }
cd7cf33d 348 wrap_read_unlock_irq();
1c21e42c 349}
350
351
f0a36bb1 352static int interrupt_reader_thread(void *data)
353{
354 unsigned long iter = 0;
7f563886 355 int i;
356
68f25f81 357 for_each_online_cpu(i) {
358 per_cpu(int_delaymax, i) = 0;
359 per_cpu(int_delaymin, i) = ULLONG_MAX;
360 per_cpu(int_delayavg, i) = 0;
361 per_cpu(int_ipi_nr, i) = 0;
362 }
f0a36bb1 363 do {
364 iter++;
365 on_each_cpu(interrupt_reader_ipi, NULL, 0);
4fd25765 366 if (INTERRUPT_READER_DELAY)
367 msleep(INTERRUPT_READER_DELAY);
f0a36bb1 368 } while (!kthread_should_stop());
369 printk("interrupt_reader_thread/%lu iterations : %lu\n",
370 (unsigned long)data, iter);
7f563886 371 for_each_online_cpu(i) {
4fd25765 372 if (!per_cpu(int_ipi_nr, i))
373 continue;
68f25f81 374 per_cpu(int_delayavg, i) /= per_cpu(int_ipi_nr, i);
7f563886 375 printk("interrupt readers on CPU %i, "
68f25f81 376 "lock delay [min,avg,max] %llu,%llu,%llu cycles\n",
377 i,
378 calibrate_cycles(per_cpu(int_delaymin, i)),
379 calibrate_cycles(per_cpu(int_delayavg, i)),
380 calibrate_cycles(per_cpu(int_delaymax, i)));
7f563886 381 }
f0a36bb1 382 return 0;
383}
384
1c21e42c 385static int trylock_interrupt_reader_thread(void *data)
386{
387 unsigned long iter = 0;
388 int i;
389
390 do {
391 iter++;
392 on_each_cpu(trylock_interrupt_reader_ipi, NULL, 0);
4fd25765 393 if (INTERRUPT_READER_DELAY)
394 msleep(INTERRUPT_READER_DELAY);
1c21e42c 395 } while (!kthread_should_stop());
396 printk("trylock_interrupt_reader_thread/%lu iterations : %lu\n",
397 (unsigned long)data, iter);
398 for_each_online_cpu(i) {
399 printk("trylock interrupt readers on CPU %i, "
400 "iterations %lu, "
401 "successful iterations : %lu\n",
402 i, per_cpu(trylock_int_iter, i),
403 per_cpu(trylock_int_success, i));
68f25f81 404 per_cpu(trylock_int_iter, i) = 0;
405 per_cpu(trylock_int_success, i) = 0;
1c21e42c 406 }
407 return 0;
408}
409
f0a36bb1 410static int writer_thread(void *data)
411{
412 int i;
413 int new;
414 unsigned long iter = 0;
68f25f81 415 cycles_t time1, time2, delay, delaymax = 0, delaymin = ULLONG_MAX,
416 delayavg = 0;
f0a36bb1 417
418 printk("writer_thread/%lu runnning\n", (unsigned long)data);
419 do {
420 iter++;
ae4a4ebf 421 //preempt_disable(); /* for get_cycles accuracy */
68f25f81 422 rdtsc_barrier();
7f563886 423 time1 = get_cycles();
68f25f81 424 rdtsc_barrier();
425
cd7cf33d 426 wrap_write_lock();
68f25f81 427
428 rdtsc_barrier();
7f563886 429 time2 = get_cycles();
68f25f81 430 rdtsc_barrier();
431 delay = time2 - time1;
432 delaymax = max(delaymax, delay);
433 delaymin = min(delaymin, delay);
434 delayavg += delay;
f0a36bb1 435 new = (int)get_cycles();
436 for (i = 0; i < NR_VARS; i++) {
437 var[i] = new;
438 }
cd7cf33d 439
440 wrap_write_unlock();
441
ae4a4ebf 442 //preempt_enable(); /* for get_cycles accuracy */
89889f86 443 if (WRITER_DELAY > 0)
4d1751f9 444 udelay(WRITER_DELAY);
f0a36bb1 445 } while (!kthread_should_stop());
68f25f81 446 delayavg /= iter;
7f563886 447 printk("writer_thread/%lu iterations : %lu, "
68f25f81 448 "lock delay [min,avg,max] %llu,%llu,%llu cycles\n",
449 (unsigned long)data, iter,
450 calibrate_cycles(delaymin),
451 calibrate_cycles(delayavg),
452 calibrate_cycles(delaymax));
f0a36bb1 453 return 0;
454}
455
cd7cf33d 456#if (TEST_STD_RWLOCK)
457static int trylock_writer_thread(void *data)
458{
459 int i;
460 int new;
461 unsigned long iter = 0, success = 0, fail = 0;
462
463 printk("trylock_writer_thread/%lu runnning\n", (unsigned long)data);
464 do {
465#if (TEST_INTERRUPTS)
466 /* std write trylock cannot disable interrupts. */
467 local_irq_disable();
468#endif
469
470#if (TRYLOCK_WRITERS_FAIL_ITER == -1)
471 for (;;) {
472 iter++;
473 if (write_trylock(&std_rw_lock))
474 goto locked;
475 }
476#else
477 for (i = 0; i < TRYLOCK_WRITERS_FAIL_ITER; i++) {
478 iter++;
479 if (write_trylock(&std_rw_lock))
480 goto locked;
481 }
482#endif
483 fail++;
484#if (TEST_INTERRUPTS)
485 local_irq_enable();
486#endif
487 goto loop;
488locked:
489 success++;
490 new = (int)get_cycles();
491 for (i = 0; i < NR_VARS; i++) {
492 var[i] = new;
493 }
494#if (TEST_INTERRUPTS)
495 write_unlock_irq(&std_rw_lock);
496#else
497 write_unlock(&std_rw_lock);
498#endif
499loop:
500 if (TRYLOCK_WRITER_DELAY > 0)
501 udelay(TRYLOCK_WRITER_DELAY);
502 } while (!kthread_should_stop());
503 printk("trylock_writer_thread/%lu iterations : "
504 "[try,success,fail after %d try], "
505 "%lu,%lu,%lu\n",
506 (unsigned long)data, TRYLOCK_WRITERS_FAIL_ITER,
507 iter, success, fail);
508 return 0;
509}
510
511#else /* !TEST_STD_RWLOCK */
512
1c21e42c 513static int trylock_writer_thread(void *data)
514{
515 int i;
516 int new;
4fd25765 517 unsigned long iter = 0, success = 0, fail = 0;
1c21e42c 518
519 printk("trylock_writer_thread/%lu runnning\n", (unsigned long)data);
520 do {
4fd25765 521 iter++;
992fbe0f 522 if (wrap_write_trylock_else_subscribe())
4fd25765 523 goto locked;
cd7cf33d 524
4fd25765 525#if (TRYLOCK_WRITERS_FAIL_ITER == -1)
526 for (;;) {
1c21e42c 527 iter++;
992fbe0f 528 if (wrap_write_trylock_subscribed())
4fd25765 529 goto locked;
1c21e42c 530 }
4fd25765 531#else
cd7cf33d 532 for (i = 0; i < TRYLOCK_WRITERS_FAIL_ITER - 1; i++) {
4fd25765 533 iter++;
992fbe0f 534 if (wrap_write_trylock_subscribed())
4fd25765 535 goto locked;
536 }
537#endif
538 fail++;
0e0fdeb6 539 wbias_write_unsubscribe(&wbiasrwlock);
4fd25765 540 goto loop;
541locked:
1c21e42c 542 success++;
1c21e42c 543 new = (int)get_cycles();
544 for (i = 0; i < NR_VARS; i++) {
545 var[i] = new;
546 }
992fbe0f 547 wrap_write_unlock();
4fd25765 548loop:
549 if (TRYLOCK_WRITER_DELAY > 0)
550 udelay(TRYLOCK_WRITER_DELAY);
1c21e42c 551 } while (!kthread_should_stop());
4fd25765 552 printk("trylock_writer_thread/%lu iterations : "
553 "[try,success,fail after %d try], "
554 "%lu,%lu,%lu\n",
555 (unsigned long)data, TRYLOCK_WRITERS_FAIL_ITER,
556 iter, success, fail);
1c21e42c 557 return 0;
558}
559
cd7cf33d 560#endif /* TEST_STD_RWLOCK */
561
0e0fdeb6 562static void wbias_rwlock_create(void)
f0a36bb1 563{
564 unsigned long i;
565
1f5845d5 566 for (i = 0; i < NR_PREADERS; i++) {
567 printk("starting preemptable reader thread %lu\n", i);
568 preader_threads[i] = kthread_run(preader_thread, (void *)i,
569 "wbiasrwlock_preader");
570 BUG_ON(!preader_threads[i]);
571 }
572
573 for (i = 0; i < NR_NPREADERS; i++) {
574 printk("starting non-preemptable reader thread %lu\n", i);
575 npreader_threads[i] = kthread_run(npreader_thread, (void *)i,
576 "wbiasrwlock_npreader");
577 BUG_ON(!npreader_threads[i]);
f0a36bb1 578 }
579
1c21e42c 580 for (i = 0; i < NR_TRYLOCK_READERS; i++) {
581 printk("starting trylock reader thread %lu\n", i);
582 trylock_reader_threads[i] = kthread_run(trylock_reader_thread,
0e0fdeb6 583 (void *)i, "wbiasrwlock_trylock_reader");
1c21e42c 584 BUG_ON(!trylock_reader_threads[i]);
585 }
4fd25765 586 for (i = 0; i < NR_INTERRUPT_READERS; i++) {
587 printk("starting interrupt reader %lu\n", i);
588 interrupt_reader[i] = kthread_run(interrupt_reader_thread,
589 (void *)i,
0e0fdeb6 590 "wbiasrwlock_interrupt_reader");
4fd25765 591 }
592 for (i = 0; i < NR_TRYLOCK_INTERRUPT_READERS; i++) {
593 printk("starting trylock interrupt reader %lu\n", i);
594 trylock_interrupt_reader[i] =
595 kthread_run(trylock_interrupt_reader_thread,
0e0fdeb6 596 (void *)i, "wbiasrwlock_trylock_interrupt_reader");
4fd25765 597 }
f0a36bb1 598 for (i = 0; i < NR_WRITERS; i++) {
599 printk("starting writer thread %lu\n", i);
600 writer_threads[i] = kthread_run(writer_thread, (void *)i,
0e0fdeb6 601 "wbiasrwlock_writer");
f0a36bb1 602 BUG_ON(!writer_threads[i]);
603 }
1c21e42c 604 for (i = 0; i < NR_TRYLOCK_WRITERS; i++) {
605 printk("starting trylock writer thread %lu\n", i);
606 trylock_writer_threads[i] = kthread_run(trylock_writer_thread,
0e0fdeb6 607 (void *)i, "wbiasrwlock_trylock_writer");
1c21e42c 608 BUG_ON(!trylock_writer_threads[i]);
609 }
f0a36bb1 610}
611
0e0fdeb6 612static void wbias_rwlock_stop(void)
f0a36bb1 613{
614 unsigned long i;
615
1c21e42c 616 for (i = 0; i < NR_WRITERS; i++)
7f563886 617 kthread_stop(writer_threads[i]);
1c21e42c 618 for (i = 0; i < NR_TRYLOCK_WRITERS; i++)
619 kthread_stop(trylock_writer_threads[i]);
1f5845d5 620 for (i = 0; i < NR_NPREADERS; i++)
621 kthread_stop(npreader_threads[i]);
622 for (i = 0; i < NR_PREADERS; i++)
623 kthread_stop(preader_threads[i]);
1c21e42c 624 for (i = 0; i < NR_TRYLOCK_READERS; i++)
625 kthread_stop(trylock_reader_threads[i]);
4fd25765 626 for (i = 0; i < NR_INTERRUPT_READERS; i++)
627 kthread_stop(interrupt_reader[i]);
628 for (i = 0; i < NR_TRYLOCK_INTERRUPT_READERS; i++)
629 kthread_stop(trylock_interrupt_reader[i]);
f0a36bb1 630}
631
632
633static void perform_test(const char *name, void (*callback)(void))
634{
635 printk("%s\n", name);
636 callback();
637}
638
639static int my_open(struct inode *inode, struct file *file)
640{
68f25f81 641 unsigned long i;
642 cycles_t time1, time2, delay;
643
644 printk("** get_cycles calibration **\n");
645 cycles_calibration_min = ULLONG_MAX;
646 cycles_calibration_avg = 0;
647 cycles_calibration_max = 0;
648
649 local_irq_disable();
650 for (i = 0; i < 10; i++) {
651 rdtsc_barrier();
652 time1 = get_cycles();
653 rdtsc_barrier();
654 rdtsc_barrier();
655 time2 = get_cycles();
656 rdtsc_barrier();
657 delay = time2 - time1;
658 cycles_calibration_min = min(cycles_calibration_min, delay);
659 cycles_calibration_avg += delay;
660 cycles_calibration_max = max(cycles_calibration_max, delay);
661 }
662 cycles_calibration_avg /= 10;
663 local_irq_enable();
664
665 printk("get_cycles takes [min,avg,max] %llu,%llu,%llu cycles, "
666 "results calibrated on avg\n",
667 cycles_calibration_min,
668 cycles_calibration_avg,
669 cycles_calibration_max);
193771da 670 printk("\n");
68f25f81 671
672 printk("** Single writer test, no contention **\n");
dac86829 673 wbias_rwlock_profile_latency_reset();
68f25f81 674 writer_threads[0] = kthread_run(writer_thread, (void *)0,
0e0fdeb6 675 "wbiasrwlock_writer");
68f25f81 676 BUG_ON(!writer_threads[0]);
677 ssleep(SINGLE_WRITER_TEST_DURATION);
678 kthread_stop(writer_threads[0]);
193771da 679 printk("\n");
68f25f81 680
dac86829 681 wbias_rwlock_profile_latency_print();
682
4fd25765 683 printk("** Single trylock writer test, no contention **\n");
dac86829 684 wbias_rwlock_profile_latency_reset();
4fd25765 685 trylock_writer_threads[0] = kthread_run(trylock_writer_thread,
686 (void *)0,
0e0fdeb6 687 "trylock_wbiasrwlock_writer");
4fd25765 688 BUG_ON(!trylock_writer_threads[0]);
689 ssleep(SINGLE_WRITER_TEST_DURATION);
690 kthread_stop(trylock_writer_threads[0]);
193771da 691 printk("\n");
4fd25765 692
dac86829 693 wbias_rwlock_profile_latency_print();
694
1f5845d5 695 printk("** Single preemptable reader test, no contention **\n");
696 wbias_rwlock_profile_latency_reset();
697 preader_threads[0] = kthread_run(preader_thread, (void *)0,
698 "wbiasrwlock_preader");
699 BUG_ON(!preader_threads[0]);
700 ssleep(SINGLE_READER_TEST_DURATION);
701 kthread_stop(preader_threads[0]);
702 printk("\n");
703
704 wbias_rwlock_profile_latency_print();
705
706 printk("** Single non-preemptable reader test, no contention **\n");
dac86829 707 wbias_rwlock_profile_latency_reset();
1f5845d5 708 npreader_threads[0] = kthread_run(npreader_thread, (void *)0,
709 "wbiasrwlock_npreader");
710 BUG_ON(!npreader_threads[0]);
68f25f81 711 ssleep(SINGLE_READER_TEST_DURATION);
1f5845d5 712 kthread_stop(npreader_threads[0]);
193771da 713 printk("\n");
68f25f81 714
dac86829 715 wbias_rwlock_profile_latency_print();
716
1f5845d5 717 printk("** Multiple p/non-p readers test, no contention **\n");
dac86829 718 wbias_rwlock_profile_latency_reset();
1f5845d5 719 for (i = 0; i < NR_PREADERS; i++) {
720 printk("starting preader thread %lu\n", i);
721 preader_threads[i] = kthread_run(preader_thread, (void *)i,
722 "wbiasrwlock_preader");
723 BUG_ON(!preader_threads[i]);
724 }
725 for (i = 0; i < NR_NPREADERS; i++) {
726 printk("starting npreader thread %lu\n", i);
727 npreader_threads[i] = kthread_run(npreader_thread, (void *)i,
728 "wbiasrwlock_npreader");
729 BUG_ON(!npreader_threads[i]);
68f25f81 730 }
731 ssleep(SINGLE_READER_TEST_DURATION);
1f5845d5 732 for (i = 0; i < NR_NPREADERS; i++)
733 kthread_stop(npreader_threads[i]);
734 for (i = 0; i < NR_PREADERS; i++)
735 kthread_stop(preader_threads[i]);
193771da 736 printk("\n");
68f25f81 737
dac86829 738 wbias_rwlock_profile_latency_print();
739
68f25f81 740 printk("** High contention test **\n");
dac86829 741 wbias_rwlock_profile_latency_reset();
0e0fdeb6 742 perform_test("wbias-rwlock-create", wbias_rwlock_create);
f36c4112 743 ssleep(TEST_DURATION);
0e0fdeb6 744 perform_test("wbias-rwlock-stop", wbias_rwlock_stop);
193771da 745 printk("\n");
dac86829 746 wbias_rwlock_profile_latency_print();
f0a36bb1 747
748 return -EPERM;
749}
750
751
752static struct file_operations my_operations = {
753 .open = my_open,
754};
755
756int init_module(void)
757{
0e0fdeb6 758 pentry = create_proc_entry("testwbiasrwlock", 0444, NULL);
f0a36bb1 759 if (pentry)
760 pentry->proc_fops = &my_operations;
761
d1f36a28 762 printk("PTHREAD_ROFFSET : %016lX\n", PTHREAD_ROFFSET);
763 printk("PTHREAD_RMASK : %016lX\n", PTHREAD_RMASK);
764 printk("NPTHREAD_ROFFSET : %016lX\n", NPTHREAD_ROFFSET);
765 printk("NPTHREAD_RMASK : %016lX\n", NPTHREAD_RMASK);
766 printk("SOFTIRQ_ROFFSET : %016lX\n", SOFTIRQ_ROFFSET);
767 printk("SOFTIRQ_RMASK : %016lX\n", SOFTIRQ_RMASK);
768 printk("HARDIRQ_ROFFSET : %016lX\n", HARDIRQ_ROFFSET);
769 printk("HARDIRQ_RMASK : %016lX\n", HARDIRQ_RMASK);
770 printk("PTHREAD_WOFFSET : %016lX\n", PTHREAD_WOFFSET);
771 printk("PTHREAD_WMASK : %016lX\n", PTHREAD_WMASK);
772 printk("NPTHREAD_WOFFSET : %016lX\n", NPTHREAD_WOFFSET);
773 printk("NPTHREAD_WMASK : %016lX\n", NPTHREAD_WMASK);
774 printk("WRITER_MUTEX : %016lX\n", WRITER_MUTEX);
775 printk("SOFTIRQ_WMASK : %016lX\n", SOFTIRQ_WMASK);
776 printk("HARDIRQ_WMASK : %016lX\n", HARDIRQ_WMASK);
f0a36bb1 777
778 return 0;
779}
780
781void cleanup_module(void)
782{
0e0fdeb6 783 remove_proc_entry("testwbiasrwlock", NULL);
f0a36bb1 784}
785
786MODULE_LICENSE("GPL");
787MODULE_AUTHOR("Mathieu Desnoyers");
0e0fdeb6 788MODULE_DESCRIPTION("wbias rwlock test");
This page took 0.056493 seconds and 4 git commands to generate.