File: /Users/paulross/dev/linux/linux-3.13/include/linux/rwsem.h

Green shading in the line number column means the source is part of the translation unit, red means it is conditionally excluded. Highlighted line numbers link to the translation unit page. Highlighted macros link to the macro page.

       1: /* rwsem.h: R/W semaphores, public interface
       2:  *
       3:  * Written by David Howells (dhowells@redhat.com).
       4:  * Derived from asm-i386/semaphore.h
       5:  */
       6: 
       7: #ifndef _LINUX_RWSEM_H
       8: #define _LINUX_RWSEM_H
       9: 
      10: #include <linux/linkage.h>
      11: 
      12: #include <linux/types.h>
      13: #include <linux/kernel.h>
      14: #include <linux/list.h>
      15: #include <linux/spinlock.h>
      16: 
      17: #include <linux/atomic.h>
      18: 
      19: struct rw_semaphore;
      20: 
      21: #ifdef CONFIG_RWSEM_GENERIC_SPINLOCK
      22: #include <linux/rwsem-spinlock.h> /* use a generic implementation */
      23: #else
      24: /* All arch specific implementations share the same struct */
      25: struct rw_semaphore {
      26:     long            count;
      27:     raw_spinlock_t        wait_lock;
      28:     struct list_head    wait_list;
      29: #ifdef CONFIG_DEBUG_LOCK_ALLOC
      30:     struct lockdep_map    dep_map;
      31: #endif
      32: };
      33: 
      34: extern struct rw_semaphore *rwsem_down_read_failed(struct rw_semaphore *sem);
      35: extern struct rw_semaphore *rwsem_down_write_failed(struct rw_semaphore *sem);
      36: extern struct rw_semaphore *rwsem_wake(struct rw_semaphore *);
      37: extern struct rw_semaphore *rwsem_downgrade_wake(struct rw_semaphore *sem);
      38: 
      39: /* Include the arch specific part */
      40: #include <asm/rwsem.h>
      41: 
      42: /* In all implementations count != 0 means locked */
      43: static inline int rwsem_is_locked(struct rw_semaphore *sem)
      44: {
      45:     return sem->count != 0;
      46: }
      47: 
      48: #endif
      49: 
      50: /* Common initializer macros and functions */
      51: 
      52: #ifdef CONFIG_DEBUG_LOCK_ALLOC
      53: # define __RWSEM_DEP_MAP_INIT(lockname) , .dep_map = { .name = #lockname }
      54: #else
      55: # define __RWSEM_DEP_MAP_INIT(lockname)
      56: #endif
      57: 
      58: #define __RWSEM_INITIALIZER(name)            \
      59:     { RWSEM_UNLOCKED_VALUE,                \
      60:       __RAW_SPIN_LOCK_UNLOCKED(name.wait_lock),    \
      61:       LIST_HEAD_INIT((name).wait_list)        \
      62:       __RWSEM_DEP_MAP_INIT(name) }
      63: 
      64: #define DECLARE_RWSEM(name) \
      65:     struct rw_semaphore name = __RWSEM_INITIALIZER(name)
      66: 
      67: extern void __init_rwsem(struct rw_semaphore *sem, const char *name,
      68:              struct lock_class_key *key);
      69: 
      70: #define init_rwsem(sem)                        \
      71: do {                                \
      72:     static struct lock_class_key __key;            \
      73:                                 \
      74:     __init_rwsem((sem), #sem, &__key);            \
      75: } while (0)
      76: 
      77: /*
      78:  * lock for reading
      79:  */
      80: extern void down_read(struct rw_semaphore *sem);
      81: 
      82: /*
      83:  * trylock for reading -- returns 1 if successful, 0 if contention
      84:  */
      85: extern int down_read_trylock(struct rw_semaphore *sem);
      86: 
      87: /*
      88:  * lock for writing
      89:  */
      90: extern void down_write(struct rw_semaphore *sem);
      91: 
      92: /*
      93:  * trylock for writing -- returns 1 if successful, 0 if contention
      94:  */
      95: extern int down_write_trylock(struct rw_semaphore *sem);
      96: 
      97: /*
      98:  * release a read lock
      99:  */
     100: extern void up_read(struct rw_semaphore *sem);
     101: 
     102: /*
     103:  * release a write lock
     104:  */
     105: extern void up_write(struct rw_semaphore *sem);
     106: 
     107: /*
     108:  * downgrade write lock to read lock
     109:  */
     110: extern void downgrade_write(struct rw_semaphore *sem);
     111: 
     112: #ifdef CONFIG_DEBUG_LOCK_ALLOC
     113: /*
     114:  * nested locking. NOTE: rwsems are not allowed to recurse
     115:  * (which occurs if the same task tries to acquire the same
     116:  * lock instance multiple times), but multiple locks of the
     117:  * same lock class might be taken, if the order of the locks
     118:  * is always the same. This ordering rule can be expressed
     119:  * to lockdep via the _nested() APIs, but enumerating the
     120:  * subclasses that are used. (If the nesting relationship is
     121:  * static then another method for expressing nested locking is
     122:  * the explicit definition of lock class keys and the use of
     123:  * lockdep_set_class() at lock initialization time.
     124:  * See Documentation/lockdep-design.txt for more details.)
     125:  */
     126: extern void down_read_nested(struct rw_semaphore *sem, int subclass);
     127: extern void down_write_nested(struct rw_semaphore *sem, int subclass);
     128: extern void _down_write_nest_lock(struct rw_semaphore *sem, struct lockdep_map *nest_lock);
     129: 
     130: # define down_write_nest_lock(sem, nest_lock)            \
     131: do {                                \
     132:     typecheck(struct lockdep_map *, &(nest_lock)->dep_map);    \
     133:     _down_write_nest_lock(sem, &(nest_lock)->dep_map);    \
     134: } while (0);
     135: 
     136: /*
     137:  * Take/release a lock when not the owner will release it.
     138:  *
     139:  * [ This API should be avoided as much as possible - the
     140:  *   proper abstraction for this case is completions. ]
     141:  */
     142: extern void down_read_non_owner(struct rw_semaphore *sem);
     143: extern void up_read_non_owner(struct rw_semaphore *sem);
     144: #else
     145: # define down_read_nested(sem, subclass)        down_read(sem)
     146: # define down_write_nest_lock(sem, nest_lock)    down_write(sem)
     147: # define down_write_nested(sem, subclass)    down_write(sem)
     148: # define down_read_non_owner(sem)        down_read(sem)
     149: # define up_read_non_owner(sem)            up_read(sem)
     150: #endif
     151: 
     152: #endif /* _LINUX_RWSEM_H */
     153: