root/lib/percpu_test.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. percpu_test_init
  2. percpu_test_exit

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

/* [<][>][^][v][top][bottom][index][help] */