1 // SPDX-License-Identifier: GPL-2.0
3 #include <linux/export.h>
4 #include <linux/log2.h>
5 #include <linux/preempt.h>
6 #include <linux/rcupdate.h>
7 #include <linux/sched.h>
8 #include <linux/sched/rt.h>
12 #define EBUG_ON(cond) BUG_ON(cond)
14 #define EBUG_ON(cond) do {} while (0)
17 #define six_acquire(l, t) lock_acquire(l, 0, t, 0, 0, NULL, _RET_IP_)
18 #define six_release(l) lock_release(l, _RET_IP_)
20 struct six_lock_vals {
21 /* Value we add to the lock in order to take the lock: */
24 /* If the lock has this value (used as a mask), taking the lock fails: */
27 /* Value we add to the lock in order to release the lock: */
30 /* Mask that indicates lock is held for this type: */
33 /* Waitlist we wakeup when releasing the lock: */
34 enum six_lock_type unlock_wakeup;
37 #define __SIX_LOCK_HELD_read __SIX_VAL(read_lock, ~0)
38 #define __SIX_LOCK_HELD_intent __SIX_VAL(intent_lock, ~0)
39 #define __SIX_LOCK_HELD_write __SIX_VAL(seq, 1)
43 .lock_val = __SIX_VAL(read_lock, 1), \
44 .lock_fail = __SIX_LOCK_HELD_write, \
45 .unlock_val = -__SIX_VAL(read_lock, 1), \
46 .held_mask = __SIX_LOCK_HELD_read, \
47 .unlock_wakeup = SIX_LOCK_write, \
49 [SIX_LOCK_intent] = { \
50 .lock_val = __SIX_VAL(intent_lock, 1), \
51 .lock_fail = __SIX_LOCK_HELD_intent, \
52 .unlock_val = -__SIX_VAL(intent_lock, 1), \
53 .held_mask = __SIX_LOCK_HELD_intent, \
54 .unlock_wakeup = SIX_LOCK_intent, \
56 [SIX_LOCK_write] = { \
57 .lock_val = __SIX_VAL(seq, 1), \
58 .lock_fail = __SIX_LOCK_HELD_read, \
59 .unlock_val = __SIX_VAL(seq, 1), \
60 .held_mask = __SIX_LOCK_HELD_write, \
61 .unlock_wakeup = SIX_LOCK_read, \
65 static inline void six_set_owner(struct six_lock *lock, enum six_lock_type type,
66 union six_lock_state old)
68 if (type != SIX_LOCK_intent)
71 if (!old.intent_lock) {
73 lock->owner = current;
75 EBUG_ON(lock->owner != current);
79 static __always_inline bool do_six_trylock_type(struct six_lock *lock,
80 enum six_lock_type type)
82 const struct six_lock_vals l[] = LOCK_VALS;
83 union six_lock_state old;
84 u64 v = READ_ONCE(lock->state.v);
86 EBUG_ON(type == SIX_LOCK_write && lock->owner != current);
91 EBUG_ON(type == SIX_LOCK_write &&
92 ((old.v & __SIX_LOCK_HELD_write) ||
93 !(old.v & __SIX_LOCK_HELD_intent)));
95 if (old.v & l[type].lock_fail)
97 } while ((v = atomic64_cmpxchg_acquire(&lock->state.counter,
99 old.v + l[type].lock_val)) != old.v);
101 six_set_owner(lock, type, old);
105 __always_inline __flatten
106 static bool __six_trylock_type(struct six_lock *lock, enum six_lock_type type)
108 if (!do_six_trylock_type(lock, type))
111 if (type != SIX_LOCK_write)
112 six_acquire(&lock->dep_map, 1);
116 __always_inline __flatten
117 static bool __six_relock_type(struct six_lock *lock, enum six_lock_type type,
120 const struct six_lock_vals l[] = LOCK_VALS;
121 union six_lock_state old;
122 u64 v = READ_ONCE(lock->state.v);
127 if (old.seq != seq || old.v & l[type].lock_fail)
129 } while ((v = atomic64_cmpxchg_acquire(&lock->state.counter,
131 old.v + l[type].lock_val)) != old.v);
133 six_set_owner(lock, type, old);
134 if (type != SIX_LOCK_write)
135 six_acquire(&lock->dep_map, 1);
139 struct six_lock_waiter {
140 struct list_head list;
141 struct task_struct *task;
144 /* This is probably up there with the more evil things I've done */
145 #define waitlist_bitnr(id) ilog2((((union six_lock_state) { .waiters = 1 << (id) }).l))
147 #ifdef CONFIG_LOCK_SPIN_ON_OWNER
149 static inline int six_can_spin_on_owner(struct six_lock *lock)
151 struct task_struct *owner;
158 owner = READ_ONCE(lock->owner);
160 retval = owner->on_cpu;
163 * if lock->owner is not set, the mutex owner may have just acquired
164 * it and not set the owner yet or the mutex has been released.
169 static inline bool six_spin_on_owner(struct six_lock *lock,
170 struct task_struct *owner)
175 while (lock->owner == owner) {
177 * Ensure we emit the owner->on_cpu, dereference _after_
178 * checking lock->owner still matches owner. If that fails,
179 * owner might point to freed memory. If it still matches,
180 * the rcu_read_lock() ensures the memory stays valid.
184 if (!owner->on_cpu || need_resched()) {
196 static inline bool six_optimistic_spin(struct six_lock *lock, enum six_lock_type type)
198 struct task_struct *task = current;
200 if (type == SIX_LOCK_write)
204 if (!six_can_spin_on_owner(lock))
207 if (!osq_lock(&lock->osq))
211 struct task_struct *owner;
214 * If there's an owner, wait for it to either
215 * release the lock or go to sleep.
217 owner = READ_ONCE(lock->owner);
218 if (owner && !six_spin_on_owner(lock, owner))
221 if (do_six_trylock_type(lock, type)) {
222 osq_unlock(&lock->osq);
228 * When there's no owner, we might have preempted between the
229 * owner acquiring the lock and setting the owner field. If
230 * we're an RT task that will live-lock because we won't let
231 * the owner complete.
233 if (!owner && (need_resched() || rt_task(task)))
237 * The cpu_relax() call is a compiler barrier which forces
238 * everything in this loop to be re-loaded. We don't need
239 * memory barriers as we'll eventually observe the right
240 * values at the cost of a few extra spins.
245 osq_unlock(&lock->osq);
250 * If we fell out of the spin path because of need_resched(),
251 * reschedule now, before we try-lock again. This avoids getting
252 * scheduled out right after we obtained the lock.
260 #else /* CONFIG_LOCK_SPIN_ON_OWNER */
262 static inline bool six_optimistic_spin(struct six_lock *lock, enum six_lock_type type)
270 static void __six_lock_type_slowpath(struct six_lock *lock, enum six_lock_type type)
272 const struct six_lock_vals l[] = LOCK_VALS;
273 union six_lock_state old, new;
274 struct six_lock_waiter wait;
277 if (six_optimistic_spin(lock, type))
280 lock_contended(&lock->dep_map, _RET_IP_);
282 INIT_LIST_HEAD(&wait.list);
286 set_current_state(TASK_UNINTERRUPTIBLE);
287 if (type == SIX_LOCK_write)
288 EBUG_ON(lock->owner != current);
289 else if (list_empty_careful(&wait.list)) {
290 raw_spin_lock(&lock->wait_lock);
291 list_add_tail(&wait.list, &lock->wait_list[type]);
292 raw_spin_unlock(&lock->wait_lock);
295 v = READ_ONCE(lock->state.v);
299 if (!(old.v & l[type].lock_fail))
300 new.v += l[type].lock_val;
301 else if (!(new.waiters & (1 << type)))
302 new.waiters |= 1 << type;
304 break; /* waiting bit already set */
305 } while ((v = atomic64_cmpxchg_acquire(&lock->state.counter,
306 old.v, new.v)) != old.v);
308 if (!(old.v & l[type].lock_fail))
314 six_set_owner(lock, type, old);
316 __set_current_state(TASK_RUNNING);
318 if (!list_empty_careful(&wait.list)) {
319 raw_spin_lock(&lock->wait_lock);
320 list_del_init(&wait.list);
321 raw_spin_unlock(&lock->wait_lock);
326 static void __six_lock_type(struct six_lock *lock, enum six_lock_type type)
328 if (type != SIX_LOCK_write)
329 six_acquire(&lock->dep_map, 0);
331 if (!do_six_trylock_type(lock, type))
332 __six_lock_type_slowpath(lock, type);
334 lock_acquired(&lock->dep_map, _RET_IP_);
337 static inline void six_lock_wakeup(struct six_lock *lock,
338 union six_lock_state state,
339 unsigned waitlist_id)
341 struct list_head *wait_list = &lock->wait_list[waitlist_id];
342 struct six_lock_waiter *w, *next;
344 if (waitlist_id == SIX_LOCK_write && state.read_lock)
347 if (!(state.waiters & (1 << waitlist_id)))
350 clear_bit(waitlist_bitnr(waitlist_id),
351 (unsigned long *) &lock->state.v);
353 if (waitlist_id == SIX_LOCK_write) {
354 struct task_struct *p = READ_ONCE(lock->owner);
361 raw_spin_lock(&lock->wait_lock);
363 list_for_each_entry_safe(w, next, wait_list, list) {
364 list_del_init(&w->list);
366 if (wake_up_process(w->task) &&
367 waitlist_id != SIX_LOCK_read) {
368 if (!list_empty(wait_list))
369 set_bit(waitlist_bitnr(waitlist_id),
370 (unsigned long *) &lock->state.v);
375 raw_spin_unlock(&lock->wait_lock);
378 __always_inline __flatten
379 static void __six_unlock_type(struct six_lock *lock, enum six_lock_type type)
381 const struct six_lock_vals l[] = LOCK_VALS;
382 union six_lock_state state;
384 EBUG_ON(!(lock->state.v & l[type].held_mask));
385 EBUG_ON(type == SIX_LOCK_write &&
386 !(lock->state.v & __SIX_LOCK_HELD_intent));
388 if (type != SIX_LOCK_write)
389 six_release(&lock->dep_map);
391 if (type == SIX_LOCK_intent) {
392 EBUG_ON(lock->owner != current);
394 if (lock->intent_lock_recurse) {
395 --lock->intent_lock_recurse;
402 state.v = atomic64_add_return_release(l[type].unlock_val,
403 &lock->state.counter);
404 six_lock_wakeup(lock, state, l[type].unlock_wakeup);
407 #define __SIX_LOCK(type) \
408 bool six_trylock_##type(struct six_lock *lock) \
410 return __six_trylock_type(lock, SIX_LOCK_##type); \
412 EXPORT_SYMBOL_GPL(six_trylock_##type); \
414 bool six_relock_##type(struct six_lock *lock, u32 seq) \
416 return __six_relock_type(lock, SIX_LOCK_##type, seq); \
418 EXPORT_SYMBOL_GPL(six_relock_##type); \
420 void six_lock_##type(struct six_lock *lock) \
422 __six_lock_type(lock, SIX_LOCK_##type); \
424 EXPORT_SYMBOL_GPL(six_lock_##type); \
426 void six_unlock_##type(struct six_lock *lock) \
428 __six_unlock_type(lock, SIX_LOCK_##type); \
430 EXPORT_SYMBOL_GPL(six_unlock_##type);
438 /* Convert from intent to read: */
439 void six_lock_downgrade(struct six_lock *lock)
441 six_lock_increment(lock, SIX_LOCK_read);
442 six_unlock_intent(lock);
444 EXPORT_SYMBOL_GPL(six_lock_downgrade);
446 bool six_lock_tryupgrade(struct six_lock *lock)
448 const struct six_lock_vals l[] = LOCK_VALS;
449 union six_lock_state old, new;
450 u64 v = READ_ONCE(lock->state.v);
455 EBUG_ON(!(old.v & l[SIX_LOCK_read].held_mask));
457 new.v += l[SIX_LOCK_read].unlock_val;
459 if (new.v & l[SIX_LOCK_intent].lock_fail)
462 new.v += l[SIX_LOCK_intent].lock_val;
463 } while ((v = atomic64_cmpxchg_acquire(&lock->state.counter,
464 old.v, new.v)) != old.v);
466 six_set_owner(lock, SIX_LOCK_intent, old);
467 six_lock_wakeup(lock, new, l[SIX_LOCK_read].unlock_wakeup);
471 EXPORT_SYMBOL_GPL(six_lock_tryupgrade);
473 bool six_trylock_convert(struct six_lock *lock,
474 enum six_lock_type from,
475 enum six_lock_type to)
477 EBUG_ON(to == SIX_LOCK_write || from == SIX_LOCK_write);
482 if (to == SIX_LOCK_read) {
483 six_lock_downgrade(lock);
486 return six_lock_tryupgrade(lock);
489 EXPORT_SYMBOL_GPL(six_trylock_convert);
492 * Increment read/intent lock count, assuming we already have it read or intent
495 void six_lock_increment(struct six_lock *lock, enum six_lock_type type)
497 const struct six_lock_vals l[] = LOCK_VALS;
499 EBUG_ON(type == SIX_LOCK_write);
500 six_acquire(&lock->dep_map, 0);
502 /* XXX: assert already locked, and that we don't overflow: */
506 atomic64_add(l[type].lock_val, &lock->state.counter);
508 case SIX_LOCK_intent:
509 lock->intent_lock_recurse++;
516 EXPORT_SYMBOL_GPL(six_lock_increment);