2 * test-read-lock-speed.c
5 * - spin lock / spin unlock
6 * - rwlock read lock (not disabling interrupts, can deal with nesting)
7 * - using a sequence read lock (uncontended)
8 * - preempt disable/enable (RCU)
10 * Copyright 2009 - Mathieu Desnoyers <mathieu.desnoyers@polymtl.ca>
11 * Distributed under GPLv2
14 #include <linux/jiffies.h>
15 #include <linux/compiler.h>
16 #include <linux/init.h>
17 #include <linux/module.h>
18 #include <linux/math64.h>
19 #include <linux/spinlock.h>
20 #include <linux/seqlock.h>
21 #include <linux/cpumask.h>
22 #include <asm/timex.h>
23 #include <asm/system.h>
25 #define NR_LOOPS 20000
27 #ifndef CONFIG_PREEMPT
28 #error "Your kernel should be built with preemption enabled"
31 #ifdef CONFIG_DEBUG_PREEMPT
32 #error "Please disable CONFIG_DEBUG_PREEMPT"
35 #ifdef CONFIG_DEBUG_SPINLOCK
36 #error "Please disable CONFIG_DEBUG_SPINLOCK"
40 #error "Please disable CONFIG_LOCKDEP"
45 static void do_testbaseline(void)
49 cycles_t time1
, time2
, time
;
52 local_irq_save(flags
);
55 for (i
= 0; i
< NR_LOOPS
; i
++) {
59 local_irq_restore(flags
);
63 printk(KERN_ALERT
"test results: time for baseline\n");
64 printk(KERN_ALERT
"number of loops: %d\n", NR_LOOPS
);
65 printk(KERN_ALERT
"total time: %llu\n", time
);
66 time
= div_u64_rem(time
, NR_LOOPS
, &rem
);
67 printk(KERN_ALERT
"-> baseline takes %llu cycles\n", time
);
68 printk(KERN_ALERT
"test end\n");
71 static void do_test_spinlock(void)
73 static DEFINE_SPINLOCK(mylock
);
76 cycles_t time1
, time2
, time
;
80 spin_lock_irqsave(&mylock
, flags
);
82 for (i
= 0; i
< NR_LOOPS
; i
++) {
87 spin_unlock_irqrestore(&mylock
, flags
);
91 printk(KERN_ALERT
"test results: time for spinlock\n");
92 printk(KERN_ALERT
"number of loops: %d\n", NR_LOOPS
);
93 printk(KERN_ALERT
"total time: %llu\n", time
);
94 time
= div_u64_rem(time
, NR_LOOPS
, &rem
);
95 printk(KERN_ALERT
"-> spinlock takes %llu cycles\n", time
);
96 printk(KERN_ALERT
"test end\n");
99 static void do_test_read_rwlock(void)
101 static DEFINE_RWLOCK(mylock
);
104 cycles_t time1
, time2
, time
;
108 local_irq_save(flags
);
110 time1
= get_cycles();
111 for (i
= 0; i
< NR_LOOPS
; i
++) {
112 read_unlock(&mylock
);
115 time2
= get_cycles();
116 read_unlock(&mylock
);
117 local_irq_restore(flags
);
119 time
= time2
- time1
;
121 printk(KERN_ALERT
"test results: time for read rwlock\n");
122 printk(KERN_ALERT
"number of loops: %d\n", NR_LOOPS
);
123 printk(KERN_ALERT
"total time: %llu\n", time
);
124 time
= div_u64_rem(time
, NR_LOOPS
, &rem
);
125 printk(KERN_ALERT
"-> read rwlock takes %llu cycles\n", time
);
126 printk(KERN_ALERT
"test end\n");
129 static void do_test_seqlock(void)
131 static seqlock_t test_lock
;
135 cycles_t time1
, time2
, time
;
138 local_irq_save(flags
);
139 time1
= get_cycles();
140 for (i
= 0; i
< NR_LOOPS
; i
++) {
142 seq
= read_seqbegin(&test_lock
);
143 } while (read_seqretry(&test_lock
, seq
));
145 time2
= get_cycles();
146 time
= time2
- time1
;
147 local_irq_restore(flags
);
149 printk(KERN_ALERT
"test results: time for seqlock\n");
150 printk(KERN_ALERT
"number of loops: %d\n", NR_LOOPS
);
151 printk(KERN_ALERT
"total time: %llu\n", time
);
152 time
= div_u64_rem(time
, NR_LOOPS
, &rem
);
153 printk(KERN_ALERT
"-> seqlock takes %llu cycles\n", time
);
154 printk(KERN_ALERT
"test end\n");
158 * Note : This test _should_ trigger lockdep errors due to preemption
159 * disabling/enabling within irq off section. Given we are only interested in
160 * having the most precise measurement for preemption disable/enable, we don't
163 static void do_test_preempt(void)
167 cycles_t time1
, time2
, time
;
170 local_irq_save(flags
);
172 time1
= get_cycles();
173 for (i
= 0; i
< NR_LOOPS
; i
++) {
177 time2
= get_cycles();
179 time
= time2
- time1
;
180 local_irq_restore(flags
);
183 "test results: time for preempt disable/enable pairs\n");
184 printk(KERN_ALERT
"number of loops: %d\n", NR_LOOPS
);
185 printk(KERN_ALERT
"total time: %llu\n", time
);
186 time
= div_u64_rem(time
, NR_LOOPS
, &rem
);
187 printk(KERN_ALERT
"-> preempt disable/enable pair takes %llu cycles\n",
189 printk(KERN_ALERT
"test end\n");
192 static int ltt_test_init(void)
194 printk(KERN_ALERT
"test init\n");
196 printk(KERN_ALERT
"Number of active CPUs : %d\n", num_online_cpus());
199 do_test_read_rwlock();
202 return -EAGAIN
; /* Fail will directly unload the module */
205 static void ltt_test_exit(void)
207 printk(KERN_ALERT
"test exit\n");
210 module_init(ltt_test_init
)
211 module_exit(ltt_test_exit
)
213 MODULE_LICENSE("GPL");
214 MODULE_AUTHOR("Mathieu Desnoyers");
215 MODULE_DESCRIPTION("Test read lock speed");
This page took 0.03385 seconds and 5 git commands to generate.