[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