Lines Matching +full:lock +full:- +full:state
1 /* SPDX-License-Identifier: GPL-2.0 */
10 * but with an additional state: read/shared, intent, exclusive/write
12 * The purpose of the intent state is to allow for greater concurrency on tree
14 * write lock without deadlocking, so an operation that updates multiple nodes
17 * But by adding an intent state, which is exclusive with other intent locks but
23 * six_lock_read(&foo->lock);
24 * six_unlock_read(&foo->lock);
26 * An intent lock must be held before taking a write lock:
27 * six_lock_intent(&foo->lock);
28 * six_lock_write(&foo->lock);
29 * six_unlock_write(&foo->lock);
30 * six_unlock_intent(&foo->lock);
40 * There are also interfaces that take the lock type as an enum:
42 * six_lock_type(&foo->lock, SIX_LOCK_read);
43 * six_trylock_convert(&foo->lock, SIX_LOCK_read, SIX_LOCK_intent)
44 * six_lock_type(&foo->lock, SIX_LOCK_write);
45 * six_unlock_type(&foo->lock, SIX_LOCK_write);
46 * six_unlock_type(&foo->lock, SIX_LOCK_intent);
48 * Lock sequence numbers - unlock(), relock():
50 * Locks embed sequences numbers, which are incremented on write lock/unlock.
51 * This allows locks to be dropped and the retaken iff the state they protect
56 * six_lock_read(&foo->lock);
57 * u32 seq = six_lock_seq(&foo->lock);
58 * six_unlock_read(&foo->lock);
62 * if (six_relock_read(&foo->lock, seq)) { ... }
64 * If the relock operation succeeds, it is as if the lock was never unlocked.
70 * layer that tracks held locks. If a lock is known to already be held in the
71 * read or intent state, six_lock_increment() can be used to bump the "lock
72 * held in this state" counter, increasing the number of unlock calls that
76 * six_lock_read(&foo->lock);
77 * six_lock_increment(&foo->lock, SIX_LOCK_read);
78 * six_unlock_read(&foo->lock);
79 * six_unlock_read(&foo->lock);
80 * foo->lock is now fully unlocked.
82 * Since the intent state supercedes read, it's legal to increment the read
83 * counter when holding an intent lock, but not the reverse.
85 * A lock may only be held once for write: six_lock_increment(.., SIX_LOCK_write)
95 * a cache and may reused, and lock ordering is based on a property of the
96 * object that will change when the object is reused - i.e. logical key order.
98 * If looking up an object in the cache may race with object reuse, and lock
100 * correct lock order for that object and cause a deadlock. should_sleep_fn
108 * traversing lock waitlists, it is then possible for an upper layer to
116 * six_lock_waiter() will add the wait object to the waitlist re-trying taking
117 * the lock, and before calling should_sleep_fn, and the wait object will not
118 * be removed from the waitlist until either the lock has been successfully
122 * have timestamps in strictly ascending order - this is so the timestamp can
123 * be used as a cursor for lock graph traverse.
137 atomic_t state; member
158 typedef int (*six_lock_should_sleep_fn)(struct six_lock *lock, void *);
160 void six_lock_exit(struct six_lock *lock);
166 void __six_lock_init(struct six_lock *lock, const char *name,
171 * six_lock_init - initialize a six lock
172 * @lock: lock to initialize
175 #define six_lock_init(lock, flags, gfp) \ argument
179 __six_lock_init((lock), #lock, &__key, flags, gfp); \
183 * six_lock_seq - obtain current lock sequence number
184 * @lock: six_lock to obtain sequence number for
186 * @lock should be held for read or intent, and not write
188 * By saving the lock sequence number, we can unlock @lock and then (typically
191 * and state corresponding to what @lock protects is still valid.
193 static inline u32 six_lock_seq(const struct six_lock *lock) in six_lock_seq() argument
195 return lock->seq; in six_lock_seq()
198 bool six_trylock_ip(struct six_lock *lock, enum six_lock_type type, unsigned long ip);
201 * six_trylock_type - attempt to take a six lock without blocking
202 * @lock: lock to take
207 static inline bool six_trylock_type(struct six_lock *lock, enum six_lock_type type) in six_trylock_type() argument
209 return six_trylock_ip(lock, type, _THIS_IP_); in six_trylock_type()
212 int six_lock_ip_waiter(struct six_lock *lock, enum six_lock_type type,
218 * six_lock_waiter - take a lock, with full waitlist interface
219 * @lock: lock to take
221 * @wait: pointer to wait object, which will be added to lock's waitlist
231 static inline int six_lock_waiter(struct six_lock *lock, enum six_lock_type type, in six_lock_waiter() argument
235 return six_lock_ip_waiter(lock, type, wait, should_sleep_fn, p, _THIS_IP_); in six_lock_waiter()
239 * six_lock_ip - take a six lock lock
240 * @lock: lock to take
249 static inline int six_lock_ip(struct six_lock *lock, enum six_lock_type type, in six_lock_ip() argument
255 return six_lock_ip_waiter(lock, type, &wait, should_sleep_fn, p, ip); in six_lock_ip()
259 * six_lock_type - take a six lock lock
260 * @lock: lock to take
268 static inline int six_lock_type(struct six_lock *lock, enum six_lock_type type, in six_lock_type() argument
273 return six_lock_ip_waiter(lock, type, &wait, should_sleep_fn, p, _THIS_IP_); in six_lock_type()
276 bool six_relock_ip(struct six_lock *lock, enum six_lock_type type,
280 * six_relock_type - attempt to re-take a lock that was held previously
281 * @lock: lock to take
283 * @seq: lock sequence number obtained from six_lock_seq() while lock was
288 static inline bool six_relock_type(struct six_lock *lock, enum six_lock_type type, in six_relock_type() argument
291 return six_relock_ip(lock, type, seq, _THIS_IP_); in six_relock_type()
294 void six_unlock_ip(struct six_lock *lock, enum six_lock_type type, unsigned long ip);
297 * six_unlock_type - drop a six lock
298 * @lock: lock to unlock
301 * When a lock is held multiple times (because six_lock_incement()) was used),
302 * this decrements the 'lock held' counter by one.
305 * six_lock_read(&foo->lock); read count 1
306 * six_lock_increment(&foo->lock, SIX_LOCK_read); read count 2
307 * six_lock_unlock(&foo->lock, SIX_LOCK_read); read count 1
308 * six_lock_unlock(&foo->lock, SIX_LOCK_read); read count 0
310 static inline void six_unlock_type(struct six_lock *lock, enum six_lock_type type) in six_unlock_type() argument
312 six_unlock_ip(lock, type, _THIS_IP_); in six_unlock_type()
316 static inline bool six_trylock_ip_##type(struct six_lock *lock, unsigned long ip)\
318 return six_trylock_ip(lock, SIX_LOCK_##type, ip); \
321 static inline bool six_trylock_##type(struct six_lock *lock) \
323 return six_trylock_ip(lock, SIX_LOCK_##type, _THIS_IP_); \
326 static inline int six_lock_ip_waiter_##type(struct six_lock *lock, \
331 return six_lock_ip_waiter(lock, SIX_LOCK_##type, wait, should_sleep_fn, p, ip);\
334 static inline int six_lock_ip_##type(struct six_lock *lock, \
338 return six_lock_ip(lock, SIX_LOCK_##type, should_sleep_fn, p, ip);\
341 static inline bool six_relock_ip_##type(struct six_lock *lock, u32 seq, unsigned long ip)\
343 return six_relock_ip(lock, SIX_LOCK_##type, seq, ip); \
346 static inline bool six_relock_##type(struct six_lock *lock, u32 seq) \
348 return six_relock_ip(lock, SIX_LOCK_##type, seq, _THIS_IP_); \
351 static inline int six_lock_##type(struct six_lock *lock, \
354 return six_lock_ip_##type(lock, fn, p, _THIS_IP_); \
357 static inline void six_unlock_ip_##type(struct six_lock *lock, unsigned long ip) \
359 six_unlock_ip(lock, SIX_LOCK_##type, ip); \
362 static inline void six_unlock_##type(struct six_lock *lock) \
364 six_unlock_ip(lock, SIX_LOCK_##type, _THIS_IP_); \