Skip to content

Commit 8cf5322

Browse files
walken-googletorvalds
authored andcommitted
rwsem: simplify __rwsem_do_wake
This is mostly for cleanup value: - We don't need several gotos to handle the case where the first waiter is a writer. Two simple tests will do (and generate very similar code). - In the remainder of the function, we know the first waiter is a reader, so we don't have to double check that. We can use do..while loops to iterate over the readers to wake (generates slightly better code). Signed-off-by: Michel Lespinasse <walken@google.com> Reviewed-by: Peter Hurley <peter@hurleysoftware.com> Acked-by: Davidlohr Bueso <davidlohr.bueso@hp.com> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
1 parent 9b0fc9c commit 8cf5322

File tree

2 files changed

+19
-30
lines changed

2 files changed

+19
-30
lines changed

lib/rwsem-spinlock.c

Lines changed: 7 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -70,26 +70,17 @@ __rwsem_do_wake(struct rw_semaphore *sem, int wakewrite)
7070

7171
waiter = list_entry(sem->wait_list.next, struct rwsem_waiter, list);
7272

73-
if (!wakewrite) {
74-
if (waiter->type == RWSEM_WAITING_FOR_WRITE)
75-
goto out;
76-
goto dont_wake_writers;
77-
}
78-
79-
/*
80-
* as we support write lock stealing, we can't set sem->activity
81-
* to -1 here to indicate we get the lock. Instead, we wake it up
82-
* to let it go get it again.
83-
*/
8473
if (waiter->type == RWSEM_WAITING_FOR_WRITE) {
85-
wake_up_process(waiter->task);
74+
if (wakewrite)
75+
/* Wake up a writer. Note that we do not grant it the
76+
* lock - it will have to acquire it when it runs. */
77+
wake_up_process(waiter->task);
8678
goto out;
8779
}
8880

8981
/* grant an infinite number of read locks to the front of the queue */
90-
dont_wake_writers:
9182
woken = 0;
92-
while (waiter->type == RWSEM_WAITING_FOR_READ) {
83+
do {
9384
struct list_head *next = waiter->list.next;
9485

9586
list_del(&waiter->list);
@@ -99,10 +90,10 @@ __rwsem_do_wake(struct rw_semaphore *sem, int wakewrite)
9990
wake_up_process(tsk);
10091
put_task_struct(tsk);
10192
woken++;
102-
if (list_empty(&sem->wait_list))
93+
if (next == &sem->wait_list)
10394
break;
10495
waiter = list_entry(next, struct rwsem_waiter, list);
105-
}
96+
} while (waiter->type != RWSEM_WAITING_FOR_WRITE);
10697

10798
sem->activity += woken;
10899

lib/rwsem.c

Lines changed: 12 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -68,20 +68,17 @@ __rwsem_do_wake(struct rw_semaphore *sem, int wake_type)
6868
signed long woken, loop, adjustment;
6969

7070
waiter = list_entry(sem->wait_list.next, struct rwsem_waiter, list);
71-
if (waiter->type != RWSEM_WAITING_FOR_WRITE)
72-
goto readers_only;
73-
74-
if (wake_type == RWSEM_WAKE_READ_OWNED)
75-
/* Another active reader was observed, so wakeup is not
76-
* likely to succeed. Save the atomic op.
77-
*/
71+
if (waiter->type == RWSEM_WAITING_FOR_WRITE) {
72+
if (wake_type != RWSEM_WAKE_READ_OWNED)
73+
/* Wake writer at the front of the queue, but do not
74+
* grant it the lock yet as we want other writers
75+
* to be able to steal it. Readers, on the other hand,
76+
* will block as they will notice the queued writer.
77+
*/
78+
wake_up_process(waiter->task);
7879
goto out;
80+
}
7981

80-
/* Wake up the writing waiter and let the task grab the sem: */
81-
wake_up_process(waiter->task);
82-
goto out;
83-
84-
readers_only:
8582
/* If we come here from up_xxxx(), another thread might have reached
8683
* rwsem_down_failed_common() before we acquired the spinlock and
8784
* woken up a waiter, making it now active. We prefer to check for
@@ -125,15 +122,16 @@ __rwsem_do_wake(struct rw_semaphore *sem, int wake_type)
125122
rwsem_atomic_add(adjustment, sem);
126123

127124
next = sem->wait_list.next;
128-
for (loop = woken; loop > 0; loop--) {
125+
loop = woken;
126+
do {
129127
waiter = list_entry(next, struct rwsem_waiter, list);
130128
next = waiter->list.next;
131129
tsk = waiter->task;
132130
smp_mb();
133131
waiter->task = NULL;
134132
wake_up_process(tsk);
135133
put_task_struct(tsk);
136-
}
134+
} while (--loop);
137135

138136
sem->wait_list.next = next;
139137
next->prev = &sem->wait_list;

0 commit comments

Comments
 (0)