From: Andreas HUBERT Date: Thu, 13 Nov 2008 23:10:01 +0000 (+0100) Subject: * src/vm/signal.cpp, X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=commitdiff_plain;h=c301444089e85b07706f8551fefb493b4e64b07f;p=cacao.git * src/vm/signal.cpp, src/vm/signallocal.hpp: Switched to C++. --HG-- rename : src/vm/signal.c => src/vm/signal.cpp rename : src/vm/signallocal.h => src/vm/signallocal.hpp --- diff --git a/src/native/vm/openjdk/jvm.cpp b/src/native/vm/openjdk/jvm.cpp index 2133bf626..c13f6ece6 100644 --- a/src/native/vm/openjdk/jvm.cpp +++ b/src/native/vm/openjdk/jvm.cpp @@ -85,7 +85,7 @@ #include "vm/primitive.hpp" #include "vm/properties.hpp" #include "vm/resolve.hpp" -#include "vm/signallocal.h" +#include "vm/signallocal.hpp" #include "vm/string.hpp" #include "vm/vm.hpp" diff --git a/src/threads/posix/thread-posix.cpp b/src/threads/posix/thread-posix.cpp index 6a8b82feb..40c59aa68 100644 --- a/src/threads/posix/thread-posix.cpp +++ b/src/threads/posix/thread-posix.cpp @@ -66,7 +66,7 @@ #include "vm/globals.hpp" #include "vm/javaobjects.hpp" #include "vm/options.h" -#include "vm/signallocal.h" +#include "vm/signallocal.hpp" #include "vm/string.hpp" #include "vm/vm.hpp" diff --git a/src/vm/Makefile.am b/src/vm/Makefile.am index 677a10663..7480e961b 100644 --- a/src/vm/Makefile.am +++ b/src/vm/Makefile.am @@ -122,8 +122,8 @@ libvm_la_SOURCES = \ resolve.cpp \ resolve.hpp \ $(RT_TIMING_SOURCES) \ - signal.c \ - signallocal.h \ + signal.cpp \ + signallocal.hpp \ $(STACKMAP_SOURCES) \ $(STATISTICS_SOURCES) \ string.cpp \ diff --git a/src/vm/jit/alpha/freebsd/md-os.c b/src/vm/jit/alpha/freebsd/md-os.c index e60626f3f..3d9169da8 100644 --- a/src/vm/jit/alpha/freebsd/md-os.c +++ b/src/vm/jit/alpha/freebsd/md-os.c @@ -35,7 +35,7 @@ #include "vm/jit/alpha/md-abi.h" #include "vm/global.h" -#include "vm/signallocal.h" +#include "vm/signallocal.hpp" #include "vm/jit/asmpart.h" diff --git a/src/vm/jit/alpha/linux/md-os.c b/src/vm/jit/alpha/linux/md-os.c index 8e127a9fa..1fe5e8086 100644 --- a/src/vm/jit/alpha/linux/md-os.c +++ b/src/vm/jit/alpha/linux/md-os.c @@ -39,7 +39,7 @@ #include "threads/thread.hpp" #include "vm/jit/builtin.hpp" -#include "vm/signallocal.h" +#include "vm/signallocal.hpp" #include "vm/os.hpp" #include "vm/jit/asmpart.h" diff --git a/src/vm/jit/arm/linux/md-os.c b/src/vm/jit/arm/linux/md-os.c index 1b1142e5a..10e7c13a2 100644 --- a/src/vm/jit/arm/linux/md-os.c +++ b/src/vm/jit/arm/linux/md-os.c @@ -52,7 +52,7 @@ typedef struct ucontext { #include "threads/thread.hpp" #include "vm/os.hpp" -#include "vm/signallocal.h" +#include "vm/signallocal.hpp" #include "vm/vm.hpp" #include "vm/jit/asmpart.h" diff --git a/src/vm/jit/i386/cygwin/md-os.c b/src/vm/jit/i386/cygwin/md-os.c index e35e6f6a1..add516af7 100644 --- a/src/vm/jit/i386/cygwin/md-os.c +++ b/src/vm/jit/i386/cygwin/md-os.c @@ -32,7 +32,7 @@ #include "vm/types.h" -#include "vm/signallocal.h" +#include "vm/signallocal.hpp" #include "vm/jit/asmpart.h" diff --git a/src/vm/jit/i386/darwin/md-os.c b/src/vm/jit/i386/darwin/md-os.c index 87157e500..b9f3afd9d 100644 --- a/src/vm/jit/i386/darwin/md-os.c +++ b/src/vm/jit/i386/darwin/md-os.c @@ -39,7 +39,7 @@ #include "vm/jit/builtin.hpp" #include "vm/global.h" -#include "vm/signallocal.h" +#include "vm/signallocal.hpp" #include "vm/jit/asmpart.h" #include "vm/jit/executionstate.h" diff --git a/src/vm/jit/i386/freebsd/md-os.c b/src/vm/jit/i386/freebsd/md-os.c index 9a1dc9d5e..9a1883147 100644 --- a/src/vm/jit/i386/freebsd/md-os.c +++ b/src/vm/jit/i386/freebsd/md-os.c @@ -36,7 +36,7 @@ #include "threads/thread.hpp" #include "vm/jit/builtin.hpp" -#include "vm/signallocal.h" +#include "vm/signallocal.hpp" #include "vm/jit/asmpart.h" #include "vm/jit/executionstate.h" diff --git a/src/vm/jit/i386/linux/md-os.c b/src/vm/jit/i386/linux/md-os.c index f046f37d6..19be0e4b7 100644 --- a/src/vm/jit/i386/linux/md-os.c +++ b/src/vm/jit/i386/linux/md-os.c @@ -38,7 +38,7 @@ #include "threads/thread.hpp" #include "vm/jit/builtin.hpp" -#include "vm/signallocal.h" +#include "vm/signallocal.hpp" #include "vm/jit/asmpart.h" #include "vm/jit/executionstate.h" diff --git a/src/vm/jit/i386/solaris/md-os.c b/src/vm/jit/i386/solaris/md-os.c index 67363ec8d..16e649d6d 100644 --- a/src/vm/jit/i386/solaris/md-os.c +++ b/src/vm/jit/i386/solaris/md-os.c @@ -36,7 +36,7 @@ #include "threads/thread.hpp" #include "vm/jit/builtin.hpp" -#include "vm/signallocal.h" +#include "vm/signallocal.hpp" #include "vm/jit/asmpart.h" #include "vm/jit/executionstate.h" diff --git a/src/vm/jit/m68k/linux/md-os.c b/src/vm/jit/m68k/linux/md-os.c index 21c54f56d..36e85035d 100644 --- a/src/vm/jit/m68k/linux/md-os.c +++ b/src/vm/jit/m68k/linux/md-os.c @@ -28,7 +28,7 @@ #include "vm/jit/m68k/md.h" #include "vm/jit/m68k/linux/md-abi.h" -#include "vm/signallocal.h" +#include "vm/signallocal.hpp" #include "vm/vm.hpp" #include "vm/jit/asmpart.h" diff --git a/src/vm/jit/mips/irix/md-os.c b/src/vm/jit/mips/irix/md-os.c index 39117af25..9f6a87cbf 100644 --- a/src/vm/jit/mips/irix/md-os.c +++ b/src/vm/jit/mips/irix/md-os.c @@ -38,7 +38,7 @@ #include "mm/gc.hpp" #include "vm/global.h" -#include "vm/signallocal.h" +#include "vm/signallocal.hpp" #include "vm/jit/asmpart.h" #include "vm/jit/codegen-common.hpp" diff --git a/src/vm/jit/mips/linux/md-os.c b/src/vm/jit/mips/linux/md-os.c index 2f2bee2df..e707d6ee2 100644 --- a/src/vm/jit/mips/linux/md-os.c +++ b/src/vm/jit/mips/linux/md-os.c @@ -40,7 +40,7 @@ #include "mm/gc.hpp" #include "mm/memory.hpp" -#include "vm/signallocal.h" +#include "vm/signallocal.hpp" #include "vm/os.hpp" #include "vm/jit/asmpart.h" diff --git a/src/vm/jit/powerpc/darwin/md-os.c b/src/vm/jit/powerpc/darwin/md-os.c index d2e6bf231..a809cfef2 100644 --- a/src/vm/jit/powerpc/darwin/md-os.c +++ b/src/vm/jit/powerpc/darwin/md-os.c @@ -39,7 +39,7 @@ #include "vm/jit/builtin.hpp" #include "vm/global.h" -#include "vm/signallocal.h" +#include "vm/signallocal.hpp" #include "vm/jit/asmpart.h" diff --git a/src/vm/jit/powerpc/linux/md-os.c b/src/vm/jit/powerpc/linux/md-os.c index e59a84cbb..5d2bf98e4 100644 --- a/src/vm/jit/powerpc/linux/md-os.c +++ b/src/vm/jit/powerpc/linux/md-os.c @@ -39,7 +39,7 @@ #include "threads/thread.hpp" #include "vm/jit/builtin.hpp" -#include "vm/signallocal.h" +#include "vm/signallocal.hpp" #include "vm/os.hpp" #include "vm/jit/asmpart.h" diff --git a/src/vm/jit/powerpc/netbsd/md-os.c b/src/vm/jit/powerpc/netbsd/md-os.c index a18683ef7..0fde3887c 100644 --- a/src/vm/jit/powerpc/netbsd/md-os.c +++ b/src/vm/jit/powerpc/netbsd/md-os.c @@ -31,7 +31,7 @@ #include "vm/jit/powerpc/netbsd/md-abi.h" -#include "vm/signallocal.h" +#include "vm/signallocal.hpp" #include "vm/jit/asmpart.h" #include "vm/jit/stacktrace.hpp" diff --git a/src/vm/jit/powerpc64/linux/md-os.c b/src/vm/jit/powerpc64/linux/md-os.c index ebb284b44..203cb007c 100644 --- a/src/vm/jit/powerpc64/linux/md-os.c +++ b/src/vm/jit/powerpc64/linux/md-os.c @@ -39,7 +39,7 @@ #include "threads/thread.hpp" #include "vm/jit/builtin.hpp" -#include "vm/signallocal.h" +#include "vm/signallocal.hpp" #include "vm/os.hpp" #include "vm/jit/asmpart.h" diff --git a/src/vm/jit/s390/md.c b/src/vm/jit/s390/md.c index 5e11280ac..0788e45a1 100644 --- a/src/vm/jit/s390/md.c +++ b/src/vm/jit/s390/md.c @@ -37,7 +37,7 @@ #include "threads/thread.hpp" #include "vm/exceptions.hpp" -#include "vm/signallocal.h" +#include "vm/signallocal.hpp" #include "vm/jit/asmpart.h" #include "vm/jit/abi.h" diff --git a/src/vm/jit/sparc64/linux/md-os.c b/src/vm/jit/sparc64/linux/md-os.c index e1cdfdb9f..97c10e3f6 100644 --- a/src/vm/jit/sparc64/linux/md-os.c +++ b/src/vm/jit/sparc64/linux/md-os.c @@ -34,7 +34,7 @@ #include "vm/jit/sparc64/codegen.h" #include "vm/jit/sparc64/md-abi.h" -#include "vm/signallocal.h" +#include "vm/signallocal.hpp" #include "vm/jit/asmpart.h" #include "vm/jit/stacktrace.hpp" diff --git a/src/vm/jit/sparc64/solaris/md-os.c b/src/vm/jit/sparc64/solaris/md-os.c index 7c4c802a8..8b13aa3f8 100644 --- a/src/vm/jit/sparc64/solaris/md-os.c +++ b/src/vm/jit/sparc64/solaris/md-os.c @@ -37,7 +37,7 @@ #include "vm/jit/sparc64/codegen.h" #include "vm/jit/sparc64/md-abi.h" -#include "vm/signallocal.h" +#include "vm/signallocal.hpp" #include "vm/jit/asmpart.h" #include "vm/jit/stacktrace.hpp" diff --git a/src/vm/jit/x86_64/freebsd/md-os.c b/src/vm/jit/x86_64/freebsd/md-os.c index 4b683342a..fd9244d33 100644 --- a/src/vm/jit/x86_64/freebsd/md-os.c +++ b/src/vm/jit/x86_64/freebsd/md-os.c @@ -31,7 +31,7 @@ #include "threads/thread.hpp" -#include "vm/signallocal.h" +#include "vm/signallocal.hpp" #include "vm/jit/asmpart.h" #include "vm/jit/stacktrace.hpp" diff --git a/src/vm/jit/x86_64/linux/md-os.c b/src/vm/jit/x86_64/linux/md-os.c index 5036ff2ef..78ff29675 100644 --- a/src/vm/jit/x86_64/linux/md-os.c +++ b/src/vm/jit/x86_64/linux/md-os.c @@ -40,7 +40,7 @@ #include "threads/thread.hpp" #include "vm/jit/builtin.hpp" -#include "vm/signallocal.h" +#include "vm/signallocal.hpp" #include "vm/jit/asmpart.h" #include "vm/jit/executionstate.h" diff --git a/src/vm/jit/x86_64/solaris/md-os.c b/src/vm/jit/x86_64/solaris/md-os.c index 14824a49e..cce569be9 100644 --- a/src/vm/jit/x86_64/solaris/md-os.c +++ b/src/vm/jit/x86_64/solaris/md-os.c @@ -38,7 +38,7 @@ #include "threads/thread.hpp" #include "vm/jit/builtin.hpp" -#include "vm/signallocal.h" +#include "vm/signallocal.hpp" #include "vm/jit/asmpart.h" #include "vm/jit/executionstate.h" diff --git a/src/vm/signal.c b/src/vm/signal.c deleted file mode 100644 index 73ccb0760..000000000 --- a/src/vm/signal.c +++ /dev/null @@ -1,401 +0,0 @@ -/* src/vm/signal.c - machine independent signal functions - - Copyright (C) 1996-2005, 2006, 2007, 2008 - CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO - - This file is part of CACAO. - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License as - published by the Free Software Foundation; either version 2, or (at - your option) any later version. - - This program is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - 02110-1301, USA. - -*/ - - -#include "config.h" - -#include -#include -#include -#include - -#if defined(__DARWIN__) -/* If we compile with -ansi on darwin, is not - included. So let's do it here. */ -# include -# include -#endif - -#include "arch.h" - -#if defined(ENABLE_GC_BOEHM) -# include "mm/memory.hpp" -#endif - -#include "threads/thread.hpp" -#include "threads/threadlist.hpp" - -#include "vm/exceptions.hpp" -#include "vm/globals.hpp" -#include "vm/method.hpp" -#include "vm/options.h" -#include "vm/signallocal.h" -#include "vm/vm.hpp" - -#if defined(ENABLE_STATISTICS) -# include "vm/statistics.h" -#endif - - -/* function prototypes ********************************************************/ - -void signal_handler_sighup(int sig, siginfo_t *siginfo, void *_p); - - -/* signal_init ***************************************************************** - - Initializes the signal subsystem and installs the signal handler. - -*******************************************************************************/ - -bool signal_init(void) -{ -#if !defined(__CYGWIN__) - sigset_t mask; - - TRACESUBSYSTEMINITIALIZATION("signal_init"); - -#if defined(__LINUX__) && defined(ENABLE_THREADS) - /* XXX Remove for exact-GC. */ - if (threads_pthreads_implementation_nptl) { -#endif - - /* Block the following signals (SIGINT for -c, SIGQUIT for - -\). We enable them later in signal_thread, but only for - this thread. */ - - if (sigemptyset(&mask) != 0) - vm_abort_errno("signal_init: sigemptyset failed"); - -#if !defined(WITH_JAVA_RUNTIME_LIBRARY_OPENJDK) - /* Let OpenJDK handle SIGINT itself. */ - - if (sigaddset(&mask, SIGINT) != 0) - vm_abort_errno("signal_init: sigaddset failed"); -#endif - -#if !defined(__FREEBSD__) - if (sigaddset(&mask, SIGQUIT) != 0) - vm_abort_errno("signal_init: sigaddset failed"); -#endif - - if (sigprocmask(SIG_BLOCK, &mask, NULL) != 0) - vm_abort_errno("signal_init: sigprocmask failed"); - -#if defined(__LINUX__) && defined(ENABLE_THREADS) - /* XXX Remove for exact-GC. */ - } -#endif - -#if defined(ENABLE_GC_BOEHM) - /* Allocate something so the garbage collector's signal handlers - are installed. */ - - (void) GCNEW(int); -#endif - - /* Install signal handlers for signals we want to catch in all - threads. */ - -#if defined(ENABLE_JIT) -# if defined(ENABLE_INTRP) - if (!opt_intrp) { -# endif - /* SIGSEGV handler */ - - signal_register_signal(SIGSEGV, (functionptr) md_signal_handler_sigsegv, - SA_NODEFER | SA_SIGINFO); - -# if defined(SIGBUS) - signal_register_signal(SIGBUS, (functionptr) md_signal_handler_sigsegv, - SA_NODEFER | SA_SIGINFO); -# endif - -# if SUPPORT_HARDWARE_DIVIDE_BY_ZERO - /* SIGFPE handler */ - - signal_register_signal(SIGFPE, (functionptr) md_signal_handler_sigfpe, - SA_NODEFER | SA_SIGINFO); -# endif - -# if defined(__ALPHA__) || defined(__ARM__) || defined(__I386__) || defined(__MIPS__) || defined(__POWERPC__) || defined(__POWERPC64__) || defined(__S390__) || defined(__X86_64__) || defined(__M68K__) - /* XXX use better defines for that (in arch.h) */ - /* SIGILL handler */ - - signal_register_signal(SIGILL, (functionptr) md_signal_handler_sigill, - SA_NODEFER | SA_SIGINFO); -# endif - -# if defined(__POWERPC__) - /* XXX use better defines for that (in arch.h) */ - /* SIGTRAP handler */ - - signal_register_signal(SIGTRAP, (functionptr) md_signal_handler_sigtrap, - SA_NODEFER | SA_SIGINFO); -# endif -# if defined(ENABLE_INTRP) - } -# endif - -#if defined(__DARWIN__) - do { - struct utsname name; - kern_return_t kr; - - /* Check if we're on 10.4 (Tiger/8.x) or earlier */ - if (uname(&name) != 0) - break; - - /* Make sure the string is large enough */ - /* Check the major number (ascii comparison) */ - /* Verify that we're not looking at '10.' by checking for a trailing period. */ - if (name.release[0] == '\0' || name.release[0] > '8' || name.release[1] != '.') - break; - - /* Reset CrashReporter's task signal handler */ - kr = task_set_exception_ports(mach_task_self(), - EXC_MASK_BAD_ACCESS -# if defined(__I386__) - | EXC_MASK_BAD_INSTRUCTION -#endif - , MACH_PORT_NULL, - EXCEPTION_STATE_IDENTITY, - MACHINE_THREAD_STATE); - - assert(kr == KERN_SUCCESS); - } while (false); -#endif -#endif /* !defined(ENABLE_JIT) */ - -#if defined(ENABLE_THREADS) - /* SIGHUP handler for threads_thread_interrupt */ - - signal_register_signal(Signal_INTERRUPT_SYSTEM_CALL, (functionptr) signal_handler_sighup, 0); -#endif - -#if defined(ENABLE_THREADS) && defined(ENABLE_GC_CACAO) - /* SIGUSR1 handler for the exact GC to suspend threads */ - - signal_register_signal(SIGUSR1, (functionptr) md_signal_handler_sigusr1, - SA_SIGINFO); -#endif - -#if defined(ENABLE_THREADS) && defined(ENABLE_PROFILING) - /* SIGUSR2 handler for profiling sampling */ - - signal_register_signal(SIGUSR2, (functionptr) md_signal_handler_sigusr2, - SA_SIGINFO); -#endif - -#endif /* !defined(__CYGWIN__) */ - - return true; -} - - -/* signal_register_signal ****************************************************** - - Register the specified handler with the specified signal. - -*******************************************************************************/ - -void signal_register_signal(int signum, functionptr handler, int flags) -{ - struct sigaction act; - - void (*function)(int, siginfo_t *, void *); - - function = (void (*)(int, siginfo_t *, void *)) handler; - - if (sigemptyset(&act.sa_mask) != 0) - vm_abort_errno("signal_register_signal: sigemptyset failed"); - - act.sa_sigaction = function; - act.sa_flags = flags; - - if (sigaction(signum, &act, NULL) != 0) - vm_abort_errno("signal_register_signal: sigaction failed"); -} - - -/* signal_thread ************************************************************ - - This thread sets the signal mask to catch the user input signals - (SIGINT, SIGQUIT). We use such a thread, so we don't get the - signals on every single thread running. - -*******************************************************************************/ - -static void signal_thread(void) -{ - threadobject *t; - sigset_t mask; - int sig; - int result; - - t = THREADOBJECT; - - if (sigemptyset(&mask) != 0) - vm_abort_errno("signal_thread: sigemptyset failed"); - -#if !defined(WITH_JAVA_RUNTIME_LIBRARY_OPENJDK) - /* Let OpenJDK handle SIGINT itself. */ - - if (sigaddset(&mask, SIGINT) != 0) - vm_abort_errno("signal_thread: sigaddset failed"); -#endif - -#if !defined(__FREEBSD__) - if (sigaddset(&mask, SIGQUIT) != 0) - vm_abort_errno("signal_thread: sigaddset failed"); -#endif - - for (;;) { - /* just wait for a signal */ - -#if defined(ENABLE_THREADS) - thread_set_state_waiting(t); -#endif - - // sigwait can return EINTR (unlike what the Linux man-page - // says). - do { - result = sigwait(&mask, &sig); - } while (result == EINTR); - - if (result != 0) - vm_abort_errnum(result, "signal_thread: sigwait failed"); - -#if defined(ENABLE_THREADS) - thread_set_state_runnable(t); -#endif - - /* Handle the signal. */ - - signal_thread_handler(sig); - } -} - - -/* signal_thread_handler ******************************************************* - - Handles the signals caught in the signal handler thread. Also used - from sun.misc.Signal with OpenJDK. - -*******************************************************************************/ - -void signal_thread_handler(int sig) -{ - switch (sig) { - case SIGINT: - /* exit the vm properly */ - - vm_exit(1); - break; - - case SIGQUIT: - /* print a thread dump */ -#if defined(ENABLE_THREADS) - ThreadList_dump_threads(); -#endif - -#if defined(ENABLE_STATISTICS) - if (opt_stat) - statistics_print_memory_usage(); -#endif - break; - -#if defined(WITH_JAVA_RUNTIME_LIBRARY_OPENJDK) - default: { - // For OpenJDK we dispatch all unknown signals to Java. - methodinfo* m = class_resolvemethod(class_sun_misc_Signal, utf_dispatch, utf_int__void); - (void) vm_call_method(m, NULL, sig); - - if (exceptions_get_exception()) { - log_println("signal_thread_handler: Java signal handler throw an exception while dispatching signal %d:", sig); - exceptions_print_stacktrace(); - vm_abort("signal_thread_handler: Aborting..."); - } - break; - } -#else - default: - vm_abort("signal_thread_handler: Unknown signal %d", sig); -#endif - } -} - - -/* signal_start_thread ********************************************************* - - Starts the signal handler thread. - -*******************************************************************************/ - -bool signal_start_thread(void) -{ -#if defined(ENABLE_THREADS) - utf *name; - - name = utf_new_char("Signal Handler"); - - if (!threads_thread_start_internal(name, signal_thread)) - return false; - - /* everything's ok */ - - return true; -#else -#warning FIX ME! -#endif -} - - -/* signal_handler_sighup ******************************************************* - - This handler is required by threads_thread_interrupt and does - nothing. - -*******************************************************************************/ - -#if defined(ENABLE_THREADS) -void signal_handler_sighup(int sig, siginfo_t *siginfo, void *_p) -{ - /* do nothing */ -} -#endif - - -/* - * These are local overrides for various environment variables in Emacs. - * Please do not remove this and leave it at the end of the file, where - * Emacs will automagically detect them. - * --------------------------------------------------------------------- - * Local variables: - * mode: c - * indent-tabs-mode: t - * c-basic-offset: 4 - * tab-width: 4 - * End: - */ diff --git a/src/vm/signal.cpp b/src/vm/signal.cpp new file mode 100644 index 000000000..15d6263b6 --- /dev/null +++ b/src/vm/signal.cpp @@ -0,0 +1,401 @@ +/* src/vm/signal.c - machine independent signal functions + + Copyright (C) 1996-2005, 2006, 2007, 2008 + CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO + + This file is part of CACAO. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2, or (at + your option) any later version. + + This program is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + 02110-1301, USA. + +*/ + + +#include "config.h" + +#include +#include +#include +#include + +#if defined(__DARWIN__) +/* If we compile with -ansi on darwin, is not + included. So let's do it here. */ +# include +# include +#endif + +#include "arch.h" + +#if defined(ENABLE_GC_BOEHM) +# include "mm/memory.hpp" +#endif + +#include "threads/thread.hpp" +#include "threads/threadlist.hpp" + +#include "vm/exceptions.hpp" +#include "vm/globals.hpp" +#include "vm/method.hpp" +#include "vm/options.h" +#include "vm/signallocal.hpp" +#include "vm/vm.hpp" + +#if defined(ENABLE_STATISTICS) +# include "vm/statistics.h" +#endif + + +/* function prototypes ********************************************************/ + +void signal_handler_sighup(int sig, siginfo_t *siginfo, void *_p); + + +/* signal_init ***************************************************************** + + Initializes the signal subsystem and installs the signal handler. + +*******************************************************************************/ + +bool signal_init(void) +{ +#if !defined(__CYGWIN__) + sigset_t mask; + + TRACESUBSYSTEMINITIALIZATION("signal_init"); + +#if defined(__LINUX__) && defined(ENABLE_THREADS) + /* XXX Remove for exact-GC. */ + if (threads_pthreads_implementation_nptl) { +#endif + + /* Block the following signals (SIGINT for -c, SIGQUIT for + -\). We enable them later in signal_thread, but only for + this thread. */ + + if (sigemptyset(&mask) != 0) + vm_abort_errno("signal_init: sigemptyset failed"); + +#if !defined(WITH_JAVA_RUNTIME_LIBRARY_OPENJDK) + /* Let OpenJDK handle SIGINT itself. */ + + if (sigaddset(&mask, SIGINT) != 0) + vm_abort_errno("signal_init: sigaddset failed"); +#endif + +#if !defined(__FREEBSD__) + if (sigaddset(&mask, SIGQUIT) != 0) + vm_abort_errno("signal_init: sigaddset failed"); +#endif + + if (sigprocmask(SIG_BLOCK, &mask, NULL) != 0) + vm_abort_errno("signal_init: sigprocmask failed"); + +#if defined(__LINUX__) && defined(ENABLE_THREADS) + /* XXX Remove for exact-GC. */ + } +#endif + +#if defined(ENABLE_GC_BOEHM) + /* Allocate something so the garbage collector's signal handlers + are installed. */ + + (void) GCNEW(int); +#endif + + /* Install signal handlers for signals we want to catch in all + threads. */ + +#if defined(ENABLE_JIT) +# if defined(ENABLE_INTRP) + if (!opt_intrp) { +# endif + /* SIGSEGV handler */ + + signal_register_signal(SIGSEGV, (functionptr) md_signal_handler_sigsegv, + SA_NODEFER | SA_SIGINFO); + +# if defined(SIGBUS) + signal_register_signal(SIGBUS, (functionptr) md_signal_handler_sigsegv, + SA_NODEFER | SA_SIGINFO); +# endif + +# if SUPPORT_HARDWARE_DIVIDE_BY_ZERO + /* SIGFPE handler */ + + signal_register_signal(SIGFPE, (functionptr) md_signal_handler_sigfpe, + SA_NODEFER | SA_SIGINFO); +# endif + +# if defined(__ALPHA__) || defined(__ARM__) || defined(__I386__) || defined(__MIPS__) || defined(__POWERPC__) || defined(__POWERPC64__) || defined(__S390__) || defined(__X86_64__) || defined(__M68K__) + /* XXX use better defines for that (in arch.h) */ + /* SIGILL handler */ + + signal_register_signal(SIGILL, (functionptr) md_signal_handler_sigill, + SA_NODEFER | SA_SIGINFO); +# endif + +# if defined(__POWERPC__) + /* XXX use better defines for that (in arch.h) */ + /* SIGTRAP handler */ + + signal_register_signal(SIGTRAP, (functionptr) md_signal_handler_sigtrap, + SA_NODEFER | SA_SIGINFO); +# endif +# if defined(ENABLE_INTRP) + } +# endif + +#if defined(__DARWIN__) + do { + struct utsname name; + kern_return_t kr; + + /* Check if we're on 10.4 (Tiger/8.x) or earlier */ + if (uname(&name) != 0) + break; + + /* Make sure the string is large enough */ + /* Check the major number (ascii comparison) */ + /* Verify that we're not looking at '10.' by checking for a trailing period. */ + if (name.release[0] == '\0' || name.release[0] > '8' || name.release[1] != '.') + break; + + /* Reset CrashReporter's task signal handler */ + kr = task_set_exception_ports(mach_task_self(), + EXC_MASK_BAD_ACCESS +# if defined(__I386__) + | EXC_MASK_BAD_INSTRUCTION +#endif + , MACH_PORT_NULL, + EXCEPTION_STATE_IDENTITY, + MACHINE_THREAD_STATE); + + assert(kr == KERN_SUCCESS); + } while (false); +#endif +#endif /* !defined(ENABLE_JIT) */ + +#if defined(ENABLE_THREADS) + /* SIGHUP handler for threads_thread_interrupt */ + + signal_register_signal(Signal_INTERRUPT_SYSTEM_CALL, (functionptr) signal_handler_sighup, 0); +#endif + +#if defined(ENABLE_THREADS) && defined(ENABLE_GC_CACAO) + /* SIGUSR1 handler for the exact GC to suspend threads */ + + signal_register_signal(SIGUSR1, (functionptr) md_signal_handler_sigusr1, + SA_SIGINFO); +#endif + +#if defined(ENABLE_THREADS) && defined(ENABLE_PROFILING) + /* SIGUSR2 handler for profiling sampling */ + + signal_register_signal(SIGUSR2, (functionptr) md_signal_handler_sigusr2, + SA_SIGINFO); +#endif + +#endif /* !defined(__CYGWIN__) */ + + return true; +} + + +/* signal_register_signal ****************************************************** + + Register the specified handler with the specified signal. + +*******************************************************************************/ + +void signal_register_signal(int signum, functionptr handler, int flags) +{ + struct sigaction act; + + void (*function)(int, siginfo_t *, void *); + + function = (void (*)(int, siginfo_t *, void *)) handler; + + if (sigemptyset(&act.sa_mask) != 0) + vm_abort_errno("signal_register_signal: sigemptyset failed"); + + act.sa_sigaction = function; + act.sa_flags = flags; + + if (sigaction(signum, &act, NULL) != 0) + vm_abort_errno("signal_register_signal: sigaction failed"); +} + + +/* signal_thread ************************************************************ + + This thread sets the signal mask to catch the user input signals + (SIGINT, SIGQUIT). We use such a thread, so we don't get the + signals on every single thread running. + +*******************************************************************************/ + +static void signal_thread(void) +{ + threadobject *t; + sigset_t mask; + int sig; + int result; + + t = THREADOBJECT; + + if (sigemptyset(&mask) != 0) + vm_abort_errno("signal_thread: sigemptyset failed"); + +#if !defined(WITH_JAVA_RUNTIME_LIBRARY_OPENJDK) + /* Let OpenJDK handle SIGINT itself. */ + + if (sigaddset(&mask, SIGINT) != 0) + vm_abort_errno("signal_thread: sigaddset failed"); +#endif + +#if !defined(__FREEBSD__) + if (sigaddset(&mask, SIGQUIT) != 0) + vm_abort_errno("signal_thread: sigaddset failed"); +#endif + + for (;;) { + /* just wait for a signal */ + +#if defined(ENABLE_THREADS) + thread_set_state_waiting(t); +#endif + + // sigwait can return EINTR (unlike what the Linux man-page + // says). + do { + result = sigwait(&mask, &sig); + } while (result == EINTR); + + if (result != 0) + vm_abort_errnum(result, "signal_thread: sigwait failed"); + +#if defined(ENABLE_THREADS) + thread_set_state_runnable(t); +#endif + + /* Handle the signal. */ + + signal_thread_handler(sig); + } +} + + +/* signal_thread_handler ******************************************************* + + Handles the signals caught in the signal handler thread. Also used + from sun.misc.Signal with OpenJDK. + +*******************************************************************************/ + +void signal_thread_handler(int sig) +{ + switch (sig) { + case SIGINT: + /* exit the vm properly */ + + vm_exit(1); + break; + + case SIGQUIT: + /* print a thread dump */ +#if defined(ENABLE_THREADS) + ThreadList::dump_threads(); +#endif + +#if defined(ENABLE_STATISTICS) + if (opt_stat) + statistics_print_memory_usage(); +#endif + break; + +#if defined(WITH_JAVA_RUNTIME_LIBRARY_OPENJDK) + default: { + // For OpenJDK we dispatch all unknown signals to Java. + methodinfo* m = class_resolvemethod(class_sun_misc_Signal, utf_dispatch, utf_int__void); + (void) vm_call_method(m, NULL, sig); + + if (exceptions_get_exception()) { + log_println("signal_thread_handler: Java signal handler throw an exception while dispatching signal %d:", sig); + exceptions_print_stacktrace(); + vm_abort("signal_thread_handler: Aborting..."); + } + break; + } +#else + default: + vm_abort("signal_thread_handler: Unknown signal %d", sig); +#endif + } +} + + +/* signal_start_thread ********************************************************* + + Starts the signal handler thread. + +*******************************************************************************/ + +bool signal_start_thread(void) +{ +#if defined(ENABLE_THREADS) + utf *name; + + name = utf_new_char("Signal Handler"); + + if (!threads_thread_start_internal(name, signal_thread)) + return false; + + /* everything's ok */ + + return true; +#else +#warning FIX ME! +#endif +} + + +/* signal_handler_sighup ******************************************************* + + This handler is required by threads_thread_interrupt and does + nothing. + +*******************************************************************************/ + +#if defined(ENABLE_THREADS) +void signal_handler_sighup(int sig, siginfo_t *siginfo, void *_p) +{ + /* do nothing */ +} +#endif + + +/* + * These are local overrides for various environment variables in Emacs. + * Please do not remove this and leave it at the end of the file, where + * Emacs will automagically detect them. + * --------------------------------------------------------------------- + * Local variables: + * mode: c++ + * indent-tabs-mode: t + * c-basic-offset: 4 + * tab-width: 4 + * End: + */ diff --git a/src/vm/signallocal.h b/src/vm/signallocal.h deleted file mode 100644 index 469d949a4..000000000 --- a/src/vm/signallocal.h +++ /dev/null @@ -1,99 +0,0 @@ -/* src/vm/signallocal.h - machine independent signal functions - - Copyright (C) 1996-2005, 2006, 2007, 2008 - CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO - - This file is part of CACAO. - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License as - published by the Free Software Foundation; either version 2, or (at - your option) any later version. - - This program is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - 02110-1301, USA. - -*/ - - -#ifndef _CACAO_SIGNAL_H -#define _CACAO_SIGNAL_H - -#include "config.h" - -#ifdef __cplusplus -extern "C" { -#endif - -#include - -#include "vm/global.h" - - -// Signal defines. - -#if defined(__LINUX__) -// See openjdk/jdk/src/solaris/native/java/net/linux_close.c (sigWakeup) -// See openjdk/jdk/src/solaris/native/sun/nio/ch/NativeThread.c (INTERRUPT_SIGNAL) -# define Signal_INTERRUPT_SYSTEM_CALL (__SIGRTMAX - 2) -#else -# define Signal_INTERRUPT_SYSTEM_CALL SIGHUP -#endif - - -/* function prototypes ********************************************************/ - -bool signal_init(void); -void signal_register_signal(int signum, functionptr handler, int flags); - -void signal_thread_handler(int sig); -bool signal_start_thread(void); - -/* machine dependent signal handler */ - -void md_signal_handler_sigsegv(int sig, siginfo_t *siginfo, void *_p); - -#if SUPPORT_HARDWARE_DIVIDE_BY_ZERO -void md_signal_handler_sigfpe(int sig, siginfo_t *siginfo, void *_p); -#endif - -#if defined(__ALPHA__) || defined(__ARM__) || defined(__I386__) || defined(__MIPS__) || defined(__POWERPC__) || defined(__POWERPC64__) || defined(__S390__) || defined(__X86_64__) || defined(__M68K__) -/* XXX use better defines for that (in arch.h) */ -void md_signal_handler_sigill(int sig, siginfo_t *siginfo, void *_p); -#endif - -#if defined(__POWERPC__) -/* XXX use better defines for that (in arch.h) */ -void md_signal_handler_sigtrap(int sig, siginfo_t *siginfo, void *_p); -#endif - -void md_signal_handler_sigusr1(int sig, siginfo_t *siginfo, void *_p); - -void md_signal_handler_sigusr2(int sig, siginfo_t *siginfo, void *_p); - -#ifdef __cplusplus -} -#endif - -#endif /* _CACAO_SIGNAL_H */ - - -/* - * These are local overrides for various environment variables in Emacs. - * Please do not remove this and leave it at the end of the file, where - * Emacs will automagically detect them. - * --------------------------------------------------------------------- - * Local variables: - * mode: c - * indent-tabs-mode: t - * c-basic-offset: 4 - * tab-width: 4 - * End: - */ diff --git a/src/vm/signallocal.hpp b/src/vm/signallocal.hpp new file mode 100644 index 000000000..94d1727cc --- /dev/null +++ b/src/vm/signallocal.hpp @@ -0,0 +1,99 @@ +/* src/vm/signallocal.h - machine independent signal functions + + Copyright (C) 1996-2005, 2006, 2007, 2008 + CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO + + This file is part of CACAO. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2, or (at + your option) any later version. + + This program is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + 02110-1301, USA. + +*/ + + +#ifndef _CACAO_SIGNAL_H +#define _CACAO_SIGNAL_H + +#include "config.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +#include "vm/global.h" + + +// Signal defines. + +#if defined(__LINUX__) +// See openjdk/jdk/src/solaris/native/java/net/linux_close.c (sigWakeup) +// See openjdk/jdk/src/solaris/native/sun/nio/ch/NativeThread.c (INTERRUPT_SIGNAL) +# define Signal_INTERRUPT_SYSTEM_CALL (__SIGRTMAX - 2) +#else +# define Signal_INTERRUPT_SYSTEM_CALL SIGHUP +#endif + + +/* function prototypes ********************************************************/ + +bool signal_init(void); +void signal_register_signal(int signum, functionptr handler, int flags); + +void signal_thread_handler(int sig); +bool signal_start_thread(void); + +/* machine dependent signal handler */ + +void md_signal_handler_sigsegv(int sig, siginfo_t *siginfo, void *_p); + +#if SUPPORT_HARDWARE_DIVIDE_BY_ZERO +void md_signal_handler_sigfpe(int sig, siginfo_t *siginfo, void *_p); +#endif + +#if defined(__ALPHA__) || defined(__ARM__) || defined(__I386__) || defined(__MIPS__) || defined(__POWERPC__) || defined(__POWERPC64__) || defined(__S390__) || defined(__X86_64__) || defined(__M68K__) +/* XXX use better defines for that (in arch.h) */ +void md_signal_handler_sigill(int sig, siginfo_t *siginfo, void *_p); +#endif + +#if defined(__POWERPC__) +/* XXX use better defines for that (in arch.h) */ +void md_signal_handler_sigtrap(int sig, siginfo_t *siginfo, void *_p); +#endif + +void md_signal_handler_sigusr1(int sig, siginfo_t *siginfo, void *_p); + +void md_signal_handler_sigusr2(int sig, siginfo_t *siginfo, void *_p); + +#ifdef __cplusplus +} +#endif + +#endif /* _CACAO_SIGNAL_H */ + + +/* + * These are local overrides for various environment variables in Emacs. + * Please do not remove this and leave it at the end of the file, where + * Emacs will automagically detect them. + * --------------------------------------------------------------------- + * Local variables: + * mode: c++ + * indent-tabs-mode: t + * c-basic-offset: 4 + * tab-width: 4 + * End: + */ diff --git a/src/vm/vm.cpp b/src/vm/vm.cpp index 5719f86ff..448e4a7e9 100644 --- a/src/vm/vm.cpp +++ b/src/vm/vm.cpp @@ -74,7 +74,7 @@ #include "vm/os.hpp" #include "vm/primitive.hpp" #include "vm/properties.hpp" -#include "vm/signallocal.h" +#include "vm/signallocal.hpp" #include "vm/statistics.h" #include "vm/string.hpp" #include "vm/suck.hpp"