[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] Re: [PATCH v3 4/5] evtchn: convert domain event lock to an r/w one
On 09.12.2020 12:54, Julien Grall wrote: > On 23/11/2020 13:29, Jan Beulich wrote: >> @@ -620,7 +620,7 @@ int evtchn_close(struct domain *d1, int >> long rc = 0; >> >> again: >> - spin_lock(&d1->event_lock); >> + write_lock(&d1->event_lock); >> >> if ( !port_is_valid(d1, port1) ) >> { >> @@ -690,13 +690,11 @@ int evtchn_close(struct domain *d1, int >> BUG(); >> >> if ( d1 < d2 ) >> - { >> - spin_lock(&d2->event_lock); >> - } >> + read_lock(&d2->event_lock); > > This change made me realized that I don't quite understand how the > rwlock is meant to work for event_lock. I was actually expecting this to > be a write_lock() given there are state changed in the d2 events. Well, the protection needs to be against racing changes, i.e. parallel invocations of this same function, or evtchn_close(). It is debatable whether evtchn_status() and domain_dump_evtchn_info() would better also be locked out (other read_lock() uses aren't applicable to interdomain channels). > Could you outline how a developper can find out whether he/she should > use read_lock or write_lock? I could try to, but it would again be a port type dependent model, just like for the per-channel locks. So I'd like it to be clarified first whether you aren't instead indirectly asking for these to become write_lock(). >> --- a/xen/common/rwlock.c >> +++ b/xen/common/rwlock.c >> @@ -102,6 +102,14 @@ void queue_write_lock_slowpath(rwlock_t >> spin_unlock(&lock->lock); >> } >> >> +void _rw_barrier(rwlock_t *lock) >> +{ >> + check_barrier(&lock->lock.debug); >> + smp_mb(); >> + while ( _rw_is_locked(lock) ) >> + arch_lock_relax(); >> + smp_mb(); >> +} > > As I pointed out when this implementation was first proposed (see [1]), > there is a risk that the loop will never exit. The [1] reference was missing, but I recall you saying so. > I think the following implementation would be better (although it is ugly): > > write_lock(); > /* do nothing */ > write_unlock(); > > This will act as a barrier between lock held before and after the call. Right, and back then I indicated agreement. When getting to actually carry out the change, I realized though that then the less restrictive check_barrier() can't be used anymore (or to be precise, it could be used, but the stronger check_lock() would subsequently still come into play). This isn't a problem here, but would be for any IRQ-safe r/w lock that the barrier may want to be used on down the road. Thinking about it, a read_lock() / read_unlock() pair would suffice though. But this would then still have check_lock() involved. Given all of this, maybe it's better not to introduce the function at all and instead open-code the read_lock() / read_unlock() pair at the use site. > As an aside, I think the introduction of rw_barrier() deserve to be a in > separate patch to help the review. I'm aware there are differing views on this - to me, putting this in a separate patch would be introduction of dead code. But as per above maybe the function now won't get introduced anymore anyway. Jan
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |