8ba2d0ad |
1 | /* test-nop-speed.c |
2 | * |
3 | */ |
4 | |
5 | #include <linux/module.h> |
6 | #include <linux/proc_fs.h> |
7 | #include <linux/sched.h> |
8 | #include <linux/timex.h> |
9 | #include <asm/atomic.h> |
10 | #include <asm/ptrace.h> |
11 | |
12 | #define NR_TESTS 10000000 |
13 | |
14 | int var, var2; |
15 | atomic_t atomicval; |
16 | |
17 | struct proc_dir_entry *pentry = NULL; |
18 | |
19 | |
20 | static inline int test_nop_atomic_add_return(int i, atomic_t *v) |
21 | { |
22 | int __i = i; |
23 | asm volatile(".byte 0x90;" |
24 | "xaddl %0, %1;" |
25 | : "+r" (i), "+m" (v->counter) |
26 | : : "memory"); |
27 | return i + __i; |
28 | } |
29 | |
30 | static inline int test_prefix_atomic_add_return(int i, atomic_t *v) |
31 | { |
32 | int __i = i; |
33 | asm volatile(".byte 0x3E;" |
34 | "xaddl %0, %1;" |
35 | : "+r" (i), "+m" (v->counter) |
36 | : : "memory"); |
37 | return i + __i; |
38 | } |
39 | |
40 | static inline int test_lock_atomic_add_return(int i, atomic_t *v) |
41 | { |
42 | int __i = i; |
43 | asm volatile(".byte 0xf0;" |
44 | "xaddl %0, %1;" |
45 | : "+r" (i), "+m" (v->counter) |
46 | : : "memory"); |
47 | return i + __i; |
48 | } |
49 | |
50 | |
51 | |
52 | void empty(void) |
53 | { |
54 | asm volatile (""); |
55 | var += 50; |
56 | var /= 10; |
57 | var *= var2; |
58 | } |
59 | |
60 | void testnop(void) |
61 | { |
62 | test_nop_atomic_add_return(5, &atomicval); |
63 | var += 50; |
64 | var /= 10; |
65 | var *= var2; |
66 | } |
67 | |
68 | void testprefix(void) |
69 | { |
70 | test_prefix_atomic_add_return(5, &atomicval); |
71 | var += 50; |
72 | var /= 10; |
73 | var *= var2; |
74 | } |
75 | |
76 | void testlock(void) |
77 | { |
78 | test_lock_atomic_add_return(5, &atomicval); |
79 | var += 50; |
80 | var /= 10; |
81 | var *= var2; |
82 | } |
83 | |
84 | |
85 | |
86 | void perform_test(const char *name, void (*callback)(void)) |
87 | { |
88 | unsigned int i; |
89 | cycles_t cycles1, cycles2; |
90 | unsigned long flags; |
91 | |
92 | local_irq_save(flags); |
93 | rdtsc_barrier(); |
94 | cycles1 = get_cycles(); |
95 | rdtsc_barrier(); |
96 | for(i=0; i<NR_TESTS; i++) { |
97 | callback(); |
98 | } |
99 | rdtsc_barrier(); |
100 | cycles2 = get_cycles(); |
101 | rdtsc_barrier(); |
102 | local_irq_restore(flags); |
103 | printk("test %s cycles : %llu\n", name, cycles2-cycles1); |
104 | } |
105 | |
106 | static int my_open(struct inode *inode, struct file *file) |
107 | { |
108 | printk("NR_TESTS %d\n", NR_TESTS); |
109 | |
110 | perform_test("empty", empty); |
111 | perform_test("test 1-byte nop xadd", testnop); |
112 | perform_test("test DS override prefix xadd", testprefix); |
113 | perform_test("test LOCK xadd", testlock); |
114 | |
115 | return -EPERM; |
116 | } |
117 | |
118 | |
119 | static struct file_operations my_operations = { |
120 | .open = my_open, |
121 | }; |
122 | |
123 | int init_module(void) |
124 | { |
125 | pentry = create_proc_entry("testprefix", 0444, NULL); |
126 | if (pentry) |
127 | pentry->proc_fops = &my_operations; |
128 | |
129 | return 0; |
130 | } |
131 | |
132 | void cleanup_module(void) |
133 | { |
134 | remove_proc_entry("testprefix", NULL); |
135 | } |
136 | |
137 | MODULE_LICENSE("GPL"); |
138 | MODULE_AUTHOR("Mathieu Desnoyers"); |
139 | MODULE_DESCRIPTION("prefix test"); |