Back to home page

LXR

 
 

    


0001 #include <linux/module.h>
0002 
0003 /* validate @native and @pcp counter values match @expected */
0004 #define CHECK(native, pcp, expected)                                    \
0005     do {                                                            \
0006         WARN((native) != (expected),                            \
0007              "raw %ld (0x%lx) != expected %lld (0x%llx)",   \
0008              (native), (native),                \
0009              (long long)(expected), (long long)(expected)); \
0010         WARN(__this_cpu_read(pcp) != (expected),                \
0011              "pcp %ld (0x%lx) != expected %lld (0x%llx)",   \
0012              __this_cpu_read(pcp), __this_cpu_read(pcp),    \
0013              (long long)(expected), (long long)(expected)); \
0014     } while (0)
0015 
0016 static DEFINE_PER_CPU(long, long_counter);
0017 static DEFINE_PER_CPU(unsigned long, ulong_counter);
0018 
0019 static int __init percpu_test_init(void)
0020 {
0021     /*
0022      * volatile prevents compiler from optimizing it uses, otherwise the
0023      * +ul_one/-ul_one below would replace with inc/dec instructions.
0024      */
0025     volatile unsigned int ui_one = 1;
0026     long l = 0;
0027     unsigned long ul = 0;
0028 
0029     pr_info("percpu test start\n");
0030 
0031     preempt_disable();
0032 
0033     l += -1;
0034     __this_cpu_add(long_counter, -1);
0035     CHECK(l, long_counter, -1);
0036 
0037     l += 1;
0038     __this_cpu_add(long_counter, 1);
0039     CHECK(l, long_counter, 0);
0040 
0041     ul = 0;
0042     __this_cpu_write(ulong_counter, 0);
0043 
0044     ul += 1UL;
0045     __this_cpu_add(ulong_counter, 1UL);
0046     CHECK(ul, ulong_counter, 1);
0047 
0048     ul += -1UL;
0049     __this_cpu_add(ulong_counter, -1UL);
0050     CHECK(ul, ulong_counter, 0);
0051 
0052     ul += -(unsigned long)1;
0053     __this_cpu_add(ulong_counter, -(unsigned long)1);
0054     CHECK(ul, ulong_counter, -1);
0055 
0056     ul = 0;
0057     __this_cpu_write(ulong_counter, 0);
0058 
0059     ul -= 1;
0060     __this_cpu_dec(ulong_counter);
0061     CHECK(ul, ulong_counter, -1);
0062     CHECK(ul, ulong_counter, ULONG_MAX);
0063 
0064     l += -ui_one;
0065     __this_cpu_add(long_counter, -ui_one);
0066     CHECK(l, long_counter, 0xffffffff);
0067 
0068     l += ui_one;
0069     __this_cpu_add(long_counter, ui_one);
0070     CHECK(l, long_counter, (long)0x100000000LL);
0071 
0072 
0073     l = 0;
0074     __this_cpu_write(long_counter, 0);
0075 
0076     l -= ui_one;
0077     __this_cpu_sub(long_counter, ui_one);
0078     CHECK(l, long_counter, -1);
0079 
0080     l = 0;
0081     __this_cpu_write(long_counter, 0);
0082 
0083     l += ui_one;
0084     __this_cpu_add(long_counter, ui_one);
0085     CHECK(l, long_counter, 1);
0086 
0087     l += -ui_one;
0088     __this_cpu_add(long_counter, -ui_one);
0089     CHECK(l, long_counter, (long)0x100000000LL);
0090 
0091     l = 0;
0092     __this_cpu_write(long_counter, 0);
0093 
0094     l -= ui_one;
0095     this_cpu_sub(long_counter, ui_one);
0096     CHECK(l, long_counter, -1);
0097     CHECK(l, long_counter, ULONG_MAX);
0098 
0099     ul = 0;
0100     __this_cpu_write(ulong_counter, 0);
0101 
0102     ul += ui_one;
0103     __this_cpu_add(ulong_counter, ui_one);
0104     CHECK(ul, ulong_counter, 1);
0105 
0106     ul = 0;
0107     __this_cpu_write(ulong_counter, 0);
0108 
0109     ul -= ui_one;
0110     __this_cpu_sub(ulong_counter, ui_one);
0111     CHECK(ul, ulong_counter, -1);
0112     CHECK(ul, ulong_counter, ULONG_MAX);
0113 
0114     ul = 3;
0115     __this_cpu_write(ulong_counter, 3);
0116 
0117     ul = this_cpu_sub_return(ulong_counter, ui_one);
0118     CHECK(ul, ulong_counter, 2);
0119 
0120     ul = __this_cpu_sub_return(ulong_counter, ui_one);
0121     CHECK(ul, ulong_counter, 1);
0122 
0123     preempt_enable();
0124 
0125     pr_info("percpu test done\n");
0126     return -EAGAIN;  /* Fail will directly unload the module */
0127 }
0128 
0129 static void __exit percpu_test_exit(void)
0130 {
0131 }
0132 
0133 module_init(percpu_test_init)
0134 module_exit(percpu_test_exit)
0135 
0136 MODULE_LICENSE("GPL");
0137 MODULE_AUTHOR("Greg Thelen");
0138 MODULE_DESCRIPTION("percpu operations test");