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