linux/kernel/rwsem.c
<<
>>
Prefs
   1/* kernel/rwsem.c: R/W semaphores, public implementation
   2 *
   3 * Written by David Howells (dhowells@redhat.com).
   4 * Derived from asm-i386/semaphore.h
   5 */
   6
   7#include <linux/types.h>
   8#include <linux/kernel.h>
   9#include <linux/sched.h>
  10#include <linux/export.h>
  11#include <linux/rwsem.h>
  12
  13#include <linux/atomic.h>
  14
  15/*
  16 * lock for reading
  17 */
  18void __sched down_read(struct rw_semaphore *sem)
  19{
  20        might_sleep();
  21        rwsem_acquire_read(&sem->dep_map, 0, 0, _RET_IP_);
  22
  23        LOCK_CONTENDED(sem, __down_read_trylock, __down_read);
  24}
  25
  26EXPORT_SYMBOL(down_read);
  27
  28/*
  29 * trylock for reading -- returns 1 if successful, 0 if contention
  30 */
  31int down_read_trylock(struct rw_semaphore *sem)
  32{
  33        int ret = __down_read_trylock(sem);
  34
  35        if (ret == 1)
  36                rwsem_acquire_read(&sem->dep_map, 0, 1, _RET_IP_);
  37        return ret;
  38}
  39
  40EXPORT_SYMBOL(down_read_trylock);
  41
  42/*
  43 * lock for writing
  44 */
  45void __sched down_write(struct rw_semaphore *sem)
  46{
  47        might_sleep();
  48        rwsem_acquire(&sem->dep_map, 0, 0, _RET_IP_);
  49
  50        LOCK_CONTENDED(sem, __down_write_trylock, __down_write);
  51}
  52
  53EXPORT_SYMBOL(down_write);
  54
  55/*
  56 * trylock for writing -- returns 1 if successful, 0 if contention
  57 */
  58int down_write_trylock(struct rw_semaphore *sem)
  59{
  60        int ret = __down_write_trylock(sem);
  61
  62        if (ret == 1)
  63                rwsem_acquire(&sem->dep_map, 0, 1, _RET_IP_);
  64        return ret;
  65}
  66
  67EXPORT_SYMBOL(down_write_trylock);
  68
  69/*
  70 * release a read lock
  71 */
  72void up_read(struct rw_semaphore *sem)
  73{
  74        rwsem_release(&sem->dep_map, 1, _RET_IP_);
  75
  76        __up_read(sem);
  77}
  78
  79EXPORT_SYMBOL(up_read);
  80
  81/*
  82 * release a write lock
  83 */
  84void up_write(struct rw_semaphore *sem)
  85{
  86        rwsem_release(&sem->dep_map, 1, _RET_IP_);
  87
  88        __up_write(sem);
  89}
  90
  91EXPORT_SYMBOL(up_write);
  92
  93/*
  94 * downgrade write lock to read lock
  95 */
  96void downgrade_write(struct rw_semaphore *sem)
  97{
  98        /*
  99         * lockdep: a downgraded write will live on as a write
 100         * dependency.
 101         */
 102        __downgrade_write(sem);
 103}
 104
 105EXPORT_SYMBOL(downgrade_write);
 106
 107#ifdef CONFIG_DEBUG_LOCK_ALLOC
 108
 109void down_read_nested(struct rw_semaphore *sem, int subclass)
 110{
 111        might_sleep();
 112        rwsem_acquire_read(&sem->dep_map, subclass, 0, _RET_IP_);
 113
 114        LOCK_CONTENDED(sem, __down_read_trylock, __down_read);
 115}
 116
 117EXPORT_SYMBOL(down_read_nested);
 118
 119void _down_write_nest_lock(struct rw_semaphore *sem, struct lockdep_map *nest)
 120{
 121        might_sleep();
 122        rwsem_acquire_nest(&sem->dep_map, 0, 0, nest, _RET_IP_);
 123
 124        LOCK_CONTENDED(sem, __down_write_trylock, __down_write);
 125}
 126
 127EXPORT_SYMBOL(_down_write_nest_lock);
 128
 129void down_read_non_owner(struct rw_semaphore *sem)
 130{
 131        might_sleep();
 132
 133        __down_read(sem);
 134}
 135
 136EXPORT_SYMBOL(down_read_non_owner);
 137
 138void down_write_nested(struct rw_semaphore *sem, int subclass)
 139{
 140        might_sleep();
 141        rwsem_acquire(&sem->dep_map, subclass, 0, _RET_IP_);
 142
 143        LOCK_CONTENDED(sem, __down_write_trylock, __down_write);
 144}
 145
 146EXPORT_SYMBOL(down_write_nested);
 147
 148void up_read_non_owner(struct rw_semaphore *sem)
 149{
 150        __up_read(sem);
 151}
 152
 153EXPORT_SYMBOL(up_read_non_owner);
 154
 155#endif
 156
 157
 158