2 * Copyright (C) 2005-2012 Junjiro R. Okajima
4 * This program, aufs is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
20 * simple read-write semaphore wrappers
23 #ifndef __AUFS_RWSEM_H__
24 #define __AUFS_RWSEM_H__
31 struct rw_semaphore rwsem;
32 #ifdef CONFIG_AUFS_DEBUG
33 /* just for debugging, not almighty counter */
38 #ifdef CONFIG_AUFS_DEBUG
39 #define AuDbgCntInit(rw) do { \
40 atomic_set(&(rw)->rcnt, 0); \
41 atomic_set(&(rw)->wcnt, 0); \
42 smp_mb(); /* atomic set */ \
45 #define AuDbgRcntInc(rw) atomic_inc(&(rw)->rcnt)
46 #define AuDbgRcntDec(rw) WARN_ON(atomic_dec_return(&(rw)->rcnt) < 0)
47 #define AuDbgWcntInc(rw) atomic_inc(&(rw)->wcnt)
48 #define AuDbgWcntDec(rw) WARN_ON(atomic_dec_return(&(rw)->wcnt) < 0)
50 #define AuDbgCntInit(rw) do {} while (0)
51 #define AuDbgRcntInc(rw) do {} while (0)
52 #define AuDbgRcntDec(rw) do {} while (0)
53 #define AuDbgWcntInc(rw) do {} while (0)
54 #define AuDbgWcntDec(rw) do {} while (0)
55 #endif /* CONFIG_AUFS_DEBUG */
57 /* to debug easier, do not make them inlined functions */
58 #define AuRwMustNoWaiters(rw) AuDebugOn(!list_empty(&(rw)->rwsem.wait_list))
59 /* rwsem_is_locked() is unusable */
60 #define AuRwMustReadLock(rw) AuDebugOn(atomic_read(&(rw)->rcnt) <= 0)
61 #define AuRwMustWriteLock(rw) AuDebugOn(atomic_read(&(rw)->wcnt) <= 0)
62 #define AuRwMustAnyLock(rw) AuDebugOn(atomic_read(&(rw)->rcnt) <= 0 \
63 && atomic_read(&(rw)->wcnt) <= 0)
64 #define AuRwDestroy(rw) AuDebugOn(atomic_read(&(rw)->rcnt) \
65 || atomic_read(&(rw)->wcnt))
67 #define au_rw_class(rw, key) lockdep_set_class(&(rw)->rwsem, key)
69 static inline void au_rw_init(struct au_rwsem *rw)
72 init_rwsem(&rw->rwsem);
75 static inline void au_rw_init_wlock(struct au_rwsem *rw)
78 down_write(&rw->rwsem);
82 static inline void au_rw_init_wlock_nested(struct au_rwsem *rw,
86 down_write_nested(&rw->rwsem, lsc);
90 static inline void au_rw_read_lock(struct au_rwsem *rw)
92 down_read(&rw->rwsem);
96 static inline void au_rw_read_lock_nested(struct au_rwsem *rw, unsigned int lsc)
98 down_read_nested(&rw->rwsem, lsc);
102 static inline void au_rw_read_unlock(struct au_rwsem *rw)
104 AuRwMustReadLock(rw);
109 static inline void au_rw_dgrade_lock(struct au_rwsem *rw)
111 AuRwMustWriteLock(rw);
114 downgrade_write(&rw->rwsem);
117 static inline void au_rw_write_lock(struct au_rwsem *rw)
119 down_write(&rw->rwsem);
123 static inline void au_rw_write_lock_nested(struct au_rwsem *rw,
126 down_write_nested(&rw->rwsem, lsc);
130 static inline void au_rw_write_unlock(struct au_rwsem *rw)
132 AuRwMustWriteLock(rw);
134 up_write(&rw->rwsem);
137 /* why is not _nested version defined */
138 static inline int au_rw_read_trylock(struct au_rwsem *rw)
140 int ret = down_read_trylock(&rw->rwsem);
146 static inline int au_rw_write_trylock(struct au_rwsem *rw)
148 int ret = down_write_trylock(&rw->rwsem);
160 #define AuSimpleLockRwsemFuncs(prefix, param, rwsem) \
161 static inline void prefix##_read_lock(param) \
162 { au_rw_read_lock(rwsem); } \
163 static inline void prefix##_write_lock(param) \
164 { au_rw_write_lock(rwsem); } \
165 static inline int prefix##_read_trylock(param) \
166 { return au_rw_read_trylock(rwsem); } \
167 static inline int prefix##_write_trylock(param) \
168 { return au_rw_write_trylock(rwsem); }
169 /* why is not _nested version defined */
170 /* static inline void prefix##_read_trylock_nested(param, lsc)
171 { au_rw_read_trylock_nested(rwsem, lsc)); }
172 static inline void prefix##_write_trylock_nestd(param, lsc)
173 { au_rw_write_trylock_nested(rwsem, lsc); } */
175 #define AuSimpleUnlockRwsemFuncs(prefix, param, rwsem) \
176 static inline void prefix##_read_unlock(param) \
177 { au_rw_read_unlock(rwsem); } \
178 static inline void prefix##_write_unlock(param) \
179 { au_rw_write_unlock(rwsem); } \
180 static inline void prefix##_downgrade_lock(param) \
181 { au_rw_dgrade_lock(rwsem); }
183 #define AuSimpleRwsemFuncs(prefix, param, rwsem) \
184 AuSimpleLockRwsemFuncs(prefix, param, rwsem) \
185 AuSimpleUnlockRwsemFuncs(prefix, param, rwsem)
187 #endif /* __KERNEL__ */
188 #endif /* __AUFS_RWSEM_H__ */