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