0001
0002 #include <linux/init.h>
0003 #include <linux/kthread.h>
0004 #include <linux/hrtimer.h>
0005 #include <linux/fs.h>
0006 #include <linux/debugfs.h>
0007 #include <linux/export.h>
0008 #include <linux/spinlock.h>
0009 #include <asm/debug.h>
0010
0011 static int ss_get(void *data, u64 *val)
0012 {
0013 ktime_t start, finish;
0014 int loops;
0015 int cont;
0016 DEFINE_RAW_SPINLOCK(ss_spin);
0017
0018 loops = 1000000;
0019 cont = 1;
0020
0021 start = ktime_get();
0022
0023 while (cont) {
0024 raw_spin_lock(&ss_spin);
0025 loops--;
0026 if (loops == 0)
0027 cont = 0;
0028 raw_spin_unlock(&ss_spin);
0029 }
0030
0031 finish = ktime_get();
0032
0033 *val = ktime_us_delta(finish, start);
0034
0035 return 0;
0036 }
0037
0038 DEFINE_DEBUGFS_ATTRIBUTE(fops_ss, ss_get, NULL, "%llu\n");
0039
0040
0041
0042 struct spin_multi_state {
0043 raw_spinlock_t lock;
0044 atomic_t start_wait;
0045 atomic_t enter_wait;
0046 atomic_t exit_wait;
0047 int loops;
0048 };
0049
0050 struct spin_multi_per_thread {
0051 struct spin_multi_state *state;
0052 ktime_t start;
0053 };
0054
0055 static int multi_other(void *data)
0056 {
0057 int loops;
0058 int cont;
0059 struct spin_multi_per_thread *pt = data;
0060 struct spin_multi_state *s = pt->state;
0061
0062 loops = s->loops;
0063 cont = 1;
0064
0065 atomic_dec(&s->enter_wait);
0066
0067 while (atomic_read(&s->enter_wait))
0068 ;
0069
0070 pt->start = ktime_get();
0071
0072 atomic_dec(&s->start_wait);
0073
0074 while (atomic_read(&s->start_wait))
0075 ;
0076
0077 while (cont) {
0078 raw_spin_lock(&s->lock);
0079 loops--;
0080 if (loops == 0)
0081 cont = 0;
0082 raw_spin_unlock(&s->lock);
0083 }
0084
0085 atomic_dec(&s->exit_wait);
0086 while (atomic_read(&s->exit_wait))
0087 ;
0088 return 0;
0089 }
0090
0091 static int multi_get(void *data, u64 *val)
0092 {
0093 ktime_t finish;
0094 struct spin_multi_state ms;
0095 struct spin_multi_per_thread t1, t2;
0096
0097 ms.lock = __RAW_SPIN_LOCK_UNLOCKED("multi_get");
0098 ms.loops = 1000000;
0099
0100 atomic_set(&ms.start_wait, 2);
0101 atomic_set(&ms.enter_wait, 2);
0102 atomic_set(&ms.exit_wait, 2);
0103 t1.state = &ms;
0104 t2.state = &ms;
0105
0106 kthread_run(multi_other, &t2, "multi_get");
0107
0108 multi_other(&t1);
0109
0110 finish = ktime_get();
0111
0112 *val = ktime_us_delta(finish, t1.start);
0113
0114 return 0;
0115 }
0116
0117 DEFINE_DEBUGFS_ATTRIBUTE(fops_multi, multi_get, NULL, "%llu\n");
0118
0119 static int __init spinlock_test(void)
0120 {
0121 debugfs_create_file_unsafe("spin_single", S_IRUGO, mips_debugfs_dir, NULL,
0122 &fops_ss);
0123 debugfs_create_file_unsafe("spin_multi", S_IRUGO, mips_debugfs_dir, NULL,
0124 &fops_multi);
0125 return 0;
0126 }
0127 device_initcall(spinlock_test);