$OpenBSD$
--- src/threads/native/threads.c.orig	Mon Feb 13 18:14:32 2006
+++ src/threads/native/threads.c	Thu Apr 20 00:23:32 2006
@@ -45,6 +45,12 @@
 #include <errno.h>
 
 #include <pthread.h>
+
+#ifdef __OPENBSD__
+#define __OPENBSD__DEBUG__
+#include <pthread_np.h>
+#endif
+
 #include <semaphore.h>
 
 #include "config.h"
@@ -665,7 +671,6 @@ bool threads_init(u1 *stackbottom)
 	return true;
 }
 
-
 void initThread(java_lang_VMThread *t)
 {
 	threadobject *thread = (threadobject*) t;
@@ -1224,7 +1229,210 @@ static bool timeIsEarlier(const struct t
 	return timespec_less(&tsnow, tv);
 }
 
+#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
+
 /* waitWithTimeout *************************************************************
 
    XXX
@@ -1239,6 +1447,13 @@ static bool waitWithTimeout(threadobject
 
 	t->isSleeping = true;
 
+#if defined( __OPENBSD__ )
+#if defined( __OPENBSD__DEBUG__ )
+	bump_count(t);
+#endif
+	pthread_yield();
+#endif
+
 	if (wakeupTime->tv_sec || wakeupTime->tv_nsec) {
 		while (!t->interrupted && !t->signaled && timeIsEarlier(wakeupTime))
 			pthread_cond_timedwait(&t->waitCond, &t->waitLock, wakeupTime);
@@ -1431,13 +1646,23 @@ void threads_dump(void)
 	nativethread       *nt;
 	java_lang_Thread   *t;
 	utf                *name;
+	int                count;
 
-	tobj = mainthreadobj;
-
 	printf("Full thread dump CACAO "VERSION":\n");
 
+#ifdef __OPENBSD__
+	count = 0;
+	tobj = mainthreadobj;
+	do {
+		count += 1;
+		tobj = tobj->info.next;
+	} while (tobj && (tobj != mainthreadobj));
+	printf("Thread count %d\n", count);
+#endif
+
 	/* iterate over all started threads */
 
+	tobj = mainthreadobj;
 	do {
 		/* get thread objects */
 
@@ -1475,6 +1700,8 @@ void threads_dump(void)
 		}
 
 		tobj = tobj->info.next;
+
+		count += 1;
 	} while (tobj && (tobj != mainthreadobj));
 }
 
