$FreeBSD$

--- ../src/solaris/hpi/native_threads/src/threads_bsd.c	7 Feb 2002 05:19:54 -0000	1.12
+++ ../src/solaris/hpi/native_threads/src/threads_bsd.c	25 Feb 2003 16:31:54 -0000
@@ -22,32 +22,23 @@
 #include "np.h"
 
 #include <pthread.h>
+#include <pthread_np.h>
 
 #if defined(__FreeBSD__)
 
-#include <pthread_np.h>
+#include <assert.h>
 
-/* Remove defines from pthread.h so pthread_private.h can be included */
-#undef pthread_condattr_default
-#undef pthread_mutexattr_default
 #undef pthread_attr_default
+#undef pthread_mutexattr_default
+#undef pthread_condattr_default
 #include "pthread_private.h"
 
-#include <assert.h>
-#include <ucontext.h>
-#include <machine/ucontext.h>
-
-#include <sys/exec.h>
-#include <vm/vm.h>
-#include <vm/pmap.h>
-#include <machine/pmap.h>
-#include <machine/vmparam.h>
-
 #endif
 
 #include <string.h>
 #include <signal.h>
 #include <sys/signal.h>
+#include <sys/time.h>
 #include <sys/resource.h>
 #include <stdlib.h>
 #include <string.h>
@@ -63,14 +54,9 @@
 /* Private functions used to implement native threading. --billh */
 
 #ifdef DEBUG_BSD_NATIVE_THREADS
-void _pthread_suspend_all_np(void);
-void _pthread_resume_all_np(void);
-#endif
-void record_uc(sys_thread_t *, ucontext_t *);
-void record_gc_registers_of(sys_thread_t *);
-
-void dumpThreadStates();
 void dumpThreadLogStates(pthread_t);
+void dumpThreadStates();
+#endif
 
 /*
  * Suspend a thread.  Used to implement java.lang.Thread.suspend(),
@@ -108,28 +94,24 @@
 int
 np_stackinfo(void **addr, long *sizep)
 {
-    thread_t self = pthread_self();
-    int base;
-    int size;
-
-    if (!pthread_equal(self, _thread_initial)) {
-        *addr = self->stack;
-	*sizep = (long) PTHREAD_STACK_DEFAULT;
-
-    } else {
-	/* in main()'s thread */
-	struct rlimit r;
-
-	if (getrlimit(RLIMIT_STACK, &r) == -1)
-	    return SYS_ERR;
-
-	/* PS_STRINGS is also from sys/exec.h in FreeBSD, but as macro. --billh */
-
-	*addr  = (void *) (PS_STRINGS +1);
-	*sizep = (long)r.rlim_cur;
-    }
+    pthread_attr_t attr;
+    size_t size;
 
+    if ((errno = pthread_attr_init(&attr)))
+	return SYS_ERR;
+    if ((errno = pthread_attr_get_np(pthread_self(), &attr)))
+	goto err;
+    if ((errno = pthread_attr_getstackaddr(&attr, addr)))
+	goto err;
+    if ((errno = pthread_attr_getstacksize(&attr, &size)))
+	goto err;
+    *sizep = size;
+    pthread_attr_destroy(&attr);
     return SYS_OK;
+
+err:
+    pthread_attr_destroy(&attr);
+    return SYS_ERR;
 }
 
 /*
@@ -177,7 +159,7 @@
 	Do this for the FreeBSD implementation too, since this is a silly
 	function anyways.  --billh
 */
-	return TRUE;
+    return TRUE;
 }
 
 
@@ -190,38 +172,54 @@
 static void
 record_thread_regs()
 {
-    sys_thread_t *tid;
+    struct pthread *self = pthread_self();
+    sys_thread_t *tid = ThreadQueue;
     int i;
-    int sp;
 
-    tid = ThreadQueue;
-    for (i = 0; i < ActiveThreadCount && tid != 0; i++) {
-	int i;
-
-	if (tid->sys_thread != 0) {
-#ifdef __bsdi__
-	    /* if thread has already been initialized */
-	    if (pthread_getstackpointer_np(tid->sys_thread, &sp) == 0)
-		tid->sp = sp;
-	    else
-		tid->sp = 0;
-#elif __FreeBSD__
-#endif
-            tid->sp = tid->sys_thread->stack;
-//#endif	//__FreeBSD__
-/*	Potential race here if the stack isn't setup before GC. --billh */
-	} else {
+    for (i = 0; i < ActiveThreadCount && tid != NULL; i++, tid = tid->next) {
+	struct pthread *thread = tid->sys_thread;
+
+	if (thread == 0) {
 	    /*
 	     * thread is still in the process of being initalized.
 	     * So GC should not care about this thread. Just
 	     * set its sp to 0, and this will force GC to ignore it.
 	     */
 	    tid->sp = 0;
+	    continue;
 	}
 
-	record_gc_registers_of(tid);
+        tid->sp = thread->stack;
+/*	Potential race here if the stack isn't setup before GC. --billh */
 
-	tid = tid->next;
+	/*
+	 * The thread that calls this function will alway be the JVM GC thread,
+	 * so skip over it in the list of threads.
+	 */
+	if (thread != self && (thread->flags & PTHREAD_FLAGS_PRIVATE) == 0) {
+	    register_t *regbase;
+
+#ifdef DEBUG_BSD_NATIVE_THREADS
+	    /*
+	     * Got search candidate..
+	     */
+	    if (thread->state != PS_SUSPENDED)
+		dumpThreadLogStates(thread);
+#endif
+
+	    regbase = (register_t*) &thread->ctx.jb[0];
+	    tid->regs[0] = regbase[6];	/* eax */
+	    tid->regs[1] = 0;		/* ecx (missing) */
+	    tid->regs[2] = 0;		/* edx (missing) */
+	    tid->regs[3] = regbase[1];	/* ebx */
+	    tid->regs[4] = regbase[3];	/* ebp */
+	    tid->regs[5] = regbase[4];	/* esi */
+	    tid->regs[6] = regbase[5];	/* edi */
+
+#ifdef DEBUG_BSD_NATIVE_THREADS
+	    dumpThreadStates();
+#endif
+	}
     }
 
 #ifdef DEBUG_BSD_NATIVE_THREADS
@@ -239,14 +237,7 @@
 {
     sysAssert(SYS_QUEUE_LOCKED(sysThreadSelf()));
 
-#ifdef DEBUG_BSD_NATIVE_THREADS
-    _pthread_suspend_all_np();
-#else
-    pthread_single_np();
-#endif
-
-//usleep(100000 *3);
-
+    pthread_suspend_all_np();
     record_thread_regs();
     return SYS_OK;
 }
@@ -259,42 +250,13 @@
 np_multi(void)
 {
     sysAssert(SYS_QUEUE_LOCKED(sysThreadSelf()));
-#ifdef DEBUG_BSD_NATIVE_THREADS
-    _pthread_resume_all_np();
-#else
-    pthread_multi_np();
-#endif
+    pthread_resume_all_np();
 }
 
-
-
-
+#ifdef DEBUG_BSD_NATIVE_THREADS
 /* pthreads hackery begins --billh */
 
-#define ANALRETENTIVE (6 + 1)
-
-char SuspendList[ANALRETENTIVE][16] = 
-{
-	"SUSP_NO",		/* Not suspended. */
-	"SUSP_YES",		/* Suspended. */
-	"SUSP_JOIN",		/* Suspended, joining. */  
-	"SUSP_NOWAIT",		/* Suspended, was in a mutex or condition queue. */
-	"SUSP_MUTEX_WAIT",	/* Suspended, still in a mutex queue. */
-	"SUSP_COND_WAIT",	/* Suspended, still in a condition queue. */
-	"susp boundless"
-};
-
-char *getSuspendStateString(enum pthread_susp suspendState)
-{
-	if (suspendState < ANALRETENTIVE)
-		return &SuspendList[suspendState][0];
-	else 
-		return &SuspendList[ANALRETENTIVE-1][0];
-}
-
-#define SATAN (21 + 1) /* for the error string at the end of the list */
-
-char SignalList [SATAN][16]
+char SignalList [][16]
 =
 {
 	"PS_RUNNING",
@@ -316,18 +278,17 @@
 	"PS_JOIN",
 	"PS_SUSPENDED",
 	"PS_DEAD",
-	"PS_DEADLCK",
+	"PS_DEADLOCK",
 	"PS_STATE_MAX",
-	"PS_REQUEST_WAITING_SUSPENDED",
 	"boundless"
 };
 
 char *getThreadStateString(enum pthread_state threadState)
 {
 	if (threadState < SATAN)
-		return &SignalList[threadState][0];
-	else 
-		return &SignalList[SATAN-1][0];
+		return SignalList[threadState];
+	else
+		return SignalList[SATAN-1];
 }
 
 void dumpThreadStates()
@@ -336,114 +297,29 @@
 	struct pthread	*thread;
 	struct pthread	*self = pthread_self();
 
-#ifdef DEBUG_BSD_NATIVE_THREADS
 	_thread_kern_sig_defer();
 	TAILQ_FOREACH(thread, &_thread_list, tle) {
 		if (thread != self) { /* special case this --billh */
-			printf("\tthread %d\t%s\t%s\n",
+			printf("\tthread %d\t%s\n",
 				threadCount,
-				getThreadStateString(thread->state),
-				getSuspendStateString(thread->suspended));
+				getThreadStateString(thread->state));
 
 			if (thread->state != PS_SUSPENDED)
 				dumpThreadLogStates(thread);
-		}
-		else
-		{
-			printf("\tgc thread %d\t%s\t%s\n",
+		} else {
+			printf("\tgc thread %d\t%s\n",
 				threadCount,
-				getThreadStateString(thread->state),
-				getSuspendStateString(thread->suspended));
+				getThreadStateString(thread->state))
 		}
 		++threadCount;
 	}
 	_thread_kern_sig_undefer();
 	printf("\n");
-#endif
-}
-
-
-#ifdef DEBUG_BSD_NATIVE_THREADS
-extern void _pthread_suspend_np_by_pthread_common(pthread_t);
-extern void _pthread_resume_by_pthread_common(pthread_t, enum pthread_susp);
-
-void
-_pthread_suspend_all_np(void)
-{
-	struct pthread	*thread;
-	struct pthread	*self = pthread_self();
-
-fprintf(stderr, "pthread_suspend_all_np\n");
-	/*
-	 * Defer signals to protect the scheduling queues from
-	 * access by the signal handler:
-	 */
-	_thread_kern_sig_defer();
-
-	/* Suspend all threads other than the current thread: */
-	TAILQ_FOREACH(thread, &_thread_list, tle) {
-		if (thread != self) {
-			_pthread_suspend_np_by_pthread_common(thread);
-		}
-	}
-
-	/*
-	 * Undefer and handle pending signals, yielding if necessary:
-	 */
-	_thread_kern_sig_undefer();
-fprintf(stderr, "pthread_suspend_all_np END\n");
-}
-
-/* Resume a thread: */
-void
-_pthread_resume_all_np(void)
-{
-	enum		pthread_susp old_suspended;
-	struct pthread	*thread;
-	struct pthread	*self = pthread_self();
-
-fprintf(stderr, "pthread_resume_all_np\n");
-	_thread_kern_sig_defer();
-
-	/*
-		Iterate through the thread list and resume suspended threads.
-		this is copied from pthread_resume_np(). --billh
-	*/
-
-	TAILQ_FOREACH(thread, &_thread_list, tle) {
-		if (thread != self) {
-			/* Cancel any pending suspensions: */
-
-			old_suspended = thread->suspended;
-			thread->suspended = SUSP_NO;
-
-			_pthread_resume_by_pthread_common(thread, old_suspended);
-
-		} // if !thread_self
-	} // TAILQ_FOREACH
-
-	/*
-	 * Undefer and handle pending signals, yielding if
-	 * necessary:
-	 */
-	_thread_kern_sig_undefer();
-fprintf(stderr, "pthread_resume_all_np END\n");
 }
-#endif
 
 /*
 	[A snippet from Dan Eichen's email on the subject]
 
-	It uses _longjmp (non-signal-saving/restoring) for the most part.
-	The only exception is when the process (currently running thread) is 
-	interrupted by a signal.  So your context types are a jmp_buf and
-	a ucontext_t (if interrupted by a signal).  If thread->ctxtype is
-	CTX_UC, the context is stored as a ucontext in thread->ctx.uc.
-	Otherwise, the context is stored as a jmp_buf in thread->ctx.jb.
-	We don't currently use CTX_JB and CTX_SJB, so don't even bother
-	with those cases.  Those should go away actually; all we need
-	to know is if it is a ucontext_t or a jmp_buf.
-
 	You can also look at src/gnu/usr.bin/binutils/gdb/freebsd-uthread.c.
 	It knows how to iterate through all the threads and pull out
 	(and even set) thread contexts.
@@ -462,19 +338,8 @@
 	--billh
 */
 
-void clear_gc_registers(sys_thread_t * jthread)
-{
-/* clear out x86 registers for the thread's "self" --billh */
-
-	jthread->regs[0] = 0; jthread->regs[1] = 0;
-	jthread->regs[2] = 0; jthread->regs[3] = 0;
-	jthread->regs[4] = 0; jthread->regs[5] = 0;
-	jthread->regs[6] = 0;
-}
-
 void dumpThreadLogStates(pthread_t thread)
 {
-#ifdef DEBUG_BSD_NATIVE_THREADS
 int i;
 	for(i=0; i < STATE_LOG_SIZE; ++i)
 	{
@@ -494,311 +359,5 @@
 		}
 	}
 	printf("\t\t***XXX\n");
-#endif
-}
-
-void record_gc_registers_of(sys_thread_t *javaThread)
-{
-struct pthread	*self	= pthread_self();
-struct pthread	*thread	= NULL;
-
-	assert( javaThread != NULL );
-	assert( javaThread->sys_thread != NULL );
-
-	thread = javaThread->sys_thread;
-
-	/*
-	 * The thread that calls this function will alway be the JVM GC thread,
-	 * so skip over it in the list of threads.
-	 */
-	if (	(thread == self)
-		|| ((thread->flags & PTHREAD_FLAGS_PRIVATE) != 1)
-	   )
-	{
-		record_uc(javaThread, &thread->ctx.uc);
-#ifdef DEBUG_BSD_NATIVE_THREADS
-		goto Terminate; // And do nothing with this pthread entry. 
-#endif
-	}
-
-	/*
-	 * Got search candiate..
-	 */
-	if (thread->state != PS_SUSPENDED)
-		dumpThreadLogStates(thread);
-
-	switch ((int)thread->ctxtype)
-	{
-		case CTX_JB_NOSIG:	/* 0) jmp_buf context without signal mask for blocking IO, etc... */
-		case CTX_JB:		/* 1) should never be CTX_JB */
-		case CTX_SJB:		/* 2) should never be CTX_SJB */
-			clear_gc_registers(javaThread);
-#ifdef DEBUG_BSD_NATIVE_THREADS
-			goto Terminate;
-#endif
-			break;
-		case CTX_UC:		/* 3) */
-			/* context is a ucontext_t */
-			record_uc(javaThread, &thread->ctx.uc);
-#ifdef DEBUG_BSD_NATIVE_THREADS
-			goto Terminate;
-#endif
-			break;
-		default:
-#ifdef DEBUG_BSD_NATIVE_THREADS
-			fprintf(stderr, "ctxtype failed %d.\n", thread->ctxtype);
-			goto TermFailed;
-#endif
-			break;
-	}
-
-#ifdef DEBUG_BSD_NATIVE_THREADS
-TermFailed:
-	fprintf(stderr, "Failed to find pthread struct.\n"); fflush(stderr);
-	assert(0);
-
-Terminate:
-	dumpThreadStates();
-#endif
 }
-
-void record_uc(sys_thread_t *t, ucontext_t *uc)
-{
-	mcontext_t *mc = &(uc->uc_mcontext);
-
-	t->regs[0] = mc->mc_eax;
-	t->regs[1] = mc->mc_ecx;
-	t->regs[2] = mc->mc_edx;
-	t->regs[3] = mc->mc_ebx;
-	t->regs[4] = mc->mc_ebp;
-	t->regs[5] = mc->mc_esi;
-	t->regs[6] = mc->mc_edi;
-}
-
-/*
-From /usr/src/lib/libc/i386/gen/_setjmp.S:
-ENTRY(_setjmp)
-	movl	4(%esp),%eax
-	movl	0(%esp),%edx
-	movl	%edx, 0(%eax)	/ * rta * /
-	movl	%ebx, 4(%eax)
-	movl	%esp, 8(%eax)
-	movl	%ebp,12(%eax)
-	movl	%esi,16(%eax)
-	movl	%edi,20(%eax)
-	fnstcw	24(%eax)
-	xorl	%eax,%eax
-	ret
-
-typedef JmpBufStruct
-{
-	int	edx, // Accumulator for operands and results data.
-		ebx, // Pointer to data in the DS segment.
-		esp, // Stack pointer (in the SS segment).
-		ebp, // Pointer to data on the stack (in the SS segment).
-		esi, // Pointer to data in the segment pointer to by the DS register; source pointer for string operations.
-		edi; // Pointer to data (or destination) in the segment pointer to by the ES register; destination pointer for string operations.
-
-} JmpBufStruct;
-
-
-void record_jb(sys_thread_t *t, JmpBufStruct *jb)
-{
-	t->regs[0] = jb->eax; // What about these two register ? they seem missing in jmp_buf.
-	t->regs[1] = / *jb->ecx;* / 0;
-	t->regs[2] = jb->edx; // The rest of these registers are defined...
-	t->regs[3] = jb->ebx;
-	t->regs[4] = jb->ebp;
-	t->regs[5] = jb->esi;
-	t->regs[6] = jb->edi;
-}
-*/
-
-#if 0
-static void
-finish_suspension(void *arg)
-{
-	if (_thread_run->suspended != SUSP_NO)
-		_thread_kern_sched_state(PS_SUSPENDED, __FILE__, __LINE__);
-}
-
-void _pthread_suspend_np_by_pthread_common(pthread_t thread)
-{
-struct timeval  tv;
-struct timespec current_ts;
-
-	switch (thread->state) {
-	case PS_RUNNING:
-		/*
-		 * Remove the thread from the priority queue and
-		 * set the state to suspended:
-		 */
-		PTHREAD_PRIOQ_REMOVE(thread);
-		PTHREAD_SET_STATE(thread, PS_SUSPENDED);
-		break;
-
-	case PS_SPINBLOCK:
-	case PS_FDR_WAIT:
-	case PS_FDW_WAIT:
-	case PS_POLL_WAIT:
-	case PS_SELECT_WAIT:
-		/*
-		 * Remove these threads from the work queue
-		 * and mark the operation as interrupted:
-		 */
-		if ((thread->flags & PTHREAD_FLAGS_IN_WORKQ) != 0)
-			PTHREAD_WORKQ_REMOVE(thread);
-		_thread_seterrno(thread,EINTR);
-
-		/* FALLTHROUGH */
-	case PS_SLEEP_WAIT:
-		thread->interrupted = 1;
-
-		/* FALLTHROUGH */
-	case PS_SIGTHREAD:
-	case PS_WAIT_WAIT:
-	case PS_SIGSUSPEND:
-	case PS_SIGWAIT:
-		/*
-		 * Remove these threads from the waiting queue and
-		 * set their state to suspended:
-		 */
-		PTHREAD_WAITQ_REMOVE(thread);
-		PTHREAD_SET_STATE(thread, PS_SUSPENDED);
-		break;
-
-	case PS_MUTEX_WAIT:
-		/* Mark the thread as suspended and still in a queue. */
-		thread->suspended = SUSP_MUTEX_WAIT;
-
-		PTHREAD_SET_STATE(thread, PS_SUSPENDED);
-		break;
-	case PS_COND_WAIT:
-#if 0
-		/* This is for a pthreads_cond_timedwait() --billh */
-		if (thread->wakeup_time.tv_sec != -1) {
-			/* (1) Use to restore the waiting-queue time that's left when the
-			 * thread is resumed. --billh
-			 */
-			_subtract_timespec3(thread, &current_ts, &thread->remaining_wakeup_time);
-
-			/* (2) So that it's inserted at the end of the waiting queue and
-			 * not scanned by the uthreads_kern.c waiting queue logic. It also
-			 * means to make it wait forever.
-			 */
-			thread->wakeup_time.tv_sec  = -1;
-			thread->wakeup_time.tv_nsec = -1;
-
-			/* (3) Remove and reinsert it at the end of waiting-queue
-			 * (automatic on the insertion attempt when (2)).
-			 */
-			PTHREAD_WORKQ_REMOVE(thread);
-			PTHREAD_WORKQ_INSERT(thread);
-		}
-#endif
-
-		/* Mark the thread as suspended and still in a queue. */
-		thread->suspended = SUSP_COND_WAIT;
-
-		PTHREAD_SET_STATE(thread, PS_SUSPENDED);
-		break;
-	case PS_JOIN:
-		/* Mark the thread as suspended and joining: */
-		thread->suspended = SUSP_JOIN;
-
-		PTHREAD_NEW_STATE(thread, PS_SUSPENDED);
-		break;
-	case PS_FDLR_WAIT:
-	case PS_FDLW_WAIT:
-	case PS_FILE_WAIT:
-		/* Mark the thread as suspended: */
-		thread->suspended = SUSP_YES;
-
-		/*
-		 * Threads in these states may be in queues.
-		 * In order to preserve queue integrity, the
-		 * cancelled thread must remove itself from the
-		 * queue.  Mark the thread as interrupted and
-		 * set the state to running.  When the thread
-		 * resumes, it will remove itself from the queue
-		 * and call the suspension completion routine.
-		 */
-		thread->interrupted = 1;
-		_thread_seterrno(thread, EINTR);
-		PTHREAD_NEW_STATE(thread, PS_RUNNING);
-		thread->continuation = finish_suspension;
-		break;
-
-	case PS_DEAD:
-	case PS_DEADLOCK:
-	case PS_STATE_MAX:
-	case PS_SUSPENDED:
-		/* Nothing needs to be done: */
-		break;
-	}
-}
-
-void _pthread_resume_by_pthread_common(pthread_t thread, enum pthread_susp old_suspended)
-{
-struct timeval  tv;
-struct timespec current_ts,
-		remaining_spec;
-
-	/* Is it currently suspended? */
-	if (thread->state == PS_SUSPENDED) {
-		/*
-		 * Defer signals to protect the scheduling queues
-		 * from access by the signal handler:
-		 */
-		_thread_kern_sig_defer();
-
-		switch (old_suspended) {
-		case SUSP_MUTEX_WAIT:
-			/* Set the thread's state back. */
-			PTHREAD_SET_STATE(thread,PS_MUTEX_WAIT);
-			break;
-		case SUSP_COND_WAIT:
-			/* For cases where it was doing a pthread_cond_timedwait()
-			 * Mark the remaining suspend time.
-			 * --billh
-			 */
-#if 0
-			if (thread->remaining_wakeup_time.tv_sec != -1) {
-				GET_CURRENT_TOD(tv);
-				TIMEVAL_TO_TIMESPEC(&tv, &current_ts);
-
-				_subtract_timespec3(remaining_spec, &thread->wakeup_time, &current_ts);
-				_thread_kern_set_timeout_by_pthread_timespec(thread, &remaining_spec);
-			}
-#endif
-
-			/* Set the thread's state back. */
-			PTHREAD_SET_STATE(thread,PS_COND_WAIT);
-			break;
-		case SUSP_JOIN:
-			/* Set the thread's state back. */
-			PTHREAD_SET_STATE(thread,PS_JOIN);
-			break;
-		case SUSP_NOWAIT:
-			/* Allow the thread to run. */
-			PTHREAD_SET_STATE(thread,PS_RUNNING);
-			PTHREAD_WAITQ_REMOVE(thread);
-			PTHREAD_PRIOQ_INSERT_TAIL(thread);
-			break;
-		case SUSP_NO:
-		case SUSP_YES:
-			/* Allow the thread to run. */
-			PTHREAD_SET_STATE(thread,PS_RUNNING);
-			PTHREAD_PRIOQ_INSERT_TAIL(thread);
-			break;
-		}
-
-		/*
-		 * Undefer and handle pending signals, yielding if
-		 * necessary:
-		 */
-		_thread_kern_sig_undefer();
-	}
-}
-
 #endif