5 #include <linux/module.h>
6 #include <linux/proc_fs.h>
7 #include <linux/sched.h>
8 #include <linux/timex.h>
9 #include <linux/wbias-rwlock.h>
10 #include <linux/kthread.h>
11 #include <linux/delay.h>
12 #include <linux/hardirq.h>
13 #include <linux/module.h>
14 #include <linux/percpu.h>
15 #include <linux/spinlock.h>
16 #include <asm/ptrace.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
30 #define NR_NPREADERS 2
31 #define NR_TRYLOCK_READERS 1
34 * 1 : test standard rwlock
35 * 0 : test wbiasrwlock
37 #define TEST_STD_RWLOCK 0
40 * 1 : test with thread and interrupt readers.
41 * 0 : test only with thread readers.
43 #define TEST_INTERRUPTS 1
46 #define NR_INTERRUPT_READERS 1
47 #define NR_TRYLOCK_INTERRUPT_READERS 1
49 #define NR_INTERRUPT_READERS 0
50 #define NR_TRYLOCK_INTERRUPT_READERS 0
54 * Writer iteration delay, in us. 0 for busy loop. Caution : writers can
57 #define WRITER_DELAY 100
58 #define TRYLOCK_WRITER_DELAY 1000
61 * Number of iterations after which a trylock writer fails.
62 * -1 for infinite loop.
64 #define TRYLOCK_WRITERS_FAIL_ITER 100
66 /* Thread and interrupt reader delay, in ms */
67 #define THREAD_READER_DELAY 0 /* busy loop */
68 #define INTERRUPT_READER_DELAY 100
70 static int var
[NR_VARS
];
71 static struct task_struct
*preader_threads
[NR_PREADERS
];
72 static struct task_struct
*npreader_threads
[NR_NPREADERS
];
73 static struct task_struct
*trylock_reader_threads
[NR_TRYLOCK_READERS
];
74 static struct task_struct
*writer_threads
[NR_WRITERS
];
75 static struct task_struct
*trylock_writer_threads
[NR_TRYLOCK_WRITERS
];
76 static struct task_struct
*interrupt_reader
[NR_INTERRUPT_READERS
];
77 static struct task_struct
*trylock_interrupt_reader
[NR_TRYLOCK_INTERRUPT_READERS
];
81 static DEFINE_RWLOCK(std_rw_lock
);
83 #define wrap_read_lock() read_lock(&std_rw_lock)
84 #define wrap_read_trylock() read_trylock(&std_rw_lock)
85 #define wrap_read_unlock() read_unlock(&std_rw_lock)
87 #define wrap_read_lock_inatomic() read_lock(&std_rw_lock)
88 #define wrap_read_trylock_inatomic() read_trylock(&std_rw_lock)
89 #define wrap_read_unlock_inatomic() read_unlock(&std_rw_lock)
91 #define wrap_read_lock_irq() read_lock(&std_rw_lock)
92 #define wrap_read_trylock_irq() read_trylock(&std_rw_lock)
93 #define wrap_read_unlock_irq() read_unlock(&std_rw_lock)
96 #define wrap_write_lock() write_lock_irq(&std_rw_lock)
97 #define wrap_write_unlock() write_unlock_irq(&std_rw_lock)
99 #define wrap_write_lock() write_lock(&std_rw_lock)
100 #define wrap_write_unlock() write_unlock(&std_rw_lock)
105 static DEFINE_WBIAS_RWLOCK(wbiasrwlock
);
107 #define wrap_read_lock() wbias_read_lock(&wbiasrwlock)
108 #define wrap_read_trylock() wbias_read_trylock(&wbiasrwlock)
109 #define wrap_read_unlock() wbias_read_unlock(&wbiasrwlock)
111 #define wrap_read_lock_inatomic() wbias_read_lock_inatomic(&wbiasrwlock)
112 #define wrap_read_trylock_inatomic() \
113 wbias_read_trylock_inatomic(&wbiasrwlock)
114 #define wrap_read_unlock_inatomic() \
115 wbias_read_unlock_inatomic(&wbiasrwlock)
117 #define wrap_read_lock_irq() wbias_read_lock_irq(&wbiasrwlock)
118 #define wrap_read_trylock_irq() wbias_read_trylock_irq(&wbiasrwlock)
119 #define wrap_read_unlock_irq() wbias_read_unlock_irq(&wbiasrwlock)
121 #if (TEST_INTERRUPTS)
122 #define wrap_write_lock() wbias_write_lock_irq(&wbiasrwlock)
123 #define wrap_write_unlock() wbias_write_unlock_irq(&wbiasrwlock)
125 #define wrap_write_lock() wbias_write_lock(&wbiasrwlock)
126 #define wrap_write_unlock() wbias_write_unlock(&wbiasrwlock)
131 static cycles_t cycles_calibration_min
,
132 cycles_calibration_avg
,
133 cycles_calibration_max
;
135 static inline cycles_t
calibrate_cycles(cycles_t cycles
)
137 return cycles
- cycles_calibration_avg
;
140 struct proc_dir_entry
*pentry
= NULL
;
142 static int p_or_np_reader_thread(const char *typename
,
143 void *data
, int preemptable
)
147 unsigned long iter
= 0;
148 cycles_t time1
, time2
, delay
, delaymax
= 0, delaymin
= ULLONG_MAX
,
151 printk("%s/%lu runnning\n", typename
, (unsigned long)data
);
157 time1
= get_cycles();
161 wrap_read_lock_inatomic();
166 time2
= get_cycles();
168 delay
= time2
- time1
;
169 delaymax
= max(delaymax
, delay
);
170 delaymin
= min(delaymin
, delay
);
173 for (i
= 1; i
< NR_VARS
; i
++) {
177 "Unequal cur %d/prev %d at i %d, iter %lu "
178 "in thread\n", cur
, prev
, i
, iter
);
182 wrap_read_unlock_inatomic();
187 if (THREAD_READER_DELAY
)
188 msleep(THREAD_READER_DELAY
);
189 } while (!kthread_should_stop());
191 printk("%s/%lu iterations : %lu", typename
,
192 (unsigned long)data
, iter
);
195 printk("%s/%lu iterations : %lu, "
196 "lock delay [min,avg,max] %llu,%llu,%llu cycles\n",
198 (unsigned long)data
, iter
,
199 calibrate_cycles(delaymin
),
200 calibrate_cycles(delayavg
),
201 calibrate_cycles(delaymax
));
206 static int preader_thread(void *data
)
208 return p_or_np_reader_thread("preader_thread", data
, 1);
211 static int npreader_thread(void *data
)
213 return p_or_np_reader_thread("npreader_thread", data
, 0);
216 static int trylock_reader_thread(void *data
)
220 unsigned long iter
= 0, success_iter
= 0;
222 printk("trylock_reader_thread/%lu runnning\n", (unsigned long)data
);
224 while (!wrap_read_trylock())
228 for (i
= 1; i
< NR_VARS
; i
++) {
232 "Unequal cur %d/prev %d at i %d, iter %lu "
233 "in thread\n", cur
, prev
, i
, iter
);
236 if (THREAD_READER_DELAY
)
237 msleep(THREAD_READER_DELAY
);
238 } while (!kthread_should_stop());
239 printk("trylock_reader_thread/%lu iterations : %lu, "
240 "successful iterations : %lu\n",
241 (unsigned long)data
, iter
, success_iter
);
245 DEFINE_PER_CPU(cycles_t
, int_delaymin
);
246 DEFINE_PER_CPU(cycles_t
, int_delayavg
);
247 DEFINE_PER_CPU(cycles_t
, int_delaymax
);
248 DEFINE_PER_CPU(cycles_t
, int_ipi_nr
);
250 static void interrupt_reader_ipi(void *data
)
254 cycles_t time1
, time2
;
255 cycles_t
*delaymax
, *delaymin
, *delayavg
, *ipi_nr
, delay
;
258 * Skip the ipi caller, not in irq context.
263 delaymax
= &per_cpu(int_delaymax
, smp_processor_id());
264 delaymin
= &per_cpu(int_delaymin
, smp_processor_id());
265 delayavg
= &per_cpu(int_delayavg
, smp_processor_id());
266 ipi_nr
= &per_cpu(int_ipi_nr
, smp_processor_id());
269 time1
= get_cycles();
272 wrap_read_lock_irq();
275 time2
= get_cycles();
277 delay
= time2
- time1
;
278 *delaymax
= max(*delaymax
, delay
);
279 *delaymin
= min(*delaymin
, delay
);
283 for (i
= 1; i
< NR_VARS
; i
++) {
287 "Unequal cur %d/prev %d at i %d in interrupt\n",
290 wrap_read_unlock_irq();
293 DEFINE_PER_CPU(unsigned long, trylock_int_iter
);
294 DEFINE_PER_CPU(unsigned long, trylock_int_success
);
296 static void trylock_interrupt_reader_ipi(void *data
)
302 * Skip the ipi caller, not in irq context.
307 per_cpu(trylock_int_iter
, smp_processor_id())++;
308 while (!wrap_read_trylock_irq())
309 per_cpu(trylock_int_iter
, smp_processor_id())++;
310 per_cpu(trylock_int_success
, smp_processor_id())++;
312 for (i
= 1; i
< NR_VARS
; i
++) {
316 "Unequal cur %d/prev %d at i %d in interrupt\n",
319 wrap_read_unlock_irq();
323 static int interrupt_reader_thread(void *data
)
325 unsigned long iter
= 0;
328 for_each_online_cpu(i
) {
329 per_cpu(int_delaymax
, i
) = 0;
330 per_cpu(int_delaymin
, i
) = ULLONG_MAX
;
331 per_cpu(int_delayavg
, i
) = 0;
332 per_cpu(int_ipi_nr
, i
) = 0;
336 on_each_cpu(interrupt_reader_ipi
, NULL
, 0);
337 if (INTERRUPT_READER_DELAY
)
338 msleep(INTERRUPT_READER_DELAY
);
339 } while (!kthread_should_stop());
340 printk("interrupt_reader_thread/%lu iterations : %lu\n",
341 (unsigned long)data
, iter
);
342 for_each_online_cpu(i
) {
343 if (!per_cpu(int_ipi_nr
, i
))
345 per_cpu(int_delayavg
, i
) /= per_cpu(int_ipi_nr
, i
);
346 printk("interrupt readers on CPU %i, "
347 "lock delay [min,avg,max] %llu,%llu,%llu cycles\n",
349 calibrate_cycles(per_cpu(int_delaymin
, i
)),
350 calibrate_cycles(per_cpu(int_delayavg
, i
)),
351 calibrate_cycles(per_cpu(int_delaymax
, i
)));
356 static int trylock_interrupt_reader_thread(void *data
)
358 unsigned long iter
= 0;
363 on_each_cpu(trylock_interrupt_reader_ipi
, NULL
, 0);
364 if (INTERRUPT_READER_DELAY
)
365 msleep(INTERRUPT_READER_DELAY
);
366 } while (!kthread_should_stop());
367 printk("trylock_interrupt_reader_thread/%lu iterations : %lu\n",
368 (unsigned long)data
, iter
);
369 for_each_online_cpu(i
) {
370 printk("trylock interrupt readers on CPU %i, "
372 "successful iterations : %lu\n",
373 i
, per_cpu(trylock_int_iter
, i
),
374 per_cpu(trylock_int_success
, i
));
375 per_cpu(trylock_int_iter
, i
) = 0;
376 per_cpu(trylock_int_success
, i
) = 0;
381 static int writer_thread(void *data
)
385 unsigned long iter
= 0;
386 cycles_t time1
, time2
, delay
, delaymax
= 0, delaymin
= ULLONG_MAX
,
389 printk("writer_thread/%lu runnning\n", (unsigned long)data
);
392 //preempt_disable(); /* for get_cycles accuracy */
394 time1
= get_cycles();
400 time2
= get_cycles();
402 delay
= time2
- time1
;
403 delaymax
= max(delaymax
, delay
);
404 delaymin
= min(delaymin
, delay
);
406 new = (int)get_cycles();
407 for (i
= 0; i
< NR_VARS
; i
++) {
413 //preempt_enable(); /* for get_cycles accuracy */
414 if (WRITER_DELAY
> 0)
415 udelay(WRITER_DELAY
);
416 } while (!kthread_should_stop());
418 printk("writer_thread/%lu iterations : %lu, "
419 "lock delay [min,avg,max] %llu,%llu,%llu cycles\n",
420 (unsigned long)data
, iter
,
421 calibrate_cycles(delaymin
),
422 calibrate_cycles(delayavg
),
423 calibrate_cycles(delaymax
));
427 #if (TEST_STD_RWLOCK)
428 static int trylock_writer_thread(void *data
)
432 unsigned long iter
= 0, success
= 0, fail
= 0;
434 printk("trylock_writer_thread/%lu runnning\n", (unsigned long)data
);
436 #if (TEST_INTERRUPTS)
437 /* std write trylock cannot disable interrupts. */
441 #if (TRYLOCK_WRITERS_FAIL_ITER == -1)
444 if (write_trylock(&std_rw_lock
))
448 for (i
= 0; i
< TRYLOCK_WRITERS_FAIL_ITER
; i
++) {
450 if (write_trylock(&std_rw_lock
))
455 #if (TEST_INTERRUPTS)
461 new = (int)get_cycles();
462 for (i
= 0; i
< NR_VARS
; i
++) {
465 #if (TEST_INTERRUPTS)
466 write_unlock_irq(&std_rw_lock
);
468 write_unlock(&std_rw_lock
);
471 if (TRYLOCK_WRITER_DELAY
> 0)
472 udelay(TRYLOCK_WRITER_DELAY
);
473 } while (!kthread_should_stop());
474 printk("trylock_writer_thread/%lu iterations : "
475 "[try,success,fail after %d try], "
477 (unsigned long)data
, TRYLOCK_WRITERS_FAIL_ITER
,
478 iter
, success
, fail
);
482 #else /* !TEST_STD_RWLOCK */
484 static int trylock_writer_thread(void *data
)
488 unsigned long iter
= 0, success
= 0, fail
= 0;
490 printk("trylock_writer_thread/%lu runnning\n", (unsigned long)data
);
493 #if (TEST_INTERRUPTS)
494 if (wbias_write_trylock_irq_else_subscribe(&wbiasrwlock
))
496 if (wbias_write_trylock_else_subscribe(&wbiasrwlock
))
500 #if (TRYLOCK_WRITERS_FAIL_ITER == -1)
503 #if (TEST_INTERRUPTS)
504 if (wbias_write_trylock_irq_subscribed(&wbiasrwlock
))
506 if (wbias_write_trylock_subscribed(&wbiasrwlock
))
511 for (i
= 0; i
< TRYLOCK_WRITERS_FAIL_ITER
- 1; i
++) {
513 #if (TEST_INTERRUPTS)
514 if (wbias_write_trylock_irq_subscribed(&wbiasrwlock
))
516 if (wbias_write_trylock_subscribed(&wbiasrwlock
))
522 wbias_write_unsubscribe(&wbiasrwlock
);
526 new = (int)get_cycles();
527 for (i
= 0; i
< NR_VARS
; i
++) {
530 #if (TEST_INTERRUPTS)
531 wbias_write_unlock_irq(&wbiasrwlock
);
533 wbias_write_unlock(&wbiasrwlock
);
536 if (TRYLOCK_WRITER_DELAY
> 0)
537 udelay(TRYLOCK_WRITER_DELAY
);
538 } while (!kthread_should_stop());
539 printk("trylock_writer_thread/%lu iterations : "
540 "[try,success,fail after %d try], "
542 (unsigned long)data
, TRYLOCK_WRITERS_FAIL_ITER
,
543 iter
, success
, fail
);
547 #endif /* TEST_STD_RWLOCK */
549 static void wbias_rwlock_create(void)
553 for (i
= 0; i
< NR_PREADERS
; i
++) {
554 printk("starting preemptable reader thread %lu\n", i
);
555 preader_threads
[i
] = kthread_run(preader_thread
, (void *)i
,
556 "wbiasrwlock_preader");
557 BUG_ON(!preader_threads
[i
]);
560 for (i
= 0; i
< NR_NPREADERS
; i
++) {
561 printk("starting non-preemptable reader thread %lu\n", i
);
562 npreader_threads
[i
] = kthread_run(npreader_thread
, (void *)i
,
563 "wbiasrwlock_npreader");
564 BUG_ON(!npreader_threads
[i
]);
567 for (i
= 0; i
< NR_TRYLOCK_READERS
; i
++) {
568 printk("starting trylock reader thread %lu\n", i
);
569 trylock_reader_threads
[i
] = kthread_run(trylock_reader_thread
,
570 (void *)i
, "wbiasrwlock_trylock_reader");
571 BUG_ON(!trylock_reader_threads
[i
]);
573 for (i
= 0; i
< NR_INTERRUPT_READERS
; i
++) {
574 printk("starting interrupt reader %lu\n", i
);
575 interrupt_reader
[i
] = kthread_run(interrupt_reader_thread
,
577 "wbiasrwlock_interrupt_reader");
579 for (i
= 0; i
< NR_TRYLOCK_INTERRUPT_READERS
; i
++) {
580 printk("starting trylock interrupt reader %lu\n", i
);
581 trylock_interrupt_reader
[i
] =
582 kthread_run(trylock_interrupt_reader_thread
,
583 (void *)i
, "wbiasrwlock_trylock_interrupt_reader");
585 for (i
= 0; i
< NR_WRITERS
; i
++) {
586 printk("starting writer thread %lu\n", i
);
587 writer_threads
[i
] = kthread_run(writer_thread
, (void *)i
,
588 "wbiasrwlock_writer");
589 BUG_ON(!writer_threads
[i
]);
591 for (i
= 0; i
< NR_TRYLOCK_WRITERS
; i
++) {
592 printk("starting trylock writer thread %lu\n", i
);
593 trylock_writer_threads
[i
] = kthread_run(trylock_writer_thread
,
594 (void *)i
, "wbiasrwlock_trylock_writer");
595 BUG_ON(!trylock_writer_threads
[i
]);
599 static void wbias_rwlock_stop(void)
603 for (i
= 0; i
< NR_WRITERS
; i
++)
604 kthread_stop(writer_threads
[i
]);
605 for (i
= 0; i
< NR_TRYLOCK_WRITERS
; i
++)
606 kthread_stop(trylock_writer_threads
[i
]);
607 for (i
= 0; i
< NR_NPREADERS
; i
++)
608 kthread_stop(npreader_threads
[i
]);
609 for (i
= 0; i
< NR_PREADERS
; i
++)
610 kthread_stop(preader_threads
[i
]);
611 for (i
= 0; i
< NR_TRYLOCK_READERS
; i
++)
612 kthread_stop(trylock_reader_threads
[i
]);
613 for (i
= 0; i
< NR_INTERRUPT_READERS
; i
++)
614 kthread_stop(interrupt_reader
[i
]);
615 for (i
= 0; i
< NR_TRYLOCK_INTERRUPT_READERS
; i
++)
616 kthread_stop(trylock_interrupt_reader
[i
]);
620 static void perform_test(const char *name
, void (*callback
)(void))
622 printk("%s\n", name
);
626 static int my_open(struct inode
*inode
, struct file
*file
)
629 cycles_t time1
, time2
, delay
;
631 printk("** get_cycles calibration **\n");
632 cycles_calibration_min
= ULLONG_MAX
;
633 cycles_calibration_avg
= 0;
634 cycles_calibration_max
= 0;
637 for (i
= 0; i
< 10; i
++) {
639 time1
= get_cycles();
642 time2
= get_cycles();
644 delay
= time2
- time1
;
645 cycles_calibration_min
= min(cycles_calibration_min
, delay
);
646 cycles_calibration_avg
+= delay
;
647 cycles_calibration_max
= max(cycles_calibration_max
, delay
);
649 cycles_calibration_avg
/= 10;
652 printk("get_cycles takes [min,avg,max] %llu,%llu,%llu cycles, "
653 "results calibrated on avg\n",
654 cycles_calibration_min
,
655 cycles_calibration_avg
,
656 cycles_calibration_max
);
659 printk("** Single writer test, no contention **\n");
660 wbias_rwlock_profile_latency_reset();
661 writer_threads
[0] = kthread_run(writer_thread
, (void *)0,
662 "wbiasrwlock_writer");
663 BUG_ON(!writer_threads
[0]);
664 ssleep(SINGLE_WRITER_TEST_DURATION
);
665 kthread_stop(writer_threads
[0]);
668 wbias_rwlock_profile_latency_print();
670 printk("** Single trylock writer test, no contention **\n");
671 wbias_rwlock_profile_latency_reset();
672 trylock_writer_threads
[0] = kthread_run(trylock_writer_thread
,
674 "trylock_wbiasrwlock_writer");
675 BUG_ON(!trylock_writer_threads
[0]);
676 ssleep(SINGLE_WRITER_TEST_DURATION
);
677 kthread_stop(trylock_writer_threads
[0]);
680 wbias_rwlock_profile_latency_print();
682 printk("** Single preemptable reader test, no contention **\n");
683 wbias_rwlock_profile_latency_reset();
684 preader_threads
[0] = kthread_run(preader_thread
, (void *)0,
685 "wbiasrwlock_preader");
686 BUG_ON(!preader_threads
[0]);
687 ssleep(SINGLE_READER_TEST_DURATION
);
688 kthread_stop(preader_threads
[0]);
691 wbias_rwlock_profile_latency_print();
693 printk("** Single non-preemptable reader test, no contention **\n");
694 wbias_rwlock_profile_latency_reset();
695 npreader_threads
[0] = kthread_run(npreader_thread
, (void *)0,
696 "wbiasrwlock_npreader");
697 BUG_ON(!npreader_threads
[0]);
698 ssleep(SINGLE_READER_TEST_DURATION
);
699 kthread_stop(npreader_threads
[0]);
702 wbias_rwlock_profile_latency_print();
704 printk("** Multiple p/non-p readers test, no contention **\n");
705 wbias_rwlock_profile_latency_reset();
706 for (i
= 0; i
< NR_PREADERS
; i
++) {
707 printk("starting preader thread %lu\n", i
);
708 preader_threads
[i
] = kthread_run(preader_thread
, (void *)i
,
709 "wbiasrwlock_preader");
710 BUG_ON(!preader_threads
[i
]);
712 for (i
= 0; i
< NR_NPREADERS
; i
++) {
713 printk("starting npreader thread %lu\n", i
);
714 npreader_threads
[i
] = kthread_run(npreader_thread
, (void *)i
,
715 "wbiasrwlock_npreader");
716 BUG_ON(!npreader_threads
[i
]);
718 ssleep(SINGLE_READER_TEST_DURATION
);
719 for (i
= 0; i
< NR_NPREADERS
; i
++)
720 kthread_stop(npreader_threads
[i
]);
721 for (i
= 0; i
< NR_PREADERS
; i
++)
722 kthread_stop(preader_threads
[i
]);
725 wbias_rwlock_profile_latency_print();
727 printk("** High contention test **\n");
728 wbias_rwlock_profile_latency_reset();
729 perform_test("wbias-rwlock-create", wbias_rwlock_create
);
730 ssleep(TEST_DURATION
);
731 perform_test("wbias-rwlock-stop", wbias_rwlock_stop
);
733 wbias_rwlock_profile_latency_print();
739 static struct file_operations my_operations
= {
743 int init_module(void)
745 pentry
= create_proc_entry("testwbiasrwlock", 0444, NULL
);
747 pentry
->proc_fops
= &my_operations
;
749 printk("PTHREAD_ROFFSET : %lX\n", PTHREAD_ROFFSET
);
750 printk("PTHREAD_RMASK : %lX\n", PTHREAD_RMASK
);
751 printk("NPTHREAD_ROFFSET : %lX\n", NPTHREAD_ROFFSET
);
752 printk("NPTHREAD_RMASK : %lX\n", NPTHREAD_RMASK
);
753 printk("SOFTIRQ_ROFFSET : %lX\n", SOFTIRQ_ROFFSET
);
754 printk("SOFTIRQ_RMASK : %lX\n", SOFTIRQ_RMASK
);
755 printk("HARDIRQ_ROFFSET : %lX\n", HARDIRQ_ROFFSET
);
756 printk("HARDIRQ_RMASK : %lX\n", HARDIRQ_RMASK
);
757 printk("PTHREAD_WOFFSET : %lX\n", PTHREAD_WOFFSET
);
758 printk("PTHREAD_WMASK : %lX\n", PTHREAD_WMASK
);
759 printk("NPTHREAD_WOFFSET : %lX\n", NPTHREAD_WOFFSET
);
760 printk("NPTHREAD_WMASK : %lX\n", NPTHREAD_WMASK
);
761 printk("WRITER_MUTEX : %lX\n", WRITER_MUTEX
);
762 printk("SOFTIRQ_WMASK : %lX\n", SOFTIRQ_WMASK
);
763 printk("HARDIRQ_WMASK : %lX\n", HARDIRQ_WMASK
);
768 void cleanup_module(void)
770 remove_proc_entry("testwbiasrwlock", NULL
);
773 MODULE_LICENSE("GPL");
774 MODULE_AUTHOR("Mathieu Desnoyers");
775 MODULE_DESCRIPTION("wbias rwlock test");