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
89889f86 21/* Test duration, in seconds */
22#define TEST_DURATION 600
23
f0a36bb1 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
7f563886 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
426d6b67 39#define HARDIRQ_WMASK (SOFTIRQ_WMASK << 1)
7f563886 40#define HARDIRQ_WOFFSET HARDIRQ_WMASK
f0a36bb1 41
42#define NR_VARS 100
43#define NR_WRITERS 3
44#define NR_READERS 6
45#define NR_INTERRUPT_READERS 2
46
89889f86 47/* Writer iteration delay, in ms. 0 for busy loop. */
48#define WRITER_DELAY 1
49
f0a36bb1 50static int var[NR_VARS];
51static struct task_struct *reader_threads[NR_READERS];
52static struct task_struct *writer_threads[NR_WRITERS];
53static struct task_struct *interrupt_reader;
54
55static struct fair_rwlock frwlock = {
56 .value = ATOMIC_LONG_INIT(0),
f0a36bb1 57};
58
59struct proc_dir_entry *pentry = NULL;
60
61static int reader_thread(void *data)
62{
63 int i;
64 int prev, cur;
65 unsigned long iter = 0;
7f563886 66 cycles_t time1, time2, delaymax = 0;
f0a36bb1 67
68 printk("reader_thread/%lu runnning\n", (unsigned long)data);
69 do {
70 iter++;
7f563886 71 preempt_disable(); /* for get_cycles accuracy */
72 time1 = get_cycles();
f0a36bb1 73 fair_read_lock(&frwlock);
7f563886 74 time2 = get_cycles();
75 delaymax = max(delaymax, time2 - time1);
f0a36bb1 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);
7f563886 85 preempt_enable(); /* for get_cycles accuracy */
f0a36bb1 86 //msleep(100);
87 } while (!kthread_should_stop());
7f563886 88 printk("reader_thread/%lu iterations : %lu, "
89 "max contention %llu cycles\n",
90 (unsigned long)data, iter, delaymax);
f0a36bb1 91 return 0;
92}
93
7f563886 94DEFINE_PER_CPU(cycles_t, int_delaymax);
95
f0a36bb1 96static void interrupt_reader_ipi(void *data)
97{
98 int i;
99 int prev, cur;
7f563886 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;
f0a36bb1 108
7f563886 109 delaymax = &per_cpu(int_delaymax, smp_processor_id());
110 time1 = get_cycles();
f0a36bb1 111 fair_read_lock(&frwlock);
7f563886 112 time2 = get_cycles();
113 *delaymax = max(*delaymax, time2 - time1);
f0a36bb1 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
125static int interrupt_reader_thread(void *data)
126{
127 unsigned long iter = 0;
7f563886 128 int i;
129
f0a36bb1 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);
7f563886 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 }
f0a36bb1 142 return 0;
143}
144
145static int writer_thread(void *data)
146{
147 int i;
148 int new;
149 unsigned long iter = 0;
7f563886 150 cycles_t time1, time2, delaymax = 0;
f0a36bb1 151
152 printk("writer_thread/%lu runnning\n", (unsigned long)data);
153 do {
154 iter++;
7f563886 155 preempt_disable(); /* for get_cycles accuracy */
156 time1 = get_cycles();
f0a36bb1 157 fair_write_lock_irq(&frwlock);
158 //fair_write_lock(&frwlock);
7f563886 159 time2 = get_cycles();
160 delaymax = max(delaymax, time2 - time1);
f0a36bb1 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);
7f563886 167 preempt_enable(); /* for get_cycles accuracy */
89889f86 168 if (WRITER_DELAY > 0)
169 msleep(WRITER_DELAY);
f0a36bb1 170 } while (!kthread_should_stop());
7f563886 171 printk("writer_thread/%lu iterations : %lu, "
172 "max contention %llu cycles\n",
173 (unsigned long)data, iter, delaymax);
f0a36bb1 174 return 0;
175}
176
177static 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
200static void fair_rwlock_stop(void)
201{
202 unsigned long i;
203
7f563886 204 for (i = 0; i < NR_WRITERS; i++) {
205 kthread_stop(writer_threads[i]);
206 }
207
f0a36bb1 208 for (i = 0; i < NR_READERS; i++) {
209 kthread_stop(reader_threads[i]);
210 }
211
7f563886 212 kthread_stop(interrupt_reader);
f0a36bb1 213}
214
215
216static void perform_test(const char *name, void (*callback)(void))
217{
218 printk("%s\n", name);
219 callback();
220}
221
222static int my_open(struct inode *inode, struct file *file)
223{
224 perform_test("fair-rwlock-create", fair_rwlock_create);
89889f86 225 ssleep(600);
f0a36bb1 226 perform_test("fair-rwlock-stop", fair_rwlock_stop);
227
228 return -EPERM;
229}
230
231
232static struct file_operations my_operations = {
233 .open = my_open,
234};
235
236int 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);
f0a36bb1 245 printk("SOFTIRQ_ROFFSET : %lX\n", SOFTIRQ_ROFFSET);
246 printk("SOFTIRQ_RMASK : %lX\n", SOFTIRQ_RMASK);
f0a36bb1 247 printk("HARDIRQ_ROFFSET : %lX\n", HARDIRQ_ROFFSET);
248 printk("HARDIRQ_RMASK : %lX\n", HARDIRQ_RMASK);
7f563886 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);
f0a36bb1 253 printk("HARDIRQ_WMASK : %lX\n", HARDIRQ_WMASK);
254
255 return 0;
256}
257
258void cleanup_module(void)
259{
260 remove_proc_entry("testfrwlock", NULL);
261}
262
263MODULE_LICENSE("GPL");
264MODULE_AUTHOR("Mathieu Desnoyers");
265MODULE_DESCRIPTION("Fair rwlock test");
This page took 0.047228 seconds and 4 git commands to generate.