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