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 /ipc | |
| 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>
Diffstat (limited to 'ipc')
| -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 | ||
