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