[kaffe] [PATCH] IA-64 fixes

Gwenole Beauchesne gbeauchesne@mandrakesoft.com
Thu May 15 09:24:02 2003


Hi,

The sysdepCallMethod() tester I posted earlier triggered a few bugs in the 
IA-64 version. Fixed hereunder among other fixlets. Patch against 1.1 CVS 
(2003/05/14). No regressions, no improvement either. :-(

BTW, we probably need proper NEED_JTHREAD_ALIGN, JTHREAD macros to align a 
new thread context, in case the enclosed jmp_buf needs special treatments.

2003-05-15  Gwenole Beauchesne  <gbeauchesne@mandrakesoft.com>

	* config/config-setjmp.h (JTHREAD_DECLARE_JMPBUF,
	JTHREAD_ACCESS_JMPBUF): Kill.
	* kaffe/kaffevm/exception.c (dispatchException): Likewise.
	* kaffe/kaffevm/exception.h (vmExcept_jumpToHandler): Likewise.
	* kaffe/kaffevm/jni.c (BEGIN_EXCEPTION_HANDLING*): Likewise.
	
	Instead, the jthread struct containing a jmp_buf must be aligned
	once it is allocated. Other occurrences were already aligned per
	natural alignment requirements in stack.

	* config/ia64/linux/md.c (IA64_context_*): Update to match current
	state-threads v1.4 code from SGI.

	* config/ia64/sysdepCallMethod.h (sysdepCallMethod): Really match
	calling conventions. We now can deal with a mix of ints, longs,
	floats and doubles correctly. Reindent.

	* kaffe/kaffevm/systems/unix-jthreads/jthread.c
	(JTHREAD_CONTEXT_SAVE, JTHREAD_CONTEXT_RESTORE): New macros
	specific to context switches.
	(newThreadCtx): Align jthread struct on 16-byte boundaries for
	jmp_buf. Move down stack adjusting.

--- kaffe-1.1.orig/config/config-setjmp.h	2002-05-29 21:46:23.000000000 +0200
+++ kaffe-1.1/config/config-setjmp.h	2003-05-14 21:39:29.000000000 +0200
@@ -90,12 +90,4 @@ typedef void* kaffe_jmp_buf[JTHREAD_JBLE
 
 #endif
 
-#if defined(__ia64__)
-#define JTHREAD_DECLARE_JMPBUF(x)	JTHREAD_JMPBUF x; void * x##_pad
-#define JTHREAD_ACCESS_JMPBUF(x, y)	(__typeof__((x)->y[0]) *) ((((unsigned long)&(x)->y) + 15) & -16)
-#else
-#define JTHREAD_DECLARE_JMPBUF(x)	JTHREAD_JMPBUF x
-#define JTHREAD_ACCESS_JMPBUF(x, y)	(x)->y
-#endif
-
 #endif
--- kaffe-1.1.orig/config/ia64/linux/md.c	2002-05-29 21:49:58.000000000 +0200
+++ kaffe-1.1/config/ia64/linux/md.c	2003-05-15 21:43:25.000000000 +0200
@@ -29,7 +29,8 @@ init_md(void)
 }
 
 /*
- * Copyright (C) 2000 Silicon Graphics, Inc.  All Rights Reserved.
+ * Portions created by SGI are Copyright (C) 2000 Silicon Graphics, Inc.
+ * All Rights Reserved.
  *
  * The internal __jmp_buf layout is different from one used
  * by setjmp()/longjmp().
@@ -92,8 +93,8 @@ init_md(void)
         asm("
         .text
         .align 32
-        .global IA64_context_save#
-        .proc IA64_context_save#
+        .global IA64_context_save
+        .proc IA64_context_save
 IA64_context_save:
         alloc r14 = ar.pfs,1,0,0,0
         mov r16 = ar.unat
@@ -103,6 +104,7 @@ IA64_context_save:
         add r3 = 8,in0
         ;;
         st8.spill.nta [r2] = sp,16    // r12 (sp)
+        ;;
         st8.spill.nta [r3] = gp,16    // r1  (gp)
         ;;
         st8.nta [r2] = r16,16         // save caller's unat
@@ -110,6 +112,7 @@ IA64_context_save:
         add r8 = 0xb0,in0
         ;;   
         st8.spill.nta [r2] = r4,16    // r4
+        ;;
         st8.spill.nta [r3] = r5,16    // r5
         add r9 = 0xc0,in0
         ;;
@@ -150,11 +153,14 @@ IA64_context_save:
         ;;
         stf.spill.nta [r8] = f30
         stf.spill.nta [r9] = f31
+
         st8.spill.nta [r2] = r6,16    // r6
+        ;;
         st8.spill.nta [r3] = r7,16    // r7
         ;;
         mov r23 = ar.bsp
         mov r25 = ar.unat
+
         st8.nta [r2] = r15,16         // b0
         st8.nta [r3] = r17,16         // b1
         ;;
@@ -189,15 +195,17 @@ IA64_context_save:
         ;;
         mov r8 = 0
         br.ret.sptk.few b0
-        .endp IA64_context_save#
+        .endp IA64_context_save
         ");
 
+
+/****************************************************************/
+
         /* IA64_context_restore(__jmp_buf env, int val) */
         asm("
         .text
-        .align 32
-        .global IA64_context_restore#
-        .proc IA64_context_restore#
+        .global IA64_context_restore
+        .proc IA64_context_restore
 IA64_context_restore:
         alloc r8 = ar.pfs,2,0,0,0
         add r2 = 0x88,in0             // r2 <- &jmpbuf.ar_bsp
@@ -296,7 +304,10 @@ IA64_context_restore:
         ldf.fill.nta f31 = [r3]
 (p6)    mov r8 = 1
 (p7)    mov r8 = in1
+
         mov pr = r24,-1
         br.ret.sptk.few b0
-        .endp IA64_context_restore#
+        .endp IA64_context_restore
         ");
+
+/****************************************************************/
--- kaffe-1.1.orig/config/ia64/linux/md.h	2002-05-29 21:49:58.000000000 +0200
+++ kaffe-1.1/config/ia64/linux/md.h	2003-05-15 21:51:34.000000000 +0200
@@ -27,10 +27,10 @@ extern int IA64_context_save(jmp_buf env
 extern void IA64_context_restore(jmp_buf env, int val);
 
 #if 0
-#undef JTHREAD_SETJMP
-#define JTHREAD_SETJMP(env)			IA64_context_save((env))
-#undef JTHREAD_LONGJMP
-#define JTHREAD_LONGJMP(env, val)		IA64_context_restore((env), (val))
+#undef  JTHREAD_CONTEXT_SAVE
+#define JTHREAD_CONTEXT_SAVE(env)		IA64_context_save((env))
+#undef  JTHREAD_CONTEXT_RESTORE
+#define JTHREAD_CONTEXT_RESTORE(env, val)	IA64_context_restore((env), (val))
 #endif
 
 #define SIGNAL_ARGS(sig, scp)			int sig, siginfo_t *sip, struct sigcontext *scp
--- kaffe-1.1.orig/config/ia64/sysdepCallMethod.h	2002-05-29 21:49:58.000000000 +0200
+++ kaffe-1.1/config/ia64/sysdepCallMethod.h	2003-05-15 21:24:55.000000000 +0200
@@ -2,7 +2,7 @@
  * ia64/sysdepCallMethod.h
  * Dynamically build function calls using IA-64 SVR4 ABI.
  *
- * Copyright (c) 2001
+ * Copyright (c) 2001-2003
  *	MandrakeSoft.  All rights reserved.
  *
  * See the file "license.terms" for information on usage and redistribution
@@ -37,6 +37,10 @@
 /* ARG_LIST is the argument list for such a function.  */
 #define ARG_LIST	a0, a1, a2, a3, a4, a5, a6, a7
 
+/* REG_ARGS is the total number of arguments passed in registers,
+   including both GPR and FPR.  */
+#define REG_ARGS	8
+
 /* GPR_ARGS is the number of GPR (integer) registers for passing
    arguments.  */
 #define GPR_ARGS	8
@@ -45,11 +49,6 @@
    arguments.  */
 #define FPR_ARGS	8
 
-/* ARG_DISPLACEMENT is the offset between the beginning of a
-   variable-sized array, allocated in the stack, and the position of
-   the first argument that can't be passed in a register.  */
-#define ARG_DISPLACEMENT	0
-
 /* ARG_GPR a case label and a statement that arranges for one integer
    argument to be passed. */
 #define ARG_GPR(N) \
@@ -67,176 +66,173 @@
    for both JIT and Interpreter (since stubs have now been deprecated).  */
 static inline void sysdepCallMethod(callMethodInfo* call)
 {
-    void *func = call->function;
-    jvalue *callargs = call->args;
-    char *calltype = call->calltype;
-    jvalue *args = callargs;
-    jvalue *last = &callargs[call->nrargs];
-    int nr_gpr = 0;
-    int nr_fpr = 0;
-    int nr_stack = 0;
-
-    unsigned long *stack;
-    unsigned long *gpr;
-    double *fpr;
-
-    /* Compute gpr[], fpr[] and stack[] arrays' size */
-    while (args != last) {
-	  switch (calltype[(args++) - callargs]) {
-	  case 'F':
-	  case 'D':
-		if (nr_fpr < FPR_ARGS) {
-		  nr_fpr++;
-		  nr_gpr++;
-		}
-		else
-		  nr_stack++;
-		break;
-		
-	  default:
-		if (nr_gpr < GPR_ARGS)
-		  nr_gpr++;
-		else
-		  nr_stack++;
-		break;
-	  }
-	}
-
-    /* Allocate all arrays with one big alloca() */
-    {
-	  int nr = nr_gpr + nr_fpr + nr_stack;
-	  
-	  /* stack, if used, must be 16 bytes aligned */
-	  if (nr_stack)
-		nr = (nr + 1) & ~1;
-
-	  /* stack[] is in called parameters area.  */
-	  stack = __builtin_alloca (8 * nr);
-
-	  /* gpr[] and fpr[] are in callee local variable area.  */
-	  gpr = stack + nr_stack;
-	  fpr = (double *)(gpr + nr_gpr);
-	  
-	  /* if __buildin_alloc() does not handle link-area, skip it.  */
-	  stack += ARG_DISPLACEMENT;
-    }
-
-    /* build gpr[], fpr[] and stack[] arrays */
-    nr_gpr = 0;
-	nr_fpr = 0;
-	nr_stack = 0;
-	
-    args = callargs;
-    while (args != last) {
-	  switch (calltype[args - callargs]) {
-	  case 'F': {
-		jvalue value = { .d = (double)args->f };
-		if (nr_fpr < FPR_ARGS) {
-		  fpr[nr_fpr++] = value.d;
-		  gpr[nr_gpr++] = value.j;
-		}
-		else {
-		  *(float *)stack = value.d;
-		  stack++;
-		}
-		break;
-	  }
-	  
-	  case 'D': {
-		jvalue value = { .d = args->d };
-	    if (nr_fpr < FPR_ARGS) {
-		  fpr[nr_fpr++] = value.d;
-		  gpr[nr_gpr++] = value.j;
-	    }
-		else {
-		  *(double *)stack = value.d;
-		  stack++;
-		}
-		break;
-	  }
-	  
-	  default:
-		if (nr_gpr < GPR_ARGS)
-		  gpr[nr_gpr++] = args->j;
-		else
-		  *stack++ = args->j;
-	  }
-	  args++;
-    }
-
-    {
-	  register ARG_TYPE a0 asm("out0");
-	  register ARG_TYPE a1 asm("out1");
-	  register ARG_TYPE a2 asm("out2");
-	  register ARG_TYPE a3 asm("out3");
-	  register ARG_TYPE a4 asm("out4");
-	  register ARG_TYPE a5 asm("out5");
-	  register ARG_TYPE a6 asm("out6");
-	  register ARG_TYPE a7 asm("out7");
-	  
-	  register double d0 asm("f8");
-	  register double d1 asm("f9");
-	  register double d2 asm("f10");
-	  register double d3 asm("f11");
-	  register double d4 asm("f12");
-	  register double d5 asm("f13");
-	  register double d6 asm("f14");
-	  register double d7 asm("f15");
-	  
-	  /* load FPR registers from fpr[] */
-	  switch (nr_fpr) {
-		ARG_FPR(7);
-		ARG_FPR(6);
-		ARG_FPR(5);
-		ARG_FPR(4);
-		ARG_FPR(3);
-		ARG_FPR(2);
-		ARG_FPR(1);
-		ARG_FPR(0);
-	  case 0:;
-	  }
-
-	  /* load GPR registers from gpr[] */
-	  switch (nr_gpr) {
-		ARG_GPR(7);
-		ARG_GPR(6);
-		ARG_GPR(5);
-		ARG_GPR(4);
-		ARG_GPR(3);
-		ARG_GPR(2);
-		ARG_GPR(1);
-		ARG_GPR(0);
-	  case 0:;
-	  }
-	  
-	  /* Ensure that the assignments to f* registers won't be optimized away. */
-	  asm ("" ::
-		   "f" (d0), "f" (d1), "f" (d2), "f" (d3),
-		   "f" (d4), "f" (d5), "f" (d6), "f" (d7));
-
-	  switch(call->retsize) {
-	  case 0:
-	    /* Must be void.  */
-	    ((void (*)(ARG_TYPES))(func))(ARG_LIST);
-	    break;
-		
-	  case 1:
-	    if (call->rettype == 'F')
-		  call->ret->f = ((jfloat (*)(ARG_TYPES))(func))(ARG_LIST);
-	    else /* Must be 32-bit or smaller int.  */
-		  call->ret->i = ((jint (*)(ARG_TYPES))(func))(ARG_LIST);
-	    break;
-
-	  default:
-	    /* It could've been `case 2;', but then we'd get an additional cmp
-	     * that we don't really need.  */
-	    if (call->rettype == 'D')
-		  call->ret->d = ((jdouble (*)(ARG_TYPES))(func))(ARG_LIST);
-	    else /* Must be jlong.  */
-		  call->ret->j = ((jlong (*)(ARG_TYPES))(func))(ARG_LIST);
-	    break;
-	  }
+  void *func = call->function;
+  jvalue *callargs = call->args;
+  char *calltype = call->calltype;
+  jvalue *args = callargs;
+  jvalue *last = &callargs[call->nrargs];
+  int nr_gpr = 0;
+  int nr_fpr = 0;
+  int nr_stack = 0;
+
+  unsigned long *stack;
+  unsigned long gpr[GPR_ARGS];
+  double fpr[FPR_ARGS];
+
+  /* Compute gpr[], fpr[] and stack[] arrays' size */
+  while (args != last) {
+    switch (calltype[(args++) - callargs]) {
+    case 'F':
+    case 'D':
+      if (nr_gpr + nr_fpr < REG_ARGS) {
+	nr_fpr++;
+	nr_gpr++;
+      }
+      else
+	nr_stack++;
+      break;
+
+    default:
+      if (nr_gpr + nr_fpr < REG_ARGS)
+	nr_gpr++;
+      else
+	nr_stack++;
+      break;
+    }
+  }
+
+  /* Allocate all arrays with one big alloca() */
+  {
+    int nr = nr_stack;
+
+    /* stack, if used, must be 16 bytes aligned */
+    if (nr_stack)
+      nr = (nr + 1) & ~1;
+
+    /* stack[] is in called parameters area.  */
+    stack = __builtin_alloca (8 * nr);
+  }
+
+  /* build gpr[], fpr[] and stack[] arrays */
+  nr_gpr = 0;
+  nr_fpr = 0;
+  nr_stack = 0;
+
+  args = callargs;
+  while (args != last) {
+    switch (calltype[args - callargs]) {
+    case 'F': {
+      jvalue value = { .d = (double)args->f };
+      if (nr_gpr + nr_fpr < REG_ARGS) {
+	fpr[nr_fpr++] = value.d;
+	/* Also pass the FP slot in GPR so that callee knows
+	   about it in case it was not prototyped beforehand. */
+	gpr[nr_gpr++] = value.j;
+      }
+      else {
+	*(float *)stack = value.d;
+	stack++;
+      }
+      break;
+    }
+
+    case 'D': {
+      jvalue value = { .d = args->d };
+      if (nr_gpr + nr_fpr < REG_ARGS) {
+	fpr[nr_fpr++] = value.d;
+	/* Also pass the FP slot in GPR so that callee knows
+	   about it in case it was not prototyped beforehand. */
+	gpr[nr_gpr++] = value.j;
+      }
+      else {
+	*(double *)stack = value.d;
+	stack++;
+      }
+      break;
+    }
+
+    default:
+      if (nr_gpr + nr_fpr < REG_ARGS)
+	gpr[nr_gpr++] = args->j;
+      else
+	*stack++ = args->j;
+    }
+    args++;
+  }
+
+  {
+    register ARG_TYPE a0 asm("out0");
+    register ARG_TYPE a1 asm("out1");
+    register ARG_TYPE a2 asm("out2");
+    register ARG_TYPE a3 asm("out3");
+    register ARG_TYPE a4 asm("out4");
+    register ARG_TYPE a5 asm("out5");
+    register ARG_TYPE a6 asm("out6");
+    register ARG_TYPE a7 asm("out7");
+
+    register double d0 asm("f8");
+    register double d1 asm("f9");
+    register double d2 asm("f10");
+    register double d3 asm("f11");
+    register double d4 asm("f12");
+    register double d5 asm("f13");
+    register double d6 asm("f14");
+    register double d7 asm("f15");
+
+    /* load FPR registers from fpr[] */
+    switch (nr_fpr) {
+      ARG_FPR(7);
+      ARG_FPR(6);
+      ARG_FPR(5);
+      ARG_FPR(4);
+      ARG_FPR(3);
+      ARG_FPR(2);
+      ARG_FPR(1);
+      ARG_FPR(0);
+    case 0:;
+    }
+
+    /* load GPR registers from gpr[] */
+    switch (nr_gpr) {
+      ARG_GPR(7);
+      ARG_GPR(6);
+      ARG_GPR(5);
+      ARG_GPR(4);
+      ARG_GPR(3);
+      ARG_GPR(2);
+      ARG_GPR(1);
+      ARG_GPR(0);
+    case 0:;
+    }
+
+    /* Ensure that the assignments to f* registers won't be optimized away. */
+    asm ("" ::
+	 "f" (d0), "f" (d1), "f" (d2), "f" (d3),
+	 "f" (d4), "f" (d5), "f" (d6), "f" (d7));
+
+    switch(call->retsize) {
+    case 0:
+      /* Must be void.  */
+      ((void (*)(ARG_TYPES))(func))(ARG_LIST);
+      break;
+
+    case 1:
+      if (call->rettype == 'F')
+	call->ret->f = ((jfloat (*)(ARG_TYPES))(func))(ARG_LIST);
+      else /* Must be 32-bit or smaller int.  */
+	call->ret->i = ((jint (*)(ARG_TYPES))(func))(ARG_LIST);
+      break;
+
+    default:
+      /* It could've been `case 2;', but then we'd get an additional cmp
+       * that we don't really need.  */
+      if (call->rettype == 'D')
+	call->ret->d = ((jdouble (*)(ARG_TYPES))(func))(ARG_LIST);
+      else /* Must be jlong.  */
+	call->ret->j = ((jlong (*)(ARG_TYPES))(func))(ARG_LIST);
+      break;
     }
+  }
 }
 
 #undef ARG_TYPE
--- kaffe-1.1.orig/kaffe/kaffevm/exception.c	2002-10-18 15:54:14.000000000 +0200
+++ kaffe-1.1/kaffe/kaffevm/exception.c	2003-05-14 20:54:41.000000000 +0200
@@ -452,7 +452,7 @@ DBG(ELOOKUP,
 
 			/* If not here, exit monitor if synchronised. */
 			if (obj != 0 && (einfo.method->accflags & ACC_SYNCHRONISED) != 0) {
-				_slowUnlockMutexIfHeld(&obj->lock, JTHREAD_ACCESS_JMPBUF(frame, jbuf));
+				_slowUnlockMutexIfHeld(&obj->lock, frame->jbuf);
 			}
 		}
 	}
--- kaffe-1.1.orig/kaffe/kaffevm/exception.h	2003-01-06 18:14:19.000000000 +0100
+++ kaffe-1.1/kaffe/kaffevm/exception.h	2003-05-14 20:55:29.000000000 +0200
@@ -92,7 +92,7 @@ typedef struct VmExceptHandler {
 	u4				pc;
 		} intrp;
 	} frame;
-	JTHREAD_DECLARE_JMPBUF		(jbuf);
+	JTHREAD_JMPBUF		jbuf;
 } VmExceptHandler;
 
 #define VMEXCEPTHANDLER_KAFFEJNI_HANDLER ((struct _methods*)1)
@@ -156,7 +156,7 @@ vmExcept_setJNIFrame(VmExceptHandler* eh
 static inline void
 vmExcept_jumpToHandler(VmExceptHandler* frame)
 {
-	JTHREAD_LONGJMP(JTHREAD_ACCESS_JMPBUF(frame, jbuf), 1);
+	JTHREAD_LONGJMP(frame->jbuf, 1);
 }
 
 #if defined(INTERPRETER)
--- kaffe-1.1.orig/kaffe/kaffevm/jni.c	2003-01-06 18:14:20.000000000 +0100
+++ kaffe-1.1/kaffe/kaffevm/jni.c	2003-05-14 20:54:17.000000000 +0200
@@ -131,7 +131,7 @@ getMethodFunc (Method* meth, Hjava_lang_
 	VmExceptHandler ebuf;				\
 	KAFFE_JNI_SETEXCEPTFP(&ebuf); 			\
 	ebuf.prev = (VmExceptHandler*)(unhand(getCurrentThread())->exceptPtr);\
-	if (JTHREAD_SETJMP(JTHREAD_ACCESS_JMPBUF(&ebuf, jbuf)) != 0) {		\
+	if (JTHREAD_SETJMP(ebuf.jbuf) != 0) {		\
 		unhand(getCurrentThread())->exceptPtr = \
 		  (struct Hkaffe_util_Ptr*)ebuf.prev;	\
 		return X;				\
@@ -142,7 +142,7 @@ getMethodFunc (Method* meth, Hjava_lang_
 	VmExceptHandler ebuf; 				\
 	KAFFE_JNI_SETEXCEPTFP(&ebuf); 			\
 	ebuf.prev = (VmExceptHandler*)(unhand(getCurrentThread())->exceptPtr);\
-	if (JTHREAD_SETJMP(JTHREAD_ACCESS_JMPBUF(&ebuf, jbuf)) != 0) {		\
+	if (JTHREAD_SETJMP(ebuf.jbuf) != 0) {		\
 		unhand(getCurrentThread())->exceptPtr = \
 		  (struct Hkaffe_util_Ptr*)ebuf.prev;	\
 		return;					\
--- kaffe-1.1.orig/kaffe/kaffevm/systems/unix-jthreads/jthread.c	2003-03-11 09:00:19.000000000 +0100
+++ kaffe-1.1/kaffe/kaffevm/systems/unix-jthreads/jthread.c	2003-05-15 21:49:36.000000000 +0200
@@ -123,6 +123,14 @@ static int  min_priority;		/* minimum su
 
 jthread* currentJThread;
 
+/* Context switch related functions */
+#ifndef JTHREAD_CONTEXT_SAVE
+#define JTHREAD_CONTEXT_SAVE(buf)		JTHREAD_SETJMP((buf))
+#endif
+#ifndef JTHREAD_CONTEXT_RESTORE
+#define JTHREAD_CONTEXT_RESTORE(buf, val)	JTHREAD_LONGJMP((buf), (val))
+#endif
+
 /* The arguments to a signal handler */
 #ifndef SIGNAL_ARGS
 #define SIGNAL_ARGS(sig, sc) int sig
@@ -898,10 +906,14 @@ newThreadCtx(int stackSize)
 {
 	jthread *ct;
 
-	ct = allocator(sizeof(jthread) + stackSize);
+	ct = allocator(sizeof(jthread) + 16 + stackSize);
 	if (ct == 0) {
 		return 0;
 	}
+#if defined(__ia64__)
+	/* (gb) Align jmp_buf on 16-byte boundaries */
+	ct = (jthread *)((((unsigned long)(ct)) & 15) ^ (unsigned long)(ct));
+#endif
 	ct->stackBase = (ct + 1);
 	ct->stackEnd = (char *) ct->stackBase + stackSize;
 	ct->restorePoint = ct->stackEnd;
@@ -1269,12 +1281,6 @@ jthread_create(unsigned char pri, void (
 	void	*oldbsp, *newbsp;
 #endif
 	size_t   page_size;
-	
-	/* Adjust stack size */
-	page_size = getpagesize();
-	if (threadStackSize == 0)
-		threadStackSize = THREADSTACKSIZE;
-	threadStackSize = (threadStackSize + page_size - 1) & -page_size;
 
 	/*
 	 * Disable stop to protect the threadLock lock, and prevent
@@ -1283,6 +1289,12 @@ jthread_create(unsigned char pri, void (
 	 */
 	jthread_disable_stop();
 
+	/* Adjust stack size */
+	page_size = getpagesize();
+	if (threadStackSize == 0)
+		threadStackSize = THREADSTACKSIZE;
+	threadStackSize = (threadStackSize + page_size - 1) & -page_size;
+
 	jmutex_lock(&threadLock);
 	jtid = newThreadCtx(threadStackSize);
 	if (!jtid) {
@@ -1319,7 +1331,7 @@ DBG(JTHREAD,
 	 *
 	 * To be safe, we immediately call a new function.
 	 */
-        if (JTHREAD_SETJMP(JTHREAD_ACCESS_JMPBUF(jtid, env))) {
+        if (JTHREAD_CONTEXT_SAVE(jtid->env)) {
 		/* new thread */
 		start_this_sucker_on_a_new_frame();
 		assert(!"Never!");
@@ -1330,9 +1342,9 @@ DBG(JTHREAD,
 	SAVE_FP(jtid->fpstate);
 #endif
 	/* set up context for new thread */
-	oldstack = GET_SP(JTHREAD_ACCESS_JMPBUF(jtid, env));
+	oldstack = GET_SP(jtid->env);
 #if defined(__ia64__)
-	oldbsp = GET_BSP(JTHREAD_ACCESS_JMPBUF(jtid, env));
+	oldbsp = GET_BSP(jtid->env);
 #endif
 
 #if defined(STACK_GROWS_UP)
@@ -1348,7 +1360,7 @@ DBG(JTHREAD,
 	 * grows downward. Both stacks start in the middle and grow outward
 	 * from each other.
 	 */
-	newstack -= (threadStackSize >> 1);
+	(char *) newstack -= (threadStackSize >> 1);
 	newbsp = newstack;
 	/* Make register stack 64-byte aligned */
 	if ((unsigned long)newbsp & 0x3f)
@@ -1364,9 +1376,9 @@ DBG(JTHREAD,
 	newstack = (void *) STACK_ALIGN(newstack);
 #endif
 
-	SET_SP(JTHREAD_ACCESS_JMPBUF(jtid, env), newstack);
+	SET_SP(jtid->env, newstack);
 #if defined(__ia64__)
-	SET_BSP(JTHREAD_ACCESS_JMPBUF(jtid, env), newbsp);
+	SET_BSP(jtid->env, newbsp);
 #endif
 
 #if defined(SET_BP)
@@ -1374,13 +1386,13 @@ DBG(JTHREAD,
 	 * Clear the base pointer in the new thread's stack.
 	 * Nice for debugging, but not strictly necessary.
 	 */
-	SET_BP(JTHREAD_ACCESS_JMPBUF(jtid, env), 0);
+	SET_BP(jtid->env, 0);
 #endif
 
 
 #if defined(FP_OFFSET)
 	/* needed for: IRIX */
-	SET_FP(JTHREAD_ACCESS_JMPBUF(jtid, env), newstack + ((void *)GET_FP(JTHREAD_ACCESS_JMPBUF(jtid, env)) - oldstack));
+	SET_FP(jtid->env, newstack + ((void *)GET_FP(jtid->env) - oldstack));
 #endif
 
         resumeThread(jtid);
@@ -1627,9 +1639,10 @@ dprintf("switch from %p to %p\n", lastTh
 #if defined(CONTEXT_SWITCH)
 				CONTEXT_SWITCH(lastThread, currentJThread);
 #else
-				if (JTHREAD_SETJMP(JTHREAD_ACCESS_JMPBUF(lastThread, env)) == 0) {
-				    lastThread->restorePoint = GET_SP(JTHREAD_ACCESS_JMPBUF(lastThread, env));
-				    JTHREAD_LONGJMP(JTHREAD_ACCESS_JMPBUF(currentJThread, env), 1);
+				if (JTHREAD_CONTEXT_SAVE(lastThread->env) == 0) {
+				    lastThread->restorePoint = 
+					GET_SP(lastThread->env);
+				    JTHREAD_CONTEXT_RESTORE(currentJThread->env, 1);
 				}
 #endif
 #if defined(LOAD_FP)
--- kaffe-1.1.orig/kaffe/kaffevm/systems/unix-jthreads/jthread.h	2002-11-27 19:32:55.000000000 +0100
+++ kaffe-1.1/kaffe/kaffevm/systems/unix-jthreads/jthread.h	2003-05-14 20:48:41.000000000 +0200
@@ -90,7 +90,7 @@ typedef struct _jthread {
 	 * used to hold the current Java thread
 	 */
 	void*				jlThread;
-	JTHREAD_DECLARE_JMPBUF		(env);
+	JTHREAD_JMPBUF			env;
 #if defined(SAVED_FP_SIZE)
 	char				fpstate[SAVED_FP_SIZE];
 #endif