-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
This is just a test program for raw_spinlocks. The main reason I wrote it is to validate my spinlock changes that I sent in a previous patch. To use it enable CONFIG_DEBUG_FS and CONFIG_SPINLOCK_TEST then at run time do: # mount -t debugfs none /sys/kernel/debug/ # cat /sys/kernel/debug/mips/spin_single # cat /sys/kernel/debug/mips/spin_multi On my 600MHz octeon cn5860 (16 CPUs) I get spin_single spin_multi base 106885 247941 spinlock_patch 75194 219465 This shows that for uncontended locks the spinlock patch gives 41% improvement and for contended locks 12% improvement (1/time). Signed-off-by: David Daney <ddaney@caviumnetworks.com> To: linux-mips@linux-mips.org Patchwork: http://patchwork.linux-mips.org/patch/969/ Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
- Loading branch information
David Daney
authored and
Ralf Baechle
committed
Feb 27, 2010
1 parent
500c2e1
commit bba9076
Showing
3 changed files
with
149 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,141 @@ | ||
#include <linux/init.h> | ||
#include <linux/kthread.h> | ||
#include <linux/hrtimer.h> | ||
#include <linux/fs.h> | ||
#include <linux/debugfs.h> | ||
#include <linux/module.h> | ||
#include <linux/spinlock.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"); | ||
|
||
|
||
extern struct dentry *mips_debugfs_dir; | ||
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); |