convert from svn repository: remove tags directory
[lttv.git] / trunk / tests / kernel / test-read-lock-speed.c
CommitLineData
f7d26a17 1/*
2 * test-read-lock-speed.c
3343768e 3 *
6087c592 4 * Compare speed of :
1b485a14 5 * - spin lock / spin unlock
fe207500 6 * - rwlock read lock
6087c592 7 * - using a sequence read lock (uncontended)
f7d26a17 8 * - preempt disable/enable (RCU)
9 *
10 * Copyright 2009 - Mathieu Desnoyers <mathieu.desnoyers@polymtl.ca>
11 * Distributed under GPLv2
3343768e 12 */
13
3343768e 14#include <linux/jiffies.h>
15#include <linux/compiler.h>
16#include <linux/init.h>
17#include <linux/module.h>
6087c592 18#include <linux/math64.h>
8593c315 19#include <linux/spinlock.h>
20#include <linux/seqlock.h>
6087c592 21#include <linux/cpumask.h>
3343768e 22#include <asm/timex.h>
23#include <asm/system.h>
24
9c1292db 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
3343768e 32#define NR_LOOPS 20000
33
6087c592 34#ifndef CONFIG_PREEMPT
28289207 35#error "Your kernel should be built with preemption enabled"
6087c592 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
3343768e 50int test_val;
51
52static void do_testbaseline(void)
53{
6087c592 54 unsigned long flags;
3343768e 55 unsigned int i;
56 cycles_t time1, time2, time;
6087c592 57 u32 rem;
3343768e 58
59 local_irq_save(flags);
60 preempt_disable();
9c1292db 61 time1 = get_timestamp();
3343768e 62 for (i = 0; i < NR_LOOPS; i++) {
63 asm volatile ("");
64 }
9c1292db 65 time2 = get_timestamp();
3343768e 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);
bc918f0f 72 printk(KERN_ALERT "total time: %llu\n", (unsigned long long)time);
6087c592 73 time = div_u64_rem(time, NR_LOOPS, &rem);
bc918f0f 74 printk(KERN_ALERT "-> baseline takes %llu cycles\n", (unsigned long long)time);
3343768e 75 printk(KERN_ALERT "test end\n");
76}
77
78static void do_test_spinlock(void)
79{
8593c315 80 static DEFINE_SPINLOCK(mylock);
6087c592 81 unsigned long flags;
3343768e 82 unsigned int i;
83 cycles_t time1, time2, time;
6087c592 84 u32 rem;
3343768e 85
86 preempt_disable();
8593c315 87 spin_lock_irqsave(&mylock, flags);
9c1292db 88 time1 = get_timestamp();
3343768e 89 for (i = 0; i < NR_LOOPS; i++) {
0c12e051 90 spin_unlock(&mylock);
91 spin_lock(&mylock);
3343768e 92 }
9c1292db 93 time2 = get_timestamp();
8593c315 94 spin_unlock_irqrestore(&mylock, flags);
3343768e 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);
bc918f0f 100 printk(KERN_ALERT "total time: %llu\n", (unsigned long long)time);
6087c592 101 time = div_u64_rem(time, NR_LOOPS, &rem);
bc918f0f 102 printk(KERN_ALERT "-> spinlock takes %llu cycles\n", (unsigned long long)time);
3343768e 103 printk(KERN_ALERT "test end\n");
104}
105
6bc6dad3 106static 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);
9c1292db 117 time1 = get_timestamp();
6bc6dad3 118 for (i = 0; i < NR_LOOPS; i++) {
119 read_unlock(&mylock);
120 read_lock(&mylock);
121 }
9c1292db 122 time2 = get_timestamp();
6bc6dad3 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);
bc918f0f 130 printk(KERN_ALERT "total time: %llu\n", (unsigned long long)time);
6bc6dad3 131 time = div_u64_rem(time, NR_LOOPS, &rem);
bc918f0f 132 printk(KERN_ALERT "-> read rwlock takes %llu cycles\n", (unsigned long long)time);
6bc6dad3 133 printk(KERN_ALERT "test end\n");
134}
135
3343768e 136static void do_test_seqlock(void)
137{
138 static seqlock_t test_lock;
8593c315 139 unsigned long seq;
6087c592 140 unsigned long flags;
3343768e 141 unsigned int i;
142 cycles_t time1, time2, time;
6087c592 143 u32 rem;
3343768e 144
472e3e15 145 local_irq_save(flags);
9c1292db 146 time1 = get_timestamp();
3343768e 147 for (i = 0; i < NR_LOOPS; i++) {
148 do {
472e3e15 149 seq = read_seqbegin(&test_lock);
150 } while (read_seqretry(&test_lock, seq));
3343768e 151 }
9c1292db 152 time2 = get_timestamp();
3343768e 153 time = time2 - time1;
472e3e15 154 local_irq_restore(flags);
3343768e 155
156 printk(KERN_ALERT "test results: time for seqlock\n");
157 printk(KERN_ALERT "number of loops: %d\n", NR_LOOPS);
bc918f0f 158 printk(KERN_ALERT "total time: %llu\n", (unsigned long long)time);
6087c592 159 time = div_u64_rem(time, NR_LOOPS, &rem);
bc918f0f 160 printk(KERN_ALERT "-> seqlock takes %llu cycles\n", (unsigned long long)time);
3343768e 161 printk(KERN_ALERT "test end\n");
162}
163
164/*
6087c592 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.
3343768e 169 */
170static void do_test_preempt(void)
171{
6087c592 172 unsigned long flags;
3343768e 173 unsigned int i;
174 cycles_t time1, time2, time;
6087c592 175 u32 rem;
3343768e 176
177 local_irq_save(flags);
178 preempt_disable();
9c1292db 179 time1 = get_timestamp();
3343768e 180 for (i = 0; i < NR_LOOPS; i++) {
3343768e 181 preempt_disable();
54e7c224 182 preempt_enable();
3343768e 183 }
9c1292db 184 time2 = get_timestamp();
3343768e 185 preempt_enable();
186 time = time2 - time1;
187 local_irq_restore(flags);
188
f7d26a17 189 printk(KERN_ALERT
190 "test results: time for preempt disable/enable pairs\n");
3343768e 191 printk(KERN_ALERT "number of loops: %d\n", NR_LOOPS);
bc918f0f 192 printk(KERN_ALERT "total time: %llu\n", (unsigned long long)time);
6087c592 193 time = div_u64_rem(time, NR_LOOPS, &rem);
3343768e 194 printk(KERN_ALERT "-> preempt disable/enable pair takes %llu cycles\n",
bc918f0f 195 (unsigned long long)time);
3343768e 196 printk(KERN_ALERT "test end\n");
197}
198
199static int ltt_test_init(void)
200{
201 printk(KERN_ALERT "test init\n");
202
6087c592 203 printk(KERN_ALERT "Number of active CPUs : %d\n", num_online_cpus());
3343768e 204 do_testbaseline();
205 do_test_spinlock();
6bc6dad3 206 do_test_read_rwlock();
3343768e 207 do_test_seqlock();
208 do_test_preempt();
209 return -EAGAIN; /* Fail will directly unload the module */
210}
211
212static void ltt_test_exit(void)
213{
214 printk(KERN_ALERT "test exit\n");
215}
216
217module_init(ltt_test_init)
218module_exit(ltt_test_exit)
219
220MODULE_LICENSE("GPL");
221MODULE_AUTHOR("Mathieu Desnoyers");
f7d26a17 222MODULE_DESCRIPTION("Test read lock speed");
This page took 0.037121 seconds and 4 git commands to generate.