update test module
[lttv.git] / trunk / tests / kernel / test-read-lock-speed.c
1 /*
2 * test-read-lock-speed.c
3 *
4 * Compare speed of :
5 * - spin lock irqsave / spin unlock irqrestore (close to rwlocks when
6 * uncontended)
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 #define NR_LOOPS 20000
26
27 #ifndef CONFIG_PREEMPT
28 #error "Your kernel should be build with preemption enabled"
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
43 int test_val;
44
45 static void do_testbaseline(void)
46 {
47 unsigned long flags;
48 unsigned int i;
49 cycles_t time1, time2, time;
50 u32 rem;
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);
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");
69 }
70
71 static void do_test_spinlock(void)
72 {
73 static DEFINE_SPINLOCK(mylock);
74 unsigned long flags;
75 unsigned int i;
76 cycles_t time1, time2, time;
77 u32 rem;
78
79 preempt_disable();
80 spin_lock_irqsave(&mylock, flags);
81 time1 = get_cycles();
82 for (i = 0; i < NR_LOOPS; i++) {
83 spin_unlock(&mylock);
84 spin_lock(&mylock);
85 }
86 time2 = get_cycles();
87 spin_unlock_irqrestore(&mylock, flags);
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);
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");
97 }
98
99 static void do_test_seqlock(void)
100 {
101 static seqlock_t test_lock;
102 unsigned long seq;
103 unsigned long flags;
104 unsigned int i;
105 cycles_t time1, time2, time;
106 u32 rem;
107
108 local_irq_save(flags);
109 time1 = get_cycles();
110 for (i = 0; i < NR_LOOPS; i++) {
111 do {
112 seq = read_seqbegin(&test_lock);
113 } while (read_seqretry(&test_lock, seq));
114 }
115 time2 = get_cycles();
116 time = time2 - time1;
117 local_irq_restore(flags);
118
119 printk(KERN_ALERT "test results: time for seqlock\n");
120 printk(KERN_ALERT "number of loops: %d\n", NR_LOOPS);
121 printk(KERN_ALERT "total time: %llu\n", time);
122 time = div_u64_rem(time, NR_LOOPS, &rem);
123 printk(KERN_ALERT "-> seqlock takes %llu cycles\n", time);
124 printk(KERN_ALERT "test end\n");
125 }
126
127 /*
128 * Note : This test _should_ trigger lockdep errors due to preemption
129 * disabling/enabling within irq off section. Given we are only interested in
130 * having the most precise measurement for preemption disable/enable, we don't
131 * care about this.
132 */
133 static void do_test_preempt(void)
134 {
135 unsigned long flags;
136 unsigned int i;
137 cycles_t time1, time2, time;
138 u32 rem;
139
140 local_irq_save(flags);
141 preempt_disable();
142 time1 = get_cycles();
143 for (i = 0; i < NR_LOOPS; i++) {
144 preempt_disable();
145 preempt_enable();
146 }
147 time2 = get_cycles();
148 preempt_enable();
149 time = time2 - time1;
150 local_irq_restore(flags);
151
152 printk(KERN_ALERT
153 "test results: time for preempt disable/enable pairs\n");
154 printk(KERN_ALERT "number of loops: %d\n", NR_LOOPS);
155 printk(KERN_ALERT "total time: %llu\n", time);
156 time = div_u64_rem(time, NR_LOOPS, &rem);
157 printk(KERN_ALERT "-> preempt disable/enable pair takes %llu cycles\n",
158 time);
159 printk(KERN_ALERT "test end\n");
160 }
161
162 static int ltt_test_init(void)
163 {
164 printk(KERN_ALERT "test init\n");
165
166 printk(KERN_ALERT "Number of active CPUs : %d\n", num_online_cpus());
167 do_testbaseline();
168 do_test_spinlock();
169 do_test_seqlock();
170 do_test_preempt();
171 return -EAGAIN; /* Fail will directly unload the module */
172 }
173
174 static void ltt_test_exit(void)
175 {
176 printk(KERN_ALERT "test exit\n");
177 }
178
179 module_init(ltt_test_init)
180 module_exit(ltt_test_exit)
181
182 MODULE_LICENSE("GPL");
183 MODULE_AUTHOR("Mathieu Desnoyers");
184 MODULE_DESCRIPTION("Test read lock speed");
This page took 0.031882 seconds and 4 git commands to generate.