]>
Commit | Line | Data |
---|---|---|
bba90760 DD |
1 | #include <linux/init.h> |
2 | #include <linux/kthread.h> | |
3 | #include <linux/hrtimer.h> | |
4 | #include <linux/fs.h> | |
5 | #include <linux/debugfs.h> | |
73bc256d | 6 | #include <linux/export.h> |
bba90760 DD |
7 | #include <linux/spinlock.h> |
8 | ||
9 | ||
10 | static int ss_get(void *data, u64 *val) | |
11 | { | |
12 | ktime_t start, finish; | |
13 | int loops; | |
14 | int cont; | |
15 | DEFINE_RAW_SPINLOCK(ss_spin); | |
16 | ||
17 | loops = 1000000; | |
18 | cont = 1; | |
19 | ||
20 | start = ktime_get(); | |
21 | ||
22 | while (cont) { | |
23 | raw_spin_lock(&ss_spin); | |
24 | loops--; | |
25 | if (loops == 0) | |
26 | cont = 0; | |
27 | raw_spin_unlock(&ss_spin); | |
28 | } | |
29 | ||
30 | finish = ktime_get(); | |
31 | ||
32 | *val = ktime_us_delta(finish, start); | |
33 | ||
34 | return 0; | |
35 | } | |
36 | ||
37 | DEFINE_SIMPLE_ATTRIBUTE(fops_ss, ss_get, NULL, "%llu\n"); | |
38 | ||
39 | ||
40 | ||
41 | struct spin_multi_state { | |
42 | raw_spinlock_t lock; | |
43 | atomic_t start_wait; | |
44 | atomic_t enter_wait; | |
45 | atomic_t exit_wait; | |
46 | int loops; | |
47 | }; | |
48 | ||
49 | struct spin_multi_per_thread { | |
50 | struct spin_multi_state *state; | |
51 | ktime_t start; | |
52 | }; | |
53 | ||
54 | static int multi_other(void *data) | |
55 | { | |
56 | int loops; | |
57 | int cont; | |
58 | struct spin_multi_per_thread *pt = data; | |
59 | struct spin_multi_state *s = pt->state; | |
60 | ||
61 | loops = s->loops; | |
62 | cont = 1; | |
63 | ||
64 | atomic_dec(&s->enter_wait); | |
65 | ||
66 | while (atomic_read(&s->enter_wait)) | |
67 | ; /* spin */ | |
68 | ||
69 | pt->start = ktime_get(); | |
70 | ||
71 | atomic_dec(&s->start_wait); | |
72 | ||
73 | while (atomic_read(&s->start_wait)) | |
74 | ; /* spin */ | |
75 | ||
76 | while (cont) { | |
77 | raw_spin_lock(&s->lock); | |
78 | loops--; | |
79 | if (loops == 0) | |
80 | cont = 0; | |
81 | raw_spin_unlock(&s->lock); | |
82 | } | |
83 | ||
84 | atomic_dec(&s->exit_wait); | |
85 | while (atomic_read(&s->exit_wait)) | |
86 | ; /* spin */ | |
87 | return 0; | |
88 | } | |
89 | ||
90 | static int multi_get(void *data, u64 *val) | |
91 | { | |
92 | ktime_t finish; | |
93 | struct spin_multi_state ms; | |
94 | struct spin_multi_per_thread t1, t2; | |
95 | ||
96 | ms.lock = __RAW_SPIN_LOCK_UNLOCKED("multi_get"); | |
97 | ms.loops = 1000000; | |
98 | ||
99 | atomic_set(&ms.start_wait, 2); | |
100 | atomic_set(&ms.enter_wait, 2); | |
101 | atomic_set(&ms.exit_wait, 2); | |
102 | t1.state = &ms; | |
103 | t2.state = &ms; | |
104 | ||
105 | kthread_run(multi_other, &t2, "multi_get"); | |
106 | ||
107 | multi_other(&t1); | |
108 | ||
109 | finish = ktime_get(); | |
110 | ||
111 | *val = ktime_us_delta(finish, t1.start); | |
112 | ||
113 | return 0; | |
114 | } | |
115 | ||
116 | DEFINE_SIMPLE_ATTRIBUTE(fops_multi, multi_get, NULL, "%llu\n"); | |
117 | ||
118 | ||
119 | extern struct dentry *mips_debugfs_dir; | |
120 | static int __init spinlock_test(void) | |
121 | { | |
122 | struct dentry *d; | |
123 | ||
124 | if (!mips_debugfs_dir) | |
125 | return -ENODEV; | |
126 | ||
127 | d = debugfs_create_file("spin_single", S_IRUGO, | |
128 | mips_debugfs_dir, NULL, | |
129 | &fops_ss); | |
130 | if (!d) | |
131 | return -ENOMEM; | |
132 | ||
133 | d = debugfs_create_file("spin_multi", S_IRUGO, | |
134 | mips_debugfs_dir, NULL, | |
135 | &fops_multi); | |
136 | if (!d) | |
137 | return -ENOMEM; | |
138 | ||
139 | return 0; | |
140 | } | |
141 | device_initcall(spinlock_test); |