Update six locks

This commit is contained in:
Kent Overstreet 2019-10-01 15:55:42 -04:00
parent db39aa3e1b
commit 98b8f8d0c0
2 changed files with 33 additions and 94 deletions

View File

@ -1,4 +1,4 @@
// SPDX-License-Identifier: GPL-2.0
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef _LINUX_SIX_H
#define _LINUX_SIX_H
@ -50,12 +50,12 @@
* six_trylock_convert(lock, from, to)
*
* A lock may be held multiple types by the same thread (for read or intent,
* not write) - up to SIX_LOCK_MAX_RECURSE. However, the six locks code does
* _not_ implement the actual recursive checks itself though - rather, if your
* code (e.g. btree iterator code) knows that the current thread already has a
* lock held, and for the correct type, six_lock_increment() may be used to
* bump up the counter for that type - the only effect is that one more call to
* unlock will be required before the lock is unlocked.
* not write). However, the six locks code does _not_ implement the actual
* recursive checks itself though - rather, if your code (e.g. btree iterator
* code) knows that the current thread already has a lock held, and for the
* correct type, six_lock_increment() may be used to bump up the counter for
* that type - the only effect is that one more call to unlock will be required
* before the lock is unlocked.
*/
#include <linux/lockdep.h>
@ -80,8 +80,8 @@ union six_lock_state {
};
struct {
unsigned read_lock:26;
unsigned intent_lock:3;
unsigned read_lock:28;
unsigned intent_lock:1;
unsigned waiters:3;
/*
* seq works much like in seqlocks: it's incremented every time
@ -96,8 +96,6 @@ union six_lock_state {
};
};
#define SIX_LOCK_MAX_RECURSE ((1 << 3) - 1)
enum six_lock_type {
SIX_LOCK_read,
SIX_LOCK_intent,
@ -106,6 +104,7 @@ enum six_lock_type {
struct six_lock {
union six_lock_state state;
unsigned intent_lock_recurse;
struct task_struct *owner;
struct optimistic_spin_queue osq;
@ -139,8 +138,6 @@ do { \
#define __SIX_VAL(field, _v) (((union six_lock_state) { .field = _v }).v)
#ifdef SIX_LOCK_SEPARATE_LOCKFNS
#define __SIX_LOCK(type) \
bool six_trylock_##type(struct six_lock *); \
bool six_relock_##type(struct six_lock *, u32); \
@ -185,41 +182,6 @@ static inline void six_unlock_type(struct six_lock *lock, enum six_lock_type typ
SIX_LOCK_DISPATCH(type, six_unlock, lock);
}
#else
bool six_trylock_type(struct six_lock *, enum six_lock_type);
bool six_relock_type(struct six_lock *, enum six_lock_type, unsigned);
void six_lock_type(struct six_lock *, enum six_lock_type);
void six_unlock_type(struct six_lock *, enum six_lock_type);
#define __SIX_LOCK(type) \
static __always_inline bool six_trylock_##type(struct six_lock *lock) \
{ \
return six_trylock_type(lock, SIX_LOCK_##type); \
} \
\
static __always_inline bool six_relock_##type(struct six_lock *lock, u32 seq)\
{ \
return six_relock_type(lock, SIX_LOCK_##type, seq); \
} \
\
static __always_inline void six_lock_##type(struct six_lock *lock) \
{ \
six_lock_type(lock, SIX_LOCK_##type); \
} \
\
static __always_inline void six_unlock_##type(struct six_lock *lock) \
{ \
six_unlock_type(lock, SIX_LOCK_##type); \
}
__SIX_LOCK(read)
__SIX_LOCK(intent)
__SIX_LOCK(write)
#undef __SIX_LOCK
#endif
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,

View File

@ -76,17 +76,6 @@ static inline void six_set_owner(struct six_lock *lock, enum six_lock_type type,
}
}
static inline void six_clear_owner(struct six_lock *lock, enum six_lock_type type)
{
if (type != SIX_LOCK_intent)
return;
EBUG_ON(lock->owner != current);
if (lock->state.intent_lock == 1)
lock->owner = NULL;
}
static __always_inline bool do_six_trylock_type(struct six_lock *lock,
enum six_lock_type type)
{
@ -393,16 +382,24 @@ static void __six_unlock_type(struct six_lock *lock, enum six_lock_type type)
EBUG_ON(type == SIX_LOCK_write &&
!(lock->state.v & __SIX_LOCK_HELD_intent));
six_clear_owner(lock, type);
six_release(&lock->dep_map);
if (type == SIX_LOCK_intent) {
EBUG_ON(lock->owner != current);
if (lock->intent_lock_recurse) {
--lock->intent_lock_recurse;
return;
}
lock->owner = NULL;
}
state.v = atomic64_add_return_release(l[type].unlock_val,
&lock->state.counter);
six_release(&lock->dep_map);
six_lock_wakeup(lock, state, l[type].unlock_wakeup);
}
#ifdef SIX_LOCK_SEPARATE_LOCKFNS
#define __SIX_LOCK(type) \
bool six_trylock_##type(struct six_lock *lock) \
{ \
@ -434,36 +431,6 @@ __SIX_LOCK(write)
#undef __SIX_LOCK
#else
bool six_trylock_type(struct six_lock *lock, enum six_lock_type type)
{
return __six_trylock_type(lock, type);
}
EXPORT_SYMBOL_GPL(six_trylock_type);
bool six_relock_type(struct six_lock *lock, enum six_lock_type type,
unsigned seq)
{
return __six_relock_type(lock, type, seq);
}
EXPORT_SYMBOL_GPL(six_relock_type);
void six_lock_type(struct six_lock *lock, enum six_lock_type type)
{
__six_lock_type(lock, type);
}
EXPORT_SYMBOL_GPL(six_lock_type);
void six_unlock_type(struct six_lock *lock, enum six_lock_type type)
{
__six_unlock_type(lock, type);
}
EXPORT_SYMBOL_GPL(six_unlock_type);
#endif
/* Convert from intent to read: */
void six_lock_downgrade(struct six_lock *lock)
{
@ -530,6 +497,16 @@ void six_lock_increment(struct six_lock *lock, enum six_lock_type type)
/* XXX: assert already locked, and that we don't overflow: */
atomic64_add(l[type].lock_val, &lock->state.counter);
switch (type) {
case SIX_LOCK_read:
atomic64_add(l[type].lock_val, &lock->state.counter);
break;
case SIX_LOCK_intent:
lock->intent_lock_recurse++;
break;
case SIX_LOCK_write:
BUG();
break;
}
}
EXPORT_SYMBOL_GPL(six_lock_increment);