diff options
author | Kent Overstreet <kent.overstreet@linux.dev> | 2023-05-20 21:44:30 -0400 |
---|---|---|
committer | Kent Overstreet <kent.overstreet@linux.dev> | 2023-10-22 17:10:02 -0400 |
commit | c4bd3491b1c0b335f63599ec96d1d4ab0d37a3c1 (patch) | |
tree | 4be0daffa01be52e7629c131bb43cbec38c943a3 /fs/bcachefs/six.h | |
parent | d2c86b77de5894bbe26ecbf5214227f61855aed7 (diff) | |
download | linux-c4bd3491b1c0b335f63599ec96d1d4ab0d37a3c1.tar.gz linux-c4bd3491b1c0b335f63599ec96d1d4ab0d37a3c1.tar.bz2 linux-c4bd3491b1c0b335f63599ec96d1d4ab0d37a3c1.zip |
six locks: Simplify dispatch
Originally, we used inlining/flattening to cause the compiler to
generate different versions of lock/trylock/relock/unlock for each lock
type - read, intent, and write. This made the individual functions
smaller and let the compiler eliminate table lookups: however, as the
code has gotten more complicated these optimizations have gotten less
worthwhile, and all the tricky inlining and dispatching made the code
less readable.
Text size: 11015 bytes -> 7467 bytes, and benchmarks show no loss of
performance.
Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
Diffstat (limited to 'fs/bcachefs/six.h')
-rw-r--r-- | fs/bcachefs/six.h | 148 |
1 files changed, 89 insertions, 59 deletions
diff --git a/fs/bcachefs/six.h b/fs/bcachefs/six.h index 2c8424bd7d2f..5ddabbfb8aba 100644 --- a/fs/bcachefs/six.h +++ b/fs/bcachefs/six.h @@ -148,37 +148,116 @@ do { \ __six_lock_init((lock), #lock, &__key, flags); \ } while (0) +bool six_trylock_ip_type(struct six_lock *lock, enum six_lock_type type, + unsigned long ip); + +static inline bool six_trylock_type(struct six_lock *lock, enum six_lock_type type) +{ + return six_trylock_ip_type(lock, type, _THIS_IP_); +} + +int six_lock_type_ip_waiter(struct six_lock *lock, enum six_lock_type type, + struct six_lock_waiter *wait, + six_lock_should_sleep_fn should_sleep_fn, void *p, + unsigned long ip); + +static inline int six_lock_type_waiter(struct six_lock *lock, enum six_lock_type type, + struct six_lock_waiter *wait, + six_lock_should_sleep_fn should_sleep_fn, void *p) +{ + return six_lock_type_ip_waiter(lock, type, wait, should_sleep_fn, p, _THIS_IP_); +} + +static inline int six_lock_ip_type(struct six_lock *lock, enum six_lock_type type, + six_lock_should_sleep_fn should_sleep_fn, void *p, + unsigned long ip) +{ + struct six_lock_waiter wait; + + return six_lock_type_ip_waiter(lock, type, &wait, should_sleep_fn, p, ip); +} + +static inline int six_lock_type(struct six_lock *lock, enum six_lock_type type, + six_lock_should_sleep_fn should_sleep_fn, void *p) +{ + struct six_lock_waiter wait; + + return six_lock_type_ip_waiter(lock, type, &wait, should_sleep_fn, p, _THIS_IP_); +} + +bool six_relock_ip_type(struct six_lock *lock, enum six_lock_type type, + unsigned seq, unsigned long ip); + +static inline bool six_relock_type(struct six_lock *lock, enum six_lock_type type, + unsigned seq) +{ + return six_relock_ip_type(lock, type, seq, _THIS_IP_); +} + +void six_unlock_ip_type(struct six_lock *lock, enum six_lock_type type, unsigned long ip); + +static inline void six_unlock_type(struct six_lock *lock, enum six_lock_type type) +{ + six_unlock_ip_type(lock, type, _THIS_IP_); +} + #define __SIX_LOCK(type) \ -bool six_trylock_ip_##type(struct six_lock *, unsigned long); \ -bool six_relock_ip_##type(struct six_lock *, u32, unsigned long); \ -int six_lock_ip_##type(struct six_lock *, six_lock_should_sleep_fn, \ - void *, unsigned long); \ -int six_lock_ip_waiter_##type(struct six_lock *, struct six_lock_waiter *,\ - six_lock_should_sleep_fn, void *, unsigned long);\ -void six_unlock_ip_##type(struct six_lock *, unsigned long); \ +static inline bool six_trylock_ip_##type(struct six_lock *lock, unsigned long ip)\ +{ \ + return six_trylock_ip_type(lock, SIX_LOCK_##type, ip); \ +} \ \ static inline bool six_trylock_##type(struct six_lock *lock) \ { \ - return six_trylock_ip_##type(lock, _THIS_IP_); \ + return six_trylock_ip_type(lock, SIX_LOCK_##type, _THIS_IP_); \ +} \ + \ +static inline int six_lock_ip_waiter_##type(struct six_lock *lock, \ + struct six_lock_waiter *wait, \ + six_lock_should_sleep_fn should_sleep_fn, void *p,\ + unsigned long ip) \ +{ \ + return six_lock_type_ip_waiter(lock, SIX_LOCK_##type, wait, should_sleep_fn, p, ip);\ +} \ + \ +static inline int six_lock_ip_##type(struct six_lock *lock, \ + six_lock_should_sleep_fn should_sleep_fn, void *p, \ + unsigned long ip) \ +{ \ + return six_lock_ip_type(lock, SIX_LOCK_##type, should_sleep_fn, p, ip);\ +} \ + \ +static inline bool six_relock_ip_##type(struct six_lock *lock, u32 seq, unsigned long ip)\ +{ \ + return six_relock_ip_type(lock, SIX_LOCK_##type, seq, ip); \ } \ + \ static inline bool six_relock_##type(struct six_lock *lock, u32 seq) \ { \ - return six_relock_ip_##type(lock, seq, _THIS_IP_); \ + return six_relock_ip_type(lock, SIX_LOCK_##type, seq, _THIS_IP_);\ } \ + \ static inline int six_lock_##type(struct six_lock *lock, \ six_lock_should_sleep_fn fn, void *p)\ { \ return six_lock_ip_##type(lock, fn, p, _THIS_IP_); \ } \ + \ static inline int six_lock_waiter_##type(struct six_lock *lock, \ struct six_lock_waiter *wait, \ six_lock_should_sleep_fn fn, void *p) \ { \ return six_lock_ip_waiter_##type(lock, wait, fn, p, _THIS_IP_); \ } \ + \ +static inline void six_unlock_ip_##type(struct six_lock *lock, unsigned long ip) \ +{ \ + six_unlock_ip_type(lock, SIX_LOCK_##type, ip); \ +} \ + \ static inline void six_unlock_##type(struct six_lock *lock) \ { \ - return six_unlock_ip_##type(lock, _THIS_IP_); \ + six_unlock_ip_type(lock, SIX_LOCK_##type, _THIS_IP_); \ } __SIX_LOCK(read) @@ -186,55 +265,6 @@ __SIX_LOCK(intent) __SIX_LOCK(write) #undef __SIX_LOCK -#define SIX_LOCK_DISPATCH(type, fn, ...) \ - switch (type) { \ - case SIX_LOCK_read: \ - return fn##_read(__VA_ARGS__); \ - case SIX_LOCK_intent: \ - return fn##_intent(__VA_ARGS__); \ - case SIX_LOCK_write: \ - return fn##_write(__VA_ARGS__); \ - default: \ - BUG(); \ - } - -static inline bool six_trylock_type(struct six_lock *lock, enum six_lock_type type) -{ - SIX_LOCK_DISPATCH(type, six_trylock, lock); -} - -static inline bool six_relock_type(struct six_lock *lock, enum six_lock_type type, - unsigned seq) -{ - SIX_LOCK_DISPATCH(type, six_relock, lock, seq); -} - -static inline int six_lock_type(struct six_lock *lock, enum six_lock_type type, - six_lock_should_sleep_fn should_sleep_fn, void *p) -{ - SIX_LOCK_DISPATCH(type, six_lock, lock, should_sleep_fn, p); -} - -static inline int six_lock_type_ip_waiter(struct six_lock *lock, enum six_lock_type type, - struct six_lock_waiter *wait, - six_lock_should_sleep_fn should_sleep_fn, void *p, - unsigned long ip) -{ - SIX_LOCK_DISPATCH(type, six_lock_ip_waiter, lock, wait, should_sleep_fn, p, ip); -} - -static inline int six_lock_type_waiter(struct six_lock *lock, enum six_lock_type type, - struct six_lock_waiter *wait, - six_lock_should_sleep_fn should_sleep_fn, void *p) -{ - SIX_LOCK_DISPATCH(type, six_lock_waiter, lock, wait, should_sleep_fn, p); -} - -static inline void six_unlock_type(struct six_lock *lock, enum six_lock_type type) -{ - SIX_LOCK_DISPATCH(type, six_unlock, lock); -} - void six_lock_downgrade(struct six_lock *); bool six_lock_tryupgrade(struct six_lock *); bool six_trylock_convert(struct six_lock *, enum six_lock_type, |