Back to home page

OSCL-LXR

 
 

    


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