b8712f8e |
1 | /* test-local.c |
2 | * |
3 | * Sample module for local.h usage. |
4 | */ |
5 | |
6 | |
7 | #include <asm/local.h> |
8 | #include <linux/init.h> |
9 | #include <linux/module.h> |
10 | #include <linux/timer.h> |
11 | |
12 | static DEFINE_PER_CPU(local_t, counters) = LOCAL_INIT(0); |
13 | |
14 | static struct timer_list test_timer; |
15 | |
16 | /* IPI called on each CPU. */ |
17 | static void test_each(void *info) |
18 | { |
19 | /* Increment the counter from a non preemptible context */ |
20 | printk("Increment on cpu %d\n", smp_processor_id()); |
21 | local_inc(&__get_cpu_var(counters)); |
22 | |
23 | /* This is what incrementing the variable would look like within a |
24 | * preemptible context (it disables preemption) : |
25 | * |
26 | * local_inc(&get_cpu_var(counters)); |
27 | * put_cpu_var(counters); |
28 | */ |
29 | } |
30 | static void do_test_timer(unsigned long data) |
31 | { |
32 | int cpu; |
33 | |
34 | /* Increment the counters */ |
35 | on_each_cpu(test_each, NULL, 0, 1); |
36 | /* Read all the counters */ |
37 | printk("Counters read from CPU %d\n", smp_processor_id()); |
38 | for_each_online_cpu(cpu) { |
39 | printk("Read : CPU %d, count %ld\n", cpu, |
40 | local_read(&per_cpu(counters, cpu))); |
41 | } |
42 | del_timer(&test_timer); |
43 | test_timer.expires = jiffies + 1000; |
44 | add_timer(&test_timer); |
45 | } |
46 | |
47 | static int __init test_init(void) |
48 | { |
49 | /* initialize the timer that will increment the counter */ |
50 | init_timer(&test_timer); |
51 | test_timer.function = do_test_timer; |
52 | test_timer.expires = jiffies + 1; |
53 | add_timer(&test_timer); |
54 | |
55 | return 0; |
56 | } |
57 | |
58 | static void __exit test_exit(void) |
59 | { |
60 | del_timer_sync(&test_timer); |
61 | } |
62 | |
63 | module_init(test_init); |
64 | module_exit(test_exit); |
65 | |
66 | MODULE_LICENSE("GPL"); |
67 | MODULE_AUTHOR("Mathieu Desnoyers"); |
68 | MODULE_DESCRIPTION("Local Atomic Ops"); |
69 | |