[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] Re: [Xen-devel] [PATCH] rwlock: allow recursive read locking when already locked in write mode
On Thu, Feb 20, 2020 at 03:23:38PM +0100, Jürgen Groß wrote: > On 20.02.20 15:11, Roger Pau Monné wrote: > > On Thu, Feb 20, 2020 at 01:48:54PM +0100, Jan Beulich wrote: > > > On 20.02.2020 13:02, Roger Pau Monne wrote: > > > > I've done some testing and at least the CPU down case is fixed now. > > > > Posting early in order to get feedback on the approach taken. > > > > > > Looks good, thanks, just a question and two comments: > > > > > > > --- a/xen/include/xen/rwlock.h > > > > +++ b/xen/include/xen/rwlock.h > > > > @@ -20,21 +20,30 @@ typedef struct { > > > > #define DEFINE_RWLOCK(l) rwlock_t l = RW_LOCK_UNLOCKED > > > > #define rwlock_init(l) (*(l) = (rwlock_t)RW_LOCK_UNLOCKED) > > > > -/* > > > > - * Writer states & reader shift and bias. > > > > - * > > > > - * Writer field is 8 bit to allow for potential optimisation, see > > > > - * _write_unlock(). > > > > - */ > > > > -#define _QW_WAITING 1 /* A writer is waiting */ > > > > -#define _QW_LOCKED 0xff /* A writer holds the lock */ > > > > -#define _QW_WMASK 0xff /* Writer mask.*/ > > > > -#define _QR_SHIFT 8 /* Reader count shift */ > > > > +/* Writer states & reader shift and bias. */ > > > > +#define _QW_WAITING 1 /* A writer is waiting > > > > */ > > > > +#define _QW_LOCKED 3 /* A writer holds the > > > > lock */ > > > > > > Aiui things would work equally well if 2 was used here? > > > > I think so, I left it as 3 because previously LOCKED would also > > include WAITING, and I didn't want to change it in case I've missed > > some code path that was relying on that. > > > > > > > > > +#define _QW_WMASK 3 /* Writer mask */ > > > > +#define _QW_CPUSHIFT 2 /* Writer CPU shift */ > > > > +#define _QW_CPUMASK 0x3ffc /* Writer CPU mask */ > > > > > > At least on x86, the shift involved here is quite certainly > > > more expensive than using wider immediates on AND and CMP > > > resulting from the _QW_MASK-based comparisons. I'd therefore > > > like to suggest to put the CPU in the low 12 bits. > > > > Hm right. The LOCKED and WAITING bits don't need shifting anyway. > > > > > > > > Another option is to use the recurse_cpu field of the > > > associated spin lock: The field is used for recursive locks > > > only, and hence the only conflict would be with > > > _spin_is_locked(), which we don't (and in the future then > > > also shouldn't) use on this lock. > > > > I looked into that also, but things get more complicated AFAICT, as it's > > not possible to atomically fetch the state of the lock and the owner > > CPU at the same time. Neither you could set the LOCKED bit and the CPU > > at the same time. > > > > > > > > > @@ -166,7 +180,8 @@ static inline void _write_unlock(rwlock_t *lock) > > > > * If the writer field is atomic, it can be cleared directly. > > > > * Otherwise, an atomic subtraction will be used to clear it. > > > > */ > > > > - atomic_sub(_QW_LOCKED, &lock->cnts); > > > > + ASSERT(_is_write_locked_by_me(atomic_read(&lock->cnts))); > > > > + atomic_sub(_write_lock_val(), &lock->cnts); > > > > > > I think this would be more efficient with atomic_and(), not > > > the least because of the then avoided smp_processor_id(). > > > Whether to mask off just _QW_WMASK or also the CPU number of > > > the last write owner would need to be determined. But with > > > using subtraction, in case of problems it'll likely be > > > harder to understand what actually went on, from looking at > > > the resulting state of the lock (this is in part a pre- > > > existing problem, but gets worse with subtraction of CPU > > > numbers). > > > > Right, a mask would be better. Right now both need to be cleared (the > > LOCKED and the CPU fields) as there's code that relies on !lock->cnts > > as a way to determine that the lock is not read or write locked. If we > > left the CPU lying around those checks would need to be adjusted. > > In case you make _QR_SHIFT 16 it is possible to just write a 2-byte zero > value for write_unlock() (like its possible to do so today using a > single byte write). That would limit the readers count to 65536, what do you think Jan? Thanks, Roger. _______________________________________________ Xen-devel mailing list Xen-devel@xxxxxxxxxxxxxxxxxxxx https://lists.xenproject.org/mailman/listinfo/xen-devel
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |