update test
[lttv.git] / trunk / tests / kernel / test-fair-rwlock.c
1 /* test-fair-rwlock.c
2 *
3 */
4
5 #include <linux/module.h>
6 #include <linux/proc_fs.h>
7 #include <linux/sched.h>
8 #include <linux/timex.h>
9 #include <linux/fair-rwlock.h>
10 #include <linux/kthread.h>
11 #include <linux/delay.h>
12 #include <linux/hardirq.h>
13 #include <linux/module.h>
14 #include <linux/percpu.h>
15 #include <asm/ptrace.h>
16
17 #if (NR_CPUS > 64 && (BITS_PER_LONG == 32 || NR_CPUS > 32768))
18 #error "fair rwlock needs more bits per long to deal with that many CPUs"
19 #endif
20
21 /* Test duration, in seconds */
22 #define TEST_DURATION 60
23
24 #define THREAD_ROFFSET 1UL
25 #define THREAD_RMASK ((NR_CPUS - 1) * THREAD_ROFFSET)
26 #define SOFTIRQ_ROFFSET (THREAD_RMASK + 1)
27 #define SOFTIRQ_RMASK ((NR_CPUS - 1) * SOFTIRQ_ROFFSET)
28 #define HARDIRQ_ROFFSET ((SOFTIRQ_RMASK | THREAD_RMASK) + 1)
29 #define HARDIRQ_RMASK ((NR_CPUS - 1) * HARDIRQ_ROFFSET)
30
31 #define SUBSCRIBERS_WOFFSET \
32 ((HARDIRQ_RMASK | SOFTIRQ_RMASK | THREAD_RMASK) + 1)
33 #define SUBSCRIBERS_WMASK \
34 ((NR_CPUS - 1) * SUBSCRIBERS_WOFFSET)
35 #define WRITER_MUTEX \
36 ((SUBSCRIBERS_WMASK | HARDIRQ_RMASK | SOFTIRQ_RMASK | THREAD_RMASK) + 1)
37 #define SOFTIRQ_WMASK (WRITER_MUTEX << 1)
38 #define SOFTIRQ_WOFFSET SOFTIRQ_WMASK
39 #define HARDIRQ_WMASK (SOFTIRQ_WMASK << 1)
40 #define HARDIRQ_WOFFSET HARDIRQ_WMASK
41
42 #define NR_VARS 100
43 #define NR_WRITERS 3
44 #define NR_READERS 6
45 #define NR_INTERRUPT_READERS 2
46
47 /* Writer iteration delay, in ms. 0 for busy loop. */
48 #define WRITER_DELAY 0
49
50 static int var[NR_VARS];
51 static struct task_struct *reader_threads[NR_READERS];
52 static struct task_struct *writer_threads[NR_WRITERS];
53 static struct task_struct *interrupt_reader;
54
55 static struct fair_rwlock frwlock = {
56 .value = ATOMIC_LONG_INIT(0),
57 };
58
59 struct proc_dir_entry *pentry = NULL;
60
61 static int reader_thread(void *data)
62 {
63 int i;
64 int prev, cur;
65 unsigned long iter = 0;
66 cycles_t time1, time2, delaymax = 0;
67
68 printk("reader_thread/%lu runnning\n", (unsigned long)data);
69 do {
70 iter++;
71 preempt_disable(); /* for get_cycles accuracy */
72 time1 = get_cycles();
73 fair_read_lock(&frwlock);
74 time2 = get_cycles();
75 delaymax = max(delaymax, time2 - time1);
76 prev = var[0];
77 for (i = 1; i < NR_VARS; i++) {
78 cur = var[i];
79 if (cur != prev)
80 printk(KERN_ALERT
81 "Unequal cur %d/prev %d at i %d, iter %lu "
82 "in thread\n", cur, prev, i, iter);
83 }
84 fair_read_unlock(&frwlock);
85 preempt_enable(); /* for get_cycles accuracy */
86 //msleep(100);
87 } while (!kthread_should_stop());
88 printk("reader_thread/%lu iterations : %lu, "
89 "max contention %llu cycles\n",
90 (unsigned long)data, iter, delaymax);
91 return 0;
92 }
93
94 DEFINE_PER_CPU(cycles_t, int_delaymax);
95
96 static void interrupt_reader_ipi(void *data)
97 {
98 int i;
99 int prev, cur;
100 cycles_t time1, time2;
101 cycles_t *delaymax;
102
103 /*
104 * Skip the ipi caller, not in irq context.
105 */
106 if (!in_irq())
107 return;
108
109 delaymax = &per_cpu(int_delaymax, smp_processor_id());
110 time1 = get_cycles();
111 fair_read_lock(&frwlock);
112 time2 = get_cycles();
113 *delaymax = max(*delaymax, time2 - time1);
114 prev = var[0];
115 for (i = 1; i < NR_VARS; i++) {
116 cur = var[i];
117 if (cur != prev)
118 printk(KERN_ALERT
119 "Unequal cur %d/prev %d at i %d in interrupt\n",
120 cur, prev, i);
121 }
122 fair_read_unlock(&frwlock);
123 }
124
125 static int interrupt_reader_thread(void *data)
126 {
127 unsigned long iter = 0;
128 int i;
129
130 do {
131 iter++;
132 on_each_cpu(interrupt_reader_ipi, NULL, 0);
133 msleep(100);
134 } while (!kthread_should_stop());
135 printk("interrupt_reader_thread/%lu iterations : %lu\n",
136 (unsigned long)data, iter);
137 for_each_online_cpu(i) {
138 printk("interrupt readers on CPU %i, "
139 "max contention : %llu cycles\n",
140 i, per_cpu(int_delaymax, i));
141 }
142 return 0;
143 }
144
145 static int writer_thread(void *data)
146 {
147 int i;
148 int new;
149 unsigned long iter = 0;
150 cycles_t time1, time2, delaymax = 0;
151
152 printk("writer_thread/%lu runnning\n", (unsigned long)data);
153 do {
154 iter++;
155 preempt_disable(); /* for get_cycles accuracy */
156 time1 = get_cycles();
157 fair_write_lock_irq(&frwlock);
158 //fair_write_lock(&frwlock);
159 time2 = get_cycles();
160 delaymax = max(delaymax, time2 - time1);
161 new = (int)get_cycles();
162 for (i = 0; i < NR_VARS; i++) {
163 var[i] = new;
164 }
165 //fair_write_unlock(&frwlock);
166 fair_write_unlock_irq(&frwlock);
167 preempt_enable(); /* for get_cycles accuracy */
168 if (WRITER_DELAY > 0)
169 msleep(WRITER_DELAY);
170 } while (!kthread_should_stop());
171 printk("writer_thread/%lu iterations : %lu, "
172 "max contention %llu cycles\n",
173 (unsigned long)data, iter, delaymax);
174 return 0;
175 }
176
177 static void fair_rwlock_create(void)
178 {
179 unsigned long i;
180
181 for (i = 0; i < NR_READERS; i++) {
182 printk("starting reader thread %lu\n", i);
183 reader_threads[i] = kthread_run(reader_thread, (void *)i,
184 "frwlock_reader");
185 BUG_ON(!reader_threads[i]);
186 }
187
188 printk("starting interrupt reader %lu\n", i);
189 interrupt_reader = kthread_run(interrupt_reader_thread, NULL,
190 "frwlock_interrupt_reader");
191
192 for (i = 0; i < NR_WRITERS; i++) {
193 printk("starting writer thread %lu\n", i);
194 writer_threads[i] = kthread_run(writer_thread, (void *)i,
195 "frwlock_writer");
196 BUG_ON(!writer_threads[i]);
197 }
198 }
199
200 static void fair_rwlock_stop(void)
201 {
202 unsigned long i;
203
204 for (i = 0; i < NR_WRITERS; i++) {
205 kthread_stop(writer_threads[i]);
206 }
207
208 for (i = 0; i < NR_READERS; i++) {
209 kthread_stop(reader_threads[i]);
210 }
211
212 kthread_stop(interrupt_reader);
213 }
214
215
216 static void perform_test(const char *name, void (*callback)(void))
217 {
218 printk("%s\n", name);
219 callback();
220 }
221
222 static int my_open(struct inode *inode, struct file *file)
223 {
224 perform_test("fair-rwlock-create", fair_rwlock_create);
225 ssleep(TEST_DURATION);
226 perform_test("fair-rwlock-stop", fair_rwlock_stop);
227
228 return -EPERM;
229 }
230
231
232 static struct file_operations my_operations = {
233 .open = my_open,
234 };
235
236 int init_module(void)
237 {
238 pentry = create_proc_entry("testfrwlock", 0444, NULL);
239 if (pentry)
240 pentry->proc_fops = &my_operations;
241
242 printk("NR_CPUS : %d\n", NR_CPUS);
243 printk("THREAD_ROFFSET : %lX\n", THREAD_ROFFSET);
244 printk("THREAD_RMASK : %lX\n", THREAD_RMASK);
245 printk("SOFTIRQ_ROFFSET : %lX\n", SOFTIRQ_ROFFSET);
246 printk("SOFTIRQ_RMASK : %lX\n", SOFTIRQ_RMASK);
247 printk("HARDIRQ_ROFFSET : %lX\n", HARDIRQ_ROFFSET);
248 printk("HARDIRQ_RMASK : %lX\n", HARDIRQ_RMASK);
249 printk("SUBSCRIBERS_WOFFSET : %lX\n", SUBSCRIBERS_WOFFSET);
250 printk("SUBSCRIBERS_WMASK : %lX\n", SUBSCRIBERS_WMASK);
251 printk("WRITER_MUTEX : %lX\n", WRITER_MUTEX);
252 printk("SOFTIRQ_WMASK : %lX\n", SOFTIRQ_WMASK);
253 printk("HARDIRQ_WMASK : %lX\n", HARDIRQ_WMASK);
254
255 return 0;
256 }
257
258 void cleanup_module(void)
259 {
260 remove_proc_entry("testfrwlock", NULL);
261 }
262
263 MODULE_LICENSE("GPL");
264 MODULE_AUTHOR("Mathieu Desnoyers");
265 MODULE_DESCRIPTION("Fair rwlock test");
This page took 0.052268 seconds and 5 git commands to generate.