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 <asm/ptrace.h>
16 #if (NR_CPUS > 512 && (BITS_PER_LONG == 32 || NR_CPUS > 1048576))
17 #error "fair rwlock needs more bits per long to deal with that many CPUs"
20 #define THREAD_ROFFSET 1UL
21 #define THREAD_RMASK ((NR_CPUS - 1) * THREAD_ROFFSET)
22 #define SOFTIRQ_ROFFSET (THREAD_RMASK + 1)
23 #define SOFTIRQ_RMASK ((NR_CPUS - 1) * SOFTIRQ_ROFFSET)
24 #define HARDIRQ_ROFFSET ((SOFTIRQ_RMASK | THREAD_RMASK) + 1)
25 #define HARDIRQ_RMASK ((NR_CPUS - 1) * HARDIRQ_ROFFSET)
27 #define THREAD_WMASK ((HARDIRQ_RMASK | SOFTIRQ_RMASK | THREAD_RMASK) + 1)
28 #define SOFTIRQ_WMASK (THREAD_WMASK << 1)
29 #define HARDIRQ_WMASK (SOFTIRQ_WMASK << 1)
34 #define NR_INTERRUPT_READERS 2
36 static int var
[NR_VARS
];
37 static struct task_struct
*reader_threads
[NR_READERS
];
38 static struct task_struct
*writer_threads
[NR_WRITERS
];
39 static struct task_struct
*interrupt_reader
;
41 static struct fair_rwlock frwlock
= {
42 .value
= ATOMIC_LONG_INIT(0),
43 .wlock
= __SPIN_LOCK_UNLOCKED(&frwlock
.wlock
),
46 struct proc_dir_entry
*pentry
= NULL
;
48 static int reader_thread(void *data
)
52 unsigned long iter
= 0;
54 printk("reader_thread/%lu runnning\n", (unsigned long)data
);
57 fair_read_lock(&frwlock
);
59 for (i
= 1; i
< NR_VARS
; i
++) {
63 "Unequal cur %d/prev %d at i %d, iter %lu "
64 "in thread\n", cur
, prev
, i
, iter
);
66 fair_read_unlock(&frwlock
);
68 } while (!kthread_should_stop());
69 printk("reader_thread/%lu iterations : %lu\n",
70 (unsigned long)data
, iter
);
74 static void interrupt_reader_ipi(void *data
)
79 fair_read_lock(&frwlock
);
81 for (i
= 1; i
< NR_VARS
; i
++) {
85 "Unequal cur %d/prev %d at i %d in interrupt\n",
88 fair_read_unlock(&frwlock
);
91 static int interrupt_reader_thread(void *data
)
93 unsigned long iter
= 0;
96 on_each_cpu(interrupt_reader_ipi
, NULL
, 0);
98 } while (!kthread_should_stop());
99 printk("interrupt_reader_thread/%lu iterations : %lu\n",
100 (unsigned long)data
, iter
);
104 static int writer_thread(void *data
)
108 unsigned long iter
= 0;
110 printk("writer_thread/%lu runnning\n", (unsigned long)data
);
113 fair_write_lock_irq(&frwlock
);
114 //fair_write_lock(&frwlock);
115 new = (int)get_cycles();
116 for (i
= 0; i
< NR_VARS
; i
++) {
119 //fair_write_unlock(&frwlock);
120 fair_write_unlock_irq(&frwlock
);
122 } while (!kthread_should_stop());
123 printk("writer_thread/%lu iterations : %lu\n",
124 (unsigned long)data
, iter
);
128 static void fair_rwlock_create(void)
132 for (i
= 0; i
< NR_READERS
; i
++) {
133 printk("starting reader thread %lu\n", i
);
134 reader_threads
[i
] = kthread_run(reader_thread
, (void *)i
,
136 BUG_ON(!reader_threads
[i
]);
139 printk("starting interrupt reader %lu\n", i
);
140 interrupt_reader
= kthread_run(interrupt_reader_thread
, NULL
,
141 "frwlock_interrupt_reader");
143 for (i
= 0; i
< NR_WRITERS
; i
++) {
144 printk("starting writer thread %lu\n", i
);
145 writer_threads
[i
] = kthread_run(writer_thread
, (void *)i
,
147 BUG_ON(!writer_threads
[i
]);
151 static void fair_rwlock_stop(void)
155 for (i
= 0; i
< NR_READERS
; i
++) {
156 kthread_stop(reader_threads
[i
]);
159 //kthread_stop(interrupt_reader);
161 for (i
= 0; i
< NR_WRITERS
; i
++) {
162 kthread_stop(writer_threads
[i
]);
167 static void perform_test(const char *name
, void (*callback
)(void))
169 printk("%s\n", name
);
173 static int my_open(struct inode
*inode
, struct file
*file
)
175 perform_test("fair-rwlock-create", fair_rwlock_create
);
177 perform_test("fair-rwlock-stop", fair_rwlock_stop
);
183 static struct file_operations my_operations
= {
187 int init_module(void)
189 pentry
= create_proc_entry("testfrwlock", 0444, NULL
);
191 pentry
->proc_fops
= &my_operations
;
193 printk("NR_CPUS : %d\n", NR_CPUS
);
194 printk("THREAD_ROFFSET : %lX\n", THREAD_ROFFSET
);
195 printk("THREAD_RMASK : %lX\n", THREAD_RMASK
);
196 printk("THREAD_WMASK : %lX\n", THREAD_WMASK
);
197 printk("SOFTIRQ_ROFFSET : %lX\n", SOFTIRQ_ROFFSET
);
198 printk("SOFTIRQ_RMASK : %lX\n", SOFTIRQ_RMASK
);
199 printk("SOFTIRQ_WMASK : %lX\n", SOFTIRQ_WMASK
);
200 printk("HARDIRQ_ROFFSET : %lX\n", HARDIRQ_ROFFSET
);
201 printk("HARDIRQ_RMASK : %lX\n", HARDIRQ_RMASK
);
202 printk("HARDIRQ_WMASK : %lX\n", HARDIRQ_WMASK
);
207 void cleanup_module(void)
209 remove_proc_entry("testfrwlock", NULL
);
212 MODULE_LICENSE("GPL");
213 MODULE_AUTHOR("Mathieu Desnoyers");
214 MODULE_DESCRIPTION("Fair rwlock test");