Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

six locks: Split out seq, use atomic_t instead of atomic64_t

Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>

+58 -71
+55 -69
fs/bcachefs/six.c
··· 32 32 * bits 29-30 has read waiters 33 33 * bits 30-31 has intent waiters 34 34 * bits 31-32 has write waiters 35 - * bits 32-64 sequence number: incremented on every write lock or 36 - * unlock, thus bit 33 (sequence number odd) indicates 37 - * lock is currently held for write 38 35 */ 39 36 40 37 #define SIX_STATE_READ_OFFSET 0 41 38 #define SIX_STATE_READ_BITS 26 42 39 43 - #define SIX_STATE_READ_LOCK ~(~0ULL << 26) 44 - #define SIX_STATE_INTENT_HELD (1ULL << 26) 45 - #define SIX_STATE_WRITE_LOCK (1ULL << 27) 46 - #define SIX_STATE_NOSPIN (1ULL << 28) 47 - #define SIX_STATE_WAITING_READ (1ULL << (29 + SIX_LOCK_read)) 48 - #define SIX_STATE_WAITING_INTENT (1ULL << (29 + SIX_LOCK_intent)) 49 - #define SIX_STATE_WAITING_WRITE (1ULL << (29 + SIX_LOCK_write)) 50 - 51 - #define SIX_STATE_SEQ_OFFSET 32 52 - #define SIX_STATE_SEQ_BITS 32 53 - #define SIX_STATE_SEQ (~0ULL << 32) 40 + #define SIX_STATE_READ_LOCK ~(~0U << 26) 41 + #define SIX_STATE_INTENT_HELD (1U << 26) 42 + #define SIX_STATE_WRITE_LOCK (1U << 27) 43 + #define SIX_STATE_NOSPIN (1U << 28) 44 + #define SIX_STATE_WAITING_READ (1U << (29 + SIX_LOCK_read)) 45 + #define SIX_STATE_WAITING_INTENT (1U << (29 + SIX_LOCK_intent)) 46 + #define SIX_STATE_WAITING_WRITE (1U << (29 + SIX_LOCK_write)) 54 47 55 48 #define SIX_LOCK_HELD_read SIX_STATE_READ_LOCK 56 49 #define SIX_LOCK_HELD_intent SIX_STATE_INTENT_HELD ··· 51 58 52 59 struct six_lock_vals { 53 60 /* Value we add to the lock in order to take the lock: */ 54 - u64 lock_val; 61 + u32 lock_val; 55 62 56 63 /* If the lock has this value (used as a mask), taking the lock fails: */ 57 - u64 lock_fail; 64 + u32 lock_fail; 58 65 59 66 /* Mask that indicates lock is held for this type: */ 60 - u64 held_mask; 67 + u32 held_mask; 61 68 62 69 /* Waitlist we wakeup when releasing the lock: */ 63 70 enum six_lock_type unlock_wakeup; ··· 65 72 66 73 static const struct six_lock_vals l[] = { 67 74 [SIX_LOCK_read] = { 68 - .lock_val = 1ULL << SIX_STATE_READ_OFFSET, 75 + .lock_val = 1U << SIX_STATE_READ_OFFSET, 69 76 .lock_fail = SIX_LOCK_HELD_write, 70 77 .held_mask = SIX_LOCK_HELD_read, 71 78 .unlock_wakeup = SIX_LOCK_write, ··· 84 91 }, 85 92 }; 86 93 87 - static inline u32 six_state_seq(u64 state) 94 + static inline void six_set_bitmask(struct six_lock *lock, u32 mask) 88 95 { 89 - return state >> SIX_STATE_SEQ_OFFSET; 96 + if ((atomic_read(&lock->state) & mask) != mask) 97 + atomic_or(mask, &lock->state); 90 98 } 91 99 92 - static inline void six_set_bitmask(struct six_lock *lock, u64 mask) 100 + static inline void six_clear_bitmask(struct six_lock *lock, u32 mask) 93 101 { 94 - if ((atomic64_read(&lock->state) & mask) != mask) 95 - atomic64_or(mask, &lock->state); 96 - } 97 - 98 - static inline void six_clear_bitmask(struct six_lock *lock, u64 mask) 99 - { 100 - if (atomic64_read(&lock->state) & mask) 101 - atomic64_and(~mask, &lock->state); 102 + if (atomic_read(&lock->state) & mask) 103 + atomic_and(~mask, &lock->state); 102 104 } 103 105 104 106 static inline void six_set_owner(struct six_lock *lock, enum six_lock_type type, 105 - u64 old, struct task_struct *owner) 107 + u32 old, struct task_struct *owner) 106 108 { 107 109 if (type != SIX_LOCK_intent) 108 110 return; ··· 133 145 struct task_struct *task, bool try) 134 146 { 135 147 int ret; 136 - u64 old, new, v; 148 + u32 old, new, v; 137 149 138 150 EBUG_ON(type == SIX_LOCK_write && lock->owner != task); 139 151 EBUG_ON(type == SIX_LOCK_write && 140 - (try != !(atomic64_read(&lock->state) & SIX_LOCK_HELD_write))); 141 - EBUG_ON(type == SIX_LOCK_write && 142 - (try != !(atomic64_read(&lock->state) & SIX_STATE_WRITE_LOCK))); 152 + (try != !(atomic_read(&lock->state) & SIX_STATE_WRITE_LOCK))); 143 153 144 154 /* 145 155 * Percpu reader mode: ··· 172 186 173 187 smp_mb(); 174 188 175 - old = atomic64_read(&lock->state); 189 + old = atomic_read(&lock->state); 176 190 ret = !(old & l[type].lock_fail); 177 191 178 192 this_cpu_sub(*lock->readers, !ret); ··· 182 196 ret = -1 - SIX_LOCK_write; 183 197 } else if (type == SIX_LOCK_write && lock->readers) { 184 198 if (try) { 185 - atomic64_add(SIX_STATE_WRITE_LOCK, &lock->state); 199 + atomic_add(SIX_STATE_WRITE_LOCK, &lock->state); 186 200 smp_mb__after_atomic(); 187 201 } 188 202 189 203 ret = !pcpu_read_count(lock); 190 204 191 205 if (try && !ret) { 192 - old = atomic64_sub_return(SIX_STATE_WRITE_LOCK, &lock->state); 206 + old = atomic_sub_return(SIX_STATE_WRITE_LOCK, &lock->state); 193 207 if (old & SIX_STATE_WAITING_READ) 194 208 ret = -1 - SIX_LOCK_read; 195 209 } 196 210 } else { 197 - v = atomic64_read(&lock->state); 211 + v = atomic_read(&lock->state); 198 212 do { 199 213 new = old = v; 200 214 ··· 204 218 break; 205 219 206 220 new += l[type].lock_val; 207 - } while ((v = atomic64_cmpxchg_acquire(&lock->state, old, new)) != old); 221 + } while ((v = atomic_cmpxchg_acquire(&lock->state, old, new)) != old); 208 222 209 - EBUG_ON(ret && !(atomic64_read(&lock->state) & l[type].held_mask)); 223 + EBUG_ON(ret && !(atomic_read(&lock->state) & l[type].held_mask)); 210 224 } 211 225 212 226 if (ret > 0) 213 227 six_set_owner(lock, type, old, task); 214 228 215 229 EBUG_ON(type == SIX_LOCK_write && try && ret <= 0 && 216 - (atomic64_read(&lock->state) & SIX_STATE_WRITE_LOCK)); 230 + (atomic_read(&lock->state) & SIX_STATE_WRITE_LOCK)); 217 231 218 232 return ret; 219 233 } ··· 263 277 } 264 278 265 279 __always_inline 266 - static void six_lock_wakeup(struct six_lock *lock, u64 state, 280 + static void six_lock_wakeup(struct six_lock *lock, u32 state, 267 281 enum six_lock_type lock_type) 268 282 { 269 283 if (lock_type == SIX_LOCK_write && (state & SIX_LOCK_HELD_read)) ··· 303 317 if (type != SIX_LOCK_write) 304 318 six_acquire(&lock->dep_map, 1, type == SIX_LOCK_read, ip); 305 319 else 306 - atomic64_add(1ULL << SIX_STATE_SEQ_OFFSET, &lock->state); 320 + lock->seq++; 321 + 307 322 return true; 308 323 } 309 324 EXPORT_SYMBOL_GPL(six_trylock_ip); ··· 469 482 six_lock_should_sleep_fn should_sleep_fn, void *p, 470 483 unsigned long ip) 471 484 { 472 - u64 old; 485 + u32 old; 473 486 int ret = 0; 474 487 475 488 if (type == SIX_LOCK_write) { 476 - EBUG_ON(atomic64_read(&lock->state) & SIX_STATE_WRITE_LOCK); 477 - atomic64_add(SIX_STATE_WRITE_LOCK, &lock->state); 489 + EBUG_ON(atomic_read(&lock->state) & SIX_STATE_WRITE_LOCK); 490 + atomic_add(SIX_STATE_WRITE_LOCK, &lock->state); 478 491 smp_mb__after_atomic(); 479 492 } 480 493 ··· 596 609 ret = do_six_trylock(lock, type, true) ? 0 597 610 : six_lock_slowpath(lock, type, wait, should_sleep_fn, p, ip); 598 611 599 - if (!ret && type == SIX_LOCK_write) 600 - atomic64_add(1ULL << SIX_STATE_SEQ_OFFSET, &lock->state); 612 + lock->seq += !ret && type == SIX_LOCK_write; 601 613 602 614 if (ret && type != SIX_LOCK_write) 603 615 six_release(&lock->dep_map, ip); ··· 610 624 __always_inline 611 625 static void do_six_unlock_type(struct six_lock *lock, enum six_lock_type type) 612 626 { 613 - u64 state; 627 + u32 state; 614 628 615 629 if (type == SIX_LOCK_intent) 616 630 lock->owner = NULL; ··· 620 634 smp_mb(); /* unlock barrier */ 621 635 this_cpu_dec(*lock->readers); 622 636 smp_mb(); /* between unlocking and checking for waiters */ 623 - state = atomic64_read(&lock->state); 637 + state = atomic_read(&lock->state); 624 638 } else { 625 - u64 v = l[type].lock_val; 639 + u32 v = l[type].lock_val; 626 640 627 641 if (type != SIX_LOCK_read) 628 - v += atomic64_read(&lock->state) & SIX_STATE_NOSPIN; 642 + v += atomic_read(&lock->state) & SIX_STATE_NOSPIN; 629 643 630 - EBUG_ON(!(atomic64_read(&lock->state) & l[type].held_mask)); 631 - state = atomic64_sub_return_release(v, &lock->state); 644 + EBUG_ON(!(atomic_read(&lock->state) & l[type].held_mask)); 645 + state = atomic_sub_return_release(v, &lock->state); 632 646 } 633 647 634 648 six_lock_wakeup(lock, state, l[type].unlock_wakeup); ··· 652 666 void six_unlock_ip(struct six_lock *lock, enum six_lock_type type, unsigned long ip) 653 667 { 654 668 EBUG_ON(type == SIX_LOCK_write && 655 - !(atomic64_read(&lock->state) & SIX_LOCK_HELD_intent)); 669 + !(atomic_read(&lock->state) & SIX_LOCK_HELD_intent)); 656 670 EBUG_ON((type == SIX_LOCK_write || 657 671 type == SIX_LOCK_intent) && 658 672 lock->owner != current); ··· 660 674 if (type != SIX_LOCK_write) 661 675 six_release(&lock->dep_map, ip); 662 676 else 663 - atomic64_add(1ULL << SIX_STATE_SEQ_OFFSET, &lock->state); 677 + lock->seq++; 664 678 665 679 if (type == SIX_LOCK_intent && 666 680 lock->intent_lock_recurse) { ··· 696 710 */ 697 711 bool six_lock_tryupgrade(struct six_lock *lock) 698 712 { 699 - u64 old, new, v = atomic64_read(&lock->state); 713 + u32 old, new, v = atomic_read(&lock->state); 700 714 701 715 do { 702 716 new = old = v; ··· 710 724 } 711 725 712 726 new |= SIX_LOCK_HELD_intent; 713 - } while ((v = atomic64_cmpxchg_acquire(&lock->state, old, new)) != old); 727 + } while ((v = atomic_cmpxchg_acquire(&lock->state, old, new)) != old); 714 728 715 729 if (lock->readers) 716 730 this_cpu_dec(*lock->readers); ··· 772 786 if (lock->readers) { 773 787 this_cpu_inc(*lock->readers); 774 788 } else { 775 - EBUG_ON(!(atomic64_read(&lock->state) & 789 + EBUG_ON(!(atomic_read(&lock->state) & 776 790 (SIX_LOCK_HELD_read| 777 791 SIX_LOCK_HELD_intent))); 778 - atomic64_add(l[type].lock_val, &lock->state); 792 + atomic_add(l[type].lock_val, &lock->state); 779 793 } 780 794 break; 781 795 case SIX_LOCK_intent: 782 - EBUG_ON(!(atomic64_read(&lock->state) & SIX_LOCK_HELD_intent)); 796 + EBUG_ON(!(atomic_read(&lock->state) & SIX_LOCK_HELD_intent)); 783 797 lock->intent_lock_recurse++; 784 798 break; 785 799 case SIX_LOCK_write: ··· 801 815 */ 802 816 void six_lock_wakeup_all(struct six_lock *lock) 803 817 { 804 - u64 state = atomic64_read(&lock->state); 818 + u32 state = atomic_read(&lock->state); 805 819 struct six_lock_waiter *w; 806 820 807 821 six_lock_wakeup(lock, state, SIX_LOCK_read); ··· 826 840 struct six_lock_count ret; 827 841 828 842 ret.n[SIX_LOCK_read] = !lock->readers 829 - ? atomic64_read(&lock->state) & SIX_STATE_READ_LOCK 843 + ? atomic_read(&lock->state) & SIX_STATE_READ_LOCK 830 844 : pcpu_read_count(lock); 831 - ret.n[SIX_LOCK_intent] = !!(atomic64_read(&lock->state) & SIX_LOCK_HELD_intent) + 845 + ret.n[SIX_LOCK_intent] = !!(atomic_read(&lock->state) & SIX_LOCK_HELD_intent) + 832 846 lock->intent_lock_recurse; 833 - ret.n[SIX_LOCK_write] = !!(atomic64_read(&lock->state) & SIX_LOCK_HELD_write); 847 + ret.n[SIX_LOCK_write] = !!(atomic_read(&lock->state) & SIX_LOCK_HELD_write); 834 848 835 849 return ret; 836 850 } ··· 861 875 if (lock->readers) { 862 876 this_cpu_add(*lock->readers, nr); 863 877 } else { 864 - EBUG_ON((int) (atomic64_read(&lock->state) & SIX_STATE_READ_LOCK) + nr < 0); 878 + EBUG_ON((int) (atomic_read(&lock->state) & SIX_STATE_READ_LOCK) + nr < 0); 865 879 /* reader count starts at bit 0 */ 866 - atomic64_add(nr, &lock->state); 880 + atomic_add(nr, &lock->state); 867 881 } 868 882 } 869 883 EXPORT_SYMBOL_GPL(six_lock_readers_add); ··· 878 892 void six_lock_exit(struct six_lock *lock) 879 893 { 880 894 WARN_ON(lock->readers && pcpu_read_count(lock)); 881 - WARN_ON(atomic64_read(&lock->state) & SIX_LOCK_HELD_read); 895 + WARN_ON(atomic_read(&lock->state) & SIX_LOCK_HELD_read); 882 896 883 897 free_percpu(lock->readers); 884 898 lock->readers = NULL; ··· 888 902 void __six_lock_init(struct six_lock *lock, const char *name, 889 903 struct lock_class_key *key, enum six_lock_init_flags flags) 890 904 { 891 - atomic64_set(&lock->state, 0); 905 + atomic_set(&lock->state, 0); 892 906 raw_spin_lock_init(&lock->wait_lock); 893 907 INIT_LIST_HEAD(&lock->wait_list); 894 908 #ifdef CONFIG_DEBUG_LOCK_ALLOC
+3 -2
fs/bcachefs/six.h
··· 138 138 }; 139 139 140 140 struct six_lock { 141 - atomic64_t state; 141 + atomic_t state; 142 + u32 seq; 142 143 unsigned intent_lock_recurse; 143 144 struct task_struct *owner; 144 145 unsigned __percpu *readers; ··· 197 196 */ 198 197 static inline u32 six_lock_seq(const struct six_lock *lock) 199 198 { 200 - return atomic64_read(&lock->state) >> 32; 199 + return lock->seq; 201 200 } 202 201 203 202 bool six_trylock_ip(struct six_lock *lock, enum six_lock_type type, unsigned long ip);