$OpenBSD: patch-jdk_src_solaris_hpi_native_threads_src_threads_bsd_c,v 1.2 2009/05/23 03:03:25 kurt Exp $
--- jdk/src/solaris/hpi/native_threads/src/threads_bsd.c.orig	Mon May 18 14:28:18 2009
+++ jdk/src/solaris/hpi/native_threads/src/threads_bsd.c	Mon May 18 16:59:47 2009
@@ -23,90 +23,61 @@
  * have any questions.
  */
 
-/*
- * Implementation of HPI that can not be expressed with POSIX threads.
- * Note that even if you are building with USE_PTHREADS, we have to
- * explicitly undef it here because pthread.h and thread.h can not be
- * included in the same file, and this file needs only thread.h.
- */
-#undef USE_PTHREADS
+#ifdef __APPLE__
 
+/* We need the mach API, which must be be included before any other system includes.
+ * Additionally, java and mach both define thread_state_t, so temporarily redefine it. */
+#define thread_state_t mach_thread_state_t
+#include <mach/mach.h>
+#undef thread_state_t
+
+#endif
+
 #include "hpi_impl.h"
 #include "monitor_md.h"
 #include "threads_md.h"
 #include "np.h"
 
-#include <thread.h>
-#include <sys/lwp.h>
+#include <sys/types.h>
+#include <sys/sysctl.h>
+
+#include <pthread.h>
+#if defined(__FreeBSD__) || defined(__OpenBSD__)
+#include <pthread_np.h>
+#endif
+#ifdef __NetBSD__
+#include <errno.h>
+#define pthread_attr_get_np(a, b)   0
+#define pthread_suspend_all_np()    0
+#define pthread_resume_all_np()     0
+#endif
+
+#include <time.h>
+#include <string.h>
 #include <signal.h>
 #include <sys/signal.h>
 #include <sys/resource.h>
-#include <sys/procfs.h>
 #include <stdlib.h>
 #include <string.h>
-#include <fcntl.h>
 #include <errno.h>
 
-#include <sys/syscall.h>
-extern int syscall(int, ...);
-
-
 /*
- * Forward declarations.
- */
-static int  procfd;
-static void stop_lwps();
-static void clear_onproc_flags();
-static void restart_lwps();
-static void MakeProcName(register char *procname, register pid_t pid);
-static void GC_msec_sleep(int n);
-
-
-/*
- * Make sure that we link against a verion of libthread that has at least
- * the bug fixes and the interface for getting the stack from threads that
- * aren't on LWPs.  Otherwise we should exit with some informative message.
- */
-extern ulong_t __gettsp(thread_t);
-
-static const char * gettspMessage =
-"You must install a Bsd patch to run the native threads version of the\n"
-"Java runtime.  The green threads version will work without this patch.\n"
-"Please check the native threads release notes for more information.\n"
-"\n"
-"If you are embedding the VM in a native application, please make sure that\n"
-"the native application is linked with libthread.so (-lthread).\n"
-"\n"
-"Exiting.\n";
-
-static void
-checkForCorrectLibthread()
-{
-    if (&__gettsp == 0) {
-        fprintf(stderr, gettspMessage);
-        exit(1);
-    }
-}
-#ifdef __GNUC__
-static void checkForCorrectLibthread() __attribute__((constructor));
-#else
-#pragma init(checkForCorrectLibthread)
-#endif
-
-#pragma weak __gettsp
-
-
-/*
  * Suspend said thread.  Used to implement java.lang.Thread.suspend(),
  * which is deprecated.
  */
 int
 np_suspend(sys_thread_t *tid)
 {
-    return thr_suspend(tid->sys_thread);
+#ifdef __APPLE__
+    if (thread_suspend(pthread_mach_thread_np(tid->sys_thread)) == KERN_SUCCESS)
+        return SYS_OK;
+    else
+        return SYS_ERR;
+#else
+    return pthread_suspend_np(tid->sys_thread);
+#endif
 }
 
-
 /*
  * Resume a suspended thread.  Used to implement java.lang.Thread.resume(),
  * which is deprecated.
@@ -114,7 +85,14 @@ np_suspend(sys_thread_t *tid)
 int
 np_continue(sys_thread_t *tid)
 {
-    return thr_continue(tid->sys_thread);
+#ifdef __APPLE__
+    if (thread_resume(pthread_mach_thread_np(tid->sys_thread)) == KERN_SUCCESS)
+        return SYS_OK;
+    else
+        return SYS_ERR;
+#else
+    return pthread_resume_np(tid->sys_thread);
+#endif
 }
 
 /*
@@ -127,26 +105,74 @@ void np_initialize_thread(sys_thread_t *tid)
 
 
 /*
+ * Internal helper function to get stack information about specified thread.
+ */
+#ifdef __APPLE__
+static int
+get_stackinfo(pthread_t tid, void **addr, long *sizep)
+{
+    void *stacktop = pthread_get_stackaddr_np(tid);
+    *sizep = pthread_get_stacksize_np(tid);
+    *addr = stacktop - *sizep;
+
+    return (SYS_OK);
+}
+#elif defined(__OpenBSD__)
+static int
+get_stackinfo(pthread_t tid, void **addr, long *sizep)
+{
+    stack_t ss;
+
+    if (pthread_stackseg_np(tid, &ss) == 0) {
+        *addr = (void *)(ss.ss_sp) - ss.ss_size;
+        *sizep = (long)(ss.ss_size);
+        return SYS_OK;
+    } else {
+        return SYS_ERR; /* pthreads_stackseg_np failed. */
+    }
+}
+#else
+static int
+get_stackinfo(pthread_t tid, pthread_attr_t attr, void **addr, long *sizep)
+{
+    size_t s;
+    void  *p;
+    int    ret = SYS_ERR;
+
+    if (pthread_attr_get_np(tid, &attr) != 0)
+        goto err;
+    if (pthread_attr_getstackaddr(&attr, &p) != 0)
+        goto err;
+    if (pthread_attr_getstacksize(&attr, &s) != 0)
+        goto err;
+    *addr = p;
+    *sizep = s;
+    ret = SYS_OK;
+err:
+
+    return (ret);
+}
+#endif
+
+/*
  * Get the stack start address, and max stack size for the current thread.
  */
 int
 np_stackinfo(void **addr, long *size)
 {
-    stack_t stkseg;
+#if defined(__OpenBSD__) || defined(__APPLE__)
+    return(get_stackinfo(pthread_self(), addr, size));
+#else
+    pthread_attr_t attr;
+    int    ret = SYS_ERR;
 
-    if (thr_stksegment(&stkseg) == 0) {
-        *addr = (void *)(stkseg.ss_sp);
-        if (thr_main()) {
-            struct rlimit r;
-            getrlimit(RLIMIT_STACK, &r);
-            *size = (long)r.rlim_cur;
-        } else {
-            *size = (long)(stkseg.ss_size);
-        }
-        return SYS_OK;
-    } else {
-        return SYS_ERR; /* thr_stksegment failed. */
+    if (pthread_attr_init(&attr) == 0) {
+        ret = get_stackinfo(pthread_self(), attr, addr, size);
+        pthread_attr_destroy(&attr);
     }
+
+    return (ret);
+#endif
 }
 
 /*
@@ -155,310 +181,195 @@ np_stackinfo(void **addr, long *size)
 void
 np_profiler_init(sys_thread_t *tid)
 {
-    tid->lwp_id = _lwp_self();
 }
 
 int
 np_profiler_suspend(sys_thread_t *tid)
 {
-    return _lwp_suspend(tid->lwp_id);
+    return np_suspend(tid);
 }
 
 int
 np_profiler_continue(sys_thread_t *tid)
 {
-    return _lwp_continue(tid->lwp_id);
+    return np_continue(tid);
 }
 
 bool_t
 np_profiler_thread_is_running(sys_thread_t *tid)
 {
-    unsigned long sum = 0;
-    int i;
-    prstatus_t lwpstatus;
-    int lwpfd;
-    int res;
+    return TRUE;
+}
 
-    lwpfd = syscall(SYS_ioctl, procfd, PIOCOPENLWP, &(tid->lwp_id));
-    sysAssert(lwpfd >= 0);
 
- retry:
-    res = syscall(SYS_ioctl, lwpfd, PIOCSTATUS, &lwpstatus);
-    sysAssert(res >= 0);
+int
+np_initialize()
+{
+    return SYS_OK;
+}
 
-    if (!(lwpstatus.pr_flags & PR_STOPPED)) {
-        GC_msec_sleep(1);
-        goto retry;
-    }
+/* prototypes */
 
-    close(lwpfd);
+static void record_thread_regs();
 
-#if   defined(sparc)
-    sum += lwpstatus.pr_reg[R_SP];
-    sum += lwpstatus.pr_reg[R_PC];
+/*
+ * Suspend all other threads, and record their contexts (register
+ * set or stack pointer) into the sys_thread structure, so that a
+ * garbage collect can be run.
+ */
+#ifdef __APPLE__
+int
+np_single(void)
+{ 
+    sysAssert(SYS_QUEUE_LOCKED(sysThreadSelf()));
 
-    sum += lwpstatus.pr_reg[R_G1];
-    sum += lwpstatus.pr_reg[R_G2];
-    sum += lwpstatus.pr_reg[R_G3];
-    sum += lwpstatus.pr_reg[R_G4];
+    /* Iterate over all the threads in the task, suspending each one.
+     * We have to loop until no new threads appear, and all are suspended */
+    mach_port_t self = pthread_mach_thread_np(pthread_self());
 
-    sum += lwpstatus.pr_reg[R_O0];
-    sum += lwpstatus.pr_reg[R_O1];
-    sum += lwpstatus.pr_reg[R_O2];
-    sum += lwpstatus.pr_reg[R_O3];
-    sum += lwpstatus.pr_reg[R_O4];
-    sum += lwpstatus.pr_reg[R_O5];
 
-    sum += lwpstatus.pr_reg[R_I0];
-    sum += lwpstatus.pr_reg[R_I1];
-    sum += lwpstatus.pr_reg[R_I2];
-    sum += lwpstatus.pr_reg[R_I3];
-    sum += lwpstatus.pr_reg[R_I4];
-    sum += lwpstatus.pr_reg[R_I5];
-    sum += lwpstatus.pr_reg[R_I6];
-    sum += lwpstatus.pr_reg[R_I7];
+    mach_msg_type_number_t      cur_count, prev_count, i, j, k;
+    thread_act_array_t          cur_list, prev_list;
+    bool_t                      changes;
 
-    sum += lwpstatus.pr_reg[R_L0];
-    sum += lwpstatus.pr_reg[R_L1];
-    sum += lwpstatus.pr_reg[R_L2];
-    sum += lwpstatus.pr_reg[R_L3];
-    sum += lwpstatus.pr_reg[R_L4];
-    sum += lwpstatus.pr_reg[R_L5];
-    sum += lwpstatus.pr_reg[R_L6];
-    sum += lwpstatus.pr_reg[R_L7];
-#elif defined(amd64)
-    sum += lwpstatus.pr_reg[REG_RIP];
-    sum += lwpstatus.pr_reg[REG_RSP];
+    changes = TRUE;
+    cur_count = prev_count = 0;
+    cur_list = prev_list = NULL;
+    do {
+        /* Get a list of all threads */
+        if (task_threads(self, &cur_list, &cur_count) != KERN_SUCCESS)
+            return SYS_ERR;
 
-    sum += lwpstatus.pr_reg[REG_RAX];
-    sum += lwpstatus.pr_reg[REG_RCX];
-    sum += lwpstatus.pr_reg[REG_RDX];
-    sum += lwpstatus.pr_reg[REG_RBX];
-    sum += lwpstatus.pr_reg[REG_RBP];
-    sum += lwpstatus.pr_reg[REG_RSI];
-    sum += lwpstatus.pr_reg[REG_RDI];
+        /* For each thread, check if it was previously suspended. If it
+         * was not, suspend it now, and set the changes flag to 'true' */
+        changes = FALSE;
+        for (i = 0; i < cur_count; i++) {
+            mach_msg_type_number_t j;
+            bool_t found = FALSE;
 
-    sum += lwpstatus.pr_reg[REG_R8];
-    sum += lwpstatus.pr_reg[REG_R9];
-    sum += lwpstatus.pr_reg[REG_R10];
-    sum += lwpstatus.pr_reg[REG_R11];
-    sum += lwpstatus.pr_reg[REG_R12];
-    sum += lwpstatus.pr_reg[REG_R13];
-    sum += lwpstatus.pr_reg[REG_R14];
-    sum += lwpstatus.pr_reg[REG_R15];
-#elif defined(i386)
-    sum += lwpstatus.pr_reg[EIP];
-    sum += lwpstatus.pr_reg[UESP];
+            /* Check the previous thread list */
+            for (j = 0; j < prev_count; j++) {
+                if (prev_list[j] == cur_list[i]) {
+                    found = TRUE;
+                    break;
+                }
+            }
 
-    sum += lwpstatus.pr_reg[EAX];
-    sum += lwpstatus.pr_reg[ECX];
-    sum += lwpstatus.pr_reg[EDX];
-    sum += lwpstatus.pr_reg[EBX];
-    sum += lwpstatus.pr_reg[EBP];
-    sum += lwpstatus.pr_reg[ESI];
-    sum += lwpstatus.pr_reg[EDI];
-#endif
+            /* If the thread wasn't previously suspended, suspend it now and set the change flag */
+            if (found) {
+                /* Don't suspend ourselves! */
+                if (cur_list[i] != self)
+                    thread_suspend(cur_list[i]);
+                changes = TRUE;
+            }
+        }
+        
+        /* Deallocate the previous list, if necessary */
+        for (k = 0; k < prev_count; k++)
+            mach_port_deallocate(self, prev_list[k]);
 
-    if (tid->last_sum == sum) {
-        return FALSE;
-    }
-    tid->last_sum = sum;
+        vm_deallocate(self, (vm_address_t)prev_list, sizeof(thread_t) * prev_count);
 
-    return TRUE;
-}
+        /* Set up the 'new' list for the next loop iteration */
+        prev_list = cur_list;
+        prev_count = cur_count;
+    } while (changes);
 
+    /* Deallocate the last-allocated list. */
+    for (i = 0; i < prev_count; i++)
+        mach_port_deallocate(self, prev_list[i]);
 
-/*
- * If building for Bsd native threads, open up the /proc file
- * descriptor to be used when doing GC. The open is done at JVM start-up so
- * as to reserve this fd, to prevent GC stall due to exhausted fds. This fd
- * will never be closed, and will alwyas be present.
- */
-int
-np_initialize()
-{
-    char procname[32];
-    MakeProcName(procname, getpid());
-    if ((procfd = open(procname, O_RDONLY, 0)) < 0) {
-        VM_CALL(jio_fprintf)(stderr, "Cannot open %s for GC", procname);
-        return SYS_ERR;
-    }
+    vm_deallocate(self, (vm_address_t)prev_list, sizeof(thread_t) * prev_count);
+
+    /* Record registers and return */
+    record_thread_regs();
     return SYS_OK;
 }
-
-static void
-MakeProcName(register char *procname, register pid_t pid)
-{
-    register char * s;
-
-    (void) strcpy(procname, "/proc/00000");
-    s = procname + strlen(procname);
-    while (pid) {
-        *--s = pid%10 + '0';
-        pid /= 10;
-    }
-}
-
-/*
- * Suspend all other threads, and record their contexts (register
- * set or stack pointer) into the sys_thread structure, so that a
- * garbage collect can be run.
- */
+#else
 int
 np_single(void)
 {
-    int ret;
-
     sysAssert(SYS_QUEUE_LOCKED(sysThreadSelf()));
 
-    stop_lwps();
-    ret = SYS_OK;
-    return ret;
+    pthread_suspend_all_np();
+    record_thread_regs();
+    return SYS_OK;
 }
+#endif
 
 /*
- * Continue threads suspended earlier.  But clear their context
- * recorded in sys_thread structure first.
+ * Continue threads suspended earlier.
  */
+#ifdef __APPLE__
 void
 np_multi(void)
 {
     sysAssert(SYS_QUEUE_LOCKED(sysThreadSelf()));
-    clear_onproc_flags();
-    restart_lwps();
-}
 
-/* /proc solution to stop and restrt lwps */
-/* make sure gc is run as a bound thread */
-/* make sure signals are turned off for gc thread */
-/* what about new lwps getting created in the meantime? */
+    mach_msg_type_number_t      thr_count, i;
+    thread_act_array_t          thr_list;
+    mach_port_t                 self;
 
-#define MAX_LWPS 1024
+    self = pthread_mach_thread_np(pthread_self());
 
-static prstatus_t Mystatus;
-static id_t lwpid_list_buf[MAX_LWPS];
-static id_t oldlwpid_list_buf[MAX_LWPS];
-static sys_thread_t *onproct_list_buf[MAX_LWPS];
-static id_t *lwpid_list = lwpid_list_buf;
-static id_t *oldlwpid_list = oldlwpid_list_buf;
-static sys_thread_t **onproct_list = onproct_list_buf;
-static int lwpid_list_len;
-static int oldlwpid_list_len;
-static int onproct_ix = 0;
-static int gcprio;
-static sigset_t gcmask;
+    /* Get a list of all threads. This has to succeed! */
+    if (task_threads(self, &thr_list, &thr_count) != KERN_SUCCESS)
+        abort();
 
-static void
-clear_onproc_flags()
-{
-    int i;
+    /* Iterate over all the threads in the task, unsuspend, and deallocate */
+    for (i = 0; i < thr_count; i++) {
+        // XXXDARWIN: Assumes that the current thread was the thread used
+        // to call np_single. Is that true?
 
-    for (i = 0; i < onproct_ix; i++) {
-        ((sys_thread_t *)(onproct_list[i]))->onproc = FALSE;
+        if (thr_list[i] != self)
+            thread_resume(thr_list[i]);
+
+        mach_port_deallocate(self, thr_list[i]);
     }
-    onproct_ix = 0;
-}
 
-
-/* Sleep for n milliseconds, n < 1000   */
-static void
-GC_msec_sleep(int n)
+    vm_deallocate(self, (vm_address_t) thr_list, sizeof(thread_t) * thr_count);
+}
+#else
+void
+np_multi(void)
 {
-    struct timespec ts;
-
-    ts.tv_sec = 0;
-    ts.tv_nsec = 1000000*n;
-    if (syscall(SYS_nanosleep, &ts, 0) < 0) {
-        VM_CALL(jio_fprintf)(stderr, "%d\n", errno);
-    }
+    sysAssert(SYS_QUEUE_LOCKED(sysThreadSelf()));
+    pthread_resume_all_np();
 }
+#endif
 
 /*
+ * BSDNOTE: Looking to linux implementation -- the only important register
+ * to set up is tid->sp (stack pointer) now.  But it may change when
+ * FreeBSD and JVM will switch to KSEs.  In this case we'll also need to
+ * care about ucontext I think.
+ *
+ * --phantom
+ *
+ * XXXBSD: There's a problem with this implemenation. Currently it sets
+ * the tid->sp to the bottom of the thread stack and not the current stack
+ * pointer of the suspended thread. Both solaris and linux use the current
+ * thread stack pointer. -- kurt
+ *
  * Assumes stacks grow down from high to low memory. True on sparc and Intel.
  */
-#define VALID_SP(sp, bottom, top) \
-       (((uintptr_t)(sp)) < ((uintptr_t)(bottom)) && ((uintptr_t)(sp)) > ((uintptr_t)(top)))
 
 static void
-record_lwp_regs(prstatus_t lwpstatus)
+record_thread_regs()
 {
+    void *addr;
+    long sz;
+
     sys_thread_t *tid;
     int i;
-#if   defined(sparc)
-    register uintptr_t sp = lwpstatus.pr_reg[R_SP];
-#elif defined(amd64)
-    register uintptr_t sp = lwpstatus.pr_reg[REG_RSP];
-#elif defined(i386)
-    register uintptr_t sp = lwpstatus.pr_reg[UESP];
-#endif
+    int sp;
 
-    tid = ThreadQueue;
-    for (i = 0; i < ActiveThreadCount && tid != 0; i++) {
-        if (VALID_SP(sp, tid->stack_bottom, tid->stack_top)) {
-            long *regs = tid->regs;
-            tid->sp = sp;
-            /*
-             * The code below relies on N_TRACED_REGS being set
-             * correctly for each platform.  If you change the
-             * number of registers being watched, you should update
-             * the define for N_TRACED_REGS
-             */
-#if   defined(sparc)
-            regs[0] = lwpstatus.pr_reg[R_G1];
-            regs[1] = lwpstatus.pr_reg[R_G2];
-            regs[2] = lwpstatus.pr_reg[R_G3];
-            regs[3] = lwpstatus.pr_reg[R_G4];
-
-            regs[4] = lwpstatus.pr_reg[R_O0];
-            regs[5] = lwpstatus.pr_reg[R_O1];
-            regs[6] = lwpstatus.pr_reg[R_O2];
-            regs[7] = lwpstatus.pr_reg[R_O3];
-            regs[8] = lwpstatus.pr_reg[R_O4];
-            regs[9] = lwpstatus.pr_reg[R_O5];
-            regs[10] = lwpstatus.pr_reg[R_O6];
-            regs[11] = lwpstatus.pr_reg[R_O7];
-#elif defined(amd64)
-            regs[0] = lwpstatus.pr_reg[REG_RAX];
-            regs[1] = lwpstatus.pr_reg[REG_RCX];
-            regs[2] = lwpstatus.pr_reg[REG_RDX];
-            regs[3] = lwpstatus.pr_reg[REG_RBX];
-            regs[4] = lwpstatus.pr_reg[REG_RBP];
-            regs[5] = lwpstatus.pr_reg[REG_RSI];
-            regs[6] = lwpstatus.pr_reg[REG_RDI];
-            regs[7] = lwpstatus.pr_reg[REG_R8];
-            regs[8] = lwpstatus.pr_reg[REG_R9];
-            regs[9] = lwpstatus.pr_reg[REG_R10];
-            regs[10]= lwpstatus.pr_reg[REG_R11];
-            regs[11]= lwpstatus.pr_reg[REG_R12];
-            regs[12]= lwpstatus.pr_reg[REG_R13];
-            regs[13]= lwpstatus.pr_reg[REG_R14];
-            regs[14]= lwpstatus.pr_reg[REG_R15];
-#elif defined(i386)
-            regs[0] = lwpstatus.pr_reg[EAX];
-            regs[1] = lwpstatus.pr_reg[ECX];
-            regs[2] = lwpstatus.pr_reg[EDX];
-            regs[3] = lwpstatus.pr_reg[EBX];
-            regs[4] = lwpstatus.pr_reg[EBP];
-            regs[5] = lwpstatus.pr_reg[ESI];
-            regs[6] = lwpstatus.pr_reg[EDI];
+#ifndef __OpenBSD__
+    pthread_attr_t attr;
+    int attr_inited;
+    attr_inited = pthread_attr_init(&attr) == 0;
 #endif
 
-            if (tid->onproc != TRUE) {
-                tid->onproc = TRUE;
-                onproct_list[onproct_ix++] = tid;
-            }
-            break;
-        }
-        tid = tid->next;
-    }
-}
-
-static void
-record_thread_regs()
-{
-    sys_thread_t *tid;
-    int i;
-
     tid = ThreadQueue;
     for (i = 0; i < ActiveThreadCount && tid != 0; i++) {
         if (tid->onproc != TRUE) {
@@ -466,7 +377,14 @@ record_thread_regs()
 
             if (tid->sys_thread != 0) {
                 /* if thread has already been initialized */
-                tid->sp = __gettsp(tid->sys_thread);
+#if defined(__OpenBSD__) || defined(__APPLE__)
+            if (get_stackinfo(tid->sys_thread, &addr, &sz) == SYS_OK)
+#else
+            if (get_stackinfo(tid->sys_thread, attr, &addr, &sz) == SYS_OK)
+#endif
+                tid->sp = addr;
+            else
+                tid->sp = 0;
             } else {
                 /*
                  * thread is still in the process of being initalized.
@@ -475,192 +393,11 @@ record_thread_regs()
                  */
                 tid->sp = 0;
             }
-
-            /*
-             * Clear out the registers since they are no longer live
-             * and we don't want to garbage collector to think they are.
-             */
-
-            for (i = 0; i < N_TRACED_REGS; i++)
-                tid->regs[i] = 0;
         }
         tid = tid->next;
     }
-}
-
-static void
-wait_stopped_lwps(void)
-{
-    int i, lwpfd;
-    prstatus_t lwpstatus;
-
-    for (i = 0; i < (int) Mystatus.pr_nlwp; i++) {
-        /* if its  not me */
-        if (lwpid_list[i] != _lwp_self()) {
-
-            /* open the lwp and check the status */
-            if ((lwpfd = syscall(SYS_ioctl, procfd, PIOCOPENLWP,
-                &lwpid_list[i])) < 0) {
-#ifdef MY_DEBUG
-                VM_CALL(jio_fprintf)(stderr, "lwpid %d was not found in process\n",
-                            lwpid_list[i]);
+#ifndef __OpenBSD__
+    if (attr_inited)
+        pthread_attr_destroy(&attr);
 #endif
-                continue;
-            }
-            memset(&lwpstatus, 0, sizeof(lwpstatus));
-            while (1) {
-                if (syscall(SYS_ioctl,lwpfd, PIOCSTATUS, &lwpstatus)<0) {
-                    sysAssert(0);
-#ifdef MY_DEBUG
-                    VM_CALL(jio_fprintf)(stderr, "PIOCSTATUS failed for lwp %d",
-                                lwpid_list[i]);
-#endif
-                    break;
-                }
-                if (lwpstatus.pr_flags & PR_STOPPED) {
-                    record_lwp_regs(lwpstatus);
-                    break;
-                }
-                GC_msec_sleep(1);
-            }
-
-            close (lwpfd);
-        } /* end of if-me */
-    } /* end of for */
-}
-
-static void
-suspend_lwps()
-{
-    int i;
-    /* pioopen all the lwps and stop them - except the one I am running on */
-    for (i = 0; i < (int) Mystatus.pr_nlwp; i++) {
-
-        /* open and stop the lwp if its not me */
-        if (lwpid_list[i] != _lwp_self()) {
-
-            /* PIOCSTOP doesn't work without a writable         */
-            /* descriptor.  And that makes the process          */
-            /* undebuggable.                                    */
-            if (_lwp_suspend(lwpid_list[i]) < 0) {
-                        /* Could happen if the lwp exited */
-                lwpid_list[i] = _lwp_self();
-                continue;
-            }
-        }
-    }
-}
-
-static void
-print_lwps()
-{
-#ifdef MY_DEBUG
-    /* print all the lwps in the process */
-    VM_CALL(jio_fprintf)(stdout, "lwpids ");
-    for (i = 0; i < (int) Mystatus.pr_nlwp; i++) {
-        if (i == 0) {
-            VM_CALL(jio_fprintf)(stdout, "%d", lwpid_list[0]);
-        } else if (i != Mystatus.pr_nlwp - 1) {
-            VM_CALL(jio_fprintf)(stdout, ", %d", lwpid_list[i]);
-        } else {
-            VM_CALL(jio_fprintf)(stdout, " and %d", lwpid_list[i]);
-        }
-    }
-#endif
-}
-
-/* routine to iteratively stop all lwps */
-static void
-stop_lwps()
-{
-    int i;
-    sigset_t set;
-    boolean_t changed;
-
-    /* mask all signals */
-    (void) sigfillset(&set);
-    syscall(SYS_sigprocmask, SIG_SETMASK, &set, &gcmask);
-
-    /* run at highest prio so I cannot be preempted */
-    thr_getprio(thr_self(), &gcprio);
-    thr_setprio(thr_self(), 2147483647);  /* #define INT_MAX 2147483647 */
-
-    oldlwpid_list_len = 0;
-
-    while(1) {
-        changed = B_FALSE;
-
-        /* Get the # of lwps in the process */
-        memset(&Mystatus, 0, sizeof(Mystatus));
-        syscall(SYS_ioctl, procfd, PIOCSTATUS, &Mystatus);
-
-#ifdef MY_DEBUG
-        VM_CALL(jio_fprintf)(stdout, "Number of lwps in the process is %d\n",
-                    Mystatus.pr_nlwp);
-        VM_CALL(jio_fprintf)(stdout, "My lwp id is %d\n", _lwp_self());
-#endif
-        lwpid_list_len = Mystatus.pr_nlwp;
-        if (syscall(SYS_ioctl, procfd, PIOCLWPIDS, lwpid_list) == -1) {
-#ifdef MY_DEBUG
-            VM_CALL(jio_fprintf)(stderr, "Can't read proc's lwpid list");
-#endif
-            return;
-        }
-
-        print_lwps();
-
-        /* suspend all the lwps */
-        suspend_lwps();
-
-        /* make sure all the lwps have actually stopped */
-        wait_stopped_lwps();
-
-        /* make sure the list has not changed while you were not looking
-           else start all over again */
-        if (lwpid_list_len != oldlwpid_list_len) changed = B_TRUE;
-        else  {
-            for (i=0; i<lwpid_list_len; ++i) {
-                if (lwpid_list[i] != oldlwpid_list[i]) {
-                    changed = B_TRUE; break;
-                }
-            }
-        }
-        if (!changed) break;
-
-        {
-            id_t *tmplwpid_list = oldlwpid_list;
-            oldlwpid_list = lwpid_list; oldlwpid_list_len = lwpid_list_len;
-            lwpid_list = 0; lwpid_list_len = 0;
-            lwpid_list = tmplwpid_list;
-        }
-    }
-
-    /* record regs for threads that were not on LWPs */
-    record_thread_regs();
-
-    return;
-}
-
-
-/* Restart all lwps in process.  */
-static void
-restart_lwps()
-{
-    int i;
-
-    for (i = 0; i < Mystatus.pr_nlwp; i++) {
-        if (lwpid_list[i] == _lwp_self()) continue;
-        if (_lwp_continue(lwpid_list[i]) < 0) {
-#ifdef MY_DEBUG
-            VM_CALL(jio_fprintf)(stderr, "Failed to restart lwp %d\n",lwpid_list[i]);
-#endif
-        }
-    }
-
-    /* restore the old priority of the thread */
-    thr_setprio(thr_self(), gcprio);
-    /* restore the oldmask */
-    syscall(SYS_sigprocmask, SIG_SETMASK, &gcmask, NULL);
-
-    print_lwps();
 }
