[kaffe] CVS kaffe (guilhem): Stack detection for unix-pthreads

Kaffe CVS cvs-commits at kaffe.org
Sun Jul 4 07:29:46 PDT 2004


PatchSet 4887 
Date: 2004/07/04 14:19:54
Author: guilhem
Branch: HEAD
Tag: (none) 
Log:
Stack detection for unix-pthreads

	* kaffe/kaffevm/systems/unix-pthreads/jsignal.h,
	kaffe/kaffevm/systems/unix-pthreads/signal.c,
	kaffe/kaffevm/systems/unix-pthreads/syscalls.c,
	kaffe/kaffevm/systems/unix-pthreads/thread-impl.c:
	Imported stack pointer detection in the unix-pthreads
	implementation of kaffe threads.

Members: 
	ChangeLog:1.2453->1.2454 
	kaffe/kaffevm/systems/unix-pthreads/jsignal.h:1.1->1.2 
	kaffe/kaffevm/systems/unix-pthreads/signal.c:1.3->1.4 
	kaffe/kaffevm/systems/unix-pthreads/syscalls.c:1.15->1.16 
	kaffe/kaffevm/systems/unix-pthreads/thread-impl.c:1.26->1.27 

Index: kaffe/ChangeLog
diff -u kaffe/ChangeLog:1.2453 kaffe/ChangeLog:1.2454
--- kaffe/ChangeLog:1.2453	Sun Jul  4 00:52:54 2004
+++ kaffe/ChangeLog	Sun Jul  4 14:19:54 2004
@@ -1,3 +1,12 @@
+2004-07-04  Guilhem Lavaux <guilhem at kaffe.org>
+
+	* kaffe/kaffevm/systems/unix-pthreads/jsignal.h,
+	kaffe/kaffevm/systems/unix-pthreads/signal.c,
+	kaffe/kaffevm/systems/unix-pthreads/syscalls.c,
+	kaffe/kaffevm/systems/unix-pthreads/thread-impl.c:
+	Imported stack pointer detection in the unix-pthreads
+	implementation of kaffe threads.
+
 2004-07-03  Dalibor Topic  <robilad at kaffe.org>
 
         * configure.ac:
Index: kaffe/kaffe/kaffevm/systems/unix-pthreads/jsignal.h
diff -u kaffe/kaffe/kaffevm/systems/unix-pthreads/jsignal.h:1.1 kaffe/kaffe/kaffevm/systems/unix-pthreads/jsignal.h:1.2
--- kaffe/kaffe/kaffevm/systems/unix-pthreads/jsignal.h:1.1	Fri Sep 17 23:19:22 1999
+++ kaffe/kaffe/kaffevm/systems/unix-pthreads/jsignal.h	Sun Jul  4 14:19:58 2004
@@ -27,6 +27,8 @@
 #ifndef UNIXJTHREAD_SIGNAL_H
 #define UNIXJTHREAD_SIGNAL_H
 
+#include "thread-internal.h"
+
 void registerSyncSignalHandler(int sig, void* handler);
 void restoreSyncSignalHandler(int sig, void* handler);
 
@@ -40,5 +42,7 @@
 void unblockSignal(int sig);
 void unblockAsyncSignals(void);
 void blockAsyncSignals(void);
+
+void detectStackBoundaries(jthread_t jtid, int mainThreadStackSize);
 
 #endif /* UNIXJTHREAD_SIGNAL_H */
Index: kaffe/kaffe/kaffevm/systems/unix-pthreads/signal.c
diff -u kaffe/kaffe/kaffevm/systems/unix-pthreads/signal.c:1.3 kaffe/kaffe/kaffevm/systems/unix-pthreads/signal.c:1.4
--- kaffe/kaffe/kaffevm/systems/unix-pthreads/signal.c:1.3	Thu Apr 22 16:28:17 2004
+++ kaffe/kaffe/kaffevm/systems/unix-pthreads/signal.c	Sun Jul  4 14:19:58 2004
@@ -19,6 +19,9 @@
 #include "jsignal.h"
 #include "md.h"
 #include "stackTrace-impl.h"
+#include "thread-internal.h"
+#include "files.h"
+#include <errno.h>
 
 #if defined(INTERPRETER)
 #define	DEFINEFRAME()		/* Does nothing */
@@ -30,7 +33,9 @@
 #define	EXCEPTIONFRAMEPTR	&frame
 #endif /* TRANSLATOR */
 
-typedef void (*exchandler_t)(struct _exceptionFrame*);
+#ifndef STACK_STRUCT
+#define STACK_STRUCT stack_t
+#endif
 
 #if defined(__WIN32__)
 #define SIG_T   void(*)()
@@ -43,6 +48,7 @@
 
 static exchandler_t nullHandler;
 static exchandler_t floatingHandler;
+static exchandler_t stackOverflowHandler;
 
 /*
  * Setup the internal exceptions.
@@ -50,10 +56,11 @@
 void
 jthread_initexceptions(exchandler_t _nullHandler,
 		       exchandler_t _floatingHandler,
-		       exchandler_t _stackOverflowHandler UNUSED)
+		       exchandler_t _stackOverflowHandler)
 {
 	nullHandler = _nullHandler;
 	floatingHandler = _floatingHandler;
+	stackOverflowHandler = _stackOverflowHandler;
 
 	if (DBGEXPR(EXCEPTION, false, true)) {
 		/* Catch signals we need to convert to exceptions */
@@ -78,6 +85,9 @@
 void
 nullException(EXCEPTIONPROTO)
 {
+        void *stackptr;
+	jthread_t current_thread;
+
 	DEFINEFRAME();
 
 	/* Restore the signal handler if necessary */
@@ -87,7 +97,18 @@
 	unblockSignal(sig);
 
 	EXCEPTIONFRAME(frame, ctx);
-	nullHandler(EXCEPTIONFRAMEPTR);
+#if defined(STACK_POINTER)
+	current_thread = jthread_current();
+	stackptr = (void *)STACK_POINTER(GET_SIGNAL_CONTEXT_POINTER(ctx));
+#if defined(STACK_GROWS_UP)
+	if (current_thread != NULL && stackptr >= current_thread->stackMax)
+#else
+	if (current_thread != NULL && stackptr <= current_thread->stackMin)
+#endif
+	  stackOverflowHandler(EXCEPTIONFRAMEPTR);
+	else
+#endif // STACK_POINTER
+	  nullHandler(EXCEPTIONFRAMEPTR);
 }
 
 /*
@@ -315,3 +336,185 @@
 	sigprocmask(SIG_BLOCK, &nsig, 0);
 	
 }
+
+#if defined(HAVE_SIGALTSTACK) && defined(SA_ONSTACK)
+static void
+setupSigAltStack(void)
+{
+        STACK_STRUCT newstack;
+
+	/*
+	 * Signals has to have their own stack so we can solve
+	 * stack problems.
+	 */
+	newstack.ss_size = THREADSTACKSIZE;
+	newstack.ss_flags = 0;
+	newstack.ss_sp = KMALLOC(newstack.ss_size);
+	if (sigaltstack(&newstack, NULL) < 0)
+	  {
+	    dprintf("Unexpected error calling sigaltstack: %s\n",
+		    SYS_ERROR(errno));
+	    EXIT(1);
+	  }
+}
+#else
+static void
+setupSigAltStack(void)
+{
+}
+#endif
+
+/* ----------------------------------------------------------------------
+ * STACK BOUNDARY DETECTORS
+ * ----------------------------------------------------------------------
+ */
+
+#if defined(KAFFEMD_STACKBASE) // STACK_POINTER
+
+/*
+ * The OS gives us the stack base. Get it and adjust the pointers.
+ */
+
+void
+detectStackBoundaries(jthread_t jtid, int mainThreadStackSize)
+{
+        void *stackPointer;
+
+	stackPointer = mdGetStackBase();
+
+	setupSigAltStack();
+
+#if defined(STACK_GROWS_UP)
+	jtid->stackMin = stackPointer;
+	jtid->stackMax = (char *)jtid->stackMin + mainThreadStackSize;
+        jtid->stackCur = jtid->stackMax;
+#else
+	jtid->stackMax = stackPointer;
+        jtid->stackMin = (char *) jtid->stackMax - mainThreadStackSize;
+        jtid->stackCur = jtid->stackMin;
+#endif
+
+}
+
+#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;
+
+	setupSigAltStack();
+
+	stackPointer = mdGetStackEnd();
+	fprintf(stderr,"stackPointer=%p\n", stackPointer);
+
+#if defined(STACK_GROWS_UP)
+	jtid->stackMax = stackPointer;
+	jtid->stackMin = (char *)jtid->stackMax - mainThreadStackSize;
+        jtid->stackCur = jtid->stackMax;
+#else
+	jtid->stackBase = stackPointer;
+        jtid->stackEnd = (char *) jtid->stackMin + mainThreadStackSize;
+        jtid->stackCur = jtid->stackMin;
+#endif
+}
+
+#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)
+{
+	char *guessPointer;
+
+	setupSigAltStack();
+
+#if defined(SIGSEGV)
+	registerSyncSignalHandler(SIGSEGV, stackOverflowDetector);
+#endif
+#if defined(SIGBUS)
+	registerSyncSignalHandler(SIGBUS, stackOverflowDetector);
+#endif
+	
+	if (JTHREAD_SETJMP(outOfLoop) == 0)
+	{
+	  unsigned int 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
+}
+
+#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
Index: kaffe/kaffe/kaffevm/systems/unix-pthreads/syscalls.c
diff -u kaffe/kaffe/kaffevm/systems/unix-pthreads/syscalls.c:1.15 kaffe/kaffe/kaffevm/systems/unix-pthreads/syscalls.c:1.16
--- kaffe/kaffe/kaffevm/systems/unix-pthreads/syscalls.c:1.15	Sun Aug 31 17:16:48 2003
+++ kaffe/kaffe/kaffevm/systems/unix-pthreads/syscalls.c	Sun Jul  4 14:19:58 2004
@@ -128,7 +128,7 @@
 /*
  * Threaded socket create.
  */
-int
+static int
 jthreadedSocket(int af, int type, int proto, int *out)
 {
         int r;
@@ -143,7 +143,7 @@
         return (r);
 }
 
-int
+static int
 jthreadedOpen(const char* path, int flags, int mode, int *out)
 {
         int r;
@@ -197,7 +197,7 @@
 {
 	int rc = 0;
 
-	if (bind(fd, addr, namelen) == -1) {
+	if (bind(fd, addr, (socklen_t)namelen) == -1) {
 		rc = errno;
 	}
 	return (rc);
@@ -264,7 +264,7 @@
 {
 	int rc = 0;
 
-	if (mkdir(path, mode) == -1) {
+	if (mkdir(path, (mode_t)mode) == -1) {
 		rc = errno;
 	}
 	return (rc);
@@ -309,7 +309,7 @@
 {
 	int rc = 0;
 
-	*out = e ? sendto(a, b, c, d, e, f) : send(a, b, c, d);
+	*out = e ? sendto(a, b, c, d, e, (socklen_t)f) : send(a, b, c, d);
 	if (*out == -1) {
 		rc = errno;
 	}
@@ -321,7 +321,7 @@
 {
 	int rc = 0;
 
-	if (setsockopt(a, b, c, d, e) == -1) {
+	if (setsockopt(a, b, c, d, (socklen_t)e) == -1) {
 		rc = errno;
 	}
 	return (rc);
@@ -416,7 +416,7 @@
 /*
  * Threaded socket connect.
  */
-int
+static int
 jthreadedConnect(int fd, struct sockaddr* addr, int len, int timeout)
 {
 	int r;
@@ -425,7 +425,7 @@
 
 	SET_DEADLINE(deadline, timeout)
 	for (;;) {
-		r = connect(fd, addr, len);
+		r = connect(fd, addr, (socklen_t)len);
 		if (r == 0 || !(errno == EINPROGRESS 
 				|| errno == EINTR || errno == EISCONN)) {
 			break;	/* success or real error */
@@ -463,7 +463,7 @@
 /*
  * Threaded socket accept.
  */
-int
+static int
 jthreadedAccept(int fd, struct sockaddr* addr, int* len, 
 		int timeout, int* out)
 {
@@ -519,7 +519,7 @@
 /*
  * Threaded read with timeout
  */
-int
+static int
 jthreadedTimedRead(int fd, void* buf, size_t len, int timeout, ssize_t *out)
 {
 	ssize_t r = -1;
@@ -538,7 +538,7 @@
 /*
  * Threaded write with timeout
  */
-int
+static int
 jthreadedTimedWrite(int fd, const void* buf, size_t len, int timeout, ssize_t *out)
 {
 	ssize_t r = -1;
@@ -557,7 +557,7 @@
 /*
  * Threaded read with no time out
  */
-int
+static int
 jthreadedRead(int fd, void* buf, size_t len, ssize_t *out)
 {
 	ssize_t r = -1;
@@ -570,7 +570,7 @@
 /*
  * Threaded write
  */
-int
+static int
 jthreadedWrite(int fd, const void* buf, size_t len, ssize_t *out)
 {
 	ssize_t r = 1;
@@ -581,9 +581,9 @@
 	while (len > 0 && r > 0) {
 		r = (ssize_t)write(fd, ptr, len);
 		if (r >= 0) {
-			ptr += r;
+			ptr = (void *)((uintp)ptr + r);
 			len -= r;
-			r = ptr - buf;
+			r = (uintp)ptr - (uintp)buf;
 			continue;
 		}
 		if (errno == EINTR) {
@@ -604,7 +604,7 @@
 /*
  * Threaded recvfrom 
  */
-int 
+static int 
 jthreadedRecvfrom(int fd, void* buf, size_t len, int flags, 
 	struct sockaddr* from, int* fromlen, int timeout, ssize_t *out)
 {
@@ -635,7 +635,7 @@
 	}
 }
 
-int 
+static int 
 jthreadedForkExec(char **argv, char **arge,
 	int ioes[4], int *outpid, const char *dir)
 {
@@ -769,7 +769,7 @@
 /* 
  * Wait for a child process.
  */
-int
+static int
 jthreadedWaitpid(int wpid, int* status, int options, int *outpid)
 {
 #if defined(HAVE_WAITPID)
@@ -788,7 +788,7 @@
 #endif
 }
 
-int
+static int
 jthreadedMmap(void **memory, size_t *size, int mode, int fd, off_t *offset)
 {
 #if defined(HAVE_MMAP)
@@ -863,7 +863,8 @@
 #endif
 }
 
-int jthreadedPipeCreate(int *read_fd, int *write_fd)
+static int
+jthreadedPipeCreate(int *read_fd, int *write_fd)
 {
 	int pairs[2];
 
Index: kaffe/kaffe/kaffevm/systems/unix-pthreads/thread-impl.c
diff -u kaffe/kaffe/kaffevm/systems/unix-pthreads/thread-impl.c:1.26 kaffe/kaffe/kaffevm/systems/unix-pthreads/thread-impl.c:1.27
--- kaffe/kaffe/kaffevm/systems/unix-pthreads/thread-impl.c:1.26	Mon May 31 19:37:51 2004
+++ kaffe/kaffe/kaffevm/systems/unix-pthreads/thread-impl.c	Sun Jul  4 14:19:58 2004
@@ -412,10 +412,10 @@
         int maxpr, int minpr,
         void *(*_allocator)(size_t),
         void (*_deallocator)(void*),
-        void *(*_reallocator)(void*,size_t),
-        void (*_destructor1)(void*),
-        void (*_onstop)(void),
-        void (*_ondeadlock)(void))
+        void *(*_reallocator)(void*,size_t) UNUSED,
+        void (*_destructor1)(void*) UNUSED,
+        void (*_onstop)(void) UNUSED,
+        void (*_ondeadlock)(void) UNUSED)
 {
   DBG(JTHREAD, dprintf("initialized\n"))
 
@@ -460,13 +460,7 @@
   /* Get stack boundaries. Note that this is just an approximation
    * which should cover all gc-relevant stack locations
    */
-#if defined(STACK_GROWS_UP)
-  nt->stackMin  = (void*) (uintp)(&nt - 0x100);
-  nt->stackMax  = (void*) ((uintp) nt->stackMin + mainThreadStackSize);
-#else
-  nt->stackMax  = (void*) (uintp)(&nt + 0x100);
-  nt->stackMin  = (void*) ((uintp) nt->stackMax - mainThreadStackSize);
-#endif
+  detectStackBoundaries(nt, mainThreadStackSize);
 
   DBG( JTHREAD, TMSG_SHORT( "create first ", nt))
 
@@ -545,7 +539,7 @@
 
   /* get the stack boundaries */
   pthread_attr_getstacksize( &cur->attr, &ss);
-
+  
 #if defined(STACK_GROWS_UP)
   cur->stackMin = &cur;
   cur->stackMax = (void*) ((unsigned long)cur->stackMin + ss);



More information about the kaffe mailing list