diff options
author | Rickard Green <[email protected]> | 2010-06-01 13:50:50 +0000 |
---|---|---|
committer | Erlang/OTP <[email protected]> | 2010-06-01 13:50:50 +0000 |
commit | b53f8a67649a371a38dc6d97b0dfe52111236a3e (patch) | |
tree | ae954fdc12817e287dab6cdce7030c9d54e83219 /erts/emulator/sys | |
parent | 6999e909a9ad22d90b64263fd5edd186ac93a990 (diff) | |
download | otp-b53f8a67649a371a38dc6d97b0dfe52111236a3e.tar.gz otp-b53f8a67649a371a38dc6d97b0dfe52111236a3e.tar.bz2 otp-b53f8a67649a371a38dc6d97b0dfe52111236a3e.zip |
OTP-8658 Add missing memory barriers in erts_poll()
Missing memory barriers in erts_poll() could cause the runtime system to
hang indefinitely.
Diffstat (limited to 'erts/emulator/sys')
-rw-r--r-- | erts/emulator/sys/common/erl_poll.c | 58 | ||||
-rw-r--r-- | erts/emulator/sys/win32/erl_poll.c | 65 |
2 files changed, 87 insertions, 36 deletions
diff --git a/erts/emulator/sys/common/erl_poll.c b/erts/emulator/sys/common/erl_poll.c index d268547e1a..09fb6337f7 100644 --- a/erts/emulator/sys/common/erl_poll.c +++ b/erts/emulator/sys/common/erl_poll.c @@ -130,13 +130,18 @@ #define ERTS_POLLSET_IS_POLLED(PS) \ ((int) erts_smp_atomic_read(&(PS)->polled)) -#define ERTS_POLLSET_SET_POLLER_WOKEN_CHK(PS) \ - ((int) erts_smp_atomic_xchg(&(PS)->woken, (long) 1)) -#define ERTS_POLLSET_SET_POLLER_WOKEN(PS) \ - erts_smp_atomic_set(&(PS)->woken, (long) 1) -#define ERTS_POLLSET_UNSET_POLLER_WOKEN(PS) \ - erts_smp_atomic_set(&(PS)->woken, (long) 0) -#define ERTS_POLLSET_IS_POLLER_WOKEN(PS) \ +#define ERTS_POLLSET_SET_POLLER_WOKEN_CHK(PS) set_poller_woken_chk((PS)) +#define ERTS_POLLSET_SET_POLLER_WOKEN(PS) \ +do { \ + ERTS_THR_MEMORY_BARRIER; \ + erts_smp_atomic_set(&(PS)->woken, (long) 1); \ +} while (0) +#define ERTS_POLLSET_UNSET_POLLER_WOKEN(PS) \ +do { \ + erts_smp_atomic_set(&(PS)->woken, (long) 0); \ + ERTS_THR_MEMORY_BARRIER; \ +} while (0) +#define ERTS_POLLSET_IS_POLLER_WOKEN(PS) \ ((int) erts_smp_atomic_read(&(PS)->woken)) #else @@ -194,13 +199,18 @@ #else -#define ERTS_POLLSET_UNSET_INTERRUPTED_CHK(PS) \ - ((int) erts_smp_atomic_xchg(&(PS)->interrupt, (long) 0)) -#define ERTS_POLLSET_UNSET_INTERRUPTED(PS) \ - erts_smp_atomic_set(&(PS)->interrupt, (long) 0) -#define ERTS_POLLSET_SET_INTERRUPTED(PS) \ - erts_smp_atomic_set(&(PS)->interrupt, (long) 1) -#define ERTS_POLLSET_IS_INTERRUPTED(PS) \ +#define ERTS_POLLSET_UNSET_INTERRUPTED_CHK(PS) unset_interrupted_chk((PS)) +#define ERTS_POLLSET_UNSET_INTERRUPTED(PS) \ +do { \ + erts_smp_atomic_set(&(PS)->interrupt, (long) 0); \ + ERTS_THR_MEMORY_BARRIER; \ +} while (0) +#define ERTS_POLLSET_SET_INTERRUPTED(PS) \ +do { \ + ERTS_THR_MEMORY_BARRIER; \ + erts_smp_atomic_set(&(PS)->interrupt, (long) 1); \ +} while (0) +#define ERTS_POLLSET_IS_INTERRUPTED(PS) \ ((int) erts_smp_atomic_read(&(PS)->interrupt)) #endif @@ -336,16 +346,30 @@ struct ErtsPollSet_ { #endif }; -#if ERTS_POLL_ASYNC_INTERRUPT_SUPPORT && !defined(ERTS_SMP) - static ERTS_INLINE int unset_interrupted_chk(ErtsPollSet ps) { + int res; +#if ERTS_POLL_ASYNC_INTERRUPT_SUPPORT && !defined(ERTS_SMP) /* This operation isn't atomic, but we have no need at all for an atomic operation here... */ - int res = ps->interrupt; + res = ps->interrupt; ps->interrupt = 0; +#else + res = (int) erts_smp_atomic_xchg(&ps->interrupt, (long) 0); + ERTS_THR_MEMORY_BARRIER; +#endif return res; + +} + +#ifdef ERTS_SMP + +static ERTS_INLINE int +set_poller_woken_chk(ErtsPollSet ps) +{ + ERTS_THR_MEMORY_BARRIER; + return (int) erts_smp_atomic_xchg(&ps->woken, (long) 1); } #endif diff --git a/erts/emulator/sys/win32/erl_poll.c b/erts/emulator/sys/win32/erl_poll.c index d816cc2c07..a766fe9575 100644 --- a/erts/emulator/sys/win32/erl_poll.c +++ b/erts/emulator/sys/win32/erl_poll.c @@ -1,19 +1,19 @@ /* * %CopyrightBegin% - * - * Copyright Ericsson AB 2007-2009. All Rights Reserved. - * + * + * Copyright Ericsson AB 2007-2010. All Rights Reserved. + * * The contents of this file are subject to the Erlang Public License, * Version 1.1, (the "License"); you may not use this file except in * compliance with the License. You should have received a copy of the * Erlang Public License along with this software. If not, it can be * retrieved online at http://www.erlang.org/. - * + * * Software distributed under the License is distributed on an "AS IS" * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See * the License for the specific language governing rights and limitations * under the License. - * + * * %CopyrightEnd% */ #ifdef HAVE_CONFIG_H @@ -304,24 +304,51 @@ struct ErtsPollSet_ { erts_smp_atomic_set(&(PS)->polled, (long) 0) #define ERTS_POLLSET_IS_POLLED(PS) \ ((int) erts_smp_atomic_read(&(PS)->polled)) -#define ERTS_POLLSET_SET_POLLER_WOKEN_CHK(PS) \ - ((int) erts_smp_atomic_xchg(&(PS)->woken, (long) 1)) -#define ERTS_POLLSET_SET_POLLER_WOKEN(PS) \ - erts_smp_atomic_set(&(PS)->woken, (long) 1) -#define ERTS_POLLSET_UNSET_POLLER_WOKEN(PS) \ - erts_smp_atomic_set(&(PS)->woken, (long) 0) -#define ERTS_POLLSET_IS_POLLER_WOKEN(PS) \ + +#define ERTS_POLLSET_SET_POLLER_WOKEN_CHK(PS) set_poller_woken_chk((PS)) +#define ERTS_POLLSET_SET_POLLER_WOKEN(PS) \ +do { \ + ERTS_THR_MEMORY_BARRIER; \ + erts_smp_atomic_set(&(PS)->woken, (long) 1); \ +} while (0) +#define ERTS_POLLSET_UNSET_POLLER_WOKEN(PS) \ +do { \ + erts_smp_atomic_set(&(PS)->woken, (long) 0); \ + ERTS_THR_MEMORY_BARRIER; \ +} while (0) +#define ERTS_POLLSET_IS_POLLER_WOKEN(PS) \ ((int) erts_smp_atomic_read(&(PS)->woken)) -#define ERTS_POLLSET_UNSET_INTERRUPTED_CHK(PS) \ - ((int) erts_smp_atomic_xchg(&(PS)->interrupt, (long) 0)) -#define ERTS_POLLSET_UNSET_INTERRUPTED(PS) \ - erts_smp_atomic_set(&(PS)->interrupt, (long) 0) -#define ERTS_POLLSET_SET_INTERRUPTED(PS) \ - erts_smp_atomic_set(&(PS)->interrupt, (long) 1) -#define ERTS_POLLSET_IS_INTERRUPTED(PS) \ +#define ERTS_POLLSET_UNSET_INTERRUPTED_CHK(PS) unset_interrupted_chk((PS)) +#define ERTS_POLLSET_UNSET_INTERRUPTED(PS) \ +do { \ + erts_smp_atomic_set(&(PS)->interrupt, (long) 0); \ + ERTS_THR_MEMORY_BARRIER; \ +} while (0) +#define ERTS_POLLSET_SET_INTERRUPTED(PS) \ +do { \ + ERTS_THR_MEMORY_BARRIER; \ + erts_smp_atomic_set(&(PS)->interrupt, (long) 1); \ +} while (0) +#define ERTS_POLLSET_IS_INTERRUPTED(PS) \ ((int) erts_smp_atomic_read(&(PS)->interrupt)) +static ERTS_INLINE int +unset_interrupted_chk(ErtsPollSet ps) +{ + int res = (int) erts_smp_atomic_xchg(&ps->interrupt, (long) 0); + ERTS_THR_MEMORY_BARRIER; + return res; + +} + +static ERTS_INLINE int +set_poller_woken_chk(ErtsPollSet ps) +{ + ERTS_THR_MEMORY_BARRIER; + return (int) erts_smp_atomic_xchg(&ps->woken, (long) 1); +} + #else #define ERTS_POLLSET_LOCK(PS) |