diff options
author | Davidlohr Bueso <dave@stgolabs.net> | 2016-11-24 09:24:18 +1100 |
---|---|---|
committer | Stephen Rothwell <sfr@canb.auug.org.au> | 2016-11-29 15:36:35 +1100 |
commit | 6dc01edbe2f64fc91fdf108b6b009a37017b09bc (patch) | |
tree | 237ea075e3f589d249cb798ff371ea3605fc0fea | |
parent | a3f61413484eaab61d7bb4c82a58b8aca504ca4c (diff) |
ipc/sem: simplify wait-wake loop
Instead of using the reverse goto, we can simplify the flow and make it
more language natural by just doing do-while instead. One would hope this
is the standard way (or obviously just with a while bucle) that we do
wait/wakeup handling in the kernel. The exact same logic is kept, just
more indented.
Link: http://lkml.kernel.org/r/1478708774-28826-2-git-send-email-dave@stgolabs.net
Signed-off-by: Davidlohr Bueso <dbueso@suse.de>
Cc: Manfred Spraul <manfred@colorfullife.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
-rw-r--r-- | ipc/sem.c | 107 |
1 files changed, 51 insertions, 56 deletions
diff --git a/ipc/sem.c b/ipc/sem.c index 77c011e90414..c8b9b7204aa7 100644 --- a/ipc/sem.c +++ b/ipc/sem.c @@ -1980,71 +1980,66 @@ SYSCALL_DEFINE4(semtimedop, int, semid, struct sembuf __user *, tsops, sma->complex_count++; } -sleep_again: - queue.status = -EINTR; - queue.sleeper = current; + do { + queue.status = -EINTR; + queue.sleeper = current; - __set_current_state(TASK_INTERRUPTIBLE); - sem_unlock(sma, locknum); - rcu_read_unlock(); + __set_current_state(TASK_INTERRUPTIBLE); + sem_unlock(sma, locknum); + rcu_read_unlock(); - if (timeout) - jiffies_left = schedule_timeout(jiffies_left); - else - schedule(); + if (timeout) + jiffies_left = schedule_timeout(jiffies_left); + else + schedule(); - /* - * fastpath: the semop has completed, either successfully or not, from - * the syscall pov, is quite irrelevant to us at this point; we're done. - * - * We _do_ care, nonetheless, about being awoken by a signal or - * spuriously. The queue.status is checked again in the slowpath (aka - * after taking sem_lock), such that we can detect scenarios where we - * were awakened externally, during the window between wake_q_add() and - * wake_up_q(). - */ - error = READ_ONCE(queue.status); - if (error != -EINTR) { /* - * User space could assume that semop() is a memory barrier: - * Without the mb(), the cpu could speculatively read in user - * space stale data that was overwritten by the previous owner - * of the semaphore. + * fastpath: the semop has completed, either successfully or not, from + * the syscall pov, is quite irrelevant to us at this point; we're done. + * + * We _do_ care, nonetheless, about being awoken by a signal or + * spuriously. The queue.status is checked again in the slowpath (aka + * after taking sem_lock), such that we can detect scenarios where we + * were awakened externally, during the window between wake_q_add() and + * wake_up_q(). */ - smp_mb(); - goto out_free; - } - - rcu_read_lock(); - sma = sem_obtain_lock(ns, semid, sops, nsops, &locknum); - error = READ_ONCE(queue.status); + error = READ_ONCE(queue.status); + if (error != -EINTR) { + /* + * User space could assume that semop() is a memory barrier: + * Without the mb(), the cpu could speculatively read in user + * space stale data that was overwritten by the previous owner + * of the semaphore. + */ + smp_mb(); + goto out_free; + } - /* - * Array removed? If yes, leave without sem_unlock(). - */ - if (IS_ERR(sma)) { - rcu_read_unlock(); - goto out_free; - } + rcu_read_lock(); + sma = sem_obtain_lock(ns, semid, sops, nsops, &locknum); + error = READ_ONCE(queue.status); - /* - * If queue.status != -EINTR we are woken up by another process. - * Leave without unlink_queue(), but with sem_unlock(). - */ - if (error != -EINTR) - goto out_unlock_free; + /* + * Array removed? If yes, leave without sem_unlock(). + */ + if (IS_ERR(sma)) { + rcu_read_unlock(); + goto out_free; + } - /* - * If an interrupt occurred we have to clean up the queue. - */ - if (timeout && jiffies_left == 0) - error = -EAGAIN; + /* + * If queue.status != -EINTR we are woken up by another process. + * Leave without unlink_queue(), but with sem_unlock(). + */ + if (error != -EINTR) + goto out_unlock_free; - /* - * If the wakeup was spurious, just retry. - */ - if (error == -EINTR && !signal_pending(current)) - goto sleep_again; + /* + * If an interrupt occurred we have to clean up the queue. + */ + if (timeout && jiffies_left == 0) + error = -EAGAIN; + } while (error == -EINTR && !signal_pending(current)); /* spurious */ unlink_queue(sma, &queue); |