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