| David Daney | bba9076 | 2010-02-16 15:26:35 -0800 | [diff] [blame] | 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/module.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); |