On Fri, Jul 13, 2018 at 02:30:53PM -0400, Waiman Long wrote: > It was discovered that a constant stream of readers might cause the > count to go negative most of the time after an initial trigger by a > writer even if no writer was present afterward. As a result, most of the > readers would have to go through the slowpath reducing their performance.
I'm slightly confused, what happens to trigger this? (also, I'm forever confused by the whole BIAS scheme) > To avoid that from happening, an additional check is added to detect > the special case that the reader in the critical section is the only > one in the wait queue and no writer is present. When that happens, it > can just have the lock and return immediately without further action. > Other incoming readers won't see a waiter is present and be forced > into the slowpath. > > The additional code is in the slowpath and so should not have an impact > on rwsem performance. However, in the special case listed above, it may > greatly improve performance. > diff --git a/kernel/locking/rwsem-xadd.c b/kernel/locking/rwsem-xadd.c > index 3064c50..bf0570e 100644 > --- a/kernel/locking/rwsem-xadd.c > +++ b/kernel/locking/rwsem-xadd.c > @@ -233,8 +233,19 @@ static void __rwsem_mark_wake(struct rw_semaphore *sem, your diff function thingy is busted, this is in fact __rwsem_down_read_failed_common you're patching. > waiter.type = RWSEM_WAITING_FOR_READ; > > raw_spin_lock_irq(&sem->wait_lock); > - if (list_empty(&sem->wait_list)) > + if (list_empty(&sem->wait_list)) { > + /* > + * In the unlikely event that the task is the only one in > + * the wait queue and a writer isn't present, it can have > + * the lock and return immediately without going through > + * the remaining slowpath code. > + */ > + if (unlikely(atomic_long_read(&sem->count) >= 0)) { > + raw_spin_unlock_irq(&sem->wait_lock); > + return sem; > + } > adjustment += RWSEM_WAITING_BIAS; > + } > list_add_tail(&waiter.list, &sem->wait_list); So without this, we would add ourselves to the list and then immediately call __rwsem_mark_wake() on ourselves and fall through the wait-loop, ow what?