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