2010-02-17 02:26:35 +03:00
# include <linux/init.h>
# include <linux/kthread.h>
# include <linux/hrtimer.h>
# include <linux/fs.h>
# include <linux/debugfs.h>
2011-07-24 00:30:40 +04:00
# include <linux/export.h>
2010-02-17 02:26:35 +03:00
# 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 ) ;