move everything out of trunk
[lttv.git] / tests / kernel / test-read-lock-speed.c
1 /*
2 * test-read-lock-speed.c
3 *
4 * Compare speed of :
5 * - spin lock / spin unlock
6 * - rwlock read lock
7 * - using a sequence read lock (uncontended)
8 * - preempt disable/enable (RCU)
9 *
10 * Copyright 2009 - Mathieu Desnoyers <mathieu.desnoyers@polymtl.ca>
11 * Distributed under GPLv2
12 */
13
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>
24
25 #ifdef CONFIG_ARM
26 #include <linux/trace-clock.h>
27 #define get_timestamp trace_clock_read64
28 #else
29 #define get_timestamp get_cycles
30 #endif
31
32 #define NR_LOOPS 20000
33
34 #ifndef CONFIG_PREEMPT
35 #error "Your kernel should be built with preemption enabled"
36 #endif
37
38 #ifdef CONFIG_DEBUG_PREEMPT
39 #error "Please disable CONFIG_DEBUG_PREEMPT"
40 #endif
41
42 #ifdef CONFIG_DEBUG_SPINLOCK
43 #error "Please disable CONFIG_DEBUG_SPINLOCK"
44 #endif
45
46 #ifdef CONFIG_LOCKDEP
47 #error "Please disable CONFIG_LOCKDEP"
48 #endif
49
50 int test_val;
51
52 static void do_testbaseline(void)
53 {
54 unsigned long flags;
55 unsigned int i;
56 cycles_t time1, time2, time;
57 u32 rem;
58
59 local_irq_save(flags);
60 preempt_disable();
61 time1 = get_timestamp();
62 for (i = 0; i < NR_LOOPS; i++) {
63 asm volatile ("");
64 }
65 time2 = get_timestamp();
66 local_irq_restore(flags);
67 preempt_enable();
68 time = time2 - time1;
69
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");
76 }
77
78 static void do_test_spinlock(void)
79 {
80 static DEFINE_SPINLOCK(mylock);
81 unsigned long flags;
82 unsigned int i;
83 cycles_t time1, time2, time;
84 u32 rem;
85
86 preempt_disable();
87 spin_lock_irqsave(&mylock, flags);
88 time1 = get_timestamp();
89 for (i = 0; i < NR_LOOPS; i++) {
90 spin_unlock(&mylock);
91 spin_lock(&mylock);
92 }
93 time2 = get_timestamp();
94 spin_unlock_irqrestore(&mylock, flags);
95 preempt_enable();
96 time = time2 - time1;
97
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");
104 }
105
106 static void do_test_read_rwlock(void)
107 {
108 static DEFINE_RWLOCK(mylock);
109 unsigned long flags;
110 unsigned int i;
111 cycles_t time1, time2, time;
112 u32 rem;
113
114 preempt_disable();
115 local_irq_save(flags);
116 read_lock(&mylock);
117 time1 = get_timestamp();
118 for (i = 0; i < NR_LOOPS; i++) {
119 read_unlock(&mylock);
120 read_lock(&mylock);
121 }
122 time2 = get_timestamp();
123 read_unlock(&mylock);
124 local_irq_restore(flags);
125 preempt_enable();
126 time = time2 - time1;
127
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");
134 }
135
136 static void do_test_seqlock(void)
137 {
138 static seqlock_t test_lock;
139 unsigned long seq;
140 unsigned long flags;
141 unsigned int i;
142 cycles_t time1, time2, time;
143 u32 rem;
144
145 local_irq_save(flags);
146 time1 = get_timestamp();
147 for (i = 0; i < NR_LOOPS; i++) {
148 do {
149 seq = read_seqbegin(&test_lock);
150 } while (read_seqretry(&test_lock, seq));
151 }
152 time2 = get_timestamp();
153 time = time2 - time1;
154 local_irq_restore(flags);
155
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");
162 }
163
164 /*
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
168 * care about this.
169 */
170 static void do_test_preempt(void)
171 {
172 unsigned long flags;
173 unsigned int i;
174 cycles_t time1, time2, time;
175 u32 rem;
176
177 local_irq_save(flags);
178 preempt_disable();
179 time1 = get_timestamp();
180 for (i = 0; i < NR_LOOPS; i++) {
181 preempt_disable();
182 preempt_enable();
183 }
184 time2 = get_timestamp();
185 preempt_enable();
186 time = time2 - time1;
187 local_irq_restore(flags);
188
189 printk(KERN_ALERT
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");
197 }
198
199 static int ltt_test_init(void)
200 {
201 printk(KERN_ALERT "test init\n");
202
203 printk(KERN_ALERT "Number of active CPUs : %d\n", num_online_cpus());
204 do_testbaseline();
205 do_test_spinlock();
206 do_test_read_rwlock();
207 do_test_seqlock();
208 do_test_preempt();
209 return -EAGAIN; /* Fail will directly unload the module */
210 }
211
212 static void ltt_test_exit(void)
213 {
214 printk(KERN_ALERT "test exit\n");
215 }
216
217 module_init(ltt_test_init)
218 module_exit(ltt_test_exit)
219
220 MODULE_LICENSE("GPL");
221 MODULE_AUTHOR("Mathieu Desnoyers");
222 MODULE_DESCRIPTION("Test read lock speed");
This page took 0.040924 seconds and 4 git commands to generate.