421991b0 |
1 | /* test-cmpxchg-nolock.c |
2 | * |
3 | * Compare local cmpxchg with irq disable / enable. |
4 | */ |
5 | |
6 | |
7 | #include <linux/jiffies.h> |
8 | #include <linux/compiler.h> |
9 | #include <linux/init.h> |
10 | #include <linux/module.h> |
11 | #include <linux/calc64.h> |
12 | #include <asm/timex.h> |
13 | #include <asm/system.h> |
14 | |
15 | #define NR_LOOPS 20000 |
16 | |
17 | int test_val; |
18 | |
19 | static void do_test_cmpxchg(void) |
20 | { |
21 | int ret; |
22 | long flags; |
23 | unsigned int i; |
24 | cycles_t time1, time2, time; |
25 | long rem; |
26 | |
27 | local_irq_save(flags); |
28 | preempt_disable(); |
29 | time1 = get_cycles(); |
30 | for (i = 0; i < NR_LOOPS; i++) { |
31 | ret = cmpxchg_local(&test_val, 0, 0); |
32 | } |
33 | time2 = get_cycles(); |
34 | local_irq_restore(flags); |
35 | preempt_enable(); |
36 | time = time2 - time1; |
37 | |
38 | printk(KERN_ALERT "test results: time for non locked cmpxchg\n"); |
39 | printk(KERN_ALERT "number of loops: %d\n", NR_LOOPS); |
40 | printk(KERN_ALERT "total time: %llu\n", time); |
41 | time = div_long_long_rem(time, NR_LOOPS, &rem); |
42 | printk(KERN_ALERT "-> non locked cmpxchg takes %llu cycles\n", time); |
43 | printk(KERN_ALERT "test end\n"); |
44 | } |
45 | |
46 | /* |
47 | * This test will have a higher standard deviation due to incoming interrupts. |
48 | */ |
49 | static void do_test_enable_int(void) |
50 | { |
51 | long flags; |
52 | unsigned int i; |
53 | cycles_t time1, time2, time; |
54 | long rem; |
55 | |
56 | local_irq_save(flags); |
57 | preempt_disable(); |
58 | time1 = get_cycles(); |
59 | for (i = 0; i < NR_LOOPS; i++) { |
60 | local_irq_restore(flags); |
61 | } |
62 | time2 = get_cycles(); |
63 | local_irq_restore(flags); |
64 | preempt_enable(); |
65 | time = time2 - time1; |
66 | |
67 | printk(KERN_ALERT "test results: time for enabling interrupts (STI)\n"); |
68 | printk(KERN_ALERT "number of loops: %d\n", NR_LOOPS); |
69 | printk(KERN_ALERT "total time: %llu\n", time); |
70 | time = div_long_long_rem(time, NR_LOOPS, &rem); |
71 | printk(KERN_ALERT "-> enabling interrupts (STI) takes %llu cycles\n", |
72 | time); |
73 | printk(KERN_ALERT "test end\n"); |
74 | } |
75 | |
76 | static void do_test_disable_int(void) |
77 | { |
78 | unsigned long flags, flags2; |
79 | unsigned int i; |
80 | cycles_t time1, time2, time; |
81 | long rem; |
82 | |
83 | local_irq_save(flags); |
84 | preempt_disable(); |
85 | time1 = get_cycles(); |
86 | for ( i = 0; i < NR_LOOPS; i++) { |
87 | local_irq_save(flags2); |
88 | } |
89 | time2 = get_cycles(); |
90 | local_irq_restore(flags); |
91 | preempt_enable(); |
92 | time = time2 - time1; |
93 | |
94 | printk(KERN_ALERT "test results: time for disabling interrupts (CLI)\n"); |
95 | printk(KERN_ALERT "number of loops: %d\n", NR_LOOPS); |
96 | printk(KERN_ALERT "total time: %llu\n", time); |
97 | time = div_long_long_rem(time, NR_LOOPS, &rem); |
7de49e3a |
98 | printk(KERN_ALERT "-> disabling interrupts (CLI) takes %llu cycles\n", |
421991b0 |
99 | time); |
100 | printk(KERN_ALERT "test end\n"); |
101 | } |
102 | |
103 | |
104 | |
105 | static int ltt_test_init(void) |
106 | { |
107 | printk(KERN_ALERT "test init\n"); |
108 | |
109 | do_test_cmpxchg(); |
110 | do_test_enable_int(); |
111 | do_test_disable_int(); |
112 | return -EAGAIN; /* Fail will directly unload the module */ |
113 | } |
114 | |
115 | static void ltt_test_exit(void) |
116 | { |
117 | printk(KERN_ALERT "test exit\n"); |
118 | } |
119 | |
120 | module_init(ltt_test_init) |
121 | module_exit(ltt_test_exit) |
122 | |
123 | MODULE_LICENSE("GPL"); |
124 | MODULE_AUTHOR("Mathieu Desnoyers"); |
125 | MODULE_DESCRIPTION("Cmpxchg vs int Test"); |
126 | |