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> 6 #include <linux/export.h> 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); 142