[kaffe] CVS kaffe (robilad): Small cleanup in signal.c

Kaffe CVS cvs-commits at kaffe.org
Sun Apr 24 06:33:56 PDT 2005


PatchSet 6418 
Date: 2005/04/24 13:27:20
Author: robilad
Branch: HEAD
Tag: (none) 
Log:
Small cleanup in signal.c

2005-04-24  Dalibor Topic  <robilad at kaffe.org>

* kaffe/kaffevm/systems/unix-pthreads/signal.c
(nullException, floatingException): Removed prototypes
that were confusing the compiler on NetBSD CVS HEAD.
(jthread_initexceptions): Moved further to the back
to make sure it picks up the declarations of
nullException and floatingException.

Members: 
	ChangeLog:1.3946->1.3947 
	kaffe/kaffevm/systems/unix-pthreads/signal.c:INITIAL->1.20 

Index: kaffe/ChangeLog
diff -u kaffe/ChangeLog:1.3946 kaffe/ChangeLog:1.3947
--- kaffe/ChangeLog:1.3946	Sun Apr 24 12:36:55 2005
+++ kaffe/ChangeLog	Sun Apr 24 13:27:20 2005
@@ -1,5 +1,14 @@
 2005-04-24  Dalibor Topic  <robilad at kaffe.org>
 
+	* kaffe/kaffevm/systems/unix-pthreads/signal.c 
+	(nullException, floatingException): Removed prototypes 
+	that were confusing the compiler on NetBSD CVS HEAD.
+	(jthread_initexceptions): Moved further to the back 
+	to make sure it picks up the declarations of 
+	nullException and floatingException.
+	
+2005-04-24  Dalibor Topic  <robilad at kaffe.org>
+
 	Resynced with GNU Classpath:
 
 	2005-04-23  Tom Tromey  <tromey at redhat.com>
===================================================================
Checking out kaffe/kaffe/kaffevm/systems/unix-pthreads/signal.c
RCS:  /home/cvs/kaffe/kaffe/kaffe/kaffevm/systems/unix-pthreads/signal.c,v
VERS: 1.20
***************
--- /dev/null	Sun Aug  4 19:57:58 2002
+++ kaffe/kaffe/kaffevm/systems/unix-pthreads/signal.c	Sun Apr 24 13:33:56 2005
@@ -0,0 +1,519 @@
+/*
+ * signal.c
+ * Implement signal-based exception handling
+ *
+ * Copyright (c) 1996, 1997, 1998, 1999
+ *	Transvirtual Technologies, Inc.  All rights reserved.
+ *
+ * See the file "license.terms" for information on usage and redistribution 
+ * of this file. 
+ */
+
+#include "config.h"
+#include "debug.h"
+#include "config-std.h"
+#include "config-signal.h"
+#include "config-mem.h"
+#include "config-setjmp.h"
+#include "gtypes.h"
+#include "jsignal.h"
+#include "md.h"
+#include "stackTrace-impl.h"
+#include "thread-internal.h"
+#include "files.h"
+#include "kaffe/jmalloc.h"
+#include <errno.h>
+#ifdef KAFFE_BOEHM_GC
+#include "boehm-gc/boehm/include/gc.h"
+#endif
+
+#if defined(INTERPRETER)
+#define	DEFINEFRAME()		/* Does nothing */
+#define	EXCEPTIONPROTO		int sig
+#define	EXCEPTIONFRAME(f, c)	/* Does nothing */
+#define	EXCEPTIONFRAMEPTR	0
+#elif defined(TRANSLATOR)
+#define	DEFINEFRAME()		exceptionFrame frame
+#define	EXCEPTIONFRAMEPTR	&frame
+#endif /* TRANSLATOR */
+
+#ifndef STACK_STRUCT
+#define STACK_STRUCT stack_t
+#endif
+
+#if defined(__WIN32__)
+#define SIG_T   void(*)()
+#else
+#define SIG_T   void*
+#endif
+
+static void ignoreSignal(int sig);
+
+static exchandler_t nullHandler;
+static exchandler_t floatingHandler;
+static exchandler_t stackOverflowHandler;
+
+/*
+ * Null exception - catches bad memory accesses.
+ */
+static void
+nullException(SIGNAL_ARGS(sig, ctx))
+{
+        void *stackptr;
+	jthread_t current_thread;
+
+	DEFINEFRAME();
+
+	/* Restore the signal handler if necessary */
+	restoreSyncSignalHandler(sig, nullException);
+
+	/* Clean up the synchronous signal state (just unblock this signal) */
+	unblockSignal(sig);
+
+	EXCEPTIONFRAME(frame, ctx);
+#if defined(STACK_POINTER)
+	current_thread = jthread_current();
+	stackptr = (void *)STACK_POINTER(GET_SIGNAL_CONTEXT_POINTER(ctx));
+	/* Here we have a stupid heuristic which may not work rightfully
+	 * if kaffe allocates a big buffer using alloca (in that case we
+	 * will get an NPE). But it is better than the previous case which was
+	 * heating nearly all NPEs on Darwin.
+	 */
+#if defined(STACK_GROWS_UP)
+	if (current_thread != NULL && stackptr >= current_thread->stackMax &&
+	    stackptr <= (void *)((uintp)current_thread->stackMax+1024))
+#else
+	if (current_thread != NULL && stackptr <= current_thread->stackMin &&
+	    stackptr >= (void *)((uintp)current_thread->stackMax-1024))
+#endif
+	  stackOverflowHandler(EXCEPTIONFRAMEPTR);
+	else
+#endif // STACK_POINTER
+	  nullHandler(EXCEPTIONFRAMEPTR);
+}
+
+/*
+ * Division by zero.
+ */
+static void
+floatingException(EXCEPTIONPROTO)
+{
+	DEFINEFRAME();
+
+	/* Restore the signal handler if necessary */
+	restoreSyncSignalHandler(sig, floatingException);
+
+	/* Clean up the synchronous signal state (just unblock this signal) */
+	unblockSignal(sig);
+
+	EXCEPTIONFRAME(frame, ctx);
+	floatingHandler(EXCEPTIONFRAMEPTR);
+}
+
+/*
+ * Setup the internal exceptions.
+ */
+void
+jthread_initexceptions(exchandler_t _nullHandler,
+		       exchandler_t _floatingHandler,
+		       exchandler_t _stackOverflowHandler)
+{
+	nullHandler = _nullHandler;
+	floatingHandler = _floatingHandler;
+	stackOverflowHandler = _stackOverflowHandler;
+
+	if (DBGEXPR(EXCEPTION, false, true)) {
+		/* Catch signals we need to convert to exceptions */
+#if defined(SIGSEGV)
+		registerSyncSignalHandler(SIGSEGV, nullException);
+#endif
+#if defined(SIGBUS)
+		registerSyncSignalHandler(SIGBUS, nullException);
+#endif
+#if defined(SIGFPE)
+		registerSyncSignalHandler(SIGFPE, floatingException);
+#endif
+#if defined(SIGPIPE)
+		ignoreSignal(SIGPIPE);
+#endif
+	}
+}
+
+
+/* -----------------------------------------------
+ * OS signal handling code.  See FAQ/FAQ.jsignal for information.
+ * ----------------------------------------------- */
+
+static void *
+registerSignalHandler(int sig, void* handler, int isAsync)
+{
+#if defined(HAVE_SIGACTION)
+	struct sigaction newact, oldact;
+
+	newact.sa_handler = (SIG_T)handler;
+	sigemptyset(&newact.sa_mask);
+
+	/*
+	 * Define sa_mask to include the signals to block when
+	 * running handler.
+	 */
+	if (isAsync) {
+		sigaddset(&newact.sa_mask, SIGIO);
+		sigaddset(&newact.sa_mask, SIGALRM);
+		sigaddset(&newact.sa_mask, SIGCHLD);
+#if defined(SIGVTALRM)
+		sigaddset(&newact.sa_mask, SIGVTALRM);
+#endif
+	}
+
+	newact.sa_flags = 0;
+#if defined(SA_SIGINFO)
+	newact.sa_flags |= SA_SIGINFO;
+#endif
+#if defined(SA_RESTART)
+	newact.sa_flags |= SA_RESTART;
+#endif
+	sigaction(sig, &newact, &oldact);
+
+	return oldact.sa_handler;
+	
+#elif defined(HAVE_SIGNAL)
+#warning The default signal() semantics may not be sufficient for Kaffe.
+	return signal(sig, (SIG_T)handler);
+
+#else
+#error No signal handler support.  Jthreads requires signal support.	
+#endif /* HAVE_SIGACTION */
+}
+
+
+/*
+ * Register a handler for an asynchronous signal.
+ */
+void *
+registerAsyncSignalHandler(int sig, void* handler)
+{
+	int validSig = 
+		(sig == SIGALRM)
+#if defined(SIGVTALRM)
+		|| (sig == SIGVTALRM) 
+#endif
+		|| (sig == SIGIO)
+		|| (sig == SIGUSR1)
+		|| (sig == SIGCHLD);
+
+	/* Make sure its really an asynchronous signal being registered. */
+	assert(handler != NULL);
+	assert(validSig);  /* Can't have the #ifdef in a macro arg. */
+
+	/*
+	 * Register an asynchronous signal handler that will block all
+	 * other asynchronous signals while the handler is running.
+	 */
+	return registerSignalHandler(sig, handler, true);
+}
+
+/*
+ * Register a signal handler for a synchronous signal.
+ */
+void *
+registerSyncSignalHandler(int sig, void* handler)
+{
+	int validSig = 0
+#if defined(SIGFPE)	       
+		|| (sig == SIGFPE)
+#endif
+#if defined(SIGSEGV)
+		|| (sig == SIGSEGV)
+#endif
+#if defined(SIGBUS)
+		|| (sig == SIGBUS)
+#endif
+		;
+	
+	assert(handler != NULL);
+	assert(validSig);
+	
+	/* Register a synchronous signal handler */
+	return registerSignalHandler(sig, handler, false);
+}
+
+/*
+ * Restore an asynchronous signal handler.  
+ * Only necesary on some platforms which don't provide SIGACTION
+ */
+#if defined(HAVE_SIGACTION)
+void
+restoreAsyncSignalHandler(int sig UNUSED, void* handler UNUSED)
+{
+}
+#else
+void
+restoreAsyncSignalHandler(int sig, void* handler)
+{
+	/* XXX need a configure-time test for this. */
+	registerAsyncSignalHandler(sig, handler);
+}
+#endif
+
+/*
+ * Restore a synchronous signal handler.  
+ * Only necesary on some platforms.
+ */
+#if defined(HAVE_SIGACTION)
+void
+restoreSyncSignalHandler(int sig UNUSED, void* handler UNUSED)
+{
+}
+#else
+void
+restoreSyncSignalHandler(int sig, void* handler)
+{
+	/* XXX need a configure-time test for this. */
+	registerSyncSignalHandler(sig, handler);
+}
+#endif
+
+/*
+ * Register a handler for a terminal (i.e., process-killing) signal.
+ * These handlers must exit().
+ */
+void
+registerTerminalSignal(int sig, void* handler)
+{
+	assert((sig == SIGINT) || (sig == SIGTERM));
+	registerSignalHandler(sig, handler, true);
+}
+
+/*
+ * Clear the given signal (i.e., restore the default behavior of the signal)
+ */
+void
+clearSignal(int sig)
+{
+	registerSignalHandler(sig, SIG_DFL, false);
+}
+
+/*
+ * Ignore the given signal.
+ */
+static void
+ignoreSignal(int sig)
+{
+	registerSignalHandler(sig, SIG_IGN, false);
+}
+
+/*
+ * Unblock the given signal.
+ */
+void
+unblockSignal(int sig)
+{
+	sigset_t nsig;
+
+	sigemptyset(&nsig);
+	sigaddset(&nsig, sig);
+	sigprocmask(SIG_UNBLOCK, &nsig, NULL);
+}
+
+/*
+ * Unblock all of the async signals.  (These are the
+ * signals specified in the sa_mask in registerAsynchSignalHandler().)
+ */
+void 
+unblockAsyncSignals(void)
+{
+	sigset_t nsig;
+
+	sigemptyset(&nsig);
+	sigaddset(&nsig, SIGIO);
+	sigaddset(&nsig, SIGALRM);
+	sigaddset(&nsig, SIGCHLD);
+#if defined(SIGVTALRM)
+	sigaddset(&nsig, SIGVTALRM);
+#endif
+	sigprocmask(SIG_UNBLOCK, &nsig, NULL);
+	
+}
+
+/*
+ * Block all of the async signals.  (These are the
+ * signals specified in the sa_mask in registerAsynchSignalHandler().)
+ */
+void 
+blockAsyncSignals(void)
+{
+	sigset_t nsig;
+
+	sigemptyset(&nsig);
+	sigaddset(&nsig, SIGIO);
+	sigaddset(&nsig, SIGALRM);
+	sigaddset(&nsig, SIGCHLD);
+#if defined(SIGVTALRM)
+	sigaddset(&nsig, SIGVTALRM);
+#endif
+	sigprocmask(SIG_BLOCK, &nsig, NULL);
+	
+}
+
+/* ----------------------------------------------------------------------
+ * STACK BOUNDARY DETECTORS
+ * ----------------------------------------------------------------------
+ */
+#if defined(KAFFE_BOEHM_GC)
+
+/*
+ * The Boehm-Weiser GC has already the stack bottom. Use the
+ * value it has detected.
+ */
+void
+detectStackBoundaries(jthread_t jtid, int mainThreadStackSize)
+{
+        void *stackPointer;
+
+	stackPointer = GC_stackbottom;
+
+	jtid->stackMax = stackPointer;
+	jtid->stackMin = (char *)jtid->stackMax - mainThreadStackSize;
+        jtid->stackCur = jtid->stackMax;
+}
+
+#elif defined(KAFFEMD_STACKBASE)
+
+/*
+ * The OS gives us the stack base. Get it and adjust the pointers.
+ */
+
+void
+detectStackBoundaries(jthread_t jtid, int mainThreadStackSize)
+{
+        void *stackPointer;
+
+	stackPointer = mdGetStackBase();
+
+	jtid->stackMin = stackPointer;
+	jtid->stackMax = (char *)jtid->stackMin + mainThreadStackSize;
+        jtid->stackCur = jtid->stackMax;
+}
+
+#elif defined(KAFFEMD_STACKEND) // KAFFEMD_STACKBASE
+
+/*
+ * Here the OS gives us the position of the end of stack. Get it
+ * and adjust our internal pointers.
+ */
+
+void
+detectStackBoundaries(jthread_t jtid, int mainThreadStackSize)
+{
+        void *stackPointer;
+
+	stackPointer = mdGetStackEnd();
+
+	jtid->stackMax = stackPointer;
+	jtid->stackMin = (char *)jtid->stackMax - mainThreadStackSize;
+        jtid->stackCur = jtid->stackMax;
+}
+
+#elif defined(SA_ONSTACK) && defined(HAVE_SIGALTSTACK) && !defined(KAFFEMD_BUGGY_STACK_OVERFLOW)
+
+static JTHREAD_JMPBUF outOfLoop;
+
+/*
+ * This function is called by the system when we go beyond stack boundaries
+ * in infiniteLoop. We get the stack address using the stack pointer register
+ * and then go back in detectStackBoundaries() using the old stack.
+ */
+static void NONRETURNING
+stackOverflowDetector(SIGNAL_ARGS(sig UNUSED, sc))
+{
+  unblockSignal(SIGSEGV);
+  JTHREAD_LONGJMP(outOfLoop, 1);
+}
+
+void kaffeNoopFunc(char c UNUSED)
+{
+}
+
+/*
+ * This is the first type of heuristic we can use to guess the boundaries.
+ * Here we are provoking a SIGSEGV by overflowing the stack. Then we get
+ * the faulty adress directly.
+ */
+void
+detectStackBoundaries(jthread_t jtid, int mainThreadStackSize)
+{
+	static volatile char *guessPointer;
+	void *handler_segv, *handler_bus;
+
+#if defined(SIGSEGV)
+	handler_segv = registerSyncSignalHandler(SIGSEGV, stackOverflowDetector);
+#endif
+#if defined(SIGBUS)
+	handler_bus = registerSyncSignalHandler(SIGBUS, stackOverflowDetector);
+#endif
+	
+	if (JTHREAD_SETJMP(outOfLoop) == 0)
+	{
+	  uintp pageSize = getpagesize();
+
+	  guessPointer = (char *)((uintp)(&jtid) & ~(pageSize-1));
+	  
+	  while (1)
+	  {
+#if defined(STACK_GROWS_UP)
+	    guessPointer -= pageSize;
+#else
+	    guessPointer += pageSize;
+#endif
+	    kaffeNoopFunc(*guessPointer);
+	  }
+	}
+
+	/* Here we have detected one the boundary of the stack.
+	 * If stack grows up then it is the upper boundary. In the other
+	 * case we have the lower boundary. As we know the stack size we
+	 * may guess the other boundary.
+	 */
+#if defined(STACK_GROWS_UP)
+	jtid->stackMin = guessPointer;
+	jtid->stackMax = (char *)jtid->stackMin + mainThreadStackSize;
+	jtid->stackCur = jtid->stackMax;
+#else
+	jtid->stackMax = guessPointer;
+	jtid->stackMin = (char *)jtid->stackMax - mainThreadStackSize;
+	jtid->stackCur = jtid->stackMin;
+#endif
+
+	/* We restore the old signal handlers (SIG_DFL and SIG_IGN are included.
+	 */ 
+#if defined(SIGSEGV)
+	registerSignalHandler(SIGSEGV, handler_segv, false);
+#endif
+#if defined(SIGBUS)
+	registerSignalHandler(SIGBUS, handler_bus, false);
+#endif
+}
+
+#else
+
+/*
+ * This is the worse heuristic in terms of precision. But
+ * this may be the only one working on this platform.
+ */
+
+void
+detectStackBoundaries(jthread_t jtid, int mainThreadStackSize)
+{
+#if defined(STACK_GROWS_UP)
+	jtid->stackMin = (void*)(uintp)(&jtid - 0x100);
+	jtid->stackMax = (char *)jtid->stackMin + mainThreadStackSize;
+        jtid->stackCur = jtid->stackMax;
+#else
+	jtid->stackMax = (void*)(uintp)(&jtid + 0x100);
+        jtid->stackMin = (char *) jtid->stackMax - mainThreadStackSize;
+        jtid->stackCur = jtid->stackMin;
+#endif
+}
+
+#endif




More information about the kaffe mailing list