percpu_test.c 3.2 KB

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