> -----Original Message----- > From: Nicolas Morey-Chaisemartin [mailto:nmo...@kalray.eu] > Sent: Thursday, December 08, 2016 5:30 PM > To: Savolainen, Petri (Nokia - FI/Espoo) <petri.savolainen@nokia-bell- > labs.com>; LNG ODP Mailman List <lng-odp@lists.linaro.org> > Subject: Re: [lng-odp] odp_rwlock_read_trylock > > > > Le 12/08/2016 à 03:50 PM, Savolainen, Petri (Nokia - FI/Espoo) a écrit : > > > >> -----Original Message----- > >> From: lng-odp [mailto:lng-odp-boun...@lists.linaro.org] On Behalf Of > >> Nicolas Morey-Chaisemartin > >> Sent: Wednesday, December 07, 2016 10:12 AM > >> To: LNG ODP Mailman List <lng-odp@lists.linaro.org> > >> Subject: [lng-odp] odp_rwlock_read_trylock > >> > >> HI, > >> > >> > >> While looking into the test/code, I noticed something weird in the > >> implementation of the rwlock read trylock on monarch. > >> > >> int odp_rwlock_read_trylock(odp_rwlock_t *rwlock) > >> { > >> uint32_t zero = 0; > >> > >> return odp_atomic_cas_acq_u32(&rwlock->cnt, &zero, (uint32_t)1); > >> } > >> > >> > >> This mean the trylock only succeed if no one was using the lock. But it > >> will fail if someone was owning it *even* if it is a reader. > >> Is this something expected? If yes, it should probably be detailed in > the > >> API. > > /** > > * Try to acquire read permission to a reader/writer lock. > > * > > * @param rwlock Pointer to a reader/writer lock > > * > > * @retval 0 Lock was not available for read access > > * @retval !0 Read access to lock acquired > > */ > > int odp_rwlock_read_trylock(odp_rwlock_t *rwlock); > > > > > > The spec just says that "read access" was not available. Implementation > decides when it's available and application just needs to re-try later on. > So, this implementation is OK by the spec. Supporting multiple readers > would improve parallelism, but it may not be optimal for performance if > the lock is free in the common case. > > > > > >> > >> The lock implementation I wrote allows to get the lock if a reader > already > >> owns it. And causes the testsuite to deadlock: > >> > >> odp_rwlock_init(rw_lock); > >> /* CU_ASSERT(odp_rwlock_is_locked(rw_lock) == 0); */ > >> > >> odp_rwlock_read_lock(rw_lock); => Lock is owned in read > >> > >> rc = odp_rwlock_read_trylock(rw_lock); => Locked is owned a second > >> time in read (rc = 1) > > > > You cannot do this on a single thread (lock the same lock twice). You > must use recursive locks if the thread holding a lock will lock it again. > > > > The issue is odp_rwlock_read_trylock fails here, but odp_rwlock_read_lock > would succeed. > Usually rwlock are recursive on the read side as it doesn't really matter > to the lock if the same thread owns it N times, or N threads own it once > each. > IMHO, in a non-concurrent setup, read_trylock should always succeed if > read_lock would succeed. > (I say non concurrent here to not acount for the case of contention on the > lock where many retries could be needed to get the lock).
We have recursive version of the lock (odp_rwlock_recursive_read_lock(), etc) and application should use that if the same thread will call lock() twice (or lock + try_lock). > > > > >> CU_ASSERT(rc == 0); > >> rc = odp_rwlock_write_trylock(rw_lock); => Expected failure > >> CU_ASSERT(rc == 0); > >> > >> odp_rwlock_read_unlock(rw_lock); => Lock is still owned once. > >> > >> > >> So either the API should describe more accurately what are the expected > >> success/failure case, or the test and implementation changed. > >> > >> On a side note, the API explicitly says that reader have the priority > on > >> writers on rwlock. Is this really an API requirement? > >> Our rwlocks are the other way around to avoid the starvation issue. Do > I > >> need to change them ? Or is it OK with the API? > >> > > Do you mean this: > > * A reader/writer lock allows multiple simultaneous readers but only > one > > * writer at a time. A thread that wants write access will have to wait > until > > * there are no threads that want read access. This causes a risk for > > * starvation. The trylock variants can be used to avoid blocking when > > * the lock is not immediately available. > > > > It could be softened with "may have to wait" and "may cause a risk". > Different RW lock implementations should be possible. > > > > -Petri > What bothers me is this: > > A thread that wants write access will have to wait until > * there are no threads that want read access. > > This clearly states that a writer cannot get the write lock if a reader > *wants* it. > I think > > A thread that wants write access will have to wait until > * there are no threads that own read permission on the lock. > > > would relax this constraint and allow for write-priority rwlock. That's OK wording. -Petri