linux/kernel/locking/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#include <linux/atomic.h>
  13
  14#include "rwsem.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        rwsem_set_owner(sem);
  53}
  54
  55EXPORT_SYMBOL(down_write);
  56
  57/*
  58 * trylock for writing -- returns 1 if successful, 0 if contention
  59 */
  60int down_write_trylock(struct rw_semaphore *sem)
  61{
  62        int ret = __down_write_trylock(sem);
  63
  64        if (ret == 1) {
  65                rwsem_acquire(&sem->dep_map, 0, 1, _RET_IP_);
  66                rwsem_set_owner(sem);
  67        }
  68
  69        return ret;
  70}
  71
  72EXPORT_SYMBOL(down_write_trylock);
  73
  74/*
  75 * release a read lock
  76 */
  77void up_read(struct rw_semaphore *sem)
  78{
  79        rwsem_release(&sem->dep_map, 1, _RET_IP_);
  80
  81        __up_read(sem);
  82}
  83
  84EXPORT_SYMBOL(up_read);
  85
  86/*
  87 * release a write lock
  88 */
  89void up_write(struct rw_semaphore *sem)
  90{
  91        rwsem_release(&sem->dep_map, 1, _RET_IP_);
  92
  93        rwsem_clear_owner(sem);
  94        __up_write(sem);
  95}
  96
  97EXPORT_SYMBOL(up_write);
  98
  99/*
 100 * downgrade write lock to read lock
 101 */
 102void downgrade_write(struct rw_semaphore *sem)
 103{
 104        /*
 105         * lockdep: a downgraded write will live on as a write
 106         * dependency.
 107         */
 108        rwsem_clear_owner(sem);
 109        __downgrade_write(sem);
 110}
 111
 112EXPORT_SYMBOL(downgrade_write);
 113
 114#ifdef CONFIG_DEBUG_LOCK_ALLOC
 115
 116void down_read_nested(struct rw_semaphore *sem, int subclass)
 117{
 118        might_sleep();
 119        rwsem_acquire_read(&sem->dep_map, subclass, 0, _RET_IP_);
 120
 121        LOCK_CONTENDED(sem, __down_read_trylock, __down_read);
 122}
 123
 124EXPORT_SYMBOL(down_read_nested);
 125
 126void _down_write_nest_lock(struct rw_semaphore *sem, struct lockdep_map *nest)
 127{
 128        might_sleep();
 129        rwsem_acquire_nest(&sem->dep_map, 0, 0, nest, _RET_IP_);
 130
 131        LOCK_CONTENDED(sem, __down_write_trylock, __down_write);
 132        rwsem_set_owner(sem);
 133}
 134
 135EXPORT_SYMBOL(_down_write_nest_lock);
 136
 137void down_read_non_owner(struct rw_semaphore *sem)
 138{
 139        might_sleep();
 140
 141        __down_read(sem);
 142}
 143
 144EXPORT_SYMBOL(down_read_non_owner);
 145
 146void down_write_nested(struct rw_semaphore *sem, int subclass)
 147{
 148        might_sleep();
 149        rwsem_acquire(&sem->dep_map, subclass, 0, _RET_IP_);
 150
 151        LOCK_CONTENDED(sem, __down_write_trylock, __down_write);
 152        rwsem_set_owner(sem);
 153}
 154
 155EXPORT_SYMBOL(down_write_nested);
 156
 157void up_read_non_owner(struct rw_semaphore *sem)
 158{
 159        __up_read(sem);
 160}
 161
 162EXPORT_SYMBOL(up_read_non_owner);
 163
 164#endif
 165
 166
 167