| #include <linux/init.h> | |
| #include <linux/kthread.h> | |
| #include <linux/hrtimer.h> | |
| #include <linux/fs.h> | |
| #include <linux/debugfs.h> | |
| #include <linux/export.h> | |
| #include <linux/spinlock.h> | |
| #include <asm/debug.h> | |
| static int ss_get(void *data, u64 *val) | |
| { | |
| ktime_t start, finish; | |
| int loops; | |
| int cont; | |
| DEFINE_RAW_SPINLOCK(ss_spin); | |
| loops = 1000000; | |
| cont = 1; | |
| start = ktime_get(); | |
| while (cont) { | |
| raw_spin_lock(&ss_spin); | |
| loops--; | |
| if (loops == 0) | |
| cont = 0; | |
| raw_spin_unlock(&ss_spin); | |
| } | |
| finish = ktime_get(); | |
| *val = ktime_us_delta(finish, start); | |
| return 0; | |
| } | |
| DEFINE_SIMPLE_ATTRIBUTE(fops_ss, ss_get, NULL, "%llu\n"); | |
| struct spin_multi_state { | |
| raw_spinlock_t lock; | |
| atomic_t start_wait; | |
| atomic_t enter_wait; | |
| atomic_t exit_wait; | |
| int loops; | |
| }; | |
| struct spin_multi_per_thread { | |
| struct spin_multi_state *state; | |
| ktime_t start; | |
| }; | |
| static int multi_other(void *data) | |
| { | |
| int loops; | |
| int cont; | |
| struct spin_multi_per_thread *pt = data; | |
| struct spin_multi_state *s = pt->state; | |
| loops = s->loops; | |
| cont = 1; | |
| atomic_dec(&s->enter_wait); | |
| while (atomic_read(&s->enter_wait)) | |
| ; /* spin */ | |
| pt->start = ktime_get(); | |
| atomic_dec(&s->start_wait); | |
| while (atomic_read(&s->start_wait)) | |
| ; /* spin */ | |
| while (cont) { | |
| raw_spin_lock(&s->lock); | |
| loops--; | |
| if (loops == 0) | |
| cont = 0; | |
| raw_spin_unlock(&s->lock); | |
| } | |
| atomic_dec(&s->exit_wait); | |
| while (atomic_read(&s->exit_wait)) | |
| ; /* spin */ | |
| return 0; | |
| } | |
| static int multi_get(void *data, u64 *val) | |
| { | |
| ktime_t finish; | |
| struct spin_multi_state ms; | |
| struct spin_multi_per_thread t1, t2; | |
| ms.lock = __RAW_SPIN_LOCK_UNLOCKED("multi_get"); | |
| ms.loops = 1000000; | |
| atomic_set(&ms.start_wait, 2); | |
| atomic_set(&ms.enter_wait, 2); | |
| atomic_set(&ms.exit_wait, 2); | |
| t1.state = &ms; | |
| t2.state = &ms; | |
| kthread_run(multi_other, &t2, "multi_get"); | |
| multi_other(&t1); | |
| finish = ktime_get(); | |
| *val = ktime_us_delta(finish, t1.start); | |
| return 0; | |
| } | |
| DEFINE_SIMPLE_ATTRIBUTE(fops_multi, multi_get, NULL, "%llu\n"); | |
| static int __init spinlock_test(void) | |
| { | |
| struct dentry *d; | |
| if (!mips_debugfs_dir) | |
| return -ENODEV; | |
| d = debugfs_create_file("spin_single", S_IRUGO, | |
| mips_debugfs_dir, NULL, | |
| &fops_ss); | |
| if (!d) | |
| return -ENOMEM; | |
| d = debugfs_create_file("spin_multi", S_IRUGO, | |
| mips_debugfs_dir, NULL, | |
| &fops_multi); | |
| if (!d) | |
| return -ENOMEM; | |
| return 0; | |
| } | |
| device_initcall(spinlock_test); |