update rwlock
[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
6bc6dad3 6 * - rwlock read lock (not disabling interrupts, can deal with nesting)
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
25#define NR_LOOPS 20000
26
6087c592 27#ifndef CONFIG_PREEMPT
28289207 28#error "Your kernel should be built with preemption enabled"
6087c592 29#endif
30
31#ifdef CONFIG_DEBUG_PREEMPT
32#error "Please disable CONFIG_DEBUG_PREEMPT"
33#endif
34
35#ifdef CONFIG_DEBUG_SPINLOCK
36#error "Please disable CONFIG_DEBUG_SPINLOCK"
37#endif
38
39#ifdef CONFIG_LOCKDEP
40#error "Please disable CONFIG_LOCKDEP"
41#endif
42
3343768e 43int test_val;
44
45static void do_testbaseline(void)
46{
6087c592 47 unsigned long flags;
3343768e 48 unsigned int i;
49 cycles_t time1, time2, time;
6087c592 50 u32 rem;
3343768e 51
52 local_irq_save(flags);
53 preempt_disable();
54 time1 = get_cycles();
55 for (i = 0; i < NR_LOOPS; i++) {
56 asm volatile ("");
57 }
58 time2 = get_cycles();
59 local_irq_restore(flags);
60 preempt_enable();
61 time = time2 - time1;
62
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);
6087c592 66 time = div_u64_rem(time, NR_LOOPS, &rem);
3343768e 67 printk(KERN_ALERT "-> baseline takes %llu cycles\n", time);
68 printk(KERN_ALERT "test end\n");
69}
70
71static void do_test_spinlock(void)
72{
8593c315 73 static DEFINE_SPINLOCK(mylock);
6087c592 74 unsigned long flags;
3343768e 75 unsigned int i;
76 cycles_t time1, time2, time;
6087c592 77 u32 rem;
3343768e 78
79 preempt_disable();
8593c315 80 spin_lock_irqsave(&mylock, flags);
3343768e 81 time1 = get_cycles();
82 for (i = 0; i < NR_LOOPS; i++) {
0c12e051 83 spin_unlock(&mylock);
84 spin_lock(&mylock);
3343768e 85 }
86 time2 = get_cycles();
8593c315 87 spin_unlock_irqrestore(&mylock, flags);
3343768e 88 preempt_enable();
89 time = time2 - time1;
90
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);
6087c592 94 time = div_u64_rem(time, NR_LOOPS, &rem);
3343768e 95 printk(KERN_ALERT "-> spinlock takes %llu cycles\n", time);
96 printk(KERN_ALERT "test end\n");
97}
98
6bc6dad3 99static void do_test_read_rwlock(void)
100{
101 static DEFINE_RWLOCK(mylock);
102 unsigned long flags;
103 unsigned int i;
104 cycles_t time1, time2, time;
105 u32 rem;
106
107 preempt_disable();
108 local_irq_save(flags);
109 read_lock(&mylock);
110 time1 = get_cycles();
111 for (i = 0; i < NR_LOOPS; i++) {
112 read_unlock(&mylock);
113 read_lock(&mylock);
114 }
115 time2 = get_cycles();
116 read_unlock(&mylock);
117 local_irq_restore(flags);
118 preempt_enable();
119 time = time2 - time1;
120
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");
127}
128
3343768e 129static void do_test_seqlock(void)
130{
131 static seqlock_t test_lock;
8593c315 132 unsigned long seq;
6087c592 133 unsigned long flags;
3343768e 134 unsigned int i;
135 cycles_t time1, time2, time;
6087c592 136 u32 rem;
3343768e 137
472e3e15 138 local_irq_save(flags);
3343768e 139 time1 = get_cycles();
140 for (i = 0; i < NR_LOOPS; i++) {
141 do {
472e3e15 142 seq = read_seqbegin(&test_lock);
143 } while (read_seqretry(&test_lock, seq));
3343768e 144 }
145 time2 = get_cycles();
3343768e 146 time = time2 - time1;
472e3e15 147 local_irq_restore(flags);
3343768e 148
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);
6087c592 152 time = div_u64_rem(time, NR_LOOPS, &rem);
3343768e 153 printk(KERN_ALERT "-> seqlock takes %llu cycles\n", time);
154 printk(KERN_ALERT "test end\n");
155}
156
157/*
6087c592 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
161 * care about this.
3343768e 162 */
163static void do_test_preempt(void)
164{
6087c592 165 unsigned long flags;
3343768e 166 unsigned int i;
167 cycles_t time1, time2, time;
6087c592 168 u32 rem;
3343768e 169
170 local_irq_save(flags);
171 preempt_disable();
172 time1 = get_cycles();
173 for (i = 0; i < NR_LOOPS; i++) {
3343768e 174 preempt_disable();
54e7c224 175 preempt_enable();
3343768e 176 }
177 time2 = get_cycles();
178 preempt_enable();
179 time = time2 - time1;
180 local_irq_restore(flags);
181
f7d26a17 182 printk(KERN_ALERT
183 "test results: time for preempt disable/enable pairs\n");
3343768e 184 printk(KERN_ALERT "number of loops: %d\n", NR_LOOPS);
185 printk(KERN_ALERT "total time: %llu\n", time);
6087c592 186 time = div_u64_rem(time, NR_LOOPS, &rem);
3343768e 187 printk(KERN_ALERT "-> preempt disable/enable pair takes %llu cycles\n",
188 time);
189 printk(KERN_ALERT "test end\n");
190}
191
192static int ltt_test_init(void)
193{
194 printk(KERN_ALERT "test init\n");
195
6087c592 196 printk(KERN_ALERT "Number of active CPUs : %d\n", num_online_cpus());
3343768e 197 do_testbaseline();
198 do_test_spinlock();
6bc6dad3 199 do_test_read_rwlock();
3343768e 200 do_test_seqlock();
201 do_test_preempt();
202 return -EAGAIN; /* Fail will directly unload the module */
203}
204
205static void ltt_test_exit(void)
206{
207 printk(KERN_ALERT "test exit\n");
208}
209
210module_init(ltt_test_init)
211module_exit(ltt_test_exit)
212
213MODULE_LICENSE("GPL");
214MODULE_AUTHOR("Mathieu Desnoyers");
f7d26a17 215MODULE_DESCRIPTION("Test read lock speed");
This page took 0.036019 seconds and 4 git commands to generate.