diff options
author | Davidlohr Bueso <dave@stgolabs.net> | 2016-12-14 18:06:46 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2016-12-14 19:04:08 -0500 |
commit | b5fa01a22e4ba9e3ca6de7cb94c3d21e42da449c (patch) | |
tree | 2fcea15a5c609e51abf25e6cff6e1630627ed068 | |
parent | f150f02cfbc7b6b980e260856555abd73235a6b0 (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.c | 108 |
1 files changed, 52 insertions, 56 deletions
@@ -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 | ||
1966 | sleep_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 | ||