forked from torvalds/linux
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
percpu: add test module for various percpu operations
Tests various percpu operations. Enable with CONFIG_PERCPU_TEST=m. Signed-off-by: Greg Thelen <[email protected]> Acked-by: Tejun Heo <[email protected]> Acked-by: Johannes Weiner <[email protected]> Signed-off-by: Andrew Morton <[email protected]> Signed-off-by: Linus Torvalds <[email protected]>
- Loading branch information
Showing
3 changed files
with
149 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,138 @@ | ||
#include <linux/module.h> | ||
|
||
/* validate @native and @pcp counter values match @expected */ | ||
#define CHECK(native, pcp, expected) \ | ||
do { \ | ||
WARN((native) != (expected), \ | ||
"raw %ld (0x%lx) != expected %lld (0x%llx)", \ | ||
(native), (native), \ | ||
(long long)(expected), (long long)(expected)); \ | ||
WARN(__this_cpu_read(pcp) != (expected), \ | ||
"pcp %ld (0x%lx) != expected %lld (0x%llx)", \ | ||
__this_cpu_read(pcp), __this_cpu_read(pcp), \ | ||
(long long)(expected), (long long)(expected)); \ | ||
} while (0) | ||
|
||
static DEFINE_PER_CPU(long, long_counter); | ||
static DEFINE_PER_CPU(unsigned long, ulong_counter); | ||
|
||
static int __init percpu_test_init(void) | ||
{ | ||
/* | ||
* volatile prevents compiler from optimizing it uses, otherwise the | ||
* +ul_one/-ul_one below would replace with inc/dec instructions. | ||
*/ | ||
volatile unsigned int ui_one = 1; | ||
long l = 0; | ||
unsigned long ul = 0; | ||
|
||
pr_info("percpu test start\n"); | ||
|
||
preempt_disable(); | ||
|
||
l += -1; | ||
__this_cpu_add(long_counter, -1); | ||
CHECK(l, long_counter, -1); | ||
|
||
l += 1; | ||
__this_cpu_add(long_counter, 1); | ||
CHECK(l, long_counter, 0); | ||
|
||
ul = 0; | ||
__this_cpu_write(ulong_counter, 0); | ||
|
||
ul += 1UL; | ||
__this_cpu_add(ulong_counter, 1UL); | ||
CHECK(ul, ulong_counter, 1); | ||
|
||
ul += -1UL; | ||
__this_cpu_add(ulong_counter, -1UL); | ||
CHECK(ul, ulong_counter, 0); | ||
|
||
ul += -(unsigned long)1; | ||
__this_cpu_add(ulong_counter, -(unsigned long)1); | ||
CHECK(ul, ulong_counter, -1); | ||
|
||
ul = 0; | ||
__this_cpu_write(ulong_counter, 0); | ||
|
||
ul -= 1; | ||
__this_cpu_dec(ulong_counter); | ||
CHECK(ul, ulong_counter, -1); | ||
CHECK(ul, ulong_counter, ULONG_MAX); | ||
|
||
l += -ui_one; | ||
__this_cpu_add(long_counter, -ui_one); | ||
CHECK(l, long_counter, 0xffffffff); | ||
|
||
l += ui_one; | ||
__this_cpu_add(long_counter, ui_one); | ||
CHECK(l, long_counter, (long)0x100000000LL); | ||
|
||
|
||
l = 0; | ||
__this_cpu_write(long_counter, 0); | ||
|
||
l -= ui_one; | ||
__this_cpu_sub(long_counter, ui_one); | ||
CHECK(l, long_counter, -1); | ||
|
||
l = 0; | ||
__this_cpu_write(long_counter, 0); | ||
|
||
l += ui_one; | ||
__this_cpu_add(long_counter, ui_one); | ||
CHECK(l, long_counter, 1); | ||
|
||
l += -ui_one; | ||
__this_cpu_add(long_counter, -ui_one); | ||
CHECK(l, long_counter, (long)0x100000000LL); | ||
|
||
l = 0; | ||
__this_cpu_write(long_counter, 0); | ||
|
||
l -= ui_one; | ||
this_cpu_sub(long_counter, ui_one); | ||
CHECK(l, long_counter, -1); | ||
CHECK(l, long_counter, ULONG_MAX); | ||
|
||
ul = 0; | ||
__this_cpu_write(ulong_counter, 0); | ||
|
||
ul += ui_one; | ||
__this_cpu_add(ulong_counter, ui_one); | ||
CHECK(ul, ulong_counter, 1); | ||
|
||
ul = 0; | ||
__this_cpu_write(ulong_counter, 0); | ||
|
||
ul -= ui_one; | ||
__this_cpu_sub(ulong_counter, ui_one); | ||
CHECK(ul, ulong_counter, -1); | ||
CHECK(ul, ulong_counter, ULONG_MAX); | ||
|
||
ul = 3; | ||
__this_cpu_write(ulong_counter, 3); | ||
|
||
ul = this_cpu_sub_return(ulong_counter, ui_one); | ||
CHECK(ul, ulong_counter, 2); | ||
|
||
ul = __this_cpu_sub_return(ulong_counter, ui_one); | ||
CHECK(ul, ulong_counter, 1); | ||
|
||
preempt_enable(); | ||
|
||
pr_info("percpu test done\n"); | ||
return -EAGAIN; /* Fail will directly unload the module */ | ||
} | ||
|
||
static void __exit percpu_test_exit(void) | ||
{ | ||
} | ||
|
||
module_init(percpu_test_init) | ||
module_exit(percpu_test_exit) | ||
|
||
MODULE_LICENSE("GPL"); | ||
MODULE_AUTHOR("Greg Thelen"); | ||
MODULE_DESCRIPTION("percpu operations test"); |