aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavidlohr Bueso <dave@stgolabs.net>2016-12-14 18:06:46 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2016-12-14 19:04:08 -0500
commitb5fa01a22e4ba9e3ca6de7cb94c3d21e42da449c (patch)
tree2fcea15a5c609e51abf25e6cff6e1630627ed068
parentf150f02cfbc7b6b980e260856555abd73235a6b0 (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. [akpm@linux-foundation.org: coding-style fixes] 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> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
-rw-r--r--ipc/sem.c108
1 files changed, 52 insertions, 56 deletions
diff --git a/ipc/sem.c b/ipc/sem.c
index 4f5af6e7d630..a82c88d0900f 100644
--- a/ipc/sem.c
+++ b/ipc/sem.c
@@ -1963,71 +1963,67 @@ SYSCALL_DEFINE4(semtimedop, int, semid, struct sembuf __user *, tsops,
1963 sma->complex_count++; 1963 sma->complex_count++;
1964 } 1964 }
1965 1965
1966sleep_again: 1966 do {
1967 queue.status = -EINTR; 1967 queue.status = -EINTR;
1968 queue.sleeper = current; 1968 queue.sleeper = current;
1969 1969
1970 __set_current_state(TASK_INTERRUPTIBLE); 1970 __set_current_state(TASK_INTERRUPTIBLE);
1971 sem_unlock(sma, locknum); 1971 sem_unlock(sma, locknum);
1972 rcu_read_unlock(); 1972 rcu_read_unlock();
1973 1973
1974 if (timeout) 1974 if (timeout)
1975 jiffies_left = schedule_timeout(jiffies_left); 1975 jiffies_left = schedule_timeout(jiffies_left);
1976 else 1976 else
1977 schedule(); 1977 schedule();
1978 1978
1979 /*
1980 * fastpath: the semop has completed, either successfully or not, from
1981 * the syscall pov, is quite irrelevant to us at this point; we're done.
1982 *
1983 * We _do_ care, nonetheless, about being awoken by a signal or
1984 * spuriously. The queue.status is checked again in the slowpath (aka
1985 * after taking sem_lock), such that we can detect scenarios where we
1986 * were awakened externally, during the window between wake_q_add() and
1987 * wake_up_q().
1988 */
1989 error = READ_ONCE(queue.status);
1990 if (error != -EINTR) {
1991 /* 1979 /*
1992 * User space could assume that semop() is a memory barrier: 1980 * fastpath: the semop has completed, either successfully or
1993 * Without the mb(), the cpu could speculatively read in user 1981 * not, from the syscall pov, is quite irrelevant to us at this
1994 * space stale data that was overwritten by the previous owner 1982 * point; we're done.
1995 * of the semaphore. 1983 *
1984 * We _do_ care, nonetheless, about being awoken by a signal or
1985 * spuriously. The queue.status is checked again in the
1986 * slowpath (aka after taking sem_lock), such that we can detect
1987 * scenarios where we were awakened externally, during the
1988 * window between wake_q_add() and wake_up_q().
1996 */ 1989 */
1997 smp_mb(); 1990 error = READ_ONCE(queue.status);
1998 goto out_free; 1991 if (error != -EINTR) {
1999 } 1992 /*
2000 1993 * User space could assume that semop() is a memory
2001 rcu_read_lock(); 1994 * barrier: Without the mb(), the cpu could
2002 sma = sem_obtain_lock(ns, semid, sops, nsops, &locknum); 1995 * speculatively read in userspace stale data that was
2003 error = READ_ONCE(queue.status); 1996 * overwritten by the previous owner of the semaphore.
1997 */
1998 smp_mb();
1999 goto out_free;
2000 }
2004 2001
2005 /* 2002 rcu_read_lock();
2006 * Array removed? If yes, leave without sem_unlock(). 2003 sma = sem_obtain_lock(ns, semid, sops, nsops, &locknum);
2007 */ 2004 error = READ_ONCE(queue.status);
2008 if (IS_ERR(sma)) {
2009 rcu_read_unlock();
2010 goto out_free;
2011 }
2012 2005
2013 /* 2006 /*
2014 * If queue.status != -EINTR we are woken up by another process. 2007 * Array removed? If yes, leave without sem_unlock().
2015 * Leave without unlink_queue(), but with sem_unlock(). 2008 */
2016 */ 2009 if (IS_ERR(sma)) {
2017 if (error != -EINTR) 2010 rcu_read_unlock();
2018 goto out_unlock_free; 2011 goto out_free;
2012 }
2019 2013
2020 /* 2014 /*
2021 * If an interrupt occurred we have to clean up the queue. 2015 * If queue.status != -EINTR we are woken up by another process.
2022 */ 2016 * Leave without unlink_queue(), but with sem_unlock().
2023 if (timeout && jiffies_left == 0) 2017 */
2024 error = -EAGAIN; 2018 if (error != -EINTR)
2019 goto out_unlock_free;
2025 2020
2026 /* 2021 /*
2027 * If the wakeup was spurious, just retry. 2022 * If an interrupt occurred we have to clean up the queue.
2028 */ 2023 */
2029 if (error == -EINTR && !signal_pending(current)) 2024 if (timeout && jiffies_left == 0)
2030 goto sleep_again; 2025 error = -EAGAIN;
2026 } while (error == -EINTR && !signal_pending(current)); /* spurious */
2031 2027
2032 unlink_queue(sma, &queue); 2028 unlink_queue(sma, &queue);
2033 2029