* src/vm/jit/arm/md-abi.c (md_param_alloc): Align stack arguments as well.
[cacao.git] / src / vm / signal.c
index c8e5a31dbbdf7368601310fc8adff4db5a4361ea..f1f1b462b970606fc4ecfecbfb54ea29c6f4a9db 100644 (file)
@@ -1,6 +1,6 @@
 /* src/vm/signal.c - machine independent signal functions
 
-   Copyright (C) 1996-2005, 2006 R. Grafl, A. Krall, C. Kruegel,
+   Copyright (C) 1996-2005, 2006, 2007 R. Grafl, A. Krall, C. Kruegel,
    C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
    E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
    J. Wenninger, Institut f. Computersprachen - TU Wien
    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
    02110-1301, USA.
 
-   Contact: cacao@cacaojvm.org
-
-   Authors: Christian Thalinger
-
-   $Id: signal.c 6256 2006-12-28 12:30:09Z twisti $
+   $Id: signal.c 7831 2007-04-26 12:48:16Z twisti $
 
 */
 
 
 #include "config.h"
 
+#include <assert.h>
 #include <errno.h>
 #include <signal.h>
 #include <stdlib.h>
 
 #include "vm/types.h"
 
+#include "arch.h"
+
+#include "mm/memory.h"
+
 #if defined(ENABLE_THREADS)
-# include "threads/native/threads.h"
+# include "threads/threads-common.h"
 #endif
 
-#include "mm/memory.h"
+#include "vm/exceptions.h"
 #include "vm/signallocal.h"
-#include "vm/options.h"
 #include "vm/vm.h"
-#include "vm/jit/stacktrace.h"
+
+#include "vmcore/options.h"
+
+#if defined(ENABLE_STATISTICS)
+# include "vmcore/statistics.h"
+#endif
 
 
 /* function prototypes ********************************************************/
 
 void signal_handler_sighup(int sig, siginfo_t *siginfo, void *_p);
-void signal_handler_sigint(int sig, siginfo_t *siginfo, void *_p);
-void signal_handler_sigquit(int sig, siginfo_t *siginfo, void *_p);
 
 
 /* signal_init *****************************************************************
@@ -75,6 +78,7 @@ void signal_init(void)
 {
 #if !defined(__CYGWIN__)
        int              pagesize;
+       sigset_t         mask;
        struct sigaction act;
 
        /* mmap a memory page at address 0x0, so our hardware-exceptions
@@ -84,6 +88,28 @@ void signal_init(void)
 
        (void) memory_mmap_anon(NULL, pagesize, PROT_NONE, MAP_PRIVATE | MAP_FIXED);
 
+       /* check if we get into trouble with our hardware-exceptions */
+
+       assert(OFFSET(java_bytearray, data) > EXCEPTION_HARDWARE_PATCHER);
+
+       /* Block the following signals (SIGINT for <ctrl>-c, SIGQUIT for
+          <ctrl>-\).  We enable them later in signal_thread, but only for
+          this thread. */
+
+       if (sigemptyset(&mask) != 0)
+               vm_abort("signal_init: sigemptyset failed: %s", strerror(errno));
+
+       if (sigaddset(&mask, SIGINT) != 0)
+               vm_abort("signal_init: sigaddset failed: %s", strerror(errno));
+
+#if !defined(__FREEBSD__)
+       if (sigaddset(&mask, SIGQUIT) != 0)
+               vm_abort("signal_init: sigaddset failed: %s", strerror(errno));
+#endif
+
+       if (sigprocmask(SIG_BLOCK, &mask, NULL) != 0)
+               vm_abort("signal_init: sigprocmask failed: %s", strerror(errno));
+
 #if defined(ENABLE_GC_BOEHM)
        /* Allocate something so the garbage collector's signal handlers
           are installed. */
@@ -91,7 +117,8 @@ void signal_init(void)
        (void) GCNEW(u1);
 #endif
 
-       /* install signal handlers we need to convert to exceptions */
+       /* Install signal handlers for signals we want to catch in all
+          threads. */
 
        sigemptyset(&act.sa_mask);
 
@@ -99,57 +126,59 @@ void signal_init(void)
 # if defined(ENABLE_INTRP)
        if (!opt_intrp) {
 # endif
-               /* catch NullPointerException/StackOverFlowException */
+               /* SIGSEGV handler */
 
                act.sa_sigaction = md_signal_handler_sigsegv;
                act.sa_flags     = SA_NODEFER | SA_SIGINFO;
 
-#if defined(SIGSEGV)
+#  if defined(SIGSEGV)
                sigaction(SIGSEGV, &act, NULL);
-#endif
+#  endif
 
-#if defined(SIGBUS)
+#  if defined(SIGBUS)
                sigaction(SIGBUS, &act, NULL);
-#endif
+#  endif
 
-               /* catch ArithmeticException */
+#  if SUPPORT_HARDWARE_DIVIDE_BY_ZERO
+               /* SIGFPE handler */
 
-#if SUPPORT_HARDWARE_DIVIDE_BY_ZERO
                act.sa_sigaction = md_signal_handler_sigfpe;
                act.sa_flags     = SA_NODEFER | SA_SIGINFO;
                sigaction(SIGFPE, &act, NULL);
-#endif
+#  endif
+
+#  if defined(__ARM__)
+               /* XXX use better defines for that (in arch.h) */
+               /* SIGILL handler */
+
+               act.sa_sigaction = md_signal_handler_sigill;
+               act.sa_flags     = SA_NODEFER | SA_SIGINFO;
+               sigaction(SIGILL, &act, NULL);
+#  endif
+
+#  if defined(__POWERPC__)
+               /* XXX use better defines for that (in arch.h) */
+               /* SIGTRAP handler */
+
+               act.sa_sigaction = md_signal_handler_sigtrap;
+               act.sa_flags     = SA_NODEFER | SA_SIGINFO;
+               sigaction(SIGTRAP, &act, NULL);
+#  endif
 # if defined(ENABLE_INTRP)
        }
 # endif
 #endif /* !defined(ENABLE_INTRP) */
 
 #if defined(ENABLE_THREADS)
-       /* catch SIGHUP for threads_thread_interrupt */
+       /* SIGHUP handler for threads_thread_interrupt */
 
        act.sa_sigaction = signal_handler_sighup;
        act.sa_flags     = 0;
        sigaction(SIGHUP, &act, NULL);
 #endif
 
-       /* catch SIGINT for exiting properly on <ctrl>-c */
-
-       act.sa_sigaction = signal_handler_sigint;
-       act.sa_flags     = SA_NODEFER | SA_SIGINFO;
-       sigaction(SIGINT, &act, NULL);
-
-#if defined(ENABLE_THREADS)
-       /* catch SIGQUIT for thread dump */
-
-# if !defined(__FREEBSD__)
-       act.sa_sigaction = signal_handler_sigquit;
-       act.sa_flags     = SA_SIGINFO;
-       sigaction(SIGQUIT, &act, NULL);
-# endif
-#endif
-
 #if defined(ENABLE_THREADS) && defined(ENABLE_PROFILING)
-       /* install signal handler for profiling sampling */
+       /* SIGUSR2 handler for profiling sampling */
 
        act.sa_sigaction = md_signal_handler_sigusr2;
        act.sa_flags     = SA_SIGINFO;
@@ -160,58 +189,108 @@ void signal_init(void)
 }
 
 
-/* signal_handler_sighup *******************************************************
+/* signal_thread ************************************************************
 
-   This handler is required by threads_thread_interrupt and does
-   nothing.
+   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.  Especially, this makes
+   problems on slow machines.
 
 *******************************************************************************/
 
-#if defined(ENABLE_THREADS)
-void signal_handler_sighup(int sig, siginfo_t *siginfo, void *_p)
+static void signal_thread(void)
 {
-       /* do nothing */
-}
+       sigset_t mask;
+       int      sig;
+
+       if (sigemptyset(&mask) != 0)
+               vm_abort("signal_thread: sigemptyset failed: %s", strerror(errno));
+
+       if (sigaddset(&mask, SIGINT) != 0)
+               vm_abort("signal_thread: sigaddset failed: %s", strerror(errno));
+
+#if !defined(__FREEBSD__)
+       if (sigaddset(&mask, SIGQUIT) != 0)
+               vm_abort("signal_thread: sigaddset failed: %s", strerror(errno));
 #endif
 
+       while (true) {
+               /* just wait for a signal */
 
-/* signal_handler_sigquit ******************************************************
+               /* XXX We don't check for an error here, although the man-page
+                  states sigwait does not return an error (which is wrong!),
+                  but it seems to make problems with Boehm-GC.  We should
+                  revisit this code with our new exact-GC. */
 
-   Handle for SIGQUIT (<ctrl>-\) which print a stacktrace for every
-   running thread.
+/*             if (sigwait(&mask, &sig) != 0) */
+/*                     vm_abort("signal_thread: sigwait failed: %s", strerror(errno)); */
+               (void) sigwait(&mask, &sig);
 
-*******************************************************************************/
+               switch (sig) {
+               case SIGINT:
+                       /* exit the vm properly */
 
+                       vm_exit(0);
+                       break;
+
+               case SIGQUIT:
+                       /* print a thread dump */
 #if defined(ENABLE_THREADS)
-void signal_handler_sigquit(int sig, siginfo_t *siginfo, void *_p)
-{
-       /* do thread dump */
+                       threads_dump();
+#endif
 
-       threads_dump();
-}
+#if defined(ENABLE_STATISTICS)
+                       if (opt_stat)
+                               statistics_print_memory_usage();
 #endif
+                       break;
+               }
+       }
 
+       /* this should not happen */
+
+       vm_abort("signal_thread: this thread should not exit!");
+}
 
-/* signal_handler_sigint *******************************************************
 
-   Handler for SIGINT (<ctrl>-c) which shuts down CACAO properly with
-   Runtime.exit(I)V.
+/* signal_start_thread *********************************************************
+
+   Starts the signal handler thread.
 
 *******************************************************************************/
 
-void signal_handler_sigint(int sig, siginfo_t *siginfo, void *_p)
+bool signal_start_thread(void)
 {
-       /* if we are already in Runtime.exit(), just do it hardcore */
+#if defined(ENABLE_THREADS)
+       utf *name;
 
-       if (vm_exiting) {
-               fprintf(stderr, "Caught SIGINT while already shutting down. Shutdown aborted...\n");
-               exit(0);
-       }
+       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 *******************************************************
 
-       /* exit the vm properly */
+   This handler is required by threads_thread_interrupt and does
+   nothing.
 
-       vm_exit(0);
+*******************************************************************************/
+
+#if defined(ENABLE_THREADS)
+void signal_handler_sighup(int sig, siginfo_t *siginfo, void *_p)
+{
+       /* do nothing */
 }
+#endif
 
 
 /*