+20
-10
kernel/locking/rwsem.c
+20
-10
kernel/locking/rwsem.c
···
335
335
struct task_struct *task;
336
336
enum rwsem_waiter_type type;
337
337
unsigned long timeout;
338
-
339
-
/* Writer only, not initialized in reader */
340
338
bool handoff_set;
341
339
};
342
340
#define rwsem_first_waiter(sem) \
···
457
459
* to give up the lock), request a HANDOFF to
458
460
* force the issue.
459
461
*/
460
-
if (!(oldcount & RWSEM_FLAG_HANDOFF) &&
461
-
time_after(jiffies, waiter->timeout)) {
462
-
adjustment -= RWSEM_FLAG_HANDOFF;
463
-
lockevent_inc(rwsem_rlock_handoff);
462
+
if (time_after(jiffies, waiter->timeout)) {
463
+
if (!(oldcount & RWSEM_FLAG_HANDOFF)) {
464
+
adjustment -= RWSEM_FLAG_HANDOFF;
465
+
lockevent_inc(rwsem_rlock_handoff);
466
+
}
467
+
waiter->handoff_set = true;
464
468
}
465
469
466
470
atomic_long_add(-adjustment, &sem->count);
···
599
599
static inline bool rwsem_try_write_lock(struct rw_semaphore *sem,
600
600
struct rwsem_waiter *waiter)
601
601
{
602
-
bool first = rwsem_first_waiter(sem) == waiter;
602
+
struct rwsem_waiter *first = rwsem_first_waiter(sem);
603
603
long count, new;
604
604
605
605
lockdep_assert_held(&sem->wait_lock);
···
609
609
bool has_handoff = !!(count & RWSEM_FLAG_HANDOFF);
610
610
611
611
if (has_handoff) {
612
-
if (!first)
612
+
/*
613
+
* Honor handoff bit and yield only when the first
614
+
* waiter is the one that set it. Otherwisee, we
615
+
* still try to acquire the rwsem.
616
+
*/
617
+
if (first->handoff_set && (waiter != first))
613
618
return false;
614
619
615
-
/* First waiter inherits a previously set handoff bit */
616
-
waiter->handoff_set = true;
620
+
/*
621
+
* First waiter can inherit a previously set handoff
622
+
* bit and spin on rwsem if lock acquisition fails.
623
+
*/
624
+
if (waiter == first)
625
+
waiter->handoff_set = true;
617
626
}
618
627
619
628
new = count;
···
1036
1027
waiter.task = current;
1037
1028
waiter.type = RWSEM_WAITING_FOR_READ;
1038
1029
waiter.timeout = jiffies + RWSEM_WAIT_TIMEOUT;
1030
+
waiter.handoff_set = false;
1039
1031
1040
1032
raw_spin_lock_irq(&sem->wait_lock);
1041
1033
if (list_empty(&sem->wait_list)) {