ANDROID: locking/rwsem: only clean RWSEM_FLAG_HANDOFF when already set
sem->count will be negative after writer is killed
if flag RWSEM_FLAG_HANDOFF is not set, we shouldn't clean again
CPU2 CPU4
task A[reader] task B[writer]
down_read_killable[locked]
sem->count=0x100
down_write_killable
sem->count=0x102[wlist not empty]
up_read
count=0x2
sig kill received
down_read_killable
sem->count=0x102[wlist not empty]
goto branch out_nolock:
list_del(&waiter.list);
wait list is empty
sem->count-RWSEM_FLAG_HANDOFF
sem->count=0xFE
list_empty(&sem->wait_list) is TRUE
sem->count andnot RWSEM_FLAG_WAITERS
sem->count=0xFC
up_read
sem->count-=0x100
sem->count=0xFFFFFFFFFFFFFFFC
DEBUG_RWSEMS_WARN_ON(tmp < 0, sem);
Bug: 204595609
Link: https://lore.kernel.org/all/a630a9aa-8c66-31c9-21a0-3d30bde2c9df@redhat.com/T/
Signed-off-by: mazhenhua <mazhenhua@xiaomi.com>
Change-Id: Ife64c179335d74768a3d68e402c72d10148f3e7e
This commit is contained in:
@@ -1287,7 +1287,7 @@ out_nolock:
|
||||
list_del(&waiter.list);
|
||||
|
||||
if (unlikely(wstate == WRITER_HANDOFF))
|
||||
atomic_long_add(-RWSEM_FLAG_HANDOFF, &sem->count);
|
||||
atomic_long_andnot(RWSEM_FLAG_HANDOFF, &sem->count);
|
||||
|
||||
if (list_empty(&sem->wait_list))
|
||||
atomic_long_andnot(RWSEM_FLAG_WAITERS, &sem->count);
|
||||
|
||||
Reference in New Issue
Block a user