linux/lib/percpu_test.c
<<
>>
Prefs
   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
  16static DEFINE_PER_CPU(long, long_counter);
  17static DEFINE_PER_CPU(unsigned long, ulong_counter);
  18
  19static 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
 129static void __exit percpu_test_exit(void)
 130{
 131}
 132
 133module_init(percpu_test_init)
 134module_exit(percpu_test_exit)
 135
 136MODULE_LICENSE("GPL");
 137MODULE_AUTHOR("Greg Thelen");
 138MODULE_DESCRIPTION("percpu operations test");
 139