$OpenBSD$
--- src/threads/native/threads.c.orig	Mon Feb 13 18:14:32 2006
+++ src/threads/native/threads.c	Sun Apr 30 23:30:40 2006
@@ -45,6 +45,34 @@
 #include <errno.h>
 
 #include <pthread.h>
+
+
+#ifdef __OPENBSD__
+
+#define GC_THREADS
+#include <boehm-gc/include/gc.h>
+
+#if 0
+/* boehm-gc/include/gc.h defined this but it is not included here */
+/* there may be some really different semantics for linker symbol resolution */
+
+extern int GC_pthread_create(
+	pthread_t *new_thread,
+	const pthread_attr_t *attr,
+	void *(*start_routine)(void *),
+	void *arg );
+
+#define pthread_create	GC_pthread_create
+#endif
+
+#include <pthread_np.h>
+#endif
+
+#ifndef pthread_create
+#error boehm-gc pthread_create not being used
+#endif
+
+
 #include <semaphore.h>
 
 #include "config.h"
@@ -665,7 +693,6 @@ bool threads_init(u1 *stackbottom)
 	return true;
 }
 
-
 void initThread(java_lang_VMThread *t)
 {
 	threadobject *thread = (threadobject*) t;
@@ -757,7 +784,11 @@ static void *threads_startup_thread(void
 	startup = NULL;
 	sem_post(psem);
 
+	pthread_set_name_np(info->tid,"java");
+
+/*
 	setPriority(info->tid, thread->o.thread->priority);
+*/
 
 #if defined(ENABLE_INTRP)
 	/* set interpreter stack */
@@ -778,12 +809,14 @@ static void *threads_startup_thread(void
 		if (!method)
 			throw_exception();
 
+		printf("starting %x\n",(long)info->tid);
 		ASM_CALLJAVAFUNCTION(method, thread, NULL, NULL, NULL);
 
 	} 
 	else {
 		/* call passed function, e.g. finalizer_thread */
 
+		printf("finalizer %x\n",(long)info->tid);
 		(function)();
 	}
 
@@ -1224,7 +1257,212 @@ static bool timeIsEarlier(const struct t
 	return timespec_less(&tsnow, tv);
 }
 
+#if 0
+#if defined( __OPENBSD__ ) && defined( __OPENBSD__DEBUG__ )
 
+/* count_vec ******************************************************************
+
+	Constructs the distribution of calls to waitWithTimeout by pthread_t
+	Prints the distribution every XDELAY microseconds
+
+	Known Bug: expired threads won't be collected
+
+*******************************************************************************/
+
+/* max entries in count_vec */
+#define NVEC	32
+
+/* microseconds between outputs */
+#define XDELAY	500000
+
+/* file to output traces */
+static FILE *count_vec_file = NULL;
+
+/* true if every new report begins with an lseek to the start of the file */
+static int count_vec_rewind = 0;
+
+/* number of times waitWithTimeout has been called */
+static unsigned long wait_count = 0;
+
+/* true if we've initialized */
+static int count_vec_initialized = 0;
+
+/* true if we've got more than NVEC pthreads */
+static int count_vec_overflow = 0;
+
+/* table of threads that have visited waitWithTimeout */
+static struct {
+	pthread_t tid;			/* pthread resources, a primary key */
+	unsigned long count;	/* number of times waitWithTimeout called by this thread */
+	threadobject *tobj;		/* yes, it's redundant, but it has the name */
+} count_vec[NVEC];
+
+/* last time waitWithTimeout was called */
+static struct timeval t0;
+
+/* init_count_vec *************************************************************
+
+	Zeros the table of pthread_t,count pairs; initializes the time t0
+	
+	Use eclipse_debug="" (or undefined) to suppress all output;
+	Use eclipse_debug=0 to write output to /dev/null
+	Use eclipse_debug=1 to output to stdout, =2 to output to stderr
+	Use eclipse_debug=path to output to the specified path, forces lseek to true
+
+*******************************************************************************/
+
+static void init_count_vec(pthread_t tid)
+{
+	int i;
+	char *env = getenv("eclipse_debug");
+#if 0
+	printf("eclipse_debug=%s\n", (env?env:"<null>")); /* reassurance */
+#endif
+	for( i=0; i<NVEC; i++ ) {
+		count_vec[i].tid = NULL;
+		count_vec[i].count = 0;
+		count_vec[i].tobj = NULL;
+	}
+	count_vec_rewind = 0;
+	if( env == NULL ) {
+		count_vec_file = NULL;
+	} else if ( *env == 0 || *env == '0' ) {
+		count_vec_file = fopen("/dev/null","w");
+	} else if ( *env == '1' ) {
+		count_vec_file = stdout;
+	} else if ( *env == '2' ) {
+		count_vec_file = stderr;
+	} else {
+		count_vec_file = fopen(env,"w");
+		count_vec_rewind = count_vec_file != NULL;
+	}
+	gettimeofday(&t0,NULL);
+	if( count_vec_file ) {
+		fprintf(count_vec_file,"[waitWithTimeout]\tpthread %p count_vec initialized\n",(void*)tid);
+		fflush(count_vec_file);
+	}
+}
+
+/* tdiff **********************************************************************
+
+	struct timeval arithmetic
+
+*******************************************************************************/
+
+static inline unsigned long tdiff(struct timeval *t1, struct timeval *t0)
+{
+	long c = 0;
+	long d = t1->tv_usec - t0->tv_usec;
+	if( d < 0 ) {
+		d += 1000000;
+		c = -1;
+	}
+	return (t1->tv_sec - t0->tv_usec + c)*1000000 + d;
+}
+
+/* thread_name_fprint *********************************************************
+
+	prints a thread's java name; borrowed from threads_ dump below
+
+*******************************************************************************/
+
+static void thread_name_fprint(threadobject* tobj)
+{
+	java_lang_VMThread *vmt;
+	nativethread       *nt;
+	java_lang_Thread   *t;
+	utf                *name;
+
+	vmt = &tobj->o;
+	nt  = &tobj->info;
+	t   = vmt->thread;
+
+	/* get thread name */
+
+	name = javastring_toutf(t->name, false);
+
+	utf_fprint( count_vec_file, name );
+
+	if (t->daemon)
+		fprintf( count_vec_file, "[daemon]" );
+}
+
+/* dump_counts ****************************************************************
+
+	Prints the table of accumulated counts on calls to waitWithTimeout
+
+*******************************************************************************/
+
+static void dump_counts(pthread_t cur_tid)
+{
+	struct timeval t1;
+	gettimeofday(&t1,NULL);
+	if( tdiff(&t1,&t0) >= XDELAY ) {
+		int i;
+		t0 = t1;
+		if( count_vec_rewind ) {
+			/* only for explicitly named files; not stdout, nor stderr */
+			rewind(count_vec_file);
+		}
+		fprintf(count_vec_file,
+			"[waitWithTimeout]\tpthread %p @%ld.%06ld wc=%10ld\n", (void*) cur_tid, t1, wait_count);
+		for( i=0; i<NVEC; i++ ) {
+			pthread_t this_tid = count_vec[i].tid;
+			if( this_tid ) {
+				fprintf(count_vec_file,"\t\t\tpthread %p %10ld ",
+					(void*) this_tid, count_vec[i].count);
+				thread_name_fprint( count_vec[i].tobj );
+				fprintf(count_vec_file,"\n");
+			} else {
+				fflush(count_vec_file);
+				return;
+			}
+		}
+	}
+}
+
+/* bump_count *****************************************************************
+
+	Increments the count for a specified thread (the current thread).
+	Prints counts after the passage of time.
+
+*******************************************************************************/
+
+static void bump_count(threadobject *tobj)
+{
+	int i;
+	pthread_t tid = tobj->info.tid;
+	wait_count += 1;
+	if( ! count_vec_initialized ) {
+		init_count_vec(tid);
+		count_vec_initialized = 1;
+	}
+	if( ! count_vec_file ) {
+		return;
+	}
+	for( i=0; i<NVEC; i++ ) {
+		pthread_t this_tid = count_vec[i].tid;
+		if( this_tid == 0 || this_tid == tid ) {
+			count_vec[i].tid = tid;
+			count_vec[i].count += 1;
+			count_vec[i].tobj = tobj;
+			if( this_tid == 0 ) {
+				fprintf(count_vec_file,"[waitWithTimeout]\tpthread %p initialized ", (void*)tid);
+				if( count_vec[i].tobj ) {
+					thread_name_fprint( count_vec[i].tobj );
+				}
+				fprintf(count_vec_file,"\n");
+				fflush(count_vec_file);
+			}
+			dump_counts(tid);
+			return;
+		}
+	}
+	count_vec_overflow = 1;
+}
+#endif
+#endif /* of if 0 */
+
 /* waitWithTimeout *************************************************************
 
    XXX
@@ -1239,6 +1477,18 @@ static bool waitWithTimeout(threadobject
 
 	t->isSleeping = true;
 
+#if 0
+#if defined( __OPENBSD__ )
+#if defined( __OPENBSD__DEBUG__ )
+	bump_count(t);
+#endif
+	pthread_yield();
+	usleep(101);
+#endif
+#endif
+	pthread_yield();
+	usleep(3);
+
 	if (wakeupTime->tv_sec || wakeupTime->tv_nsec) {
 		while (!t->interrupted && !t->signaled && timeIsEarlier(wakeupTime))
 			pthread_cond_timedwait(&t->waitCond, &t->waitLock, wakeupTime);
@@ -1431,13 +1681,25 @@ void threads_dump(void)
 	nativethread       *nt;
 	java_lang_Thread   *t;
 	utf                *name;
+	int                count;
 
-	tobj = mainthreadobj;
-
 	printf("Full thread dump CACAO "VERSION":\n");
 
+#if 0
+#ifdef __OPENBSD__
+	count = 0;
+	tobj = mainthreadobj;
+	do {
+		count += 1;
+		tobj = tobj->info.next;
+	} while (tobj && (tobj != mainthreadobj));
+	printf("Thread count %d\n", count);
+#endif
+#endif
+
 	/* iterate over all started threads */
 
+	tobj = mainthreadobj;
 	do {
 		/* get thread objects */
 
@@ -1471,10 +1733,20 @@ void threads_dump(void)
 
 			/* sleep this thread a bit, so the signal can reach the thread */
 
+#if defined(__OpenBSD__)
+			/* thread_sleep results in an illegal call to the scheduler from a signal handler */
+			/* this handler needs to spawn a thread to construct the output */
+			/* or, we need a simpler way for one thread to stack backtrace another */
+			sched_yield();
+#else
 			thread_sleep(10, 0);
+#endif
+
 		}
 
 		tobj = tobj->info.next;
+
+		count += 1;
 	} while (tobj && (tobj != mainthreadobj));
 }
 
