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: