2006-07-03 11:24:29 +04:00
/* kernel/rwsem.c: R/W semaphores, public implementation
*
* Written by David Howells ( dhowells @ redhat . com ) .
* Derived from asm - i386 / semaphore . h
*/
# include <linux/types.h>
# include <linux/kernel.h>
2007-12-18 17:21:13 +03:00
# include <linux/sched.h>
2011-05-23 22:51:41 +04:00
# include <linux/export.h>
2006-07-03 11:24:29 +04:00
# include <linux/rwsem.h>
# include <asm/system.h>
2011-07-27 03:09:06 +04:00
# include <linux/atomic.h>
2006-07-03 11:24:29 +04:00
/*
* lock for reading
*/
2007-12-18 17:21:13 +03:00
void __sched down_read ( struct rw_semaphore * sem )
2006-07-03 11:24:29 +04:00
{
might_sleep ( ) ;
rwsem_acquire_read ( & sem - > dep_map , 0 , 0 , _RET_IP_ ) ;
2007-07-19 12:48:58 +04:00
LOCK_CONTENDED ( sem , __down_read_trylock , __down_read ) ;
2006-07-03 11:24:29 +04:00
}
EXPORT_SYMBOL ( down_read ) ;
/*
* trylock for reading - - returns 1 if successful , 0 if contention
*/
int down_read_trylock ( struct rw_semaphore * sem )
{
int ret = __down_read_trylock ( sem ) ;
if ( ret = = 1 )
rwsem_acquire_read ( & sem - > dep_map , 0 , 1 , _RET_IP_ ) ;
return ret ;
}
EXPORT_SYMBOL ( down_read_trylock ) ;
/*
* lock for writing
*/
2007-12-18 17:21:13 +03:00
void __sched down_write ( struct rw_semaphore * sem )
2006-07-03 11:24:29 +04:00
{
might_sleep ( ) ;
rwsem_acquire ( & sem - > dep_map , 0 , 0 , _RET_IP_ ) ;
2007-07-19 12:48:58 +04:00
LOCK_CONTENDED ( sem , __down_write_trylock , __down_write ) ;
2006-07-03 11:24:29 +04:00
}
EXPORT_SYMBOL ( down_write ) ;
/*
* trylock for writing - - returns 1 if successful , 0 if contention
*/
int down_write_trylock ( struct rw_semaphore * sem )
{
int ret = __down_write_trylock ( sem ) ;
if ( ret = = 1 )
2007-05-08 11:29:10 +04:00
rwsem_acquire ( & sem - > dep_map , 0 , 1 , _RET_IP_ ) ;
2006-07-03 11:24:29 +04:00
return ret ;
}
EXPORT_SYMBOL ( down_write_trylock ) ;
/*
* release a read lock
*/
void up_read ( struct rw_semaphore * sem )
{
rwsem_release ( & sem - > dep_map , 1 , _RET_IP_ ) ;
__up_read ( sem ) ;
}
EXPORT_SYMBOL ( up_read ) ;
/*
* release a write lock
*/
void up_write ( struct rw_semaphore * sem )
{
rwsem_release ( & sem - > dep_map , 1 , _RET_IP_ ) ;
__up_write ( sem ) ;
}
EXPORT_SYMBOL ( up_write ) ;
/*
* downgrade write lock to read lock
*/
void downgrade_write ( struct rw_semaphore * sem )
{
/*
* lockdep : a downgraded write will live on as a write
* dependency .
*/
__downgrade_write ( sem ) ;
}
EXPORT_SYMBOL ( downgrade_write ) ;
2006-07-03 11:24:53 +04:00
# ifdef CONFIG_DEBUG_LOCK_ALLOC
void down_read_nested ( struct rw_semaphore * sem , int subclass )
{
might_sleep ( ) ;
rwsem_acquire_read ( & sem - > dep_map , subclass , 0 , _RET_IP_ ) ;
2007-07-19 12:48:58 +04:00
LOCK_CONTENDED ( sem , __down_read_trylock , __down_read ) ;
2006-07-03 11:24:53 +04:00
}
EXPORT_SYMBOL ( down_read_nested ) ;
void down_write_nested ( struct rw_semaphore * sem , int subclass )
{
might_sleep ( ) ;
rwsem_acquire ( & sem - > dep_map , subclass , 0 , _RET_IP_ ) ;
2007-07-19 12:48:58 +04:00
LOCK_CONTENDED ( sem , __down_write_trylock , __down_write ) ;
2006-07-03 11:24:53 +04:00
}
EXPORT_SYMBOL ( down_write_nested ) ;
# endif