Re: [PATCH v2 2/3] locking/rwsem: Enable early rwsem writer lock handoff

From: Waiman Long
Date: Thu Feb 23 2023 - 09:17:59 EST



On 2/23/23 07:32, Peter Zijlstra wrote:
On Thu, Feb 16, 2023 at 04:09:32PM -0500, Waiman Long wrote:
@@ -432,19 +433,39 @@ static void rwsem_mark_wake(struct rw_semaphore *sem,
* Mark writer at the front of the queue for wakeup.
* Until the task is actually later awoken later by
* the caller, other writers are able to steal it.
+ *
+ * *Unless* HANDOFF is set, in which case only the
+ * first waiter is allowed to take it.
+ *
* Readers, on the other hand, will block as they
* will notice the queued writer.
*/
wake_q_add(wake_q, waiter->task);
lockevent_inc(rwsem_wake_writer);
+
+ if ((count & RWSEM_LOCK_MASK) || !(count & RWSEM_FLAG_HANDOFF))
+ return;
+
+ /*
+ * If the rwsem is free and handoff flag is set with wait_lock
+ * held, no other CPUs can take an active lock. We can do an
+ * early handoff.
+ */
+ adjustment = RWSEM_WRITER_LOCKED - RWSEM_FLAG_HANDOFF;
+ atomic_long_set(&sem->owner, (long)waiter->task);
+ waiter->task = NULL;
+ atomic_long_add(adjustment, &sem->count);
+ rwsem_del_waiter(sem, waiter);
+ lockevent_inc(rwsem_wlock_ehandoff);
}
*sigh*... you can't even properly copy/paste from the reader side :/
This is broken, the moment you do waiter->task = NULL, waiter can
dissapear from under you and that rwsem_del_waiter() is a UaF.

Nor did you unify the reader and writer side and still have a giant
trainwreck on your hands..

Surely all that isn't too hard... let me post it.

Right, I should keep the clearing after deleting the waiter. Thanks for spotting that. I will review your patches soon.

Cheers,
Longman