5 #include <linux/module.h>
6 #include <linux/proc_fs.h>
7 #include <linux/sched.h>
8 #include <linux/timex.h>
9 #include <linux/kthread.h>
10 #include <linux/delay.h>
11 #include <linux/hardirq.h>
12 #include <linux/module.h>
13 #include <linux/percpu.h>
14 #include <linux/spinlock.h>
15 #include <asm/ptrace.h>
16 #include <linux/psrwlock.h>
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
23 /* Test duration, in seconds */
24 #define TEST_DURATION 60
28 #define NR_TRYLOCK_WRITERS 1
29 #define NR_NPREADERS 2
30 #define NR_TRYLOCK_READERS 1
33 * 1 : test standard rwlock
36 #define TEST_STD_RWLOCK 0
39 * 1 : test with thread and interrupt readers.
40 * 0 : test only with thread readers.
42 #define TEST_INTERRUPTS 1
45 #define NR_INTERRUPT_READERS 1
46 #define NR_TRYLOCK_INTERRUPT_READERS 1
48 #define NR_INTERRUPT_READERS 0
49 #define NR_TRYLOCK_INTERRUPT_READERS 0
53 * 1 : test with thread preemption readers.
54 * 0 : test only with non-preemptable thread readers.
56 #define TEST_PREEMPT 1
66 * Writer iteration delay, in us. 0 for busy loop. Caution : writers can
69 #define WRITER_DELAY 100
70 #define TRYLOCK_WRITER_DELAY 1000
73 * Number of iterations after which a trylock writer fails.
74 * -1 for infinite loop.
76 #define TRYLOCK_WRITERS_FAIL_ITER 100
78 /* Thread and interrupt reader delay, in ms */
79 #define THREAD_READER_DELAY 0 /* busy loop */
80 #define INTERRUPT_READER_DELAY 100
83 #define yield_in_non_preempt()
85 #define yield_in_non_preempt() yield()
88 static int var
[NR_VARS
];
89 static struct task_struct
*preader_threads
[NR_PREADERS
];
90 static struct task_struct
*npreader_threads
[NR_NPREADERS
];
91 static struct task_struct
*trylock_reader_threads
[NR_TRYLOCK_READERS
];
92 static struct task_struct
*writer_threads
[NR_WRITERS
];
93 static struct task_struct
*trylock_writer_threads
[NR_TRYLOCK_WRITERS
];
94 static struct task_struct
*interrupt_reader
[NR_INTERRUPT_READERS
];
95 static struct task_struct
*trylock_interrupt_reader
[NR_TRYLOCK_INTERRUPT_READERS
];
99 static DEFINE_RWLOCK(std_rw_lock
);
101 #define wrap_read_lock() read_lock(&std_rw_lock)
102 #define wrap_read_trylock() read_trylock(&std_rw_lock)
103 #define wrap_read_unlock() read_unlock(&std_rw_lock)
105 #define wrap_read_lock_inatomic() read_lock(&std_rw_lock)
106 #define wrap_read_trylock_inatomic() read_trylock(&std_rw_lock)
108 #define wrap_read_lock_irq() read_lock(&std_rw_lock)
109 #define wrap_read_trylock_irq() read_trylock(&std_rw_lock)
111 #if (TEST_INTERRUPTS)
112 #define wrap_write_lock() write_lock_irq(&std_rw_lock)
113 #define wrap_write_unlock() write_unlock_irq(&std_rw_lock)
115 #define wrap_write_lock() write_lock(&std_rw_lock)
116 #define wrap_write_unlock() write_unlock(&std_rw_lock)
119 #define wrap_write_trylock() write_trylock(&std_rw_lock)
123 #if (TEST_INTERRUPTS)
125 #define PSRWLOCKWCTX PSRW_PRIO_P
126 #define PSRWLOCKRCTX (PSR_IRQ | PSR_NPTHREAD | PSR_PTHREAD)
128 #define PSRWLOCKWCTX PSRW_PRIO_NP
129 #define PSRWLOCKRCTX (PSR_IRQ | PSR_NPTHREAD)
133 #define PSRWLOCKWCTX PSRW_PRIO_P
134 #define PSRWLOCKRCTX (PSR_NPTHREAD | PSR_PTHREAD)
136 #define PSRWLOCKWCTX PSRW_PRIO_NP
137 #define PSRWLOCKRCTX (PSR_NPTHREAD)
141 static DEFINE_PSRWLOCK(psrwlock
, PSRWLOCKWCTX
, PSRWLOCKRCTX
);
142 CHECK_PSRWLOCK_MAP(psrwlock
, PSRWLOCKWCTX
, PSRWLOCKRCTX
);
146 #define wrap_read_lock() \
147 psread_lock(&psrwlock, PSRWLOCKWCTX, PSRWLOCKRCTX)
148 #define wrap_read_trylock() \
149 psread_trylock(&psrwlock, PSRWLOCKWCTX, PSRWLOCKRCTX)
151 #define wrap_read_lock() \
152 psread_lock_inatomic(&psrwlock, PSRWLOCKWCTX, PSRWLOCKRCTX)
153 #define wrap_read_trylock() \
154 psread_trylock_inatomic(&psrwlock, PSRWLOCKWCTX, PSRWLOCKRCTX)
156 #define wrap_read_unlock() \
157 psread_unlock(&psrwlock, PSRWLOCKWCTX, PSRWLOCKRCTX)
159 #define wrap_read_lock_inatomic() \
160 psread_lock_inatomic(&psrwlock, PSRWLOCKWCTX, PSRWLOCKRCTX)
161 #define wrap_read_trylock_inatomic() \
162 psread_trylock_inatomic(&psrwlock, PSRWLOCKWCTX, PSRWLOCKRCTX)
164 #define wrap_read_lock_irq() \
165 psread_lock_irq(&psrwlock, PSRWLOCKWCTX, PSRWLOCKRCTX)
166 #define wrap_read_trylock_irq() \
167 psread_trylock_irq(&psrwlock, PSRWLOCKWCTX, PSRWLOCKRCTX)
169 #define wrap_write_lock() \
170 pswrite_lock(&psrwlock, PSRWLOCKWCTX, PSRWLOCKRCTX)
171 #define wrap_write_unlock() \
172 pswrite_unlock(&psrwlock, PSRWLOCKWCTX, PSRWLOCKRCTX)
173 #define wrap_write_trylock() \
174 pswrite_trylock(&psrwlock, PSRWLOCKWCTX, PSRWLOCKRCTX)
178 static cycles_t cycles_calibration_min
,
179 cycles_calibration_avg
,
180 cycles_calibration_max
;
182 static inline cycles_t
calibrate_cycles(cycles_t cycles
)
184 return cycles
- cycles_calibration_avg
;
187 struct proc_dir_entry
*pentry
= NULL
;
189 static int p_or_np_reader_thread(const char *typename
,
190 void *data
, int preemptable
)
194 unsigned long iter
= 0;
195 cycles_t time1
, time2
, delay
;
196 cycles_t ldelaymax
= 0, ldelaymin
= ULLONG_MAX
, ldelayavg
= 0;
197 cycles_t udelaymax
= 0, udelaymin
= ULLONG_MAX
, udelayavg
= 0;
199 printk("%s/%lu runnning\n", typename
, (unsigned long)data
);
205 time1
= get_cycles();
209 wrap_read_lock_inatomic();
214 time2
= get_cycles();
216 delay
= time2
- time1
;
217 ldelaymax
= max(ldelaymax
, delay
);
218 ldelaymin
= min(ldelaymin
, delay
);
221 for (i
= 1; i
< NR_VARS
; i
++) {
225 "Unequal cur %d/prev %d at i %d, iter %lu "
226 "in reader thread\n",
232 time1
= get_cycles();
238 time2
= get_cycles();
240 delay
= time2
- time1
;
241 udelaymax
= max(udelaymax
, delay
);
242 udelaymin
= min(udelaymin
, delay
);
248 if (THREAD_READER_DELAY
)
249 msleep(THREAD_READER_DELAY
);
250 yield_in_non_preempt();
251 } while (!kthread_should_stop());
253 printk("%s/%lu iterations : %lu", typename
,
254 (unsigned long)data
, iter
);
258 printk("%s/%lu iterations : %lu, "
259 "lock delay [min,avg,max] %llu,%llu,%llu cycles\n",
261 (unsigned long)data
, iter
,
262 calibrate_cycles(ldelaymin
),
263 calibrate_cycles(ldelayavg
),
264 calibrate_cycles(ldelaymax
));
265 printk("%s/%lu iterations : %lu, "
266 "unlock delay [min,avg,max] %llu,%llu,%llu cycles\n",
268 (unsigned long)data
, iter
,
269 calibrate_cycles(udelaymin
),
270 calibrate_cycles(udelayavg
),
271 calibrate_cycles(udelaymax
));
276 static int preader_thread(void *data
)
278 return p_or_np_reader_thread("preader_thread", data
, 1);
281 static int npreader_thread(void *data
)
283 return p_or_np_reader_thread("npreader_thread", data
, 0);
286 static int trylock_reader_thread(void *data
)
290 unsigned long iter
= 0, success_iter
= 0;
292 printk("trylock_reader_thread/%lu runnning\n", (unsigned long)data
);
297 while (!wrap_read_trylock()) {
303 for (i
= 1; i
< NR_VARS
; i
++) {
307 "Unequal cur %d/prev %d at i %d, iter %lu "
308 "in trylock reader thread\n",
316 if (THREAD_READER_DELAY
)
317 msleep(THREAD_READER_DELAY
);
318 yield_in_non_preempt();
319 } while (!kthread_should_stop());
320 printk("trylock_reader_thread/%lu iterations : %lu, "
321 "successful iterations : %lu\n",
322 (unsigned long)data
, iter
+ success_iter
, success_iter
);
326 DEFINE_PER_CPU(cycles_t
, int_ldelaymin
);
327 DEFINE_PER_CPU(cycles_t
, int_ldelayavg
);
328 DEFINE_PER_CPU(cycles_t
, int_ldelaymax
);
329 DEFINE_PER_CPU(cycles_t
, int_udelaymin
);
330 DEFINE_PER_CPU(cycles_t
, int_udelayavg
);
331 DEFINE_PER_CPU(cycles_t
, int_udelaymax
);
332 DEFINE_PER_CPU(cycles_t
, int_ipi_nr
);
334 static void interrupt_reader_ipi(void *data
)
338 cycles_t time1
, time2
;
339 cycles_t
*ldelaymax
, *ldelaymin
, *ldelayavg
, *ipi_nr
, delay
;
340 cycles_t
*udelaymax
, *udelaymin
, *udelayavg
;
343 * Skip the ipi caller, not in irq context.
348 ldelaymax
= &per_cpu(int_ldelaymax
, smp_processor_id());
349 ldelaymin
= &per_cpu(int_ldelaymin
, smp_processor_id());
350 ldelayavg
= &per_cpu(int_ldelayavg
, smp_processor_id());
351 udelaymax
= &per_cpu(int_udelaymax
, smp_processor_id());
352 udelaymin
= &per_cpu(int_udelaymin
, smp_processor_id());
353 udelayavg
= &per_cpu(int_udelayavg
, smp_processor_id());
354 ipi_nr
= &per_cpu(int_ipi_nr
, smp_processor_id());
357 time1
= get_cycles();
360 wrap_read_lock_irq();
363 time2
= get_cycles();
365 delay
= time2
- time1
;
366 *ldelaymax
= max(*ldelaymax
, delay
);
367 *ldelaymin
= min(*ldelaymin
, delay
);
371 for (i
= 1; i
< NR_VARS
; i
++) {
375 "Unequal cur %d/prev %d at i %d in interrupt\n",
379 time1
= get_cycles();
382 time2
= get_cycles();
384 delay
= time2
- time1
;
385 *udelaymax
= max(*udelaymax
, delay
);
386 *udelaymin
= min(*udelaymin
, delay
);
390 DEFINE_PER_CPU(unsigned long, trylock_int_iter
);
391 DEFINE_PER_CPU(unsigned long, trylock_int_success
);
393 static void trylock_interrupt_reader_ipi(void *data
)
399 * Skip the ipi caller, not in irq context.
404 per_cpu(trylock_int_iter
, smp_processor_id())++;
405 while (!wrap_read_trylock_irq())
406 per_cpu(trylock_int_iter
, smp_processor_id())++;
407 per_cpu(trylock_int_success
, smp_processor_id())++;
409 for (i
= 1; i
< NR_VARS
; i
++) {
413 "Unequal cur %d/prev %d at i %d in interrupt\n",
420 static int interrupt_reader_thread(void *data
)
422 unsigned long iter
= 0;
425 for_each_online_cpu(i
) {
426 per_cpu(int_ldelaymax
, i
) = 0;
427 per_cpu(int_ldelaymin
, i
) = ULLONG_MAX
;
428 per_cpu(int_ldelayavg
, i
) = 0;
429 per_cpu(int_udelaymax
, i
) = 0;
430 per_cpu(int_udelaymin
, i
) = ULLONG_MAX
;
431 per_cpu(int_udelayavg
, i
) = 0;
432 per_cpu(int_ipi_nr
, i
) = 0;
436 on_each_cpu(interrupt_reader_ipi
, NULL
, 0);
437 if (INTERRUPT_READER_DELAY
)
438 msleep(INTERRUPT_READER_DELAY
);
439 yield_in_non_preempt();
440 } while (!kthread_should_stop());
441 printk("interrupt_reader_thread/%lu iterations : %lu\n",
442 (unsigned long)data
, iter
);
443 for_each_online_cpu(i
) {
444 if (!per_cpu(int_ipi_nr
, i
))
446 per_cpu(int_ldelayavg
, i
) /= per_cpu(int_ipi_nr
, i
);
447 per_cpu(int_udelayavg
, i
) /= per_cpu(int_ipi_nr
, i
);
448 printk("interrupt readers on CPU %i, "
449 "lock delay [min,avg,max] %llu,%llu,%llu cycles\n",
451 calibrate_cycles(per_cpu(int_ldelaymin
, i
)),
452 calibrate_cycles(per_cpu(int_ldelayavg
, i
)),
453 calibrate_cycles(per_cpu(int_ldelaymax
, i
)));
454 printk("interrupt readers on CPU %i, "
455 "unlock delay [min,avg,max] %llu,%llu,%llu cycles\n",
457 calibrate_cycles(per_cpu(int_udelaymin
, i
)),
458 calibrate_cycles(per_cpu(int_udelayavg
, i
)),
459 calibrate_cycles(per_cpu(int_udelaymax
, i
)));
464 static int trylock_interrupt_reader_thread(void *data
)
466 unsigned long iter
= 0;
471 on_each_cpu(trylock_interrupt_reader_ipi
, NULL
, 0);
472 if (INTERRUPT_READER_DELAY
)
473 msleep(INTERRUPT_READER_DELAY
);
474 yield_in_non_preempt();
475 } while (!kthread_should_stop());
476 printk("trylock_interrupt_reader_thread/%lu iterations : %lu\n",
477 (unsigned long)data
, iter
);
478 for_each_online_cpu(i
) {
479 printk("trylock interrupt readers on CPU %i, "
481 "successful iterations : %lu\n",
482 i
, per_cpu(trylock_int_iter
, i
),
483 per_cpu(trylock_int_success
, i
));
484 per_cpu(trylock_int_iter
, i
) = 0;
485 per_cpu(trylock_int_success
, i
) = 0;
490 static int writer_thread(void *data
)
494 unsigned long iter
= 0;
495 cycles_t time1
, time2
, delay
;
496 cycles_t ldelaymax
= 0, ldelaymin
= ULLONG_MAX
, ldelayavg
= 0;
497 cycles_t udelaymax
= 0, udelaymin
= ULLONG_MAX
, udelayavg
= 0;
499 printk("writer_thread/%lu runnning\n", (unsigned long)data
);
506 time1
= get_cycles();
512 time2
= get_cycles();
514 delay
= time2
- time1
;
515 ldelaymax
= max(ldelaymax
, delay
);
516 ldelaymin
= min(ldelaymin
, delay
);
519 * Read the previous values, check that they are coherent.
522 for (i
= 1; i
< NR_VARS
; i
++) {
526 "Unequal cur %d/prev %d at i %d, iter %lu "
527 "in writer thread\n",
530 new = (int)get_cycles();
531 for (i
= 0; i
< NR_VARS
; i
++) {
536 time1
= get_cycles();
542 time2
= get_cycles();
544 delay
= time2
- time1
;
545 udelaymax
= max(udelaymax
, delay
);
546 udelaymin
= min(udelaymin
, delay
);
552 if (WRITER_DELAY
> 0)
553 udelay(WRITER_DELAY
);
555 * make sure we don't busy-loop faster than
556 * the lock busy-loop, it would cause reader and
559 yield_in_non_preempt();
560 } while (!kthread_should_stop());
563 printk("writer_thread/%lu iterations : %lu, "
564 "lock delay [min,avg,max] %llu,%llu,%llu cycles\n",
565 (unsigned long)data
, iter
,
566 calibrate_cycles(ldelaymin
),
567 calibrate_cycles(ldelayavg
),
568 calibrate_cycles(ldelaymax
));
569 printk("writer_thread/%lu iterations : %lu, "
570 "unlock delay [min,avg,max] %llu,%llu,%llu cycles\n",
571 (unsigned long)data
, iter
,
572 calibrate_cycles(udelaymin
),
573 calibrate_cycles(udelayavg
),
574 calibrate_cycles(udelaymax
));
578 static int trylock_writer_thread(void *data
)
582 unsigned long iter
= 0, success
= 0, fail
= 0;
584 printk("trylock_writer_thread/%lu runnning\n", (unsigned long)data
);
586 #if ((!TEST_PREEMPT) && (!TEST_STD_RWLOCK))
590 #if (TEST_STD_RWLOCK && TEST_INTERRUPTS)
591 /* std write trylock cannot disable interrupts. */
595 #if (TRYLOCK_WRITERS_FAIL_ITER == -1)
598 if (wrap_write_trylock())
603 for (i
= 0; i
< TRYLOCK_WRITERS_FAIL_ITER
; i
++) {
605 if (wrap_write_trylock())
612 #if (TEST_STD_RWLOCK && TEST_INTERRUPTS)
616 #if ((!TEST_PREEMPT) && (!TEST_STD_RWLOCK))
622 new = (int)get_cycles();
623 for (i
= 0; i
< NR_VARS
; i
++) {
627 #if ((!TEST_PREEMPT) && (!TEST_STD_RWLOCK))
631 if (TRYLOCK_WRITER_DELAY
> 0)
632 udelay(TRYLOCK_WRITER_DELAY
);
634 * make sure we don't busy-loop faster than
635 * the lock busy-loop, it would cause reader and
638 yield_in_non_preempt();
639 } while (!kthread_should_stop());
640 printk("trylock_writer_thread/%lu iterations : "
641 "[try,success,fail after %d try], "
643 (unsigned long)data
, TRYLOCK_WRITERS_FAIL_ITER
,
644 iter
, success
, fail
);
648 static void psrwlock_create(void)
652 for (i
= 0; i
< NR_PREADERS
; i
++) {
653 printk("starting preemptable reader thread %lu\n", i
);
654 preader_threads
[i
] = kthread_run(preader_thread
, (void *)i
,
656 BUG_ON(!preader_threads
[i
]);
659 for (i
= 0; i
< NR_NPREADERS
; i
++) {
660 printk("starting non-preemptable reader thread %lu\n", i
);
661 npreader_threads
[i
] = kthread_run(npreader_thread
, (void *)i
,
662 "psrwlock_npreader");
663 BUG_ON(!npreader_threads
[i
]);
666 for (i
= 0; i
< NR_TRYLOCK_READERS
; i
++) {
667 printk("starting trylock reader thread %lu\n", i
);
668 trylock_reader_threads
[i
] = kthread_run(trylock_reader_thread
,
669 (void *)i
, "psrwlock_trylock_reader");
670 BUG_ON(!trylock_reader_threads
[i
]);
672 for (i
= 0; i
< NR_INTERRUPT_READERS
; i
++) {
673 printk("starting interrupt reader %lu\n", i
);
674 interrupt_reader
[i
] = kthread_run(interrupt_reader_thread
,
676 "psrwlock_interrupt_reader");
678 for (i
= 0; i
< NR_TRYLOCK_INTERRUPT_READERS
; i
++) {
679 printk("starting trylock interrupt reader %lu\n", i
);
680 trylock_interrupt_reader
[i
] =
681 kthread_run(trylock_interrupt_reader_thread
,
682 (void *)i
, "psrwlock_trylock_interrupt_reader");
684 for (i
= 0; i
< NR_WRITERS
; i
++) {
685 printk("starting writer thread %lu\n", i
);
686 writer_threads
[i
] = kthread_run(writer_thread
, (void *)i
,
688 BUG_ON(!writer_threads
[i
]);
690 for (i
= 0; i
< NR_TRYLOCK_WRITERS
; i
++) {
691 printk("starting trylock writer thread %lu\n", i
);
692 trylock_writer_threads
[i
] = kthread_run(trylock_writer_thread
,
693 (void *)i
, "psrwlock_trylock_writer");
694 BUG_ON(!trylock_writer_threads
[i
]);
698 static void psrwlock_stop(void)
702 for (i
= 0; i
< NR_WRITERS
; i
++)
703 kthread_stop(writer_threads
[i
]);
704 for (i
= 0; i
< NR_TRYLOCK_WRITERS
; i
++)
705 kthread_stop(trylock_writer_threads
[i
]);
706 for (i
= 0; i
< NR_NPREADERS
; i
++)
707 kthread_stop(npreader_threads
[i
]);
708 for (i
= 0; i
< NR_PREADERS
; i
++)
709 kthread_stop(preader_threads
[i
]);
710 for (i
= 0; i
< NR_TRYLOCK_READERS
; i
++)
711 kthread_stop(trylock_reader_threads
[i
]);
712 for (i
= 0; i
< NR_INTERRUPT_READERS
; i
++)
713 kthread_stop(interrupt_reader
[i
]);
714 for (i
= 0; i
< NR_TRYLOCK_INTERRUPT_READERS
; i
++)
715 kthread_stop(trylock_interrupt_reader
[i
]);
719 static void perform_test(const char *name
, void (*callback
)(void))
721 printk("%s\n", name
);
725 static int my_open(struct inode
*inode
, struct file
*file
)
728 cycles_t time1
, time2
, delay
;
730 printk("** get_cycles calibration **\n");
731 cycles_calibration_min
= ULLONG_MAX
;
732 cycles_calibration_avg
= 0;
733 cycles_calibration_max
= 0;
736 for (i
= 0; i
< 10; i
++) {
738 time1
= get_cycles();
741 time2
= get_cycles();
743 delay
= time2
- time1
;
744 cycles_calibration_min
= min(cycles_calibration_min
, delay
);
745 cycles_calibration_avg
+= delay
;
746 cycles_calibration_max
= max(cycles_calibration_max
, delay
);
748 cycles_calibration_avg
/= 10;
751 printk("get_cycles takes [min,avg,max] %llu,%llu,%llu cycles, "
752 "results calibrated on avg\n",
753 cycles_calibration_min
,
754 cycles_calibration_avg
,
755 cycles_calibration_max
);
759 printk("** Single writer test, no contention **\n");
760 psrwlock_profile_latency_reset();
761 writer_threads
[0] = kthread_run(writer_thread
, (void *)0,
763 BUG_ON(!writer_threads
[0]);
764 ssleep(SINGLE_WRITER_TEST_DURATION
);
765 kthread_stop(writer_threads
[0]);
768 psrwlock_profile_latency_print();
771 #if (NR_TRYLOCK_WRITERS)
772 printk("** Single trylock writer test, no contention **\n");
773 psrwlock_profile_latency_reset();
774 trylock_writer_threads
[0] = kthread_run(trylock_writer_thread
,
776 "trylock_psrwlock_writer");
777 BUG_ON(!trylock_writer_threads
[0]);
778 ssleep(SINGLE_WRITER_TEST_DURATION
);
779 kthread_stop(trylock_writer_threads
[0]);
782 psrwlock_profile_latency_print();
786 printk("** Single preemptable reader test, no contention **\n");
787 psrwlock_profile_latency_reset();
788 preader_threads
[0] = kthread_run(preader_thread
, (void *)0,
790 BUG_ON(!preader_threads
[0]);
791 ssleep(SINGLE_READER_TEST_DURATION
);
792 kthread_stop(preader_threads
[0]);
795 psrwlock_profile_latency_print();
798 printk("** Single non-preemptable reader test, no contention **\n");
799 psrwlock_profile_latency_reset();
800 npreader_threads
[0] = kthread_run(npreader_thread
, (void *)0,
801 "psrwlock_npreader");
802 BUG_ON(!npreader_threads
[0]);
803 ssleep(SINGLE_READER_TEST_DURATION
);
804 kthread_stop(npreader_threads
[0]);
807 psrwlock_profile_latency_print();
809 printk("** Multiple p/non-p readers test, no contention **\n");
810 psrwlock_profile_latency_reset();
812 for (i
= 0; i
< NR_PREADERS
; i
++) {
813 printk("starting preader thread %lu\n", i
);
814 preader_threads
[i
] = kthread_run(preader_thread
, (void *)i
,
816 BUG_ON(!preader_threads
[i
]);
819 for (i
= 0; i
< NR_NPREADERS
; i
++) {
820 printk("starting npreader thread %lu\n", i
);
821 npreader_threads
[i
] = kthread_run(npreader_thread
, (void *)i
,
822 "psrwlock_npreader");
823 BUG_ON(!npreader_threads
[i
]);
825 ssleep(SINGLE_READER_TEST_DURATION
);
826 for (i
= 0; i
< NR_NPREADERS
; i
++)
827 kthread_stop(npreader_threads
[i
]);
829 for (i
= 0; i
< NR_PREADERS
; i
++)
830 kthread_stop(preader_threads
[i
]);
834 psrwlock_profile_latency_print();
836 printk("** High contention test **\n");
837 psrwlock_profile_latency_reset();
838 perform_test("psrwlock-create", psrwlock_create
);
839 ssleep(TEST_DURATION
);
840 perform_test("psrwlock-stop", psrwlock_stop
);
842 psrwlock_profile_latency_print();
848 static struct file_operations my_operations
= {
852 int init_module(void)
854 pentry
= create_proc_entry("testpsrwlock", 0444, NULL
);
856 pentry
->proc_fops
= &my_operations
;
858 printk("UC_READER_MASK : %08X\n", UC_READER_MASK
);
859 printk("UC_HARDIRQ_R_MASK: %08X\n", UC_HARDIRQ_READER_MASK
);
860 printk("UC_SOFTIRQ_R_MASK: %08X\n", UC_SOFTIRQ_READER_MASK
);
861 printk("UC_NPTHREA_R_MASK: %08X\n", UC_NPTHREAD_READER_MASK
);
862 printk("UC_PTHREAD_R_MASK: %08X\n", UC_PTHREAD_READER_MASK
);
863 printk("UC_WRITER : %08X\n", UC_WRITER
);
864 printk("UC_SLOW_WRITER : %08X\n", UC_SLOW_WRITER
);
865 printk("UC_WQ_ACTIVE : %08X\n", UC_WQ_ACTIVE
);
866 printk("WS_MASK : %08X\n", WS_MASK
);
867 printk("WS_WQ_MUTEX : %08X\n", WS_WQ_MUTEX
);
868 printk("WS_COUNT_MUTEX : %08X\n", WS_COUNT_MUTEX
);
869 printk("WS_LOCK_MUTEX : %08X\n", WS_LOCK_MUTEX
);
870 printk("CTX_RMASK : %016lX\n", CTX_RMASK
);
871 printk("CTX_WMASK : %016lX\n", CTX_WMASK
);
876 void cleanup_module(void)
878 remove_proc_entry("testpsrwlock", NULL
);
881 MODULE_LICENSE("GPL");
882 MODULE_AUTHOR("Mathieu Desnoyers");
883 MODULE_DESCRIPTION("psrwlock test");