diff options
author | Rickard Green <rickard@erlang.org> | 2011-12-23 14:36:59 +0100 |
---|---|---|
committer | Rickard Green <rickard@erlang.org> | 2011-12-27 15:17:44 +0100 |
commit | 54507ec64c0b1e6b2b150c69b55eb84d08b07a15 (patch) | |
tree | 30db0ee345544a1938ebdb68aab5fb51dccdf53f /erts/lib_src/pthread/ethread.c | |
parent | 6088c2c426d71a21874673ca6ddf93aa9e2ed4ab (diff) | |
download | otp-54507ec64c0b1e6b2b150c69b55eb84d08b07a15.tar.gz otp-54507ec64c0b1e6b2b150c69b55eb84d08b07a15.tar.bz2 otp-54507ec64c0b1e6b2b150c69b55eb84d08b07a15.zip |
Fix lwsync instruction feature test
A feature test for the lwsync instruction performed on PowerPC
hardware at runtime system startup got into an eternal loop if
the instruction was not supported. This bug was introduced in
erts-5.9/OTP-R15B.
Diffstat (limited to 'erts/lib_src/pthread/ethread.c')
-rw-r--r-- | erts/lib_src/pthread/ethread.c | 49 |
1 files changed, 34 insertions, 15 deletions
diff --git a/erts/lib_src/pthread/ethread.c b/erts/lib_src/pthread/ethread.c index ad29249bac..fb7d135418 100644 --- a/erts/lib_src/pthread/ethread.c +++ b/erts/lib_src/pthread/ethread.c @@ -123,34 +123,53 @@ ethr_ts_event *ethr_get_tse__(void) #if defined(ETHR_PPC_RUNTIME_CONF__) -static volatile int lwsync_caused_sigill; +#include <sys/wait.h> static void handle_lwsync_sigill(int signum) { - lwsync_caused_sigill = 1; + _exit(1); } static int ppc_init__(void) { - struct sigaction act, oact; - lwsync_caused_sigill = 0; + int pid; - sigemptyset(&act.sa_mask); - act.sa_flags = 0; - act.sa_handler = handle_lwsync_sigill; - if (sigaction(SIGILL, &act, &oact) != 0) - return errno; + /* If anything what so ever failes we assume no lwsync for safety */ + ethr_runtime__.conf.have_lwsync = 0; + + /* + * We perform the lwsync test (which might cause an illegal + * instruction signal) in a separate process in order to be + * completely certain that we do not mess up our own state. + */ + pid = fork(); + if (pid == 0) { + struct sigaction act, oact; - __asm__ __volatile__ ("lwsync\n\t" : : : "memory"); + sigemptyset(&act.sa_mask); + act.sa_flags = SA_RESETHAND; + act.sa_handler = handle_lwsync_sigill; + if (sigaction(SIGILL, &act, &oact) != 0) + _exit(2); - act.sa_flags = 0; - act.sa_handler = SIG_DFL; - if (sigaction(SIGILL, &act, &oact) != 0) - return errno; + __asm__ __volatile__ ("lwsync\n\t" : : : "memory"); + + _exit(0); + } - ethr_runtime__.conf.have_lwsync = (int) !lwsync_caused_sigill; + if (pid != -1) { + while (1) { + int status, res; + res = waitpid(pid, &status, 0); + if (res == pid) { + if (WIFEXITED(status) && WEXITSTATUS(status) == 0) + ethr_runtime__.conf.have_lwsync = 1; + break; + } + } + } return 0; } |