2 * test-read-lock-speed.c
5 * - spin lock / spin unlock
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>
26 #include <linux/trace-clock.h>
27 #define get_timestamp trace_clock_read64
29 #define get_timestamp get_cycles
32 #define NR_LOOPS 20000
34 #ifndef CONFIG_PREEMPT
35 #error "Your kernel should be built with preemption enabled"
38 #ifdef CONFIG_DEBUG_PREEMPT
39 #error "Please disable CONFIG_DEBUG_PREEMPT"
42 #ifdef CONFIG_DEBUG_SPINLOCK
43 #error "Please disable CONFIG_DEBUG_SPINLOCK"
47 #error "Please disable CONFIG_LOCKDEP"
52 static void do_testbaseline(void)
56 cycles_t time1
, time2
, time
;
59 local_irq_save(flags
);
61 time1
= get_timestamp();
62 for (i
= 0; i
< NR_LOOPS
; i
++) {
65 time2
= get_timestamp();
66 local_irq_restore(flags
);
70 printk(KERN_ALERT
"test results: time for baseline\n");
71 printk(KERN_ALERT
"number of loops: %d\n", NR_LOOPS
);
72 printk(KERN_ALERT
"total time: %llu\n", (unsigned long long)time
);
73 time
= div_u64_rem(time
, NR_LOOPS
, &rem
);
74 printk(KERN_ALERT
"-> baseline takes %llu cycles\n", (unsigned long long)time
);
75 printk(KERN_ALERT
"test end\n");
78 static void do_test_spinlock(void)
80 static DEFINE_SPINLOCK(mylock
);
83 cycles_t time1
, time2
, time
;
87 spin_lock_irqsave(&mylock
, flags
);
88 time1
= get_timestamp();
89 for (i
= 0; i
< NR_LOOPS
; i
++) {
93 time2
= get_timestamp();
94 spin_unlock_irqrestore(&mylock
, flags
);
98 printk(KERN_ALERT
"test results: time for spinlock\n");
99 printk(KERN_ALERT
"number of loops: %d\n", NR_LOOPS
);
100 printk(KERN_ALERT
"total time: %llu\n", (unsigned long long)time
);
101 time
= div_u64_rem(time
, NR_LOOPS
, &rem
);
102 printk(KERN_ALERT
"-> spinlock takes %llu cycles\n", (unsigned long long)time
);
103 printk(KERN_ALERT
"test end\n");
106 static void do_test_read_rwlock(void)
108 static DEFINE_RWLOCK(mylock
);
111 cycles_t time1
, time2
, time
;
115 local_irq_save(flags
);
117 time1
= get_timestamp();
118 for (i
= 0; i
< NR_LOOPS
; i
++) {
119 read_unlock(&mylock
);
122 time2
= get_timestamp();
123 read_unlock(&mylock
);
124 local_irq_restore(flags
);
126 time
= time2
- time1
;
128 printk(KERN_ALERT
"test results: time for read rwlock\n");
129 printk(KERN_ALERT
"number of loops: %d\n", NR_LOOPS
);
130 printk(KERN_ALERT
"total time: %llu\n", (unsigned long long)time
);
131 time
= div_u64_rem(time
, NR_LOOPS
, &rem
);
132 printk(KERN_ALERT
"-> read rwlock takes %llu cycles\n", (unsigned long long)time
);
133 printk(KERN_ALERT
"test end\n");
136 static void do_test_seqlock(void)
138 static seqlock_t test_lock
;
142 cycles_t time1
, time2
, time
;
145 local_irq_save(flags
);
146 time1
= get_timestamp();
147 for (i
= 0; i
< NR_LOOPS
; i
++) {
149 seq
= read_seqbegin(&test_lock
);
150 } while (read_seqretry(&test_lock
, seq
));
152 time2
= get_timestamp();
153 time
= time2
- time1
;
154 local_irq_restore(flags
);
156 printk(KERN_ALERT
"test results: time for seqlock\n");
157 printk(KERN_ALERT
"number of loops: %d\n", NR_LOOPS
);
158 printk(KERN_ALERT
"total time: %llu\n", (unsigned long long)time
);
159 time
= div_u64_rem(time
, NR_LOOPS
, &rem
);
160 printk(KERN_ALERT
"-> seqlock takes %llu cycles\n", (unsigned long long)time
);
161 printk(KERN_ALERT
"test end\n");
165 * Note : This test _should_ trigger lockdep errors due to preemption
166 * disabling/enabling within irq off section. Given we are only interested in
167 * having the most precise measurement for preemption disable/enable, we don't
170 static void do_test_preempt(void)
174 cycles_t time1
, time2
, time
;
177 local_irq_save(flags
);
179 time1
= get_timestamp();
180 for (i
= 0; i
< NR_LOOPS
; i
++) {
184 time2
= get_timestamp();
186 time
= time2
- time1
;
187 local_irq_restore(flags
);
190 "test results: time for preempt disable/enable pairs\n");
191 printk(KERN_ALERT
"number of loops: %d\n", NR_LOOPS
);
192 printk(KERN_ALERT
"total time: %llu\n", (unsigned long long)time
);
193 time
= div_u64_rem(time
, NR_LOOPS
, &rem
);
194 printk(KERN_ALERT
"-> preempt disable/enable pair takes %llu cycles\n",
195 (unsigned long long)time
);
196 printk(KERN_ALERT
"test end\n");
199 static int ltt_test_init(void)
201 printk(KERN_ALERT
"test init\n");
203 printk(KERN_ALERT
"Number of active CPUs : %d\n", num_online_cpus());
206 do_test_read_rwlock();
209 return -EAGAIN
; /* Fail will directly unload the module */
212 static void ltt_test_exit(void)
214 printk(KERN_ALERT
"test exit\n");
217 module_init(ltt_test_init
)
218 module_exit(ltt_test_exit
)
220 MODULE_LICENSE("GPL");
221 MODULE_AUTHOR("Mathieu Desnoyers");
222 MODULE_DESCRIPTION("Test read lock speed");
This page took 0.089007 seconds and 4 git commands to generate.