67708ee5 |
1 | /* |
2 | * test-ipi.c |
3 | * |
4 | * Copyright 2009 - Mathieu Desnoyers <mathieu.desnoyers@polymtl.ca> |
5 | * Distributed under GPLv2 |
6 | */ |
7 | |
8 | #include <linux/jiffies.h> |
9 | #include <linux/compiler.h> |
10 | #include <linux/init.h> |
11 | #include <linux/module.h> |
12 | #include <linux/math64.h> |
13 | #include <linux/spinlock.h> |
14 | #include <linux/seqlock.h> |
15 | #include <linux/cpumask.h> |
16 | #include <linux/smp.h> |
17 | #include <asm/timex.h> |
18 | #include <asm/system.h> |
19 | |
20 | #ifdef CONFIG_ARM |
21 | #include <linux/trace-clock.h> |
22 | #define get_timestamp trace_clock_read64 |
23 | #else |
24 | #define get_timestamp get_cycles |
25 | #endif |
26 | |
27 | #define NR_LOOPS 20000 |
28 | |
29 | int test_val; |
30 | |
31 | static void do_testbaseline(void) |
32 | { |
33 | unsigned long flags; |
34 | unsigned int i; |
35 | cycles_t time1, time2, time; |
36 | u32 rem; |
37 | |
38 | local_irq_save(flags); |
39 | preempt_disable(); |
40 | time1 = get_timestamp(); |
41 | for (i = 0; i < NR_LOOPS; i++) { |
42 | asm volatile (""); |
43 | } |
44 | time2 = get_timestamp(); |
45 | local_irq_restore(flags); |
46 | preempt_enable(); |
47 | time = time2 - time1; |
48 | |
49 | printk(KERN_ALERT "test results: time for baseline\n"); |
50 | printk(KERN_ALERT "number of loops: %d\n", NR_LOOPS); |
51 | printk(KERN_ALERT "total time: %llu\n", (unsigned long long)time); |
52 | time = div_u64_rem(time, NR_LOOPS, &rem); |
53 | printk(KERN_ALERT "-> baseline takes %llu cycles\n", (unsigned long long)time); |
54 | printk(KERN_ALERT "test end\n"); |
55 | } |
56 | |
57 | static void remote_wmb(void *info) |
58 | { |
59 | smp_wmb(); |
60 | } |
61 | |
62 | static void do_test_ipi(void) |
63 | { |
64 | unsigned int i; |
65 | int cpu; |
66 | cycles_t time1, time2, time; |
67 | u32 rem; |
68 | |
69 | preempt_disable(); |
70 | cpu = smp_processor_id(); |
71 | if (cpu == 0) |
72 | cpu = 1; |
73 | else |
74 | cpu = 0; |
75 | time1 = get_timestamp(); |
76 | for (i = 0; i < NR_LOOPS; i++) { |
77 | smp_call_function_single(cpu, remote_wmb, NULL, 1); |
78 | } |
79 | time2 = get_timestamp(); |
80 | preempt_enable(); |
81 | time = time2 - time1; |
82 | |
83 | printk(KERN_ALERT "test results: time for ipi\n"); |
84 | printk(KERN_ALERT "number of loops: %d\n", NR_LOOPS); |
85 | printk(KERN_ALERT "total time: %llu\n", (unsigned long long)time); |
86 | time = div_u64_rem(time, NR_LOOPS, &rem); |
87 | printk(KERN_ALERT "-> ipi takes %llu cycles\n", (unsigned long long)time); |
88 | printk(KERN_ALERT "test end\n"); |
89 | } |
90 | |
91 | static void do_test_wmb(void) |
92 | { |
93 | unsigned int i; |
94 | cycles_t time1, time2, time; |
95 | u32 rem; |
96 | |
97 | preempt_disable(); |
98 | time1 = get_timestamp(); |
99 | for (i = 0; i < NR_LOOPS; i++) { |
100 | wmb(); |
101 | } |
102 | time2 = get_timestamp(); |
103 | preempt_enable(); |
104 | time = time2 - time1; |
105 | |
106 | printk(KERN_ALERT "test results: time for ipi\n"); |
107 | printk(KERN_ALERT "number of loops: %d\n", NR_LOOPS); |
108 | printk(KERN_ALERT "total time: %llu\n", (unsigned long long)time); |
109 | time = div_u64_rem(time, NR_LOOPS, &rem); |
110 | printk(KERN_ALERT "-> ipi takes %llu cycles\n", (unsigned long long)time); |
111 | printk(KERN_ALERT "test end\n"); |
112 | } |
113 | |
114 | static int ltt_test_init(void) |
115 | { |
116 | printk(KERN_ALERT "test init\n"); |
117 | |
118 | printk(KERN_ALERT "Number of active CPUs : %d\n", num_online_cpus()); |
119 | do_testbaseline(); |
120 | do_test_ipi(); |
121 | do_test_wmb(); |
122 | return -EAGAIN; /* Fail will directly unload the module */ |
123 | } |
124 | |
125 | static void ltt_test_exit(void) |
126 | { |
127 | printk(KERN_ALERT "test exit\n"); |
128 | } |
129 | |
130 | module_init(ltt_test_init) |
131 | module_exit(ltt_test_exit) |
132 | |
133 | MODULE_LICENSE("GPL"); |
134 | MODULE_AUTHOR("Mathieu Desnoyers"); |
135 | MODULE_DESCRIPTION("Test read lock speed"); |