]> git.sesse.net Git - bcachefs-tools-debian/blob - linux/six.c
Update bcachefs sources to 1b14994029 bcachefs: Fragmentation LRU
[bcachefs-tools-debian] / linux / six.c
1 // SPDX-License-Identifier: GPL-2.0
2
3 #include <linux/export.h>
4 #include <linux/log2.h>
5 #include <linux/percpu.h>
6 #include <linux/preempt.h>
7 #include <linux/rcupdate.h>
8 #include <linux/sched.h>
9 #include <linux/sched/clock.h>
10 #include <linux/sched/rt.h>
11 #include <linux/six.h>
12 #include <linux/slab.h>
13
14 #include <trace/events/lock.h>
15
16 #ifdef DEBUG
17 #define EBUG_ON(cond)           BUG_ON(cond)
18 #else
19 #define EBUG_ON(cond)           do {} while (0)
20 #endif
21
22 #define six_acquire(l, t, r, ip)        lock_acquire(l, 0, t, r, 1, NULL, ip)
23 #define six_release(l, ip)              lock_release(l, ip)
24
25 static void do_six_unlock_type(struct six_lock *lock, enum six_lock_type type);
26
27 struct six_lock_vals {
28         /* Value we add to the lock in order to take the lock: */
29         u64                     lock_val;
30
31         /* If the lock has this value (used as a mask), taking the lock fails: */
32         u64                     lock_fail;
33
34         /* Value we add to the lock in order to release the lock: */
35         u64                     unlock_val;
36
37         /* Mask that indicates lock is held for this type: */
38         u64                     held_mask;
39
40         /* Waitlist we wakeup when releasing the lock: */
41         enum six_lock_type      unlock_wakeup;
42 };
43
44 #define __SIX_LOCK_HELD_read    __SIX_VAL(read_lock, ~0)
45 #define __SIX_LOCK_HELD_intent  __SIX_VAL(intent_lock, ~0)
46 #define __SIX_LOCK_HELD_write   __SIX_VAL(seq, 1)
47
48 #define LOCK_VALS {                                                     \
49         [SIX_LOCK_read] = {                                             \
50                 .lock_val       = __SIX_VAL(read_lock, 1),              \
51                 .lock_fail      = __SIX_LOCK_HELD_write + __SIX_VAL(write_locking, 1),\
52                 .unlock_val     = -__SIX_VAL(read_lock, 1),             \
53                 .held_mask      = __SIX_LOCK_HELD_read,                 \
54                 .unlock_wakeup  = SIX_LOCK_write,                       \
55         },                                                              \
56         [SIX_LOCK_intent] = {                                           \
57                 .lock_val       = __SIX_VAL(intent_lock, 1),            \
58                 .lock_fail      = __SIX_LOCK_HELD_intent,               \
59                 .unlock_val     = -__SIX_VAL(intent_lock, 1),           \
60                 .held_mask      = __SIX_LOCK_HELD_intent,               \
61                 .unlock_wakeup  = SIX_LOCK_intent,                      \
62         },                                                              \
63         [SIX_LOCK_write] = {                                            \
64                 .lock_val       = __SIX_VAL(seq, 1),                    \
65                 .lock_fail      = __SIX_LOCK_HELD_read,                 \
66                 .unlock_val     = __SIX_VAL(seq, 1),                    \
67                 .held_mask      = __SIX_LOCK_HELD_write,                \
68                 .unlock_wakeup  = SIX_LOCK_read,                        \
69         },                                                              \
70 }
71
72 static inline void six_set_owner(struct six_lock *lock, enum six_lock_type type,
73                                  union six_lock_state old,
74                                  struct task_struct *owner)
75 {
76         if (type != SIX_LOCK_intent)
77                 return;
78
79         if (!old.intent_lock) {
80                 EBUG_ON(lock->owner);
81                 lock->owner = owner;
82         } else {
83                 EBUG_ON(lock->owner != current);
84         }
85 }
86
87 static inline unsigned pcpu_read_count(struct six_lock *lock)
88 {
89         unsigned read_count = 0;
90         int cpu;
91
92         for_each_possible_cpu(cpu)
93                 read_count += *per_cpu_ptr(lock->readers, cpu);
94         return read_count;
95 }
96
97 /* This is probably up there with the more evil things I've done */
98 #define waitlist_bitnr(id) ilog2((((union six_lock_state) { .waiters = 1 << (id) }).l))
99
100 static int __do_six_trylock_type(struct six_lock *lock,
101                                  enum six_lock_type type,
102                                  struct task_struct *task,
103                                  bool try)
104 {
105         const struct six_lock_vals l[] = LOCK_VALS;
106         union six_lock_state old, new;
107         int ret;
108         u64 v;
109
110         EBUG_ON(type == SIX_LOCK_write && lock->owner != task);
111         EBUG_ON(type == SIX_LOCK_write && (lock->state.seq & 1));
112         EBUG_ON(type == SIX_LOCK_write && (try != !(lock->state.write_locking)));
113
114         /*
115          * Percpu reader mode:
116          *
117          * The basic idea behind this algorithm is that you can implement a lock
118          * between two threads without any atomics, just memory barriers:
119          *
120          * For two threads you'll need two variables, one variable for "thread a
121          * has the lock" and another for "thread b has the lock".
122          *
123          * To take the lock, a thread sets its variable indicating that it holds
124          * the lock, then issues a full memory barrier, then reads from the
125          * other thread's variable to check if the other thread thinks it has
126          * the lock. If we raced, we backoff and retry/sleep.
127          */
128
129         if (type == SIX_LOCK_read && lock->readers) {
130                 preempt_disable();
131                 this_cpu_inc(*lock->readers); /* signal that we own lock */
132
133                 smp_mb();
134
135                 old.v = READ_ONCE(lock->state.v);
136                 ret = !(old.v & l[type].lock_fail);
137
138                 this_cpu_sub(*lock->readers, !ret);
139                 preempt_enable();
140
141                 /*
142                  * If we failed because a writer was trying to take the
143                  * lock, issue a wakeup because we might have caused a
144                  * spurious trylock failure:
145                  */
146                 if (old.write_locking)
147                         ret = -1 - SIX_LOCK_write;
148         } else if (type == SIX_LOCK_write && lock->readers) {
149                 if (try) {
150                         atomic64_add(__SIX_VAL(write_locking, 1),
151                                      &lock->state.counter);
152                         smp_mb__after_atomic();
153                 } else if (!(lock->state.waiters & (1 << SIX_LOCK_write))) {
154                         atomic64_add(__SIX_VAL(waiters, 1 << SIX_LOCK_write),
155                                      &lock->state.counter);
156                         /*
157                          * pairs with barrier after unlock and before checking
158                          * for readers in unlock path
159                          */
160                         smp_mb__after_atomic();
161                 }
162
163                 ret = !pcpu_read_count(lock);
164
165                 /*
166                  * On success, we increment lock->seq; also we clear
167                  * write_locking unless we failed from the lock path:
168                  */
169                 v = 0;
170                 if (ret)
171                         v += __SIX_VAL(seq, 1);
172                 if (ret || try)
173                         v -= __SIX_VAL(write_locking, 1);
174
175                 if (try && !ret) {
176                         old.v = atomic64_add_return(v, &lock->state.counter);
177                         if (old.waiters & (1 << SIX_LOCK_read))
178                                 ret = -1 - SIX_LOCK_read;
179                 } else {
180                         atomic64_add(v, &lock->state.counter);
181                 }
182         } else {
183                 v = READ_ONCE(lock->state.v);
184                 do {
185                         new.v = old.v = v;
186
187                         if (!(old.v & l[type].lock_fail)) {
188                                 new.v += l[type].lock_val;
189
190                                 if (type == SIX_LOCK_write)
191                                         new.write_locking = 0;
192                         } else if (!try && !(new.waiters & (1 << type)))
193                                 new.waiters |= 1 << type;
194                         else
195                                 break; /* waiting bit already set */
196                 } while ((v = atomic64_cmpxchg_acquire(&lock->state.counter,
197                                         old.v, new.v)) != old.v);
198
199                 ret = !(old.v & l[type].lock_fail);
200
201                 EBUG_ON(ret && !(lock->state.v & l[type].held_mask));
202         }
203
204         if (ret > 0)
205                 six_set_owner(lock, type, old, task);
206
207         EBUG_ON(type == SIX_LOCK_write && (try || ret > 0) && (lock->state.write_locking));
208
209         return ret;
210 }
211
212 static inline void __six_lock_wakeup(struct six_lock *lock, enum six_lock_type lock_type)
213 {
214         struct six_lock_waiter *w, *next;
215         struct task_struct *task;
216         bool saw_one;
217         int ret;
218 again:
219         ret = 0;
220         saw_one = false;
221         raw_spin_lock(&lock->wait_lock);
222
223         list_for_each_entry_safe(w, next, &lock->wait_list, list) {
224                 if (w->lock_want != lock_type)
225                         continue;
226
227                 if (saw_one && lock_type != SIX_LOCK_read)
228                         goto unlock;
229                 saw_one = true;
230
231                 ret = __do_six_trylock_type(lock, lock_type, w->task, false);
232                 if (ret <= 0)
233                         goto unlock;
234
235                 __list_del(w->list.prev, w->list.next);
236                 task = w->task;
237                 /*
238                  * Do no writes to @w besides setting lock_acquired - otherwise
239                  * we would need a memory barrier:
240                  */
241                 barrier();
242                 w->lock_acquired = true;
243                 wake_up_process(task);
244         }
245
246         clear_bit(waitlist_bitnr(lock_type), (unsigned long *) &lock->state.v);
247 unlock:
248         raw_spin_unlock(&lock->wait_lock);
249
250         if (ret < 0) {
251                 lock_type = -ret - 1;
252                 goto again;
253         }
254 }
255
256 static inline void six_lock_wakeup(struct six_lock *lock,
257                                    union six_lock_state state,
258                                    enum six_lock_type lock_type)
259 {
260         if (lock_type == SIX_LOCK_write && state.read_lock)
261                 return;
262
263         if (!(state.waiters & (1 << lock_type)))
264                 return;
265
266         __six_lock_wakeup(lock, lock_type);
267 }
268
269 static bool do_six_trylock_type(struct six_lock *lock,
270                                 enum six_lock_type type,
271                                 bool try)
272 {
273         int ret;
274
275         ret = __do_six_trylock_type(lock, type, current, try);
276         if (ret < 0)
277                 __six_lock_wakeup(lock, -ret - 1);
278
279         return ret > 0;
280 }
281
282 __always_inline __flatten
283 static bool __six_trylock_type(struct six_lock *lock, enum six_lock_type type,
284                                unsigned long ip)
285 {
286         if (!do_six_trylock_type(lock, type, true))
287                 return false;
288
289         if (type != SIX_LOCK_write)
290                 six_acquire(&lock->dep_map, 1, type == SIX_LOCK_read, ip);
291         return true;
292 }
293
294 __always_inline __flatten
295 static bool __six_relock_type(struct six_lock *lock, enum six_lock_type type,
296                               unsigned seq, unsigned long ip)
297 {
298         const struct six_lock_vals l[] = LOCK_VALS;
299         union six_lock_state old;
300         u64 v;
301
302         EBUG_ON(type == SIX_LOCK_write);
303
304         if (type == SIX_LOCK_read &&
305             lock->readers) {
306                 bool ret;
307
308                 preempt_disable();
309                 this_cpu_inc(*lock->readers);
310
311                 smp_mb();
312
313                 old.v = READ_ONCE(lock->state.v);
314                 ret = !(old.v & l[type].lock_fail) && old.seq == seq;
315
316                 this_cpu_sub(*lock->readers, !ret);
317                 preempt_enable();
318
319                 /*
320                  * Similar to the lock path, we may have caused a spurious write
321                  * lock fail and need to issue a wakeup:
322                  */
323                 if (old.write_locking)
324                         six_lock_wakeup(lock, old, SIX_LOCK_write);
325
326                 if (ret)
327                         six_acquire(&lock->dep_map, 1, type == SIX_LOCK_read, ip);
328
329                 return ret;
330         }
331
332         v = READ_ONCE(lock->state.v);
333         do {
334                 old.v = v;
335
336                 if (old.seq != seq || old.v & l[type].lock_fail)
337                         return false;
338         } while ((v = atomic64_cmpxchg_acquire(&lock->state.counter,
339                                 old.v,
340                                 old.v + l[type].lock_val)) != old.v);
341
342         six_set_owner(lock, type, old, current);
343         if (type != SIX_LOCK_write)
344                 six_acquire(&lock->dep_map, 1, type == SIX_LOCK_read, ip);
345         return true;
346 }
347
348 #ifdef CONFIG_LOCK_SPIN_ON_OWNER
349
350 static inline bool six_can_spin_on_owner(struct six_lock *lock)
351 {
352         struct task_struct *owner;
353         bool ret;
354
355         if (need_resched())
356                 return false;
357
358         rcu_read_lock();
359         owner = READ_ONCE(lock->owner);
360         ret = !owner || owner_on_cpu(owner);
361         rcu_read_unlock();
362
363         return ret;
364 }
365
366 static inline void six_set_nospin(struct six_lock *lock)
367 {
368         union six_lock_state old, new;
369         u64 v = READ_ONCE(lock->state.v);
370
371         do {
372                 new.v = old.v = v;
373                 new.nospin = true;
374         } while ((v = atomic64_cmpxchg(&lock->state.counter, old.v, new.v)) != old.v);
375 }
376
377 static inline bool six_spin_on_owner(struct six_lock *lock,
378                                      struct task_struct *owner,
379                                      u64 end_time)
380 {
381         bool ret = true;
382         unsigned loop = 0;
383
384         rcu_read_lock();
385         while (lock->owner == owner) {
386                 /*
387                  * Ensure we emit the owner->on_cpu, dereference _after_
388                  * checking lock->owner still matches owner. If that fails,
389                  * owner might point to freed memory. If it still matches,
390                  * the rcu_read_lock() ensures the memory stays valid.
391                  */
392                 barrier();
393
394                 if (!owner_on_cpu(owner) || need_resched()) {
395                         ret = false;
396                         break;
397                 }
398
399                 if (!(++loop & 0xf) && (time_after64(sched_clock(), end_time))) {
400                         six_set_nospin(lock);
401                         ret = false;
402                         break;
403                 }
404
405                 cpu_relax();
406         }
407         rcu_read_unlock();
408
409         return ret;
410 }
411
412 static inline bool six_optimistic_spin(struct six_lock *lock, enum six_lock_type type)
413 {
414         struct task_struct *task = current;
415         u64 end_time;
416
417         if (type == SIX_LOCK_write)
418                 return false;
419
420         preempt_disable();
421         if (!six_can_spin_on_owner(lock))
422                 goto fail;
423
424         if (!osq_lock(&lock->osq))
425                 goto fail;
426
427         end_time = sched_clock() + 10 * NSEC_PER_USEC;
428
429         while (1) {
430                 struct task_struct *owner;
431
432                 /*
433                  * If there's an owner, wait for it to either
434                  * release the lock or go to sleep.
435                  */
436                 owner = READ_ONCE(lock->owner);
437                 if (owner && !six_spin_on_owner(lock, owner, end_time))
438                         break;
439
440                 if (do_six_trylock_type(lock, type, false)) {
441                         osq_unlock(&lock->osq);
442                         preempt_enable();
443                         return true;
444                 }
445
446                 /*
447                  * When there's no owner, we might have preempted between the
448                  * owner acquiring the lock and setting the owner field. If
449                  * we're an RT task that will live-lock because we won't let
450                  * the owner complete.
451                  */
452                 if (!owner && (need_resched() || rt_task(task)))
453                         break;
454
455                 /*
456                  * The cpu_relax() call is a compiler barrier which forces
457                  * everything in this loop to be re-loaded. We don't need
458                  * memory barriers as we'll eventually observe the right
459                  * values at the cost of a few extra spins.
460                  */
461                 cpu_relax();
462         }
463
464         osq_unlock(&lock->osq);
465 fail:
466         preempt_enable();
467
468         /*
469          * If we fell out of the spin path because of need_resched(),
470          * reschedule now, before we try-lock again. This avoids getting
471          * scheduled out right after we obtained the lock.
472          */
473         if (need_resched())
474                 schedule();
475
476         return false;
477 }
478
479 #else /* CONFIG_LOCK_SPIN_ON_OWNER */
480
481 static inline bool six_optimistic_spin(struct six_lock *lock, enum six_lock_type type)
482 {
483         return false;
484 }
485
486 #endif
487
488 noinline
489 static int __six_lock_type_slowpath(struct six_lock *lock, enum six_lock_type type,
490                                     struct six_lock_waiter *wait,
491                                     six_lock_should_sleep_fn should_sleep_fn, void *p,
492                                     unsigned long ip)
493 {
494         union six_lock_state old;
495         int ret = 0;
496
497         if (type == SIX_LOCK_write) {
498                 EBUG_ON(lock->state.write_locking);
499                 atomic64_add(__SIX_VAL(write_locking, 1), &lock->state.counter);
500                 smp_mb__after_atomic();
501         }
502
503         trace_contention_begin(lock, 0);
504         lock_contended(&lock->dep_map, ip);
505
506         if (six_optimistic_spin(lock, type))
507                 goto out;
508
509         wait->task              = current;
510         wait->lock_want         = type;
511         wait->lock_acquired     = false;
512
513         raw_spin_lock(&lock->wait_lock);
514         if (!(lock->state.waiters & (1 << type)))
515                 set_bit(waitlist_bitnr(type), (unsigned long *) &lock->state.v);
516         /*
517          * Retry taking the lock after taking waitlist lock, have raced with an
518          * unlock:
519          */
520         ret = __do_six_trylock_type(lock, type, current, false);
521         if (ret <= 0) {
522                 wait->start_time = local_clock();
523
524                 if (!list_empty(&lock->wait_list)) {
525                         struct six_lock_waiter *last =
526                                 list_last_entry(&lock->wait_list,
527                                         struct six_lock_waiter, list);
528
529                         if (time_before_eq64(wait->start_time, last->start_time))
530                                 wait->start_time = last->start_time + 1;
531                 }
532
533                 list_add_tail(&wait->list, &lock->wait_list);
534         }
535         raw_spin_unlock(&lock->wait_lock);
536
537         if (unlikely(ret > 0)) {
538                 ret = 0;
539                 goto out;
540         }
541
542         if (unlikely(ret < 0)) {
543                 __six_lock_wakeup(lock, -ret - 1);
544                 ret = 0;
545         }
546
547         while (1) {
548                 set_current_state(TASK_UNINTERRUPTIBLE);
549
550                 if (wait->lock_acquired)
551                         break;
552
553                 ret = should_sleep_fn ? should_sleep_fn(lock, p) : 0;
554                 if (unlikely(ret)) {
555                         raw_spin_lock(&lock->wait_lock);
556                         if (!wait->lock_acquired)
557                                 list_del(&wait->list);
558                         raw_spin_unlock(&lock->wait_lock);
559
560                         if (wait->lock_acquired)
561                                 do_six_unlock_type(lock, type);
562                         break;
563                 }
564
565                 schedule();
566         }
567
568         __set_current_state(TASK_RUNNING);
569 out:
570         if (ret && type == SIX_LOCK_write && lock->state.write_locking) {
571                 old.v = atomic64_sub_return(__SIX_VAL(write_locking, 1),
572                                             &lock->state.counter);
573                 six_lock_wakeup(lock, old, SIX_LOCK_read);
574         }
575         trace_contention_end(lock, 0);
576
577         return ret;
578 }
579
580 __always_inline __flatten
581 static int __six_lock_type_waiter(struct six_lock *lock, enum six_lock_type type,
582                          struct six_lock_waiter *wait,
583                          six_lock_should_sleep_fn should_sleep_fn, void *p,
584                          unsigned long ip)
585 {
586         int ret;
587
588         wait->start_time = 0;
589
590         if (type != SIX_LOCK_write)
591                 six_acquire(&lock->dep_map, 0, type == SIX_LOCK_read, ip);
592
593         ret = do_six_trylock_type(lock, type, true) ? 0
594                 : __six_lock_type_slowpath(lock, type, wait, should_sleep_fn, p, ip);
595
596         if (ret && type != SIX_LOCK_write)
597                 six_release(&lock->dep_map, ip);
598         if (!ret)
599                 lock_acquired(&lock->dep_map, ip);
600
601         return ret;
602 }
603
604 __always_inline
605 static int __six_lock_type(struct six_lock *lock, enum six_lock_type type,
606                            six_lock_should_sleep_fn should_sleep_fn, void *p,
607                            unsigned long ip)
608 {
609         struct six_lock_waiter wait;
610
611         return __six_lock_type_waiter(lock, type, &wait, should_sleep_fn, p, ip);
612 }
613
614 __always_inline __flatten
615 static void do_six_unlock_type(struct six_lock *lock, enum six_lock_type type)
616 {
617         const struct six_lock_vals l[] = LOCK_VALS;
618         union six_lock_state state;
619
620         if (type == SIX_LOCK_intent)
621                 lock->owner = NULL;
622
623         if (type == SIX_LOCK_read &&
624             lock->readers) {
625                 smp_mb(); /* unlock barrier */
626                 this_cpu_dec(*lock->readers);
627                 smp_mb(); /* between unlocking and checking for waiters */
628                 state.v = READ_ONCE(lock->state.v);
629         } else {
630                 u64 v = l[type].unlock_val;
631
632                 if (type != SIX_LOCK_read)
633                         v -= lock->state.v & __SIX_VAL(nospin, 1);
634
635                 EBUG_ON(!(lock->state.v & l[type].held_mask));
636                 state.v = atomic64_add_return_release(v, &lock->state.counter);
637         }
638
639         six_lock_wakeup(lock, state, l[type].unlock_wakeup);
640 }
641
642 __always_inline __flatten
643 static void __six_unlock_type(struct six_lock *lock, enum six_lock_type type,
644                               unsigned long ip)
645 {
646         EBUG_ON(type == SIX_LOCK_write &&
647                 !(lock->state.v & __SIX_LOCK_HELD_intent));
648         EBUG_ON((type == SIX_LOCK_write ||
649                  type == SIX_LOCK_intent) &&
650                 lock->owner != current);
651
652         if (type != SIX_LOCK_write)
653                 six_release(&lock->dep_map, ip);
654
655         if (type == SIX_LOCK_intent &&
656             lock->intent_lock_recurse) {
657                 --lock->intent_lock_recurse;
658                 return;
659         }
660
661         do_six_unlock_type(lock, type);
662 }
663
664 #define __SIX_LOCK(type)                                                \
665 bool six_trylock_ip_##type(struct six_lock *lock, unsigned long ip)     \
666 {                                                                       \
667         return __six_trylock_type(lock, SIX_LOCK_##type, ip);           \
668 }                                                                       \
669 EXPORT_SYMBOL_GPL(six_trylock_ip_##type);                               \
670                                                                         \
671 bool six_relock_ip_##type(struct six_lock *lock, u32 seq, unsigned long ip)\
672 {                                                                       \
673         return __six_relock_type(lock, SIX_LOCK_##type, seq, ip);       \
674 }                                                                       \
675 EXPORT_SYMBOL_GPL(six_relock_ip_##type);                                \
676                                                                         \
677 int six_lock_ip_##type(struct six_lock *lock,                           \
678                     six_lock_should_sleep_fn should_sleep_fn, void *p,  \
679                     unsigned long ip)                                   \
680 {                                                                       \
681         return __six_lock_type(lock, SIX_LOCK_##type, should_sleep_fn, p, ip);\
682 }                                                                       \
683 EXPORT_SYMBOL_GPL(six_lock_ip_##type);                                  \
684                                                                         \
685 int six_lock_ip_waiter_##type(struct six_lock *lock,                    \
686                            struct six_lock_waiter *wait,                \
687                            six_lock_should_sleep_fn should_sleep_fn, void *p,\
688                            unsigned long ip)                            \
689 {                                                                       \
690         return __six_lock_type_waiter(lock, SIX_LOCK_##type, wait, should_sleep_fn, p, ip);\
691 }                                                                       \
692 EXPORT_SYMBOL_GPL(six_lock_ip_waiter_##type);                           \
693                                                                         \
694 void six_unlock_ip_##type(struct six_lock *lock, unsigned long ip)      \
695 {                                                                       \
696         __six_unlock_type(lock, SIX_LOCK_##type, ip);                   \
697 }                                                                       \
698 EXPORT_SYMBOL_GPL(six_unlock_ip_##type);
699
700 __SIX_LOCK(read)
701 __SIX_LOCK(intent)
702 __SIX_LOCK(write)
703
704 #undef __SIX_LOCK
705
706 /* Convert from intent to read: */
707 void six_lock_downgrade(struct six_lock *lock)
708 {
709         six_lock_increment(lock, SIX_LOCK_read);
710         six_unlock_intent(lock);
711 }
712 EXPORT_SYMBOL_GPL(six_lock_downgrade);
713
714 bool six_lock_tryupgrade(struct six_lock *lock)
715 {
716         union six_lock_state old, new;
717         u64 v = READ_ONCE(lock->state.v);
718
719         do {
720                 new.v = old.v = v;
721
722                 if (new.intent_lock)
723                         return false;
724
725                 if (!lock->readers) {
726                         EBUG_ON(!new.read_lock);
727                         new.read_lock--;
728                 }
729
730                 new.intent_lock = 1;
731         } while ((v = atomic64_cmpxchg_acquire(&lock->state.counter,
732                                 old.v, new.v)) != old.v);
733
734         if (lock->readers)
735                 this_cpu_dec(*lock->readers);
736
737         six_set_owner(lock, SIX_LOCK_intent, old, current);
738
739         return true;
740 }
741 EXPORT_SYMBOL_GPL(six_lock_tryupgrade);
742
743 bool six_trylock_convert(struct six_lock *lock,
744                          enum six_lock_type from,
745                          enum six_lock_type to)
746 {
747         EBUG_ON(to == SIX_LOCK_write || from == SIX_LOCK_write);
748
749         if (to == from)
750                 return true;
751
752         if (to == SIX_LOCK_read) {
753                 six_lock_downgrade(lock);
754                 return true;
755         } else {
756                 return six_lock_tryupgrade(lock);
757         }
758 }
759 EXPORT_SYMBOL_GPL(six_trylock_convert);
760
761 /*
762  * Increment read/intent lock count, assuming we already have it read or intent
763  * locked:
764  */
765 void six_lock_increment(struct six_lock *lock, enum six_lock_type type)
766 {
767         const struct six_lock_vals l[] = LOCK_VALS;
768
769         six_acquire(&lock->dep_map, 0, type == SIX_LOCK_read, _RET_IP_);
770
771         /* XXX: assert already locked, and that we don't overflow: */
772
773         switch (type) {
774         case SIX_LOCK_read:
775                 if (lock->readers) {
776                         this_cpu_inc(*lock->readers);
777                 } else {
778                         EBUG_ON(!lock->state.read_lock &&
779                                 !lock->state.intent_lock);
780                         atomic64_add(l[type].lock_val, &lock->state.counter);
781                 }
782                 break;
783         case SIX_LOCK_intent:
784                 EBUG_ON(!lock->state.intent_lock);
785                 lock->intent_lock_recurse++;
786                 break;
787         case SIX_LOCK_write:
788                 BUG();
789                 break;
790         }
791 }
792 EXPORT_SYMBOL_GPL(six_lock_increment);
793
794 void six_lock_wakeup_all(struct six_lock *lock)
795 {
796         union six_lock_state state = lock->state;
797         struct six_lock_waiter *w;
798
799         six_lock_wakeup(lock, state, SIX_LOCK_read);
800         six_lock_wakeup(lock, state, SIX_LOCK_intent);
801         six_lock_wakeup(lock, state, SIX_LOCK_write);
802
803         raw_spin_lock(&lock->wait_lock);
804         list_for_each_entry(w, &lock->wait_list, list)
805                 wake_up_process(w->task);
806         raw_spin_unlock(&lock->wait_lock);
807 }
808 EXPORT_SYMBOL_GPL(six_lock_wakeup_all);
809
810 void six_lock_pcpu_free(struct six_lock *lock)
811 {
812         BUG_ON(lock->readers && pcpu_read_count(lock));
813         BUG_ON(lock->state.read_lock);
814
815         free_percpu(lock->readers);
816         lock->readers = NULL;
817 }
818 EXPORT_SYMBOL_GPL(six_lock_pcpu_free);
819
820 void six_lock_pcpu_alloc(struct six_lock *lock)
821 {
822 #ifdef __KERNEL__
823         if (!lock->readers)
824                 lock->readers = alloc_percpu(unsigned);
825 #endif
826 }
827 EXPORT_SYMBOL_GPL(six_lock_pcpu_alloc);
828
829 /*
830  * Returns lock held counts, for both read and intent
831  */
832 struct six_lock_count six_lock_counts(struct six_lock *lock)
833 {
834         struct six_lock_count ret;
835
836         ret.n[SIX_LOCK_read]    = !lock->readers
837                 ? lock->state.read_lock
838                 : pcpu_read_count(lock);
839         ret.n[SIX_LOCK_intent]  = lock->state.intent_lock + lock->intent_lock_recurse;
840         ret.n[SIX_LOCK_write]   = lock->state.seq & 1;
841
842         return ret;
843 }
844 EXPORT_SYMBOL_GPL(six_lock_counts);