[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] Re: [Xen-devel] [PATCH 1/2] rwlock: add per-cpu reader-writer locks
>>> On 18.11.15 at 14:49, <malcolm.crossley@xxxxxxxxxx> wrote: > On 17/11/15 17:00, Jan Beulich wrote: >>>>> On 03.11.15 at 18:58, <malcolm.crossley@xxxxxxxxxx> wrote: >>> Per-cpu read-write locks allow for the fast path read case to have low >>> overhead >>> by only setting/clearing a per-cpu variable for using the read lock. >>> The per-cpu read fast path also avoids locked compare swap operations which >>> can >>> be particularly slow on coherent multi-socket systems, particularly if >>> there is >>> heavy usage of the read lock itself. >>> >>> The per-cpu reader-writer lock uses a global variable to control the read >>> lock >>> fast path. This allows a writer to disable the fast path and ensure the >>> readers >>> use the underlying read-write lock implementation. >>> >>> Once the writer has taken the write lock and disabled the fast path, it must >>> poll the per-cpu variable for all CPU's which have entered the critical >>> section >>> for the specific read-write lock the writer is attempting to take. This >>> design >>> allows for a single per-cpu variable to be used for read/write locks >>> belonging >>> to seperate data structures as long as multiple per-cpu read locks are not >>> simultaneously held by one particular cpu. This also means per-cpu >>> reader-writer locks are not recursion safe. >> >> This sounds like pretty severe a restriction, and something to easily >> get wrong once more than a handful of users got introduced. > > I can add an ASSERT to detect the recursion for the debug hypervisor but you > are right > that it is a restriction. I believe that the tickets locks are not recursion > safe > either and rely on additional infrastructure to prevent the recursion > occurring on > the lock itself. No ordinary spin lock can be acquired recursively. The restriction here is more severe: No two spin locks protecting the same kind of resource can't be used recursively. >>> + cpumask_t active_readers; >> >> Did you consider ways to avoid such a large variable to be put on >> the stack, and none turned out suitable? > > I wasn't aware the cpumask_t variable at 32 bytes was considered problematic > for the stack. I can't think of any way around the issue without causing > further restrictions (a percpu area will prevent taking two different percpu > rwlocks at the same time). 32 bytes it is only for 256 CPU builds. What about a 4095 CPU config? Wouldn't it be possible (either excluding use of such locks from interrupt context, or by disabling interrupts for the duration of the mask's use) to have a per-CPU mask? >> I admit I can't see alternatives, but the price >> - as said above - seems quite high. Or maybe I'm misunderstanding >> the "as long as multiple per-cpu read locks are not simultaneously >> held by one particular cpu", as having made it here I can't right >> away see where that restriction comes from? > > I've tried to detail the overhead earlier in my reply. The price is > mainly paid when writers are using an uncontended lock. The grant > table write lock is almost never taken in the typical use case and > so for particular algorithms/code flows the price may be worth paying. With "price" I was really referring to the usage restriction, not any performance effect. >>> +static inline void percpu_read_unlock(rwlock_t **per_cpudata) >>> +{ >>> + this_cpu_ptr(per_cpudata) = NULL; >>> + smp_wmb(); >>> +} >>> + >>> +/* Don't inline percpu write lock as it's a complex function */ >>> +void percpu_write_lock(rwlock_t **per_cpudata, bool_t *writer_activating, >>> + rwlock_t *rwlock); >>> + >>> +static inline void percpu_write_unlock(bool_t *writer_activating, rwlock_t >>> *rwlock) >>> +{ >>> + *writer_activating = false; >>> + write_unlock(rwlock); >>> +} >> >> Considering that the arguments one needs to pass to any of the >> functions here taking multiple arguments need to be in close sync, >> I'm missing abstracting macros here that need to be passed just >> a single argument (plus a declaration and a definition one). > > I agree the per_cpudata and writer_activating arguments are both linked > "global" state and could be abstracted with macro's. The rwlock_t is a > per resource state and would need to be passed as a seperate argument. > > > So I have some high level questions: > > With the current restrictions on the percpu rwlocks (no recursion and no > accessing two percpu rwlocks resources simultaneously on the same PCPU, > Do you think it is worth creating a generic implementation? Yes, namely with Andrew already hinting at the p2m lock also wanting to be converted to this model. > Or should I just add a grant table specific implementation because the grant > table code conforms to the above restrictions? > > What requirements would there be for a generic percpu rwlock implementation > to be accepted? At least the multiple resource lock issue should be avoided, and I think I've pointed out before how I think this can be achieved without any fundamental changes. > Is infrastructure allowing percpu areas to be used in data structures > required? At some point it seems this would be desirable, but I think I've explained a way to avoid this getting overly complex for now. > Does the "no recursion" restriction need to be removed? Preferably yes, but I think this one can be easier lived with. > Does the "no accessing two percpu rwlock resources simultaneously on the > same PCPU" > restriction need to be removed? See above - yes. Jan _______________________________________________ Xen-devel mailing list Xen-devel@xxxxxxxxxxxxx http://lists.xen.org/xen-devel
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |