## Process this file with automake to produce Makefile.in
-# $Id: Makefile.am 993 2004-03-30 21:36:03Z twisti $
+# $Id: Makefile.am 1073 2004-05-19 23:21:15Z stefan $
@SET_MAKE@
gnuclasspathnat/native/jni/java-lang/.libs/libjavalang.a \
gnuclasspathnat/native/jni/java-lang/.libs/libjavalangreflect.a \
@AWT_OBJS@ \
- @ZIP_LIBS@
+ @ZIP_LIBS@ \
+ @THREAD_LIB@
cacao_DEPENDENCIES = \
gnuclasspathnat/native/jni/java-lang/.libs/libjavalang.a \
@THREAD_OBJ@ \
@ZIP_LIBS@ \
- toolbox/libtoolbox.a
+ toolbox/libtoolbox.a \
+ @THREAD_LIB@
cacaoh_DEPENDENCIES = \
$(BOEHM_LIBS) \
AC_DEFINE([DONT_FREE_FIRST], 1, [don't free first])
LIBTHREAD="libthreads.a"
- THREAD_OBJ="threads/libthreads.a -lpthread"
+ THREAD_OBJ="threads/libthreads.a"
+ THREAD_LIB=-lpthread
AC_SUBST(LIBTHREAD)
AC_SUBST(THREAD_OBJ)
+ AC_SUBST(THREAD_LIB)
fi
dnl Check whether the compiler supports the __thread keyword.
Changes: Mark Probst
Philipp Tomsich
- $Id: headers.c 1070 2004-05-19 16:32:18Z stefan $
+ $Id: headers.c 1073 2004-05-19 23:21:15Z stefan $
*/
void asm_handle_builtin_exception(classinfo *c) {}
void asm_getclassvalues_atomic() {}
+#if defined(__DARWIN__)
+int cacao_catch_Handler() {}
+#endif
+
#if defined(USE_THREADS) && defined(NATIVE_THREADS)
threadcritnode asm_criticalsections;
#endif
## Process this file with automake to produce Makefile.in
-# $Id: Makefile.am 568 2003-11-06 14:42:16Z twisti $
+# $Id: Makefile.am 1073 2004-05-19 23:21:15Z stefan $
INCLUDES = -I$(top_srcdir)/jit
disass.c \
disass.h \
native-math.h \
+ machine-instr.h \
ppc-dis.c \
ppc-opc.c
ppc.h \
Authors: Andreas Krall
Reinhard Grafl
- $Id: asmpart.S 1059 2004-05-16 13:16:15Z twisti $
+ $Id: asmpart.S 1073 2004-05-19 23:21:15Z stefan $
*/
-
+#include "config.h"
#include "offsets.h"
.globl _asm_initialize_thread_stack
.globl _asm_perform_threadswitch
.globl _asm_switchstackandcall
+ .globl _asm_criticalsections
+ .globl _asm_getclassvalues_atomic
.globl _string_java_lang_NullPointerException
.globl _string_java_lang_ArrayIndexOutOfBoundsException
.globl _string_java_lang_ClassCastException
.globl _builtin_asm_get_exceptionptrptr
+#if !defined(USE_THREADS) || !defined(NATIVE_THREADS)
.globl __exceptionptr
+#endif
.globl _builtin_throw_exception
.globl _class_load
.globl _class_link
.globl _class_init
- .globl _catch_Handler
.globl _new_exception
.globl _new_exception_message
.globl _new_exception_int
- .globl _asm_sighandler
-
jitcompile:
.long _jit_compile
builtin_asm_get_exceptionptrptr:
.long _builtin_asm_get_exceptionptrptr
+#if !defined(USE_THREADS) || !defined(NATIVE_THREADS)
_exceptionptr:
.long __exceptionptr
-
-catch_Handler:
- .long _catch_Handler
+#endif
#define MethodPointer -8
L_class_loaded:
lwz itmp3,offclasslinked(r7)
mr. itmp3,itmp3
+ addi r1,r1,-16*4 /* allocate stack */
+ stw r7,13*4(r1)
bne L_class_linked
- addi r1,r1,-16*4 /* allocate stack */
stw r3,7*4(r1) /* save used registers */
stw r4,8*4(r1) /* 6*4 (linkage) + 1*4 (arg1) + 7*4 (save) */
stw r2,9*4(r1)
stw xpc,11*4(r1)
mflr xptr
stw xptr,12*4(r1)
- stw r7,13*4(r1)
mr r3,r7 /* arg1 = exceptionclass */
bl 0f
lwz xpc,11*4(r1)
lwz itmp3,12*4(r1)
mtlr itmp3
- lwz r7,13*4(r1)
- addi r1,r1,16*4
L_class_linked:
+_crit_restart1:
+ lwz r7,13*4(r1)
+_crit_begin1:
lwz r6,offobjvftbl(xptr) /* r6 = vftblptr(xptr) */
lwz r7,offclassvftbl(r7) /* r7 = vftblptr(catchtype) class (not obj) */
lwz r6,offbaseval(r6) /* r6 = baseval(xptr) */
lwz r8,offbaseval(r7) /* r8 = baseval(catchtype) */
lwz r7,offdiffval(r7) /* r7 = diffval(catchtype) */
+_crit_end1:
subf r6,r8,r6 /* r6 = baseval(xptr) - baseval(catchtype) */
cmplw r6,r7 /* xptr is instanceof catchtype */
+ addi r1,r1,16*4
bgt ex_table_cont /* if (false) continue */
ex_handle_it:
blr
L_initializererror:
+0:
#if defined(USE_THREADS) && defined(NATIVE_THREADS)
-#error XXX TWISTI please check me for correctness
mflr r0
stw r0,8(r1)
addi r1,r1,-4*8 /* preserve linkage area (24 bytes) */
mtlr r0
addi r1,r1,4*8
#else
- lwz itmp2,lo16(_exceptionptr-0b)(pv)
- lwz xptr,0(itmp2) /* get the exception pointer */
- li r0,0
- stw r0,0(itmp2) /* clear the exception pointer */
+ lwz r3,lo16(_exceptionptr-0b)(pv)
#endif
+ lwz xptr,0(r3) /* get the exception pointer */
+ li r0,0
+ stw r0,0(r3) /* clear the exception pointer */
mflr xpc
b _asm_handle_nat_exception
blr
-#define C_RED_ZONE 224
-
-_asm_sighandler:
- addi r1,r1,-32*4 - 32 - C_RED_ZONE
- stmw r0,32(r1)
- mflr r0
- stw r0,28(r1)
-
- bl 0f
-0:
- mflr r31
- lwz r0,lo16(catch_Handler-0b)(r31)
- mtctr r0
- addi r3,r1,32
- bctrl
-
- lwz r0,28(r1)
- mtlr r0
- cmpwi r3,0
- bne 1f
- lmw r2,32+8(r1)
- lwz r0,32(r1)
- addi r1,r1,32*4 + 32 + C_RED_ZONE
- b _asm_handle_exception
+_asm_getclassvalues_atomic:
+_crit_restart2:
+_crit_begin2:
+ lwz r6,offbaseval(r3)
+ lwz r7,offdiffval(r3)
+ lwz r8,offbaseval(r4)
+_crit_end2:
+ stw r6,offcast_super_baseval(r5)
+ stw r7,offcast_super_diffval(r5)
+ stw r8,offcast_sub_baseval(r5)
+ blr
-1:
- mtctr r3
- lmw r2,32+8(r1)
- lwz r0,32(r1)
- addi r1,r1,32*4 + 32 + C_RED_ZONE
- bctr
+ .data
+_asm_criticalsections:
+#if defined(USE_THREADS) && defined(NATIVE_THREADS)
+ .long _crit_begin1
+ .long _crit_end1
+ .long _crit_restart1
+ .long _crit_begin2
+ .long _crit_end2
+ .long _crit_restart2
+#endif
+ .long 0
/*
* These are local overrides for various environment variables in Emacs.
Authors: Andreas Krall
Stefan Ring
- $Id: codegen.c 1059 2004-05-16 13:16:15Z twisti $
+ $Id: codegen.c 1073 2004-05-19 23:21:15Z stefan $
*/
-
+#include "global.h"
#include <stdio.h>
#include <signal.h>
#include "types.h"
//#include <architecture/ppc/cframe.h>
-/* NullPointerException signal handler for hardware null pointer check */
-
-void asm_sighandler();
-
-int lastsig;
-int crashpc;
+#if defined(USE_THREADS) && defined(NATIVE_THREADS)
+void thread_restartcriticalsection(void *u)
+{
+}
+#endif
-int catch_Handler(int *regs)
+int cacao_catch_Handler(mach_port_t thread)
{
- sigset_t nsig;
- int instr, reg;
+ unsigned int *regs;
+ unsigned int crashpc;
+ s4 instr, reg;
java_objectheader *xptr;
- instr = *(int *) crashpc;
+ /* Mach stuff */
+ thread_state_flavor_t flavor = PPC_THREAD_STATE;
+ mach_msg_type_number_t thread_state_count = PPC_THREAD_STATE_COUNT;
+ ppc_thread_state_t thread_state;
+ kern_return_t r;
+
+ r = thread_get_state(thread, flavor,
+ (natural_t*)&thread_state, &thread_state_count);
+ if (r != KERN_SUCCESS)
+ panic("thread_get_state failed");
+
+ regs = &thread_state.r0;
+ crashpc = thread_state.srr0;
+
+ instr = *(s4*) crashpc;
reg = (instr >> 16) & 31;
if (!regs[reg]) {
- sigemptyset(&nsig);
- sigaddset(&nsig, lastsig);
- sigprocmask(SIG_UNBLOCK, &nsig, NULL); /* unblock signal */
-
xptr = new_exception(string_java_lang_NullPointerException);
regs[REG_ITMP2_XPC] = crashpc;
regs[REG_ITMP1_XPTR] = (u4) xptr;
- return 0;
+ r = thread_set_state(thread, flavor,
+ (natural_t*)&thread_state, thread_state_count);
+ if (r != KERN_SUCCESS)
+ panic("thread_set_state failed");
+
+ return 1;
}
panic("segfault");
-
return 0;
}
-void catch_NullPointerException(int sig, void *code, struct sigcontext *ctx)
-{
- int oldsp = ctx->sc_sp;
-
- lastsig = sig;
- crashpc = ctx->sc_ir;
- ctx->sc_ir = (s4) asm_sighandler;
-}
-
-
void init_exceptions(void)
{
- /* install signal handlers we need to convert to exceptions */
-
- if (!checknull) {
-#if defined(SIGSEGV)
- signal(SIGSEGV, (void*) catch_NullPointerException);
-#endif
-
-#if defined(SIGBUS)
- signal(SIGBUS, (void*) catch_NullPointerException);
-#endif
- }
}
void adjust_argvars(stackptr s, int d, int *fa, int *ia)
*ia += (IS_2_WORD_TYPE(s->type)) ? 2 : 1;
}
-void nocode()
-{
- printf("NOCODE\n");
-}
-
-
#define intmaxf(a,b) (((a)<(b)) ? (b) : (a))
s4 dblargs = 0;
M_MFLR(REG_ITMP3);
+ /* XXX must be a multiple of 16 */
M_LDA(REG_SP, REG_SP, -(24 + (INT_ARG_CNT + FLT_ARG_CNT + 1) * 8));
M_IST(REG_ITMP3, REG_SP, 24 + (INT_ARG_CNT + FLT_ARG_CNT) * 8);
{
classinfo *super = (classinfo*) iptr->val.a;
+#if defined(USE_THREADS) && defined(NATIVE_THREADS)
+ codegen_threadcritrestart((u1*) mcodeptr - mcodebase);
+#endif
var_to_reg_int(s1, src, REG_ITMP1);
d = reg_of_var(iptr->dst, REG_ITMP3);
if (s1 == d) {
M_ALD(REG_ITMP1, s1, OFFSET(java_objectheader, vftbl));
a = dseg_addaddress ((void*) super->vftbl);
M_ALD(REG_ITMP2, REG_PV, a);
+#if defined(USE_THREADS) && defined(NATIVE_THREADS)
+ codegen_threadcritstart((u1*) mcodeptr - mcodebase);
+#endif
M_ILD(REG_ITMP1, REG_ITMP1, OFFSET(vftbl, baseval));
M_ILD(REG_ITMP3, REG_ITMP2, OFFSET(vftbl, baseval));
M_ILD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl, diffval));
+#if defined(USE_THREADS) && defined(NATIVE_THREADS)
+ codegen_threadcritstop((u1*) mcodeptr - mcodebase);
+#endif
M_ISUB(REG_ITMP1, REG_ITMP3, REG_ITMP1);
M_CMPU(REG_ITMP1, REG_ITMP2);
M_CLR(d);
{
classinfo *super = (classinfo*) iptr->val.a;
+#if defined(USE_THREADS) && defined(NATIVE_THREADS)
+ codegen_threadcritrestart((u1*) mcodeptr - mcodebase);
+#endif
d = reg_of_var(iptr->dst, REG_ITMP1);
var_to_reg_int(s1, src, d);
if (iptr->op1) { /* class/interface */
else { /* class */
M_BEQ(8 + (s1 == REG_ITMP1));
M_ALD(REG_ITMP2, s1, OFFSET(java_objectheader, vftbl));
+#if defined(USE_THREADS) && defined(NATIVE_THREADS)
+ codegen_threadcritstart((u1*) mcodeptr - mcodebase);
+#endif
M_ILD(REG_ITMP3, REG_ITMP2, OFFSET(vftbl, baseval));
a = dseg_addaddress ((void*) super->vftbl);
M_ALD(REG_ITMP2, REG_PV, a);
if (d != REG_ITMP1) {
M_ILD(REG_ITMP1, REG_ITMP2, OFFSET(vftbl, baseval));
M_ILD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl, diffval));
+#if defined(USE_THREADS) && defined(NATIVE_THREADS)
+ codegen_threadcritstop((u1*) mcodeptr - mcodebase);
+#endif
M_ISUB(REG_ITMP3, REG_ITMP1, REG_ITMP3);
}
else {
M_ISUB(REG_ITMP3, REG_ITMP2, REG_ITMP3);
M_ALD(REG_ITMP2, REG_PV, a);
M_ILD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl, diffval));
+#if defined(USE_THREADS) && defined(NATIVE_THREADS)
+ codegen_threadcritstop((u1*) mcodeptr - mcodebase);
+#endif
}
M_CMPU(REG_ITMP3, REG_ITMP2);
M_BGT(0);
} else {
xcodeptr = mcodeptr;
+ /* XXX this cannot work - there is no link area */
M_IADD_IMM(REG_SP, -1 * 8, REG_SP);
M_IST(REG_ITMP2_XPC, REG_SP, 0 * 8);
mcodeptr = cs;
*(cs-1) = (u4) f; /* address of native method */
+#if defined(USE_THREADS) && defined(NATIVE_THREADS)
+ *(cs-2) = (u4) builtin_get_exceptionptrptr;
+#else
*(cs-2) = (u4) (&_exceptionptr); /* address of exceptionptr */
+#endif
*(cs-3) = (u4) asm_handle_nat_exception; /* addr of asm exception handler */
*(cs-4) = (u4) (&env); /* addr of jni_environement */
*(cs-5) = (u4) builtin_trace_args;
s4 dblargs = 0;
/* M_MFLR(REG_ITMP3); */
+ /* XXX must be a multiple of 16 */
M_LDA(REG_SP, REG_SP, -(24 + (INT_ARG_CNT + FLT_ARG_CNT + 1) * 8));
/* M_IST(REG_ITMP3, REG_SP, 24 + (INT_ARG_CNT + FLT_ARG_CNT) * 8); */
M_MTLR(REG_ITMP3);
}
+#if defined(USE_THREADS) && defined(NATIVE_THREADS)
+ if (IS_FLT_DBL_TYPE(m->returntype))
+ if (IS_2_WORD_TYPE(m->returntype))
+ M_DST(REG_FRESULT, REG_SP, 56);
+ else
+ M_FST(REG_FRESULT, REG_SP, 56);
+ else {
+ M_IST(REG_RESULT, REG_SP, 56);
+ if (IS_2_WORD_TYPE(m->returntype))
+ M_IST(REG_RESULT2, REG_SP, 60);
+ }
+
+ M_ALD(REG_ITMP2, REG_PV, -2 * 4); /* builtin_get_exceptionptrptr */
+ M_MTCTR(REG_ITMP2);
+ M_JSR;
+ disp = -(s4) (mcodeptr - (s4 *) cs) * 4;
+ M_MFLR(REG_ITMP1);
+ M_LDA(REG_PV, REG_ITMP1, disp);
+ M_MOV(REG_RESULT, REG_ITMP2);
+
+ if (IS_FLT_DBL_TYPE(m->returntype))
+ if (IS_2_WORD_TYPE(m->returntype))
+ M_DLD(REG_FRESULT, REG_SP, 56);
+ else
+ M_FLD(REG_FRESULT, REG_SP, 56);
+ else {
+ M_ILD(REG_RESULT, REG_SP, 56);
+ if (IS_2_WORD_TYPE(m->returntype))
+ M_ILD(REG_RESULT2, REG_SP, 60);
+ }
+#else
M_ALD(REG_ITMP2, REG_PV, -2 * 4); /* get address of exceptionptr */
+#endif
M_ALD(REG_ITMP1, REG_ITMP2, 0); /* load exception into reg. itmp1 */
M_TST(REG_ITMP1);
M_BNE(4); /* if no exception then return */
--- /dev/null
+#ifndef _MACHINE_INSTR_H
+#define _MACHINE_INSTR_H
+
+static inline long
+atomic_swap (volatile long *p, long val)
+{
+ long int result;
+ __asm__ __volatile__ ("\n\
+0: lwarx %0,0,%1 \n\
+ stwcx. %2,0,%1 \n\
+ bne- 0b \n\
+" : "=&r"(result) : "r"(p), "r"(val) : "cr0", "memory");
+ return result;
+}
+
+static inline int
+compare_and_swap (volatile long *p, long oldval, long newval)
+{
+ int result;
+ __asm__ __volatile__ ("\n\
+0: lwarx %0,0,%1 \n\
+ sub%I2c. %0,%0,%2 \n\
+ cntlzw %0,%0 \n\
+ bne- 1f \n\
+ stwcx. %3,0,%1 \n\
+ bne- 0b \n\
+1: \n\
+" : "=&b"(result) : "r"(p), "Ir"(oldval), "r"(newval) : "cr0", "memory");
+ return result >> 5;
+}
+
+#endif
#else /* BROKEN_EXCEPTION_HANDLING */
/* Pass it along to the next exception handler
(which should call SIGBUS/SIGSEGV) */
- return FWD();
+ if (cacao_catch_Handler(thread))
+ return KERN_SUCCESS;
+ return FWD();
#endif /* !BROKEN_EXCEPTION_HANDLING */
}
#else /* BROKEN_EXCEPTION_HANDLING */
/* Pass it along to the next exception handler
(which should call SIGBUS/SIGSEGV) */
- return FWD();
+ if (cacao_catch_Handler(thread))
+ return KERN_SUCCESS;
+ return FWD();
#endif /* !BROKEN_EXCEPTION_HANDLING */
}
Changes: Mark Probst
Philipp Tomsich
- $Id: headers.c 1070 2004-05-19 16:32:18Z stefan $
+ $Id: headers.c 1073 2004-05-19 23:21:15Z stefan $
*/
void asm_handle_builtin_exception(classinfo *c) {}
void asm_getclassvalues_atomic() {}
+#if defined(__DARWIN__)
+int cacao_catch_Handler() {}
+#endif
+
#if defined(USE_THREADS) && defined(NATIVE_THREADS)
threadcritnode asm_criticalsections;
#endif
#include "../mm/boehm-gc/include/gc.h"
#endif
+#ifdef MUTEXSIM
+
+typedef struct {
+ pthread_mutex_t mutex;
+ pthread_t owner;
+ int count;
+} pthread_mutex_rec_t;
+
+static void pthread_mutex_init_rec(pthread_mutex_rec_t *m)
+{
+ pthread_mutex_init(&m->mutex, NULL);
+ m->count = 0;
+}
+
+static void pthread_mutex_destroy_rec(pthread_mutex_rec_t *m)
+{
+ pthread_mutex_destroy(&m->mutex);
+}
+
+static void pthread_mutex_lock_rec(pthread_mutex_rec_t *m)
+{
+ for (;;)
+ if (!m->count)
+ {
+ pthread_mutex_lock(&m->mutex);
+ m->owner = pthread_self();
+ m->count++;
+ break;
+ } else {
+ if (m->owner != pthread_self())
+ pthread_mutex_lock(&m->mutex);
+ else
+ {
+ m->count++;
+ break;
+ }
+ }
+}
+
+static void pthread_mutex_unlock_rec(pthread_mutex_rec_t *m)
+{
+ if (!--m->count)
+ pthread_mutex_unlock(&m->mutex);
+}
+
+#else /* MUTEXSIM */
+
+#define pthread_mutex_lock_rec pthread_mutex_lock
+#define pthread_mutex_unlock_rec pthread_mutex_unlock
+#define pthread_mutex_rec_t pthread_mutex_t
+
+#endif /* MUTEXSIM */
+
#include "machine-instr.h"
static struct avl_table *criticaltree;
__thread threadobject *threadobj;
#endif
-static pthread_mutex_t cast_mutex = PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP;
-static pthread_mutex_t compiler_mutex = PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP;
-static pthread_mutex_t tablelock = PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP;
-
-void cast_lock()
-{
- pthread_mutex_lock(&cast_mutex);
-}
-
-void cast_unlock()
-{
- pthread_mutex_unlock(&cast_mutex);
-}
+static pthread_mutex_rec_t compiler_mutex;
+static pthread_mutex_rec_t tablelock;
void compiler_lock()
{
- pthread_mutex_lock(&compiler_mutex);
+ pthread_mutex_lock_rec(&compiler_mutex);
}
void compiler_unlock()
{
- pthread_mutex_unlock(&compiler_mutex);
+ pthread_mutex_unlock_rec(&compiler_mutex);
}
void tables_lock()
{
- pthread_mutex_lock(&tablelock);
+ pthread_mutex_lock_rec(&tablelock);
}
void tables_unlock()
{
- pthread_mutex_unlock(&tablelock);
+ pthread_mutex_unlock_rec(&tablelock);
}
static int criticalcompare(const void *pa, const void *pb, void *param)
thread_registercritical(n++);
}
-static pthread_mutex_t threadlistlock = PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP;
+static pthread_mutex_t threadlistlock;
-static pthread_mutex_t stopworldlock = PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP;
+static pthread_mutex_t stopworldlock;
volatile int stopworldwhere;
static sem_t suspend_ack;
pthread_mutex_unlock(&stopworldlock);
}
+#if !defined(__DARWIN__)
/* Caller must hold threadlistlock */
static int cast_sendsignals(int sig, int count)
{
return count-1;
}
+#endif
void cast_stopworld()
{
int count, i;
lock_stopworld(2);
pthread_mutex_lock(&threadlistlock);
+#if defined(__DARWIN__)
+ /* XXX stop threads using mach functions */
+#else
count = cast_sendsignals(GC_signum1(), 0);
for (i=0; i<count; i++)
sem_wait(&suspend_ack);
+#endif
pthread_mutex_unlock(&threadlistlock);
}
void cast_startworld()
{
pthread_mutex_lock(&threadlistlock);
+#if defined(__DARWIN__)
+ /* XXX resume threads using mach functions */
+#else
cast_sendsignals(GC_signum2(), -1);
+#endif
pthread_mutex_unlock(&threadlistlock);
unlock_stopworld();
}
+#if !defined(__DARWIN__)
static void sigsuspend_handler(ucontext_t *ctx)
{
int sig;
sigsuspend_handler(ctx);
return 1;
}
+#endif
static void setthreadobject(threadobject *thread)
{
void
initThreadsEarly()
{
+#ifndef MUTEXSIM
+ pthread_mutexattr_t mutexattr;
+ pthread_mutexattr_init(&mutexattr);
+ pthread_mutexattr_settype(&mutexattr, PTHREAD_MUTEX_RECURSIVE);
+ pthread_mutex_init(&compiler_mutex, &mutexattr);
+ pthread_mutex_init(&tablelock, &mutexattr);
+ pthread_mutexattr_destroy(&mutexattr);
+#else
+ pthread_mutex_init_rec(&compiler_mutex);
+ pthread_mutex_init_rec(&tablelock);
+#endif
+
+ pthread_mutex_init(&threadlistlock, NULL);
+ pthread_mutex_init(&stopworldlock, NULL);
+
/* Allocate something so the garbage collector's signal handlers are */
/* installed. */
heap_allocate(1, false, NULL);
static void *threadstartup(void *t)
{
startupinfo *startup = t;
- t = NULL;
threadobject *thread = startup->thread;
sem_t *psem = startup->psem;
nativethread *info = &thread->info;
threadobject *tnext;
methodinfo *method;
+ t = NULL;
+#if defined(__DARWIN__)
+ info->mach_thread = mach_thread_self();
+#endif
setthreadobject(thread);
pthread_mutex_lock(&threadlistlock);
#include "nat/java_lang_Throwable.h"
#include "nat/java_lang_Thread.h"
+#if defined(__DARWIN__)
+#include <mach/mach.h>
+
+/* We need to emulate recursive mutexes. */
+#define MUTEXSIM
+#endif
+
struct _threadobject;
typedef struct monitorLockRecord {
methodinfo *_threadrootmethod;
void *_stackframeinfo;
pthread_t tid;
+#if defined(__DARWIN__)
+ mach_port_t mach_thread;
+#endif
pthread_mutex_t joinMutex;
pthread_cond_t joinCond;
} nativethread;
Authors: Reinhard Grafl
- $Id: logging.h 1067 2004-05-18 10:25:51Z stefan $
+ $Id: logging.h 1073 2004-05-19 23:21:15Z stefan $
*/
#include <stdio.h>
+/* This is to bring in the conflicting panic from darwin */
+#include <sys/mman.h>
+#define panic cacao_panic
#define PANICIF(when,txt) if(when)panic(txt)
## Process this file with automake to produce Makefile.in
-# $Id: Makefile.am 568 2003-11-06 14:42:16Z twisti $
+# $Id: Makefile.am 1073 2004-05-19 23:21:15Z stefan $
INCLUDES = -I$(top_srcdir)/jit
disass.c \
disass.h \
native-math.h \
+ machine-instr.h \
ppc-dis.c \
ppc-opc.c
ppc.h \
Authors: Andreas Krall
Reinhard Grafl
- $Id: asmpart.S 1059 2004-05-16 13:16:15Z twisti $
+ $Id: asmpart.S 1073 2004-05-19 23:21:15Z stefan $
*/
-
+#include "config.h"
#include "offsets.h"
.globl _asm_initialize_thread_stack
.globl _asm_perform_threadswitch
.globl _asm_switchstackandcall
+ .globl _asm_criticalsections
+ .globl _asm_getclassvalues_atomic
.globl _string_java_lang_NullPointerException
.globl _string_java_lang_ArrayIndexOutOfBoundsException
.globl _string_java_lang_ClassCastException
.globl _builtin_asm_get_exceptionptrptr
+#if !defined(USE_THREADS) || !defined(NATIVE_THREADS)
.globl __exceptionptr
+#endif
.globl _builtin_throw_exception
.globl _class_load
.globl _class_link
.globl _class_init
- .globl _catch_Handler
.globl _new_exception
.globl _new_exception_message
.globl _new_exception_int
- .globl _asm_sighandler
-
jitcompile:
.long _jit_compile
builtin_asm_get_exceptionptrptr:
.long _builtin_asm_get_exceptionptrptr
+#if !defined(USE_THREADS) || !defined(NATIVE_THREADS)
_exceptionptr:
.long __exceptionptr
-
-catch_Handler:
- .long _catch_Handler
+#endif
#define MethodPointer -8
L_class_loaded:
lwz itmp3,offclasslinked(r7)
mr. itmp3,itmp3
+ addi r1,r1,-16*4 /* allocate stack */
+ stw r7,13*4(r1)
bne L_class_linked
- addi r1,r1,-16*4 /* allocate stack */
stw r3,7*4(r1) /* save used registers */
stw r4,8*4(r1) /* 6*4 (linkage) + 1*4 (arg1) + 7*4 (save) */
stw r2,9*4(r1)
stw xpc,11*4(r1)
mflr xptr
stw xptr,12*4(r1)
- stw r7,13*4(r1)
mr r3,r7 /* arg1 = exceptionclass */
bl 0f
lwz xpc,11*4(r1)
lwz itmp3,12*4(r1)
mtlr itmp3
- lwz r7,13*4(r1)
- addi r1,r1,16*4
L_class_linked:
+_crit_restart1:
+ lwz r7,13*4(r1)
+_crit_begin1:
lwz r6,offobjvftbl(xptr) /* r6 = vftblptr(xptr) */
lwz r7,offclassvftbl(r7) /* r7 = vftblptr(catchtype) class (not obj) */
lwz r6,offbaseval(r6) /* r6 = baseval(xptr) */
lwz r8,offbaseval(r7) /* r8 = baseval(catchtype) */
lwz r7,offdiffval(r7) /* r7 = diffval(catchtype) */
+_crit_end1:
subf r6,r8,r6 /* r6 = baseval(xptr) - baseval(catchtype) */
cmplw r6,r7 /* xptr is instanceof catchtype */
+ addi r1,r1,16*4
bgt ex_table_cont /* if (false) continue */
ex_handle_it:
blr
L_initializererror:
+0:
#if defined(USE_THREADS) && defined(NATIVE_THREADS)
-#error XXX TWISTI please check me for correctness
mflr r0
stw r0,8(r1)
addi r1,r1,-4*8 /* preserve linkage area (24 bytes) */
mtlr r0
addi r1,r1,4*8
#else
- lwz itmp2,lo16(_exceptionptr-0b)(pv)
- lwz xptr,0(itmp2) /* get the exception pointer */
- li r0,0
- stw r0,0(itmp2) /* clear the exception pointer */
+ lwz r3,lo16(_exceptionptr-0b)(pv)
#endif
+ lwz xptr,0(r3) /* get the exception pointer */
+ li r0,0
+ stw r0,0(r3) /* clear the exception pointer */
mflr xpc
b _asm_handle_nat_exception
blr
-#define C_RED_ZONE 224
-
-_asm_sighandler:
- addi r1,r1,-32*4 - 32 - C_RED_ZONE
- stmw r0,32(r1)
- mflr r0
- stw r0,28(r1)
-
- bl 0f
-0:
- mflr r31
- lwz r0,lo16(catch_Handler-0b)(r31)
- mtctr r0
- addi r3,r1,32
- bctrl
-
- lwz r0,28(r1)
- mtlr r0
- cmpwi r3,0
- bne 1f
- lmw r2,32+8(r1)
- lwz r0,32(r1)
- addi r1,r1,32*4 + 32 + C_RED_ZONE
- b _asm_handle_exception
+_asm_getclassvalues_atomic:
+_crit_restart2:
+_crit_begin2:
+ lwz r6,offbaseval(r3)
+ lwz r7,offdiffval(r3)
+ lwz r8,offbaseval(r4)
+_crit_end2:
+ stw r6,offcast_super_baseval(r5)
+ stw r7,offcast_super_diffval(r5)
+ stw r8,offcast_sub_baseval(r5)
+ blr
-1:
- mtctr r3
- lmw r2,32+8(r1)
- lwz r0,32(r1)
- addi r1,r1,32*4 + 32 + C_RED_ZONE
- bctr
+ .data
+_asm_criticalsections:
+#if defined(USE_THREADS) && defined(NATIVE_THREADS)
+ .long _crit_begin1
+ .long _crit_end1
+ .long _crit_restart1
+ .long _crit_begin2
+ .long _crit_end2
+ .long _crit_restart2
+#endif
+ .long 0
/*
* These are local overrides for various environment variables in Emacs.
Authors: Andreas Krall
Stefan Ring
- $Id: codegen.c 1059 2004-05-16 13:16:15Z twisti $
+ $Id: codegen.c 1073 2004-05-19 23:21:15Z stefan $
*/
-
+#include "global.h"
#include <stdio.h>
#include <signal.h>
#include "types.h"
//#include <architecture/ppc/cframe.h>
-/* NullPointerException signal handler for hardware null pointer check */
-
-void asm_sighandler();
-
-int lastsig;
-int crashpc;
+#if defined(USE_THREADS) && defined(NATIVE_THREADS)
+void thread_restartcriticalsection(void *u)
+{
+}
+#endif
-int catch_Handler(int *regs)
+int cacao_catch_Handler(mach_port_t thread)
{
- sigset_t nsig;
- int instr, reg;
+ unsigned int *regs;
+ unsigned int crashpc;
+ s4 instr, reg;
java_objectheader *xptr;
- instr = *(int *) crashpc;
+ /* Mach stuff */
+ thread_state_flavor_t flavor = PPC_THREAD_STATE;
+ mach_msg_type_number_t thread_state_count = PPC_THREAD_STATE_COUNT;
+ ppc_thread_state_t thread_state;
+ kern_return_t r;
+
+ r = thread_get_state(thread, flavor,
+ (natural_t*)&thread_state, &thread_state_count);
+ if (r != KERN_SUCCESS)
+ panic("thread_get_state failed");
+
+ regs = &thread_state.r0;
+ crashpc = thread_state.srr0;
+
+ instr = *(s4*) crashpc;
reg = (instr >> 16) & 31;
if (!regs[reg]) {
- sigemptyset(&nsig);
- sigaddset(&nsig, lastsig);
- sigprocmask(SIG_UNBLOCK, &nsig, NULL); /* unblock signal */
-
xptr = new_exception(string_java_lang_NullPointerException);
regs[REG_ITMP2_XPC] = crashpc;
regs[REG_ITMP1_XPTR] = (u4) xptr;
- return 0;
+ r = thread_set_state(thread, flavor,
+ (natural_t*)&thread_state, thread_state_count);
+ if (r != KERN_SUCCESS)
+ panic("thread_set_state failed");
+
+ return 1;
}
panic("segfault");
-
return 0;
}
-void catch_NullPointerException(int sig, void *code, struct sigcontext *ctx)
-{
- int oldsp = ctx->sc_sp;
-
- lastsig = sig;
- crashpc = ctx->sc_ir;
- ctx->sc_ir = (s4) asm_sighandler;
-}
-
-
void init_exceptions(void)
{
- /* install signal handlers we need to convert to exceptions */
-
- if (!checknull) {
-#if defined(SIGSEGV)
- signal(SIGSEGV, (void*) catch_NullPointerException);
-#endif
-
-#if defined(SIGBUS)
- signal(SIGBUS, (void*) catch_NullPointerException);
-#endif
- }
}
void adjust_argvars(stackptr s, int d, int *fa, int *ia)
*ia += (IS_2_WORD_TYPE(s->type)) ? 2 : 1;
}
-void nocode()
-{
- printf("NOCODE\n");
-}
-
-
#define intmaxf(a,b) (((a)<(b)) ? (b) : (a))
s4 dblargs = 0;
M_MFLR(REG_ITMP3);
+ /* XXX must be a multiple of 16 */
M_LDA(REG_SP, REG_SP, -(24 + (INT_ARG_CNT + FLT_ARG_CNT + 1) * 8));
M_IST(REG_ITMP3, REG_SP, 24 + (INT_ARG_CNT + FLT_ARG_CNT) * 8);
{
classinfo *super = (classinfo*) iptr->val.a;
+#if defined(USE_THREADS) && defined(NATIVE_THREADS)
+ codegen_threadcritrestart((u1*) mcodeptr - mcodebase);
+#endif
var_to_reg_int(s1, src, REG_ITMP1);
d = reg_of_var(iptr->dst, REG_ITMP3);
if (s1 == d) {
M_ALD(REG_ITMP1, s1, OFFSET(java_objectheader, vftbl));
a = dseg_addaddress ((void*) super->vftbl);
M_ALD(REG_ITMP2, REG_PV, a);
+#if defined(USE_THREADS) && defined(NATIVE_THREADS)
+ codegen_threadcritstart((u1*) mcodeptr - mcodebase);
+#endif
M_ILD(REG_ITMP1, REG_ITMP1, OFFSET(vftbl, baseval));
M_ILD(REG_ITMP3, REG_ITMP2, OFFSET(vftbl, baseval));
M_ILD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl, diffval));
+#if defined(USE_THREADS) && defined(NATIVE_THREADS)
+ codegen_threadcritstop((u1*) mcodeptr - mcodebase);
+#endif
M_ISUB(REG_ITMP1, REG_ITMP3, REG_ITMP1);
M_CMPU(REG_ITMP1, REG_ITMP2);
M_CLR(d);
{
classinfo *super = (classinfo*) iptr->val.a;
+#if defined(USE_THREADS) && defined(NATIVE_THREADS)
+ codegen_threadcritrestart((u1*) mcodeptr - mcodebase);
+#endif
d = reg_of_var(iptr->dst, REG_ITMP1);
var_to_reg_int(s1, src, d);
if (iptr->op1) { /* class/interface */
else { /* class */
M_BEQ(8 + (s1 == REG_ITMP1));
M_ALD(REG_ITMP2, s1, OFFSET(java_objectheader, vftbl));
+#if defined(USE_THREADS) && defined(NATIVE_THREADS)
+ codegen_threadcritstart((u1*) mcodeptr - mcodebase);
+#endif
M_ILD(REG_ITMP3, REG_ITMP2, OFFSET(vftbl, baseval));
a = dseg_addaddress ((void*) super->vftbl);
M_ALD(REG_ITMP2, REG_PV, a);
if (d != REG_ITMP1) {
M_ILD(REG_ITMP1, REG_ITMP2, OFFSET(vftbl, baseval));
M_ILD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl, diffval));
+#if defined(USE_THREADS) && defined(NATIVE_THREADS)
+ codegen_threadcritstop((u1*) mcodeptr - mcodebase);
+#endif
M_ISUB(REG_ITMP3, REG_ITMP1, REG_ITMP3);
}
else {
M_ISUB(REG_ITMP3, REG_ITMP2, REG_ITMP3);
M_ALD(REG_ITMP2, REG_PV, a);
M_ILD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl, diffval));
+#if defined(USE_THREADS) && defined(NATIVE_THREADS)
+ codegen_threadcritstop((u1*) mcodeptr - mcodebase);
+#endif
}
M_CMPU(REG_ITMP3, REG_ITMP2);
M_BGT(0);
} else {
xcodeptr = mcodeptr;
+ /* XXX this cannot work - there is no link area */
M_IADD_IMM(REG_SP, -1 * 8, REG_SP);
M_IST(REG_ITMP2_XPC, REG_SP, 0 * 8);
mcodeptr = cs;
*(cs-1) = (u4) f; /* address of native method */
+#if defined(USE_THREADS) && defined(NATIVE_THREADS)
+ *(cs-2) = (u4) builtin_get_exceptionptrptr;
+#else
*(cs-2) = (u4) (&_exceptionptr); /* address of exceptionptr */
+#endif
*(cs-3) = (u4) asm_handle_nat_exception; /* addr of asm exception handler */
*(cs-4) = (u4) (&env); /* addr of jni_environement */
*(cs-5) = (u4) builtin_trace_args;
s4 dblargs = 0;
/* M_MFLR(REG_ITMP3); */
+ /* XXX must be a multiple of 16 */
M_LDA(REG_SP, REG_SP, -(24 + (INT_ARG_CNT + FLT_ARG_CNT + 1) * 8));
/* M_IST(REG_ITMP3, REG_SP, 24 + (INT_ARG_CNT + FLT_ARG_CNT) * 8); */
M_MTLR(REG_ITMP3);
}
+#if defined(USE_THREADS) && defined(NATIVE_THREADS)
+ if (IS_FLT_DBL_TYPE(m->returntype))
+ if (IS_2_WORD_TYPE(m->returntype))
+ M_DST(REG_FRESULT, REG_SP, 56);
+ else
+ M_FST(REG_FRESULT, REG_SP, 56);
+ else {
+ M_IST(REG_RESULT, REG_SP, 56);
+ if (IS_2_WORD_TYPE(m->returntype))
+ M_IST(REG_RESULT2, REG_SP, 60);
+ }
+
+ M_ALD(REG_ITMP2, REG_PV, -2 * 4); /* builtin_get_exceptionptrptr */
+ M_MTCTR(REG_ITMP2);
+ M_JSR;
+ disp = -(s4) (mcodeptr - (s4 *) cs) * 4;
+ M_MFLR(REG_ITMP1);
+ M_LDA(REG_PV, REG_ITMP1, disp);
+ M_MOV(REG_RESULT, REG_ITMP2);
+
+ if (IS_FLT_DBL_TYPE(m->returntype))
+ if (IS_2_WORD_TYPE(m->returntype))
+ M_DLD(REG_FRESULT, REG_SP, 56);
+ else
+ M_FLD(REG_FRESULT, REG_SP, 56);
+ else {
+ M_ILD(REG_RESULT, REG_SP, 56);
+ if (IS_2_WORD_TYPE(m->returntype))
+ M_ILD(REG_RESULT2, REG_SP, 60);
+ }
+#else
M_ALD(REG_ITMP2, REG_PV, -2 * 4); /* get address of exceptionptr */
+#endif
M_ALD(REG_ITMP1, REG_ITMP2, 0); /* load exception into reg. itmp1 */
M_TST(REG_ITMP1);
M_BNE(4); /* if no exception then return */
--- /dev/null
+#ifndef _MACHINE_INSTR_H
+#define _MACHINE_INSTR_H
+
+static inline long
+atomic_swap (volatile long *p, long val)
+{
+ long int result;
+ __asm__ __volatile__ ("\n\
+0: lwarx %0,0,%1 \n\
+ stwcx. %2,0,%1 \n\
+ bne- 0b \n\
+" : "=&r"(result) : "r"(p), "r"(val) : "cr0", "memory");
+ return result;
+}
+
+static inline int
+compare_and_swap (volatile long *p, long oldval, long newval)
+{
+ int result;
+ __asm__ __volatile__ ("\n\
+0: lwarx %0,0,%1 \n\
+ sub%I2c. %0,%0,%2 \n\
+ cntlzw %0,%0 \n\
+ bne- 1f \n\
+ stwcx. %3,0,%1 \n\
+ bne- 0b \n\
+1: \n\
+" : "=&b"(result) : "r"(p), "Ir"(oldval), "r"(newval) : "cr0", "memory");
+ return result >> 5;
+}
+
+#endif
#include "../mm/boehm-gc/include/gc.h"
#endif
+#ifdef MUTEXSIM
+
+typedef struct {
+ pthread_mutex_t mutex;
+ pthread_t owner;
+ int count;
+} pthread_mutex_rec_t;
+
+static void pthread_mutex_init_rec(pthread_mutex_rec_t *m)
+{
+ pthread_mutex_init(&m->mutex, NULL);
+ m->count = 0;
+}
+
+static void pthread_mutex_destroy_rec(pthread_mutex_rec_t *m)
+{
+ pthread_mutex_destroy(&m->mutex);
+}
+
+static void pthread_mutex_lock_rec(pthread_mutex_rec_t *m)
+{
+ for (;;)
+ if (!m->count)
+ {
+ pthread_mutex_lock(&m->mutex);
+ m->owner = pthread_self();
+ m->count++;
+ break;
+ } else {
+ if (m->owner != pthread_self())
+ pthread_mutex_lock(&m->mutex);
+ else
+ {
+ m->count++;
+ break;
+ }
+ }
+}
+
+static void pthread_mutex_unlock_rec(pthread_mutex_rec_t *m)
+{
+ if (!--m->count)
+ pthread_mutex_unlock(&m->mutex);
+}
+
+#else /* MUTEXSIM */
+
+#define pthread_mutex_lock_rec pthread_mutex_lock
+#define pthread_mutex_unlock_rec pthread_mutex_unlock
+#define pthread_mutex_rec_t pthread_mutex_t
+
+#endif /* MUTEXSIM */
+
#include "machine-instr.h"
static struct avl_table *criticaltree;
__thread threadobject *threadobj;
#endif
-static pthread_mutex_t cast_mutex = PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP;
-static pthread_mutex_t compiler_mutex = PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP;
-static pthread_mutex_t tablelock = PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP;
-
-void cast_lock()
-{
- pthread_mutex_lock(&cast_mutex);
-}
-
-void cast_unlock()
-{
- pthread_mutex_unlock(&cast_mutex);
-}
+static pthread_mutex_rec_t compiler_mutex;
+static pthread_mutex_rec_t tablelock;
void compiler_lock()
{
- pthread_mutex_lock(&compiler_mutex);
+ pthread_mutex_lock_rec(&compiler_mutex);
}
void compiler_unlock()
{
- pthread_mutex_unlock(&compiler_mutex);
+ pthread_mutex_unlock_rec(&compiler_mutex);
}
void tables_lock()
{
- pthread_mutex_lock(&tablelock);
+ pthread_mutex_lock_rec(&tablelock);
}
void tables_unlock()
{
- pthread_mutex_unlock(&tablelock);
+ pthread_mutex_unlock_rec(&tablelock);
}
static int criticalcompare(const void *pa, const void *pb, void *param)
thread_registercritical(n++);
}
-static pthread_mutex_t threadlistlock = PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP;
+static pthread_mutex_t threadlistlock;
-static pthread_mutex_t stopworldlock = PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP;
+static pthread_mutex_t stopworldlock;
volatile int stopworldwhere;
static sem_t suspend_ack;
pthread_mutex_unlock(&stopworldlock);
}
+#if !defined(__DARWIN__)
/* Caller must hold threadlistlock */
static int cast_sendsignals(int sig, int count)
{
return count-1;
}
+#endif
void cast_stopworld()
{
int count, i;
lock_stopworld(2);
pthread_mutex_lock(&threadlistlock);
+#if defined(__DARWIN__)
+ /* XXX stop threads using mach functions */
+#else
count = cast_sendsignals(GC_signum1(), 0);
for (i=0; i<count; i++)
sem_wait(&suspend_ack);
+#endif
pthread_mutex_unlock(&threadlistlock);
}
void cast_startworld()
{
pthread_mutex_lock(&threadlistlock);
+#if defined(__DARWIN__)
+ /* XXX resume threads using mach functions */
+#else
cast_sendsignals(GC_signum2(), -1);
+#endif
pthread_mutex_unlock(&threadlistlock);
unlock_stopworld();
}
+#if !defined(__DARWIN__)
static void sigsuspend_handler(ucontext_t *ctx)
{
int sig;
sigsuspend_handler(ctx);
return 1;
}
+#endif
static void setthreadobject(threadobject *thread)
{
void
initThreadsEarly()
{
+#ifndef MUTEXSIM
+ pthread_mutexattr_t mutexattr;
+ pthread_mutexattr_init(&mutexattr);
+ pthread_mutexattr_settype(&mutexattr, PTHREAD_MUTEX_RECURSIVE);
+ pthread_mutex_init(&compiler_mutex, &mutexattr);
+ pthread_mutex_init(&tablelock, &mutexattr);
+ pthread_mutexattr_destroy(&mutexattr);
+#else
+ pthread_mutex_init_rec(&compiler_mutex);
+ pthread_mutex_init_rec(&tablelock);
+#endif
+
+ pthread_mutex_init(&threadlistlock, NULL);
+ pthread_mutex_init(&stopworldlock, NULL);
+
/* Allocate something so the garbage collector's signal handlers are */
/* installed. */
heap_allocate(1, false, NULL);
static void *threadstartup(void *t)
{
startupinfo *startup = t;
- t = NULL;
threadobject *thread = startup->thread;
sem_t *psem = startup->psem;
nativethread *info = &thread->info;
threadobject *tnext;
methodinfo *method;
+ t = NULL;
+#if defined(__DARWIN__)
+ info->mach_thread = mach_thread_self();
+#endif
setthreadobject(thread);
pthread_mutex_lock(&threadlistlock);
#include "nat/java_lang_Throwable.h"
#include "nat/java_lang_Thread.h"
+#if defined(__DARWIN__)
+#include <mach/mach.h>
+
+/* We need to emulate recursive mutexes. */
+#define MUTEXSIM
+#endif
+
struct _threadobject;
typedef struct monitorLockRecord {
methodinfo *_threadrootmethod;
void *_stackframeinfo;
pthread_t tid;
+#if defined(__DARWIN__)
+ mach_port_t mach_thread;
+#endif
pthread_mutex_t joinMutex;
pthread_cond_t joinCond;
} nativethread;
Authors: Reinhard Grafl
- $Id: logging.h 1067 2004-05-18 10:25:51Z stefan $
+ $Id: logging.h 1073 2004-05-19 23:21:15Z stefan $
*/
#include <stdio.h>
+/* This is to bring in the conflicting panic from darwin */
+#include <sys/mman.h>
+#define panic cacao_panic
#define PANICIF(when,txt) if(when)panic(txt)