Added license information
[kvmfornfv.git] / kernel / lib / percpu_test.c
1 #include <linux/module.h>
2
3 /* validate @native and @pcp counter values match @expected */
4 #define CHECK(native, pcp, expected)                                    \
5         do {                                                            \
6                 WARN((native) != (expected),                            \
7                      "raw %ld (0x%lx) != expected %lld (0x%llx)",       \
8                      (native), (native),                                \
9                      (long long)(expected), (long long)(expected));     \
10                 WARN(__this_cpu_read(pcp) != (expected),                \
11                      "pcp %ld (0x%lx) != expected %lld (0x%llx)",       \
12                      __this_cpu_read(pcp), __this_cpu_read(pcp),        \
13                      (long long)(expected), (long long)(expected));     \
14         } while (0)
15
16 static DEFINE_PER_CPU(long, long_counter);
17 static DEFINE_PER_CPU(unsigned long, ulong_counter);
18
19 static int __init percpu_test_init(void)
20 {
21         /*
22          * volatile prevents compiler from optimizing it uses, otherwise the
23          * +ul_one/-ul_one below would replace with inc/dec instructions.
24          */
25         volatile unsigned int ui_one = 1;
26         long l = 0;
27         unsigned long ul = 0;
28
29         pr_info("percpu test start\n");
30
31         preempt_disable();
32
33         l += -1;
34         __this_cpu_add(long_counter, -1);
35         CHECK(l, long_counter, -1);
36
37         l += 1;
38         __this_cpu_add(long_counter, 1);
39         CHECK(l, long_counter, 0);
40
41         ul = 0;
42         __this_cpu_write(ulong_counter, 0);
43
44         ul += 1UL;
45         __this_cpu_add(ulong_counter, 1UL);
46         CHECK(ul, ulong_counter, 1);
47
48         ul += -1UL;
49         __this_cpu_add(ulong_counter, -1UL);
50         CHECK(ul, ulong_counter, 0);
51
52         ul += -(unsigned long)1;
53         __this_cpu_add(ulong_counter, -(unsigned long)1);
54         CHECK(ul, ulong_counter, -1);
55
56         ul = 0;
57         __this_cpu_write(ulong_counter, 0);
58
59         ul -= 1;
60         __this_cpu_dec(ulong_counter);
61         CHECK(ul, ulong_counter, -1);
62         CHECK(ul, ulong_counter, ULONG_MAX);
63
64         l += -ui_one;
65         __this_cpu_add(long_counter, -ui_one);
66         CHECK(l, long_counter, 0xffffffff);
67
68         l += ui_one;
69         __this_cpu_add(long_counter, ui_one);
70         CHECK(l, long_counter, (long)0x100000000LL);
71
72
73         l = 0;
74         __this_cpu_write(long_counter, 0);
75
76         l -= ui_one;
77         __this_cpu_sub(long_counter, ui_one);
78         CHECK(l, long_counter, -1);
79
80         l = 0;
81         __this_cpu_write(long_counter, 0);
82
83         l += ui_one;
84         __this_cpu_add(long_counter, ui_one);
85         CHECK(l, long_counter, 1);
86
87         l += -ui_one;
88         __this_cpu_add(long_counter, -ui_one);
89         CHECK(l, long_counter, (long)0x100000000LL);
90
91         l = 0;
92         __this_cpu_write(long_counter, 0);
93
94         l -= ui_one;
95         this_cpu_sub(long_counter, ui_one);
96         CHECK(l, long_counter, -1);
97         CHECK(l, long_counter, ULONG_MAX);
98
99         ul = 0;
100         __this_cpu_write(ulong_counter, 0);
101
102         ul += ui_one;
103         __this_cpu_add(ulong_counter, ui_one);
104         CHECK(ul, ulong_counter, 1);
105
106         ul = 0;
107         __this_cpu_write(ulong_counter, 0);
108
109         ul -= ui_one;
110         __this_cpu_sub(ulong_counter, ui_one);
111         CHECK(ul, ulong_counter, -1);
112         CHECK(ul, ulong_counter, ULONG_MAX);
113
114         ul = 3;
115         __this_cpu_write(ulong_counter, 3);
116
117         ul = this_cpu_sub_return(ulong_counter, ui_one);
118         CHECK(ul, ulong_counter, 2);
119
120         ul = __this_cpu_sub_return(ulong_counter, ui_one);
121         CHECK(ul, ulong_counter, 1);
122
123         preempt_enable();
124
125         pr_info("percpu test done\n");
126         return -EAGAIN;  /* Fail will directly unload the module */
127 }
128
129 static void __exit percpu_test_exit(void)
130 {
131 }
132
133 module_init(percpu_test_init)
134 module_exit(percpu_test_exit)
135
136 MODULE_LICENSE("GPL");
137 MODULE_AUTHOR("Greg Thelen");
138 MODULE_DESCRIPTION("percpu operations test");