diff options
author | Michel Lespinasse <walken@google.com> | 2013-05-07 09:45:58 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2013-05-07 10:20:16 -0400 |
commit | 8cf5322ce69afea1fab6a6270db24d057d664798 (patch) | |
tree | a7b49b135dc7703a4a709562178a847fb9bc4f77 /lib/rwsem-spinlock.c | |
parent | 9b0fc9c09f1b262b7fe697eba6b05095d78850e5 (diff) |
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>
Diffstat (limited to 'lib/rwsem-spinlock.c')
-rw-r--r-- | lib/rwsem-spinlock.c | 23 |
1 files changed, 7 insertions, 16 deletions
diff --git a/lib/rwsem-spinlock.c b/lib/rwsem-spinlock.c index 5f117f37ac0a..9be8a9144978 100644 --- a/lib/rwsem-spinlock.c +++ b/lib/rwsem-spinlock.c | |||
@@ -70,26 +70,17 @@ __rwsem_do_wake(struct rw_semaphore *sem, int wakewrite) | |||
70 | 70 | ||
71 | waiter = list_entry(sem->wait_list.next, struct rwsem_waiter, list); | 71 | waiter = list_entry(sem->wait_list.next, struct rwsem_waiter, list); |
72 | 72 | ||
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 | */ | ||
84 | if (waiter->type == RWSEM_WAITING_FOR_WRITE) { | 73 | 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); | ||
86 | goto out; | 78 | goto out; |
87 | } | 79 | } |
88 | 80 | ||
89 | /* grant an infinite number of read locks to the front of the queue */ | 81 | /* grant an infinite number of read locks to the front of the queue */ |
90 | dont_wake_writers: | ||
91 | woken = 0; | 82 | woken = 0; |
92 | while (waiter->type == RWSEM_WAITING_FOR_READ) { | 83 | do { |
93 | struct list_head *next = waiter->list.next; | 84 | struct list_head *next = waiter->list.next; |
94 | 85 | ||
95 | list_del(&waiter->list); | 86 | list_del(&waiter->list); |
@@ -99,10 +90,10 @@ __rwsem_do_wake(struct rw_semaphore *sem, int wakewrite) | |||
99 | wake_up_process(tsk); | 90 | wake_up_process(tsk); |
100 | put_task_struct(tsk); | 91 | put_task_struct(tsk); |
101 | woken++; | 92 | woken++; |
102 | if (list_empty(&sem->wait_list)) | 93 | if (next == &sem->wait_list) |
103 | break; | 94 | break; |
104 | waiter = list_entry(next, struct rwsem_waiter, list); | 95 | waiter = list_entry(next, struct rwsem_waiter, list); |
105 | } | 96 | } while (waiter->type != RWSEM_WAITING_FOR_WRITE); |
106 | 97 | ||
107 | sem->activity += woken; | 98 | sem->activity += woken; |
108 | 99 | ||