You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@harmony.apache.org by ge...@apache.org on 2005/12/01 07:04:00 UTC

svn commit: r350181 [165/198] - in /incubator/harmony/enhanced/trunk/sandbox/contribs/ibm_core: ./ depends/ depends/files/ depends/jars/ depends/libs/ depends/libs/linux.IA32/ depends/libs/win.IA32/ depends/oss/ depends/oss/linux.IA32/ depends/oss/win....

Added: incubator/harmony/enhanced/trunk/sandbox/contribs/ibm_core/native-src/linux.IA32/thread/hythread.c
URL: http://svn.apache.org/viewcvs/incubator/harmony/enhanced/trunk/sandbox/contribs/ibm_core/native-src/linux.IA32/thread/hythread.c?rev=350181&view=auto
==============================================================================
--- incubator/harmony/enhanced/trunk/sandbox/contribs/ibm_core/native-src/linux.IA32/thread/hythread.c (added)
+++ incubator/harmony/enhanced/trunk/sandbox/contribs/ibm_core/native-src/linux.IA32/thread/hythread.c Wed Nov 30 21:29:27 2005
@@ -0,0 +1,3682 @@
+/* Copyright 1991, 2005 The Apache Software Foundation or its licensors, as applicable
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * @file
+ * @ingroup Thread
+ * @brief Threading and synchronization support
+ */
+
+#include "threaddef.h"
+#include <stdlib.h>
+
+#define CDEV_CURRENT_FUNCTION _prototypes_private
+static hythread_t allocate_thread PROTOTYPE ((int globalIsLocked));
+static void free_thread
+PROTOTYPE ((hythread_t thread, int globalAlreadyLocked));
+static IDATA interrupt_waiting_thread
+PROTOTYPE ((hythread_t self, hythread_t threadToInterrupt));
+static void remove_from_queue
+PROTOTYPE ((hythread_t volatile *queue, hythread_t thread));
+static IDATA destroy_thread
+PROTOTYPE ((hythread_t thread, int globalAlreadyLocked));
+void VMCALL hythread_shutdown PROTOTYPE ((void));
+static void HYTHREAD_PROC tls_null_finalizer PROTOTYPE ((void *entry));
+static I_32 HYTHREAD_PROC interruptServer PROTOTYPE ((void *entryArg));
+static hythread_monitor_t VMCALL hythread_monitor_acquire
+PROTOTYPE ((hythread_t self, IDATA policy, IDATA policyData));
+void VMCALL hythread_init PROTOTYPE ((hythread_library_t lib));
+static IDATA init_global_monitor PROTOTYPE ((hythread_library_t lib));
+static void tls_finalize PROTOTYPE ((hythread_t thread));
+static void free_monitor_pools PROTOTYPE ((void));
+static void *VMCALL thread_malloc PROTOTYPE ((void *unused, U_32 size));
+static void NORETURN internal_exit PROTOTYPE ((void));
+static IDATA monitor_wait
+PROTOTYPE ((hythread_monitor_t monitor, I_64 millis, IDATA nanos,
+            IDATA interruptable));
+static IDATA monitor_enter
+PROTOTYPE ((hythread_t self, hythread_monitor_t monitor));
+static UDATA init_monitor
+PROTOTYPE ((hythread_monitor_t monitor, UDATA flags));
+
+static IDATA monitor_enter_three_tier
+PROTOTYPE ((hythread_t self, hythread_monitor_t monitor));
+
+static hytime_t getCurrentCycles PROTOTYPE ((void));
+static hythread_monitor_pool_t allocate_monitor_pool PROTOTYPE ((void));
+static IDATA create_thread
+PROTOTYPE ((hythread_t * handle, UDATA stacksize, UDATA priority,
+            UDATA suspend, hythread_entrypoint_t entrypoint, void *entryarg,
+            int globalIsLocked));
+static void interrupt_thread
+PROTOTYPE ((hythread_t thread, UDATA interruptFlag));
+
+static void unblock_spinlock_threads
+PROTOTYPE ((hythread_t self, hythread_monitor_t monitor));
+
+static void notify_thread
+PROTOTYPE ((hythread_t threadToNotify, int setNotifiedFlag));
+static IDATA monitor_exit
+PROTOTYPE ((hythread_t self, hythread_monitor_t monitor));
+static WRAPPER_TYPE thread_wrapper PROTOTYPE ((WRAPPER_ARG arg));
+static void VMCALL thread_free PROTOTYPE ((void *unused, void *ptr));
+static void enqueue_thread
+PROTOTYPE ((hythread_t * queue, hythread_t thread));
+static IDATA monitor_notify_one_or_all
+PROTOTYPE ((hythread_monitor_t monitor, int notifyall));
+
+#undef CDEV_CURRENT_FUNCTION
+
+#if defined(THREAD_ASSERTS)
+/*
+ * Helper variable for asserts.
+ * We use this to keep track of when the global lock is owned.
+ * We don't want to do a re-entrant enter on the global lock 
+ */
+hythread_t global_lock_owner = UNOWNED;
+#endif
+
+#define BOUNDED_I64_TO_IDATA(longValue) ((longValue) > 0x7FFFFFFF ? 0x7FFFFFFF : (IDATA)(longValue))
+
+#define HYTHREAD_MAX_TLS_KEYS (sizeof( ((HyThreadLibrary*)NULL)->tls_finalizers ) / sizeof( ((HyThreadLibrary*)NULL)->tls_finalizers[0] ))
+
+#define CDEV_CURRENT_FUNCTION hythread_init
+/**
+ * Initialize a Hy threading library.
+ * 
+ * @note This must only be called once.
+ * 
+ * If any OS threads were created before calling this function, they must be attached using
+ * hythread_attach before accessing any Hy thread library functions. 
+ * 
+ * @param[in] lib pointer to the Hy thread library to be initialized (non-NULL)
+ * @return The Hy thread library's initStatus will be set to 0 on success or 
+ * a negative value on failure.
+ * 
+ * @see hythread_attach, hythread_shutdown
+ */
+void VMCALL
+hythread_init (hythread_library_t lib)
+{
+  ASSERT (lib);
+
+  lib->spinlock = 0;
+  lib->threadCount = 0;
+  lib->globals = NULL;
+  lib->stack_usage = 0;
+
+  /* set all TLS finalizers to NULL. This indicates that the key is unused */
+  memset (lib->tls_finalizers, 0, sizeof (lib->tls_finalizers));
+
+  STATIC_ASSERT (CALLER_LAST_INDEX <= MAX_CALLER_INDEX);
+
+  if (TLS_ALLOC (lib->self_ptr))
+    goto init_cleanup1;
+
+  lib->monitor_pool = allocate_monitor_pool ();
+  if (lib->monitor_pool == NULL)
+    goto init_cleanup2;
+
+  if (!MUTEX_INIT (lib->monitor_mutex))
+    goto init_cleanup3;
+  if (!MUTEX_INIT (lib->tls_mutex))
+    goto init_cleanup4;
+  if (!MUTEX_INIT (lib->global_mutex))
+    goto init_cleanup5;
+
+  lib->thread_pool =
+    pool_new (sizeof (HyThread), 0, 0, 0, thread_malloc, thread_free, NULL);
+  if (lib->thread_pool == NULL)
+    goto init_cleanup6;
+
+  lib->global_pool =
+    pool_new (sizeof (HyThreadGlobal), 0, 0, 0, thread_malloc, thread_free,
+              NULL);
+  if (lib->global_pool == NULL)
+    goto init_cleanup7;
+
+  if (init_global_monitor (lib))
+    goto init_cleanup8;
+
+  lib->initStatus = 1;
+  return;
+
+init_cleanup8:pool_kill (lib->global_pool);
+init_cleanup7:pool_kill (lib->thread_pool);
+init_cleanup6:MUTEX_DESTROY (lib->global_mutex);
+init_cleanup5:MUTEX_DESTROY (lib->tls_mutex);
+init_cleanup4:MUTEX_DESTROY (lib->monitor_mutex);
+init_cleanup3:free_monitor_pools ();
+init_cleanup2:TLS_DESTROY (lib->self_ptr);
+init_cleanup1:lib->initStatus = -1;
+}
+
+#undef CDEV_CURRENT_FUNCTION
+
+#define CDEV_CURRENT_FUNCTION hythread_self
+/** 
+ * Return the hythread_t for the current thread.
+ * 
+ * @note Must be called only by an attached thread
+ * 
+ * @return hythread_t for the current thread
+ *
+ * @see hythread_attach
+ * 
+ */
+hythread_t VMCALL
+hythread_self (void)
+{
+  return MACRO_SELF ();
+}
+
+#undef CDEV_CURRENT_FUNCTION
+
+#define CDEV_CURRENT_FUNCTION hythread_create
+/**
+ * Create a new OS thread.
+ * 
+ * The created thread is attached to the threading library.<br>
+ * <br>
+ * Unlike POSIX, this doesn't require an attributes structure.
+ * Instead, any interesting attributes (e.g. stacksize) are
+ * passed in with the arguments.
+ *
+ * @param[out] handle a pointer to a hythread_t which will point to the thread (if successfully created)
+ * @param[in] stacksize the size of the new thread's stack (bytes)<br>
+ *			0 indicates use default size
+ * @param[in] priority priorities range from HYTHREAD_PRIORITY_MIN to HYTHREAD_PRIORITY_MAX (inclusive)
+ * @param[in] suspend set to non-zero to create the thread in a suspended state.
+ * @param[in] entrypoint pointer to the function which the thread will run
+ * @param[in] entryarg a value to pass to the entrypoint function
+ *
+ * @return  0 on success or negative value on failure
+ *
+ * @see hythread_exit, hythread_resume
+ */
+IDATA VMCALL
+hythread_create (hythread_t * handle, UDATA stacksize, UDATA priority,
+                 UDATA suspend, hythread_entrypoint_t entrypoint,
+                 void *entryarg)
+{
+  return create_thread (handle, stacksize, priority, suspend, entrypoint,
+                        entryarg, GLOBAL_NOT_LOCKED);
+}
+
+#undef CDEV_CURRENT_FUNCTION
+
+#define CDEV_CURRENT_FUNCTION create_thread
+/*
+ * Create a new OS thread and attach it.
+ */
+static IDATA
+create_thread (hythread_t * handle, UDATA stacksize, UDATA priority,
+               UDATA suspend, hythread_entrypoint_t entrypoint,
+               void *entryarg, int globalIsLocked)
+{
+  hythread_t thread;
+  hythread_library_t lib = GLOBAL_DATA (default_library);
+
+  ASSERT (lib->initStatus);
+
+  if (priority > HYTHREAD_PRIORITY_MAX)
+    {
+      goto cleanup0;
+    }
+
+  if (stacksize == 0)
+    {
+      stacksize = STACK_DEFAULT_SIZE;
+    }
+
+  thread = allocate_thread (globalIsLocked);
+  if (!thread)
+    {
+      goto cleanup0;
+    }
+  if (handle)
+    {
+      *handle = thread;
+    }
+  thread->library = lib;
+  thread->priority = priority;
+  thread->attachcount = 0;
+  thread->stacksize = stacksize;
+
+  memset (thread->tls, 0, sizeof (thread->tls));
+
+  thread->interrupter = NULL;
+
+  if (!COND_INIT (thread->condition))
+    {
+      goto cleanup1;
+    }
+  if (!MUTEX_INIT (thread->mutex))
+    {
+      goto cleanup2;
+    }
+
+  thread->flags = suspend ? HYTHREAD_FLAG_SUSPENDED : 0;
+  thread->entrypoint = entrypoint;
+  thread->entryarg = entryarg;
+
+  if (IS_JLM_ENABLED (thread))
+    {
+      hythread_jlm_thread_init (thread);
+    }
+
+#if defined(LINUX)
+  thread->jumpBuffer = NULL;
+#endif
+
+  if (!THREAD_CREATE (thread, stacksize, priority, thread_wrapper, thread))
+    {
+      goto cleanup3;
+    }
+
+  return 0;
+
+/* Cleanup points */
+cleanup3:MUTEX_DESTROY (thread->mutex);
+cleanup2:COND_DESTROY (thread->condition);
+cleanup1:free_thread (thread, GLOBAL_NOT_LOCKED);
+cleanup0:if (handle)
+    *handle = NULL;
+  return -1;
+}
+
+#undef CDEV_CURRENT_FUNCTION
+
+#define CDEV_CURRENT_FUNCTION hythread_attach
+/**
+ * Attach an OS thread to the threading library.
+ * 
+ * Create a new hythread_t to represent the existing OS thread.
+ * Attaching a thread is required when a thread was created 
+ * outside of the Hy threading library wants to use any of the 
+ * Hy threading library functionality.
+ *
+ * If the OS thread is already attached, handle is set to point 
+ * to the existing hythread_t.
+ *
+ * @param[out] handle pointer to a hythread_t to be set (will be ignored if null)
+ * @return  0 on success or negative value on failure
+ *
+ * @see hythread_detach
+ */
+IDATA VMCALL
+hythread_attach (hythread_t * handle)
+{
+  hythread_t thread;
+
+  if (init_thread_library ())
+    {
+      goto cleanup0;
+    }
+
+  if ((thread = MACRO_SELF ()) != NULL)
+    {
+      if (handle)
+        {
+          *handle = thread;
+        }
+      THREAD_LOCK (thread, thread, CALLER_ATTACH);
+      thread->attachcount++;
+      THREAD_UNLOCK (thread, thread);
+      return 0;
+    }
+
+  thread = allocate_thread (GLOBAL_NOT_LOCKED);
+  if (!thread)
+    {
+      goto cleanup0;
+    }
+
+  thread->library = GLOBAL_DATA (default_library);
+  thread->attachcount = 1;
+  thread->priority = HYTHREAD_PRIORITY_NORMAL;
+  thread->flags = HYTHREAD_FLAG_ATTACHED;
+
+  if (!COND_INIT (thread->condition))
+    {
+      goto cleanup1;
+    }
+
+  if (!MUTEX_INIT (thread->mutex))
+    {
+      goto cleanup2;
+    }
+
+#if defined(WIN32)
+  {
+    DuplicateHandle (GetCurrentProcess (), GetCurrentThread (),
+                     GetCurrentProcess (), &thread->handle, 0, TRUE,
+                     DUPLICATE_SAME_ACCESS);
+  }
+#else
+  thread->handle = THREAD_SELF ();
+#endif
+
+  initialize_thread_priority (thread);
+
+  TLS_SET (thread->library->self_ptr, thread);
+
+  thread->tid = RAS_THREAD_ID ();
+
+  if (handle)
+    {
+      *handle = thread;
+    }
+  return 0;
+
+/* failure points */
+cleanup2:COND_DESTROY (thread->condition);
+cleanup1:free_thread (thread, GLOBAL_NOT_LOCKED);
+cleanup0:return -1;
+}
+
+#undef CDEV_CURRENT_FUNCTION
+
+#define CDEV_CURRENT_FUNCTION hythread_suspend
+/**
+ * Suspend the current thread. 
+ * 
+ * Stop the current thread from executing until it is resumed.
+ * 
+ * @return none
+ *
+ * @see hythread_resume
+ */
+void VMCALL
+hythread_suspend (void)
+{
+  hythread_t self = MACRO_SELF ();
+  ASSERT (self);
+
+  THREAD_LOCK (self, self, CALLER_SUSPEND);
+  self->flags |= HYTHREAD_FLAG_SUSPENDED;
+
+  COND_WAIT (self->condition, self->mutex);
+  if ((self->flags & HYTHREAD_FLAG_SUSPENDED) == 0)
+    break;
+  COND_WAIT_LOOP ();
+
+  THREAD_UNLOCK (self, self);
+}
+
+#undef CDEV_CURRENT_FUNCTION
+
+#define CDEV_CURRENT_FUNCTION hythread_resume
+/**
+ * Resume a thread. 
+ *
+ * Take a threads out of the suspended state. 
+ * 
+ * If the thread is not suspended, no action is taken.
+ *
+ * @param[in] thread a thread to be resumed
+ * @return none
+ * 
+ * @see hythread_create, hythread_suspend
+ */
+void VMCALL
+hythread_resume (hythread_t thread)
+{
+  hythread_t self;
+
+  ASSERT (thread);
+
+  if ((thread->flags & HYTHREAD_FLAG_SUSPENDED) == 0)
+    {
+      /* it wasn't suspended! */
+      return;
+    }
+
+  self = MACRO_SELF ();
+  ASSERT (self);
+
+  THREAD_LOCK (self, thread, CALLER_RESUME);
+
+  /* 
+   * The thread _should_ only be OS suspended once, but
+   * handle the case where it's suspended more than once anyway.
+   */
+  COND_NOTIFY_ALL (thread->condition);
+  thread->flags &= ~HYTHREAD_FLAG_SUSPENDED;
+
+  THREAD_UNLOCK (self, thread);
+}
+
+#undef CDEV_CURRENT_FUNCTION
+
+#define CDEV_CURRENT_FUNCTION hythread_yield
+/** 
+ * Yield the processor.
+ * 
+ * @return none
+ */
+void VMCALL
+hythread_yield (void)
+{
+  THREAD_YIELD ();
+}
+
+#undef CDEV_CURRENT_FUNCTION
+
+#define CDEV_CURRENT_FUNCTION hythread_monitor_init
+/*
+ * Acquire and initialize a new monitor from the threading library.
+ *
+ * @param[out] handle pointer to a hythread_monitor_t to be set to point to the new monitor
+ * @param[in] flags initial flag values for the monitor
+ * @return 0 on success, negative value on failure
+ * 
+ * @deprecated This has been replaced by hythread_monitor_init_with_name
+ * @see hythread_monitor_init_with_name
+ */
+IDATA VMCALL
+hythread_monitor_init (hythread_monitor_t * handle, UDATA flags)
+{
+  IDATA rc;
+
+  /* Initialize monitor with default locking policy */
+  rc =
+    hythread_monitor_init_policy (handle, flags, HYTHREAD_LOCKING_DEFAULT,
+                                  HYTHREAD_LOCKING_NO_DATA);
+  return rc;
+}
+
+#undef CDEV_CURRENT_FUNCTION
+
+#define CDEV_CURRENT_FUNCTION hythread_monitor_init_policy
+/*
+ * Acquire and initialize a new monitor with given locking policy from the threading library.
+ *
+ * @param[out] handle pointer to a hythread_monitor_t to be set to point to the new monitor
+ * @param[in] flags initial flag values for the monitor
+ * @param[in] locking policy for the monitor 
+ * @param[in] data associated with locking policy or HYTHREAD_LOCKING_NO_DATA
+ * @return 0 on success, negative value on failure
+ * 
+ */
+IDATA VMCALL
+hythread_monitor_init_policy (hythread_monitor_t * handle, UDATA flags,
+                              IDATA policy, IDATA policyData)
+{
+  hythread_monitor_t monitor;
+
+  hythread_t self = MACRO_SELF ();
+  ASSERT (self);
+  ASSERT (handle);
+
+  monitor = hythread_monitor_acquire (self, policy, policyData);
+  if (NULL == monitor)
+    {
+      return -1;
+    }
+
+  if (init_monitor (monitor, flags) != 0)
+    {
+      return -1;
+    }
+
+  if (IS_JLM_ENABLED (self))
+    {
+      hythread_jlm_monitor_init (monitor);
+    }
+
+  *handle = monitor;
+  return 0;
+}
+
+#undef CDEV_CURRENT_FUNCTION
+
+#define CDEV_CURRENT_FUNCTION hythread_monitor_destroy
+/**
+ * Destroy a monitor.
+ * 
+ * Destroying a monitor frees the internal resources associated
+ * with it.
+ *
+ * @note A monitor must NOT be destroyed if threads are waiting on
+ * it, or if it is currently owned.
+ *
+ * @param[in] monitor a monitor to be destroyed
+ * @return  0 on success or non-0 on failure (the monitor is in use)
+ * 
+ * @see hythread_monitor_init_with_name
+ */
+IDATA VMCALL
+hythread_monitor_destroy (hythread_monitor_t monitor)
+{
+  hythread_t self = MACRO_SELF ();
+
+  ASSERT (self);
+  ASSERT (monitor);
+
+  GLOBAL_LOCK (self, CALLER_MONITOR_DESTROY);
+
+  if (monitor->owner || monitor->waiting)
+    {
+      /* This monitor is in use! It was probably abandoned when a thread was cancelled.
+       * There's actually a very small timing hole here -- if the thread had just locked the 
+       * mutex and not yet set the owner field when it was cancelled, we have no way of
+       * knowing that the mutex may be in an invalid state. The same thing can happen
+       * if the thread has just cleared the field and is about to unlock the mutex.
+       * Hopefully the OS takes care of this for us, but it might not.
+       */
+      GLOBAL_UNLOCK (self);
+      return HYTHREAD_ILLEGAL_MONITOR_STATE;
+    }
+
+  monitor->owner = (hythread_t) self->library->monitor_pool->next_free;
+  monitor->count = FREE_TAG;
+  monitor->userData = 0;
+  self->library->monitor_pool->next_free = monitor;
+
+  GLOBAL_UNLOCK (self);
+  return 0;
+}
+
+#undef CDEV_CURRENT_FUNCTION
+
+#define CDEV_CURRENT_FUNCTION hythread_monitor_enter
+/**
+ * Enter a monitor.
+ * 
+ * A thread may re-enter a monitor it owns multiple times, but must
+ * exit the monitor the same number of times before any other thread
+ * wanting to enter the monitor is permitted to continue.
+ *
+ * @param[in] monitor a monitor to be entered
+ * @return 0 on success<br>
+ * HYTHREAD_PRIORITY_INTERRUPTED if the thread was priority interrupted while blocked
+ * 
+ * @see hythread_monitor_enter_using_threadId, hythread_monitor_exit, hythread_monitor_exit_using_threadId
+ */
+IDATA VMCALL
+hythread_monitor_enter (hythread_monitor_t monitor)
+{
+  hythread_t self = MACRO_SELF ();
+
+  ASSERT (self);
+  ASSERT (monitor);
+  ASSERT (FREE_TAG != monitor->count);
+
+  if (monitor->owner == self)
+    {
+      ASSERT (monitor->count >= 1);
+      monitor->count++;
+
+      if (IS_JLM_ENABLED (self))
+        {
+          ASSERT (monitor->tracing);
+          monitor->tracing->recursive_count++;
+          monitor->tracing->enter_count++;
+        }                       /* if (IS_JLM_ENABLED(self)) */
+
+      return 0;
+    }
+
+  return monitor_enter (self, monitor);
+}
+
+#undef CDEV_CURRENT_FUNCTION
+
+#define CDEV_CURRENT_FUNCTION hythread_monitor_exit
+/**
+ * Exit a monitor.
+ * 
+ * Exit a monitor, and if the owning count is zero, release it.
+ *
+ * @param[in] monitor a monitor to be exited
+ * @return 0 on success, <br>HYTHREAD_ILLEGAL_MONITOR_STATE if the current thread does not own the monitor
+ * 
+ * @see hythread_monitor_exit_using_threadId, hythread_monitor_enter, hythread_monitor_enter_using_threadId
+ */
+IDATA VMCALL
+hythread_monitor_exit (hythread_monitor_t monitor)
+{
+  hythread_t self = MACRO_SELF ();
+
+  ASSERT (self);
+  ASSERT (monitor);
+  ASSERT (FREE_TAG != monitor->count);
+
+  if (monitor->owner != self)
+    {
+      return HYTHREAD_ILLEGAL_MONITOR_STATE;
+    }
+
+  return monitor_exit (self, monitor);
+}
+
+#undef CDEV_CURRENT_FUNCTION
+
+#define CDEV_CURRENT_FUNCTION hythread_monitor_wait
+/** 
+ * Wait on a monitor until notified.
+ *
+ * Release the monitor, wait for a signal (notification), then re-acquire the monitor.
+ * 
+ * @param[in] monitor a monitor to be waited on
+ * @return 0 if the monitor has been waited on, notified, and reobtained<br>
+ * HYTHREAD_INVALID_ARGUMENT if millis or nanos is out of range (millis or nanos < 0, or nanos >= 1E6)<br>
+ * HYTHREAD_ILLEGAL_MONITOR_STATE if the current thread does not own the monitor
+ * 
+ * @see hythread_monitor_wait_interruptable, hythread_monitor_wait_timed, hythread_monitor_enter
+ * 
+ */
+IDATA VMCALL
+hythread_monitor_wait (hythread_monitor_t monitor)
+{
+  return monitor_wait (monitor, 0, 0, WAIT_UNINTERRUPTABLE);
+}
+
+#undef CDEV_CURRENT_FUNCTION
+
+#define CDEV_CURRENT_FUNCTION hythread_monitor_notify
+/**
+ * Notify a single thread waiting on a monitor.
+ * 
+ * A thread is considered to be waiting on the monitor if 
+ * it is currently blocked while executing hythread_monitor_wait on the monitor.
+ * 
+ * If no threads are waiting, no action is taken.
+ *
+ * @param[in] monitor a monitor to be signaled
+ * @return  0 once the monitor has been signaled<br>HYTHREAD_ILLEGAL_MONITOR_STATE if the current thread does not own the monitor
+ * 
+ * @see hythread_monitor_notify_all, hythread_monitor_enter, hythread_monitor_wait
+ */
+IDATA VMCALL
+hythread_monitor_notify (hythread_monitor_t monitor)
+{
+  return monitor_notify_one_or_all (monitor, NOTIFY_ONE);
+}
+
+#undef CDEV_CURRENT_FUNCTION
+
+#define CDEV_CURRENT_FUNCTION hythread_monitor_notify_all
+/**
+ * Notify all threads waiting on a monitor.
+ * 
+ * A thread is considered to be waiting on the monitor if 
+ * it is currently blocked while executing hythread_monitor_wait on the monitor.
+ * 
+ * If no threads are waiting, no action is taken.
+ *
+ *
+ * @param[in] monitor a monitor to be signaled
+ * @return  0 once the monitor has been signaled<br>HYTHREAD_ILLEGAL_MONITOR_STATE if the current thread does not own the monitor
+ * 
+ * @see hythread_monitor_notify, hythread_monitor_enter, hythread_monitor_wait
+ */
+IDATA VMCALL
+hythread_monitor_notify_all (hythread_monitor_t monitor)
+{
+  return monitor_notify_one_or_all (monitor, NOTIFY_ALL);
+}
+
+#undef CDEV_CURRENT_FUNCTION
+
+#define CDEV_CURRENT_FUNCTION hythread_tls_alloc
+/**
+ * Allocate a thread local storage (TLS) key.
+ * 
+ * Create and return a new, unique key for thread local storage.  
+ * 
+ * @note The hande returned will be >=0, so it is safe to test the handle against 0 to see if it's been
+ * allocated yet.
+ * 
+ * @param[out] handle pointer to a key to be initialized with a key value
+ * @return 0 on success or negative value if a key could not be allocated (i.e. all TLS has been allocated)
+ * 
+ * @see hythread_tls_free, hythread_tls_set
+ */
+IDATA VMCALL
+hythread_tls_alloc (hythread_tls_key_t * handle)
+{
+  return hythread_tls_alloc_with_finalizer (handle, tls_null_finalizer);
+}
+
+#undef CDEV_CURRENT_FUNCTION
+
+#define CDEV_CURRENT_FUNCTION hythread_tls_free
+/**
+ * Release a TLS key.
+ * 
+ * Release a TLS key previously allocated by hythread_tls_alloc.
+ * 
+ * @param[in] key TLS key to be freed
+ * @return 0 on success or negative value on failure
+ *
+ * @see hythread_tls_alloc, hythread_tls_set
+ *
+ */
+IDATA VMCALL
+hythread_tls_free (hythread_tls_key_t key)
+{
+  HyPoolState state;
+  hythread_t each;
+  hythread_library_t lib = GLOBAL_DATA (default_library);
+  ASSERT (lib);
+
+  /* clear the TLS in every existing thread */
+  GLOBAL_LOCK_SIMPLE (lib);
+  each = pool_startDo (lib->thread_pool, &state);
+  while (each)
+    {
+      each->tls[key - 1] = NULL;
+      each = pool_nextDo (&state);
+    }
+  GLOBAL_UNLOCK_SIMPLE (lib);
+
+  /* now return the key to the free set */
+  MUTEX_ENTER (lib->tls_mutex);
+  lib->tls_finalizers[key - 1] = NULL;
+  MUTEX_EXIT (lib->tls_mutex);
+
+  return 0;
+}
+
+#undef CDEV_CURRENT_FUNCTION
+
+#define CDEV_CURRENT_FUNCTION hythread_tls_set
+/**
+ * Set a thread's TLS value.
+ *
+ * @param[in] thread a thread 
+ * @param[in] key key to have TLS value set (any value returned by hythread_alloc)
+ * @param[in] value value to be stored in TLS
+ * @return 0 on success or negative value on failure
+ *  
+ * @see hythread_tls_alloc, hythread_tls_free, hythread_tls_get
+ */
+IDATA VMCALL
+hythread_tls_set (hythread_t thread, hythread_tls_key_t key, void *value)
+{
+  thread->tls[key - 1] = value;
+
+  return 0;
+}
+
+#undef CDEV_CURRENT_FUNCTION
+
+#define CDEV_CURRENT_FUNCTION hythread_set_priority
+/**
+ * Set a thread's execution priority.
+ * 
+ * @param[in] thread a thread
+ * @param[in] priority
+ * Use the following symbolic constants for priorities:<br>
+ *				HYTHREAD_PRIORITY_MAX<br>
+ *				HYTHREAD_PRIORITY_USER_MAX<br>
+ *				HYTHREAD_PRIORITY_NORMAL<br>
+ *				HYTHREAD_PRIORITY_USER_MIN<br>
+ *				HYTHREAD_PRIORITY_MIN<br>
+ * 
+ * @returns 0 on success or negative value on failure (priority wasn't changed)
+ * 
+ * 
+ */
+IDATA VMCALL
+hythread_set_priority (hythread_t thread, UDATA priority)
+{
+  ASSERT (thread);
+
+  if (priority > HYTHREAD_PRIORITY_MAX)
+    {
+      return -1;
+    }
+
+  if (THREAD_SET_PRIORITY (thread->handle, priority_map[priority]))
+    {
+      return -1;
+    }
+
+  thread->priority = priority;
+
+  return 0;
+}
+
+#undef CDEV_CURRENT_FUNCTION
+
+#define CDEV_CURRENT_FUNCTION hythread_interrupt
+/** 
+ * Interrupt a thread.
+ * 
+ * If the thread is currently blocked (i.e. waiting on a monitor_wait or sleeping)
+ * resume the thread and cause it to return from the blocking function with
+ * HYTHREAD_INTERRUPTED.
+ * 
+ * @param[in] thread a thead to be interrupted
+ * @return none
+ */
+void VMCALL
+hythread_interrupt (hythread_t thread)
+{
+  interrupt_thread (thread, HYTHREAD_FLAG_INTERRUPTED);
+}
+
+#undef CDEV_CURRENT_FUNCTION
+
+#define CDEV_CURRENT_FUNCTION hythread_interrupted
+/**
+ * Return the value of a thread's interrupted flag.
+ * 
+ * @param[in] thread thread to be queried
+ * @return 0 if not interrupted, non-zero if interrupted
+ */
+UDATA VMCALL
+hythread_interrupted (hythread_t thread)
+{
+  ASSERT (thread);
+  return (thread->flags & HYTHREAD_FLAG_INTERRUPTED) != 0;
+}
+
+#undef CDEV_CURRENT_FUNCTION
+
+#define CDEV_CURRENT_FUNCTION hythread_clear_interrupted
+/**
+ * Clear the interrupted flag of the current thread and return its previous value.
+ * 
+ * @return  previous value of interrupted flag: non-zero if the thread had been interrupted.
+ */
+UDATA VMCALL
+hythread_clear_interrupted (void)
+{
+  UDATA oldFlags;
+  hythread_t self = MACRO_SELF ();
+  ASSERT (self);
+
+  THREAD_LOCK (self, self, CALLER_CLEAR_INTERRUPTED);
+  oldFlags = self->flags;
+  self->flags = oldFlags & ~HYTHREAD_FLAG_INTERRUPTED;
+  THREAD_UNLOCK (self, self);
+
+  return (oldFlags & HYTHREAD_FLAG_INTERRUPTED) != 0;
+
+}
+
+#undef CDEV_CURRENT_FUNCTION
+
+#define CDEV_CURRENT_FUNCTION remove_from_queue
+/*
+ * Remove a thread from a monitor's queue.
+ * 
+ * @param[in] queue head of a monitor's queue
+ * @param[in] thread thread to be removed from queue
+ * @return none
+ */
+static void
+remove_from_queue (hythread_t volatile *queue, hythread_t thread)
+{
+  hythread_t queued, next;
+
+  ASSERT (thread);
+
+  if ((queued = *queue) == NULL)
+    return;
+
+  if (queued == thread)
+    {
+      *queue = thread->next;
+      thread->next = NULL;
+    }
+  else
+    {
+      while ((next = queued->next) != NULL && next != thread)
+        {
+          queued = next;
+        }
+      if (next != NULL)
+        {
+          queued->next = thread->next;
+          thread->next = NULL;
+        }
+    }
+
+  ASSERT (NULL == thread->next);
+}
+
+#undef CDEV_CURRENT_FUNCTION
+
+#define CDEV_CURRENT_FUNCTION allocate_monitor_pool
+/*
+ * Create and initialize a pool of monitors.
+ * 
+ * @return pointer to a new monitor pool on success, NULL on failure
+ * 
+ */
+static hythread_monitor_pool_t
+allocate_monitor_pool (void)
+{
+  int i;
+  hythread_monitor_t entry;
+  hythread_monitor_pool_t pool =
+    (hythread_monitor_pool_t) malloc (sizeof (HyThreadMonitorPool));
+  if (pool == NULL)
+    {
+      return NULL;
+    }
+  memset (pool, 0, sizeof (HyThreadMonitorPool));
+
+  pool->next_free = entry = &pool->entries[0];
+  for (i = 0; i < MONITOR_POOL_SIZE - 1; i++, entry++)
+    {
+      entry->count = FREE_TAG;
+      entry->owner = (hythread_t) (entry + 1);
+      /* entry->waiting = entry->blocked = NULL; *//* (unnecessary) */
+      entry->flags = HYTHREAD_MONITOR_MUTEX_UNINITIALIZED;
+    }
+  /* initialize the last monitor */
+  entry->count = FREE_TAG;
+  entry->flags = HYTHREAD_MONITOR_MUTEX_UNINITIALIZED;
+
+  return pool;
+}
+
+#undef CDEV_CURRENT_FUNCTION
+
+#define CDEV_CURRENT_FUNCTION thread_wrapper
+/*
+ * Function we pass to the OS for new threads.
+ * 
+ * @param arg pointer to the hythread_t for the new thread
+ * @return none
+ */
+static WRAPPER_TYPE
+thread_wrapper (WRAPPER_ARG arg)
+{
+  hythread_t thread = (hythread_t) arg;
+  hythread_library_t lib = thread->library;
+  UDATA flags;
+
+  ASSERT (thread);
+  ASSERT (lib);
+
+  thread->tid = RAS_THREAD_ID ();
+
+  TLS_SET (lib->self_ptr, thread);
+
+  if (lib->stack_usage)
+    {
+      paint_stack (thread);
+    }
+
+  if (thread->flags & HYTHREAD_FLAG_CANCELED)
+    {
+      internal_exit ();
+    }
+
+  /* Handle the create-suspended case */
+  /* (This code is basically the same as hythread_suspend, but we need to
+     test the condition under mutex or else there's a timing hole) */
+  THREAD_LOCK (thread, thread, CALLER_THREAD_WRAPPER);
+  if (thread->flags & HYTHREAD_FLAG_SUSPENDED)
+    {
+      COND_WAIT (thread->condition, thread->mutex);
+      if ((thread->flags & HYTHREAD_FLAG_SUSPENDED) == 0)
+        break;
+      COND_WAIT_LOOP ();
+    }
+  thread->flags |= HYTHREAD_FLAG_STARTED;
+  flags = thread->flags;
+  THREAD_UNLOCK (thread, thread);
+
+  if (thread->flags & HYTHREAD_FLAG_CANCELED)
+    {
+      internal_exit ();
+    }
+
+#if defined(LINUX)
+  /* Workaround for NPTL bug on Linux. See hythread_exit() */
+  {
+    jmp_buf jumpBuffer;
+    if (0 == setjmp (jumpBuffer))
+      {
+        thread->jumpBuffer = &jumpBuffer;
+        thread->entrypoint (thread->entryarg);
+      }
+    thread->jumpBuffer = NULL;
+  }
+#else
+  thread->entrypoint (thread->entryarg);
+#endif
+
+  internal_exit ();
+  /* UNREACHABLE */
+  WRAPPER_RETURN ();
+}
+
+#undef CDEV_CURRENT_FUNCTION
+
+#define CDEV_CURRENT_FUNCTION monitor_notify_one_or_all
+/*
+ * Signal one or all threads waiting on the monitor.
+ * 
+ * If no threads are waiting, this does nothing.
+ * 
+ * @param[in] monitor monitor to be notified on
+ * @param[in] notifyall 0 to notify one, non-zero to notify all
+ * @return 0 once the monitor has been signalled<br>
+ * HYTHREAD_ILLEGAL_MONITOR_STATE if the current thread does not 
+ * own the monitor
+ * 
+ */
+static IDATA
+monitor_notify_one_or_all (hythread_monitor_t monitor, int notifyall)
+{
+
+  hythread_t self = MACRO_SELF ();
+  hythread_t queue, next;
+  int someoneNotified = 0;
+
+  ASSERT (self);
+  ASSERT (monitor);
+
+  if (monitor->owner != self)
+    {
+      ASSERT_DEBUG (0);
+      return HYTHREAD_ILLEGAL_MONITOR_STATE;
+    }
+
+  MONITOR_LOCK (self, monitor, CALLER_NOTIFY_ONE_OR_ALL);
+
+  next = monitor->waiting;
+
+  while (next)
+    {
+      queue = next;
+      next = queue->next;
+      THREAD_LOCK (self, queue, CALLER_NOTIFY_ONE_OR_ALL);
+      if (queue->flags & HYTHREAD_FLAG_WAITING)
+        {
+          notify_thread (queue, SET_NOTIFIED_FLAG);
+          someoneNotified = 1;
+        }
+      THREAD_UNLOCK (self, queue);
+
+      if ((someoneNotified) && (!notifyall))
+        {
+          break;
+        }
+    }
+
+  MONITOR_UNLOCK (self, monitor);
+
+  return 0;
+
+}
+
+#undef CDEV_CURRENT_FUNCTION
+
+#define CDEV_CURRENT_FUNCTION notify_thread
+/*
+ * Notify a thread.
+ * 
+ * Helper routine because we notify a thread in 
+ * a couple of places.
+ * @note: assumes the caller has THREAD_LOCK'd the 
+ * thread being notified (and owns the monitor being notified on)
+ * @param[in] threadToNotify thread to notify
+ * @param[in] setNotifiedFlag indicates whether to set the notified thread's notified flag.
+ * @return none
+ */
+static void
+notify_thread (hythread_t threadToNotify, int setNotifiedFlag)
+{
+  ASSERT (threadToNotify);
+  ASSERT (threadToNotify->flags & HYTHREAD_FLAG_WAITING);
+
+  threadToNotify->flags &= ~HYTHREAD_FLAG_WAITING;
+  threadToNotify->flags |= HYTHREAD_FLAG_BLOCKED;
+  if (setNotifiedFlag)
+    {
+      threadToNotify->flags |= HYTHREAD_FLAG_NOTIFIED;
+    }
+  COND_NOTIFY_ALL (threadToNotify->condition);
+}
+
+#undef CDEV_CURRENT_FUNCTION
+
+#define CDEV_CURRENT_FUNCTION hythread_sleep_interruptable
+/** 
+ * Suspend the current thread from executing 
+ * for at least the specified time.
+ *
+ * @param[in] millis
+ * @param[in] nanos 
+ * @return  0 on success<br>
+ *    HYTHREAD_INVALID_ARGUMENT if the arguments are invalid<br>
+ *    HYTHREAD_INTERRUPTED if the sleep was interrupted
+ *
+ * @see hythread_sleep
+ */
+IDATA VMCALL
+hythread_sleep_interruptable (I_64 millis, IDATA nanos)
+{
+  hythread_t self = MACRO_SELF ();
+  IDATA boundedMillis = BOUNDED_I64_TO_IDATA (millis);
+
+  ASSERT (self);
+
+  if ((millis < 0) || (nanos < 0) || (nanos >= 1000000))
+    {
+      return HYTHREAD_INVALID_ARGUMENT;
+    }
+
+  THREAD_LOCK (self, self, CALLER_SLEEP_INTERRUPTABLE);
+
+  if (self->flags & HYTHREAD_FLAG_INTERRUPTED)
+    {
+      self->flags &= ~HYTHREAD_FLAG_INTERRUPTED;
+      THREAD_UNLOCK (self, self);
+      return HYTHREAD_INTERRUPTED;
+    }
+
+  if (self->flags & HYTHREAD_FLAG_PRIORITY_INTERRUPTED)
+    {
+      self->flags &= ~HYTHREAD_FLAG_PRIORITY_INTERRUPTED;
+      THREAD_UNLOCK (self, self);
+      return HYTHREAD_PRIORITY_INTERRUPTED;
+    }
+
+  self->flags |=
+    HYTHREAD_FLAG_SLEEPING | HYTHREAD_FLAG_INTERRUPTABLE |
+    HYTHREAD_FLAG_TIMER_SET;
+
+  COND_WAIT_IF_TIMEDOUT (self->condition, self->mutex, boundedMillis, nanos)
+  {
+    break;
+  }
+  else
+  {
+    if (self->flags & HYTHREAD_FLAG_INTERRUPTED)
+      {
+        self->flags &=
+          ~(HYTHREAD_FLAG_INTERRUPTED | HYTHREAD_FLAG_SLEEPING |
+            HYTHREAD_FLAG_INTERRUPTABLE | HYTHREAD_FLAG_TIMER_SET);
+        THREAD_UNLOCK (self, self);
+        return HYTHREAD_INTERRUPTED;
+      }
+    if (self->flags & HYTHREAD_FLAG_PRIORITY_INTERRUPTED)
+      {
+        self->flags &=
+          ~(HYTHREAD_FLAG_PRIORITY_INTERRUPTED | HYTHREAD_FLAG_SLEEPING |
+            HYTHREAD_FLAG_INTERRUPTABLE | HYTHREAD_FLAG_TIMER_SET);
+        THREAD_UNLOCK (self, self);
+        return HYTHREAD_PRIORITY_INTERRUPTED;
+      }
+  }
+  COND_WAIT_TIMED_LOOP ();
+
+  self->flags &=
+    ~(HYTHREAD_FLAG_SLEEPING | HYTHREAD_FLAG_INTERRUPTABLE |
+      HYTHREAD_FLAG_TIMER_SET);
+  THREAD_UNLOCK (self, self);
+  return 0;
+}
+
+#undef CDEV_CURRENT_FUNCTION
+
+#define CDEV_CURRENT_FUNCTION hythread_sleep
+/** 
+ * Suspend the current thread from executing 
+ * for at least the specified time.
+ *
+ * @param[in] millis minimum number of milliseconds to sleep
+ * @return  0 on success<br> HYTHREAD_INVALID_ARGUMENT if millis < 0
+ *
+ * @see hythread_sleep_interruptable
+ */
+IDATA VMCALL
+hythread_sleep (I_64 millis)
+{
+  hythread_t self = MACRO_SELF ();
+
+  IDATA boundedMillis = (millis > 0x7FFFFFFF ? 0x7FFFFFFF : (IDATA) millis);
+
+  ASSERT (self);
+
+  if (millis < 0)
+    {
+      return HYTHREAD_INVALID_ARGUMENT;
+    }
+
+  THREAD_LOCK (self, self, CALLER_SLEEP);
+
+  self->flags |= HYTHREAD_FLAG_SLEEPING | HYTHREAD_FLAG_TIMER_SET;
+
+  COND_WAIT_IF_TIMEDOUT (self->condition, self->mutex, boundedMillis, 0)
+  {
+    break;
+  }
+  COND_WAIT_TIMED_LOOP ();
+
+  self->flags &= ~(HYTHREAD_FLAG_SLEEPING | HYTHREAD_FLAG_TIMER_SET);
+  THREAD_UNLOCK (self, self);
+  return 0;
+}
+
+#undef CDEV_CURRENT_FUNCTION
+
+#define CDEV_CURRENT_FUNCTION hythread_monitor_lock
+/*
+ * Acquire the threading library's global lock.
+ * 
+ * @param[in] self hythread_t for the current thread
+ * @param[in] monitor must be NULL
+ * @return none
+ * 
+ * @deprecated This has been replaced by hythread_lib_lock.
+ * @see hythread_lib_lock, hythread_lib_unlock
+ */
+void VMCALL
+hythread_monitor_lock (hythread_t self, hythread_monitor_t monitor)
+{
+  ASSERT (self);
+
+  if (monitor == NULL)
+    {
+      GLOBAL_LOCK (self, CALLER_GLOBAL_LOCK);
+    }
+  else
+    {
+      ASSERT (0);
+    }
+}
+
+#undef CDEV_CURRENT_FUNCTION
+
+#define CDEV_CURRENT_FUNCTION hythread_monitor_unlock
+/*
+ * Release the threading library's global lock.
+ * 
+ * @param[in] self hythread_t for the current thread
+ * @param[in] monitor
+ * @return none
+ * 
+ * @deprecated This has been replaced by hythread_lib_unlock.
+ * @see hythread_lib_lock, hythread_lib_unlock
+ */
+void VMCALL
+hythread_monitor_unlock (hythread_t self, hythread_monitor_t monitor)
+{
+  ASSERT (self);
+
+  if (monitor == NULL)
+    {
+      GLOBAL_UNLOCK (self);
+    }
+  else
+    {
+      ASSERT (0);
+    }
+}
+
+#undef CDEV_CURRENT_FUNCTION
+
+#define CDEV_CURRENT_FUNCTION hythread_monitor_acquire
+/*
+ * Acquire a monitor from the threading library. (Private)
+ * 
+ * @param[in] self current thread
+ * @param[in] locking policy 
+ * @param[in] locking policy data or HYTHREAD_LOCKING_NO_DATA
+ * @return NULL on failure, non-NULL on success
+ *
+ * @see hythread_monitor_init_with_name, hythread_monitor_destroy
+ *
+ * 
+ */
+static hythread_monitor_t VMCALL
+hythread_monitor_acquire (hythread_t self, IDATA policy, IDATA policyData)
+{
+  hythread_monitor_t entry;
+  hythread_monitor_pool_t pool = self->library->monitor_pool;
+  IDATA rc;
+
+  ASSERT (self);
+  ASSERT (pool);
+
+  GLOBAL_LOCK (self, CALLER_MONITOR_ACQUIRE);
+
+  entry = pool->next_free;
+  if (entry == NULL)
+    {
+      hythread_monitor_pool_t last_pool = pool;
+      while (last_pool->next != NULL)
+        last_pool = last_pool->next;
+      last_pool->next = allocate_monitor_pool ();
+      if (last_pool->next == NULL)
+        {
+          /* failed to grow monitor pool */
+          GLOBAL_UNLOCK (self);
+          return NULL;
+        }
+      entry = last_pool->next->next_free;
+    }
+
+  /* the first time that a mutex is acquired from the pool, we need to 
+   * initialize its mutex
+   */
+  if (entry->flags == HYTHREAD_MONITOR_MUTEX_UNINITIALIZED)
+    {
+
+      rc = MUTEX_INIT (entry->mutex);
+
+      if (!rc)
+        {
+          /* failed to initialize mutex */
+          ASSERT_DEBUG (0);
+          GLOBAL_UNLOCK (self);
+          return NULL;
+        }
+
+      entry->flags = 0;
+
+    }
+
+  pool->next_free = (hythread_monitor_t) entry->owner;
+  entry->count = 0;
+
+  GLOBAL_UNLOCK (self);
+
+  return entry;
+}
+
+#undef CDEV_CURRENT_FUNCTION
+
+#define CDEV_CURRENT_FUNCTION hythread_cancel
+/** 
+ * Terminate a running thread.
+ * 
+ * @note This should only be used as a last resort.  The system may be in
+ * an unpredictable state once a thread is cancelled.  In addition, the thread
+ * may not even stop running if it refuses to cancel.
+ * 
+ * @param[in] thread a thread to be terminated 
+ * @return none
+ */
+void VMCALL
+hythread_cancel (hythread_t thread)
+{
+  hythread_monitor_t monitor = NULL;
+  hythread_t self = MACRO_SELF ();
+
+  ASSERT (thread);
+  THREAD_LOCK (self, thread, CALLER_CANCEL);
+
+  /* Special case -- we can cancel cleanly if the thread hasn't started yet */
+  if ((thread->flags & HYTHREAD_FLAG_STARTED) == 0)
+    {
+      thread->flags |= HYTHREAD_FLAG_CANCELED;
+      THREAD_UNLOCK (self, thread);
+      hythread_resume (thread);
+      return;
+    }
+
+  THREAD_CANCEL (thread->handle);
+
+  thread->flags |= HYTHREAD_FLAG_CANCELED;
+
+  THREAD_UNLOCK (self, thread);
+
+}
+
+#undef CDEV_CURRENT_FUNCTION
+
+#define CDEV_CURRENT_FUNCTION hythread_detach
+/**
+ * Detach a thread from the threading library.
+ * 
+ * @note Assumes that the thread being detached is already attached.<br>
+ * 
+ * If the thread is an attached thread, then detach should only be called by the thread
+ * itself. Internal resources associated with the thread are freed.
+ * 
+ * If the thread is already dead, this call will destroy it.
+ * 
+ * @param[in] thread a hythread_t representing the thread to be detached.
+ * If this is NULL, the current thread is detached.
+ * @return none
+ * 
+ * @see hythread_attach
+ */
+void VMCALL
+hythread_detach (hythread_t thread)
+{
+  UDATA destroy = 0;
+  UDATA attached = 0;
+  hythread_t self = MACRO_SELF ();
+
+  if (thread == NULL)
+    {
+      thread = self;
+    }
+  ASSERT (thread);
+
+  THREAD_LOCK (self, thread, CALLER_DETACH);
+  if (thread->attachcount < 1)
+    {
+      /* error! */
+    }
+  else
+    {
+      if (--thread->attachcount == 0)
+        {
+          if (thread->flags & HYTHREAD_FLAG_ATTACHED)
+            {
+              /* this is an attached thread, and it is now fully
+                 detached.  Mark it dead so that it can be destroyed */
+              thread->flags |= HYTHREAD_FLAG_DEAD;
+              attached = destroy = 1;
+            }
+          else
+            {
+              destroy = thread->flags & HYTHREAD_FLAG_DEAD;
+            }
+        }
+    }
+  THREAD_UNLOCK (self, thread);
+
+  if (destroy)
+    {
+      hythread_library_t library = thread->library;
+
+      tls_finalize (thread);
+
+      destroy_thread (thread, GLOBAL_NOT_LOCKED);
+      if (attached)
+        {
+          TLS_SET (library->self_ptr, NULL);
+        }
+    }
+}
+
+#undef CDEV_CURRENT_FUNCTION
+
+#define CDEV_CURRENT_FUNCTION hythread_exit
+/**
+ * Exit the current thread.
+ * 
+ * If the thread has been detached, it is destroyed.
+ * 
+ * If monitor is not NULL, the monitor will be exited before the thread terminates. 
+ * This is useful if the thread wishes to signal its termination to a watcher, since
+ * it exits the monitor and terminates the thread without ever returning control
+ * to the thread's routine, which might be running in a DLL which is about to
+ * be closed.
+ *
+ * @param[in] monitor monitor to be exited before exiting (ignored if NULL)
+ * @return none
+ */
+void VMCALL NORETURN
+hythread_exit (hythread_monitor_t monitor)
+{
+  hythread_t self = MACRO_SELF ();
+
+  if (monitor)
+    {
+      hythread_monitor_exit (monitor);
+    }
+
+  /* Walk all monitors: if this thread owns a monitor, exit it */
+  monitor = NULL;
+  while ((monitor = hythread_monitor_walk (monitor)) != NULL)
+    {
+      if (monitor->owner == self)
+        {
+          monitor->count = 1;   /* exit n-1 times */
+          hythread_monitor_exit (monitor);
+        }
+    }
+
+#if defined(LINUX)
+  /* NPTL calls __pthread_unwind() from pthread_exit(). That walks the stack.
+   * We can't allow that to happen, since our caller might have already been 
+   * unloaded. Walking the calling frame could cause a crash. Instead, we
+   * longjmp back out to the initial frame.
+   */
+  if (self->jumpBuffer)
+    {
+      longjmp (*(jmp_buf *) self->jumpBuffer, 1);
+    }
+#endif
+
+  internal_exit ();
+
+}
+
+#undef CDEV_CURRENT_FUNCTION
+
+#define CDEV_CURRENT_FUNCTION hythread_priority_interrupt
+/** 
+ * Priority interrupt a thread.
+ *
+ * If the thread is currently blocked (i.e. waiting on a monitor_wait or sleeping)
+ * resume the thread and return from the blocking function with
+ * HYTHREAD_PRIORITY_INTERRUPTED
+ * 
+ * @param[in] thread a thead to be priority interrupted
+ * @return none
+ */
+void VMCALL
+hythread_priority_interrupt (hythread_t thread)
+{
+  interrupt_thread (thread, HYTHREAD_FLAG_PRIORITY_INTERRUPTED);
+}
+
+#undef CDEV_CURRENT_FUNCTION
+
+#define CDEV_CURRENT_FUNCTION hythread_priority_interrupted
+/**
+ * Return the value of a thread's priority interrupted flag.
+ * 
+ * @param[in] thread thread to be queried
+ * @return 0 if not priority interrupted, non-zero if priority interrupted flag set
+ */
+UDATA VMCALL
+hythread_priority_interrupted (hythread_t thread)
+{
+  return (thread->flags & HYTHREAD_FLAG_PRIORITY_INTERRUPTED) != 0;
+}
+
+#undef CDEV_CURRENT_FUNCTION
+
+#define CDEV_CURRENT_FUNCTION hythread_clear_priority_interrupted
+/**
+ * Clear the priority interrupted flag of the current thread and return its previous value.
+ * 
+ * @return  previous value of priority interrupted flag: nonzero if the thread had been priority interrupted.
+ */
+UDATA VMCALL
+hythread_clear_priority_interrupted (void)
+{
+  UDATA oldFlags;
+  hythread_t self = MACRO_SELF ();
+  ASSERT (self);
+
+  THREAD_LOCK (self, self, CALLER_CLEAR_PRIORITY_INTERRUPTED);
+  oldFlags = self->flags;
+  self->flags = oldFlags & ~HYTHREAD_FLAG_PRIORITY_INTERRUPTED;
+  THREAD_UNLOCK (self, self);
+
+  return (oldFlags & HYTHREAD_FLAG_PRIORITY_INTERRUPTED) != 0;
+}
+
+#undef CDEV_CURRENT_FUNCTION
+
+#define CDEV_CURRENT_FUNCTION hythread_monitor_try_enter
+/** 
+ * Attempt to enter a monitor without blocking.
+ * 
+ * If the thread must block before it enters the monitor this function
+ * returns immediately with a negative value to indicate failure.
+ * 
+ * @param[in] monitor a monitor
+ * @return  0 on success or negative value on failure
+ *
+ * @see hythread_monitor_try_enter_using_threadId
+ *
+ */
+IDATA VMCALL
+hythread_monitor_try_enter (hythread_monitor_t monitor)
+{
+  return hythread_monitor_try_enter_using_threadId (monitor, MACRO_SELF ());
+}
+
+#undef CDEV_CURRENT_FUNCTION
+
+#define CDEV_CURRENT_FUNCTION hythread_shutdown
+/**
+ * Shut down the Hy threading library associated with the current thread.
+ * 
+ * @return none
+ * 
+ * @see hythread_init
+ */
+void VMCALL
+hythread_shutdown (void)
+{
+  hythread_library_t lib = GLOBAL_DATA (default_library);
+  ASSERT (lib);
+  MUTEX_DESTROY (lib->tls_mutex);
+  MUTEX_DESTROY (lib->monitor_mutex);
+  MUTEX_DESTROY (lib->global_mutex);
+  pool_kill (lib->global_pool);
+  free_monitor_pools ();
+#if !defined(LINUX)
+  TLS_DESTROY (lib->self_ptr);
+  pool_kill (lib->thread_pool);
+#endif /* LINUX */
+
+}
+
+#undef CDEV_CURRENT_FUNCTION
+
+#define CDEV_CURRENT_FUNCTION allocate_thread
+/*
+ * Allocate a hythread_t from the hythread_t pool.
+ * 
+ * @note assumes the threading library's thread pool is already initialized
+ * @param[in] globalIsLocked indicates whether the threading library global mutex is already locked.
+ * @return a new hythread_t on success, NULL on failure.
+ * 
+ */
+static hythread_t
+allocate_thread (int globalIsLocked)
+{
+  hythread_t result;
+  hythread_library_t lib = GLOBAL_DATA (default_library);
+  ASSERT (lib);
+
+  if (!globalIsLocked)
+    {
+      GLOBAL_LOCK_SIMPLE (lib);
+    }
+  lib->threadCount++;
+  result = pool_newElement (lib->thread_pool);
+  if (!globalIsLocked)
+    {
+      GLOBAL_UNLOCK_SIMPLE (lib);
+    }
+
+  if (result)
+    {
+      memset (result, 0, sizeof (HyThread));
+    }
+
+  return result;
+}
+
+#undef CDEV_CURRENT_FUNCTION
+
+#define CDEV_CURRENT_FUNCTION free_thread
+/*
+ * Return a hythread_t to the threading library's monitor pool.
+ *
+ * @param[in] thread thread to be returned to the pool
+ * @param[in] globalAlreadyLocked indicated whether the threading library global 
+ * mutex is already locked
+ * @return none
+ */
+static void
+free_thread (hythread_t thread, int globalAlreadyLocked)
+{
+  hythread_library_t lib = thread->library;
+
+  ASSERT (thread);
+
+  if (!globalAlreadyLocked)
+    {
+      GLOBAL_LOCK_SIMPLE (lib);
+    }
+  pool_removeElement (lib->thread_pool, thread);
+  lib->threadCount--;
+
+  if (!globalAlreadyLocked)
+    {
+      GLOBAL_UNLOCK_SIMPLE (lib);
+    }
+
+}
+
+#undef CDEV_CURRENT_FUNCTION
+
+#define CDEV_CURRENT_FUNCTION thread_malloc
+/*
+ * Malloc a thread (hythread_t struct).
+ * 
+ * Helper function used by the library's thread pool
+ * 
+ * @param unused ignored
+ * @param size size of struct to be alloc'd
+ * @return pointer to the malloc'd memory<br>
+ * 0 on failure
+ *
+ */
+static void *VMCALL
+thread_malloc (void *unused, U_32 size)
+{
+  return malloc (size);
+}
+
+#undef CDEV_CURRENT_FUNCTION
+
+#define CDEV_CURRENT_FUNCTION thread_free
+/*
+ * Free a thread (hythread_t struct)
+ * Function used by the library's thread pool
+ * 
+ * @param unused ignored
+ * @param prt pointer to hythread_t to be freed
+ * @return none
+ *
+ */
+static void VMCALL
+thread_free (void *unused, void *ptr)
+{
+  free (ptr);
+}
+
+#undef CDEV_CURRENT_FUNCTION
+
+#define CDEV_CURRENT_FUNCTION free_monitor_pools
+/*
+ * Free the Hy threading library's monitor pool.
+ * 
+ * This requires destroying each and every one of the 
+ * monitors in the pool.
+ * 
+ * @return none
+ */
+static void
+free_monitor_pools (void)
+{
+  hythread_library_t lib = GLOBAL_DATA (default_library);
+  hythread_monitor_pool_t pool = lib->monitor_pool;
+
+  ASSERT (lib);
+  ASSERT (pool);
+
+  while (pool)
+    {
+      int i;
+      hythread_monitor_pool_t next = pool->next;
+      hythread_monitor_t entry = &pool->entries[0];
+      for (i = 0; i < MONITOR_POOL_SIZE - 1; i++, entry++)
+        {
+          if (entry->flags != HYTHREAD_MONITOR_MUTEX_UNINITIALIZED)
+            {
+              MUTEX_DESTROY (entry->mutex);
+            }
+        }
+      free (pool);
+      pool = next;
+    }
+
+}
+
+#undef CDEV_CURRENT_FUNCTION
+
+#define CDEV_CURRENT_FUNCTION init_global_monitor
+/* 
+ * Initialize the mutex used to synchronize access 
+ * to thread library global data.
+ *
+ * @param[in] lib pointer to the thread library
+ * @return 0 on success or negative value on failure
+ * 
+ */
+static IDATA
+init_global_monitor (hythread_library_t lib)
+{
+  hythread_monitor_pool_t pool = lib->monitor_pool;
+  hythread_monitor_t monitor = pool->next_free;
+  ASSERT (monitor);
+  pool->next_free = (hythread_monitor_t) monitor->owner;
+
+  if (init_monitor (monitor, 0) != 0)
+    {
+      return -1;
+    }
+  if (!MUTEX_INIT (monitor->mutex))
+    {
+      return -1;
+    }
+
+  monitor->name = "Thread global";
+
+  *hythread_global ("global_monitor") = (UDATA) monitor;
+
+  return 0;
+}
+
+#undef CDEV_CURRENT_FUNCTION
+
+#define CDEV_CURRENT_FUNCTION internal_exit
+/*
+ * Exit from the current thread.
+ * 
+ * If the thread has been detached it is destroyed.
+ */
+static void NORETURN
+internal_exit (void)
+{
+
+  hythread_t self = MACRO_SELF ();
+  hythread_library_t lib = self->library;
+  int detached;
+
+  ASSERT (self);
+  ASSERT (lib);
+
+  tls_finalize (self);
+
+  GLOBAL_LOCK (self, CALLER_INTERNAL_EXIT1);
+  THREAD_LOCK (self, self, CALLER_INTERNAL_EXIT1);
+  self->flags |= HYTHREAD_FLAG_DEAD;
+  detached = self->attachcount == 0;
+
+  /* 
+   * Is there an interruptServer thread out there
+   * trying to interrupt us? Its services are 
+   * no longer required.
+   */
+  if (self->interrupter)
+    {
+      THREAD_LOCK (self, self->interrupter, CALLER_INTERNAL_EXIT1);
+      self->interrupter->flags |= HYTHREAD_FLAG_CANCELED;
+      THREAD_UNLOCK (self, self->interrupter);
+      self->interrupter = NULL;
+    }
+
+  THREAD_UNLOCK (self, self);
+
+  /* On z/OS we create the thread in the detached state, so the */
+  /* call to pthread_detach is not required.                     @dfa1 */
+  THREAD_DETACH (self->handle);
+
+  if (detached)
+    {
+      destroy_thread (self, GLOBAL_IS_LOCKED);
+    }
+
+  GLOBAL_UNLOCK_SIMPLE (lib);
+  THREAD_EXIT ();
+  ASSERT (0);
+  /* UNREACHABLE */
+
+}
+
+#undef CDEV_CURRENT_FUNCTION
+
+#define CDEV_CURRENT_FUNCTION enqueue_thread
+/*
+ * Add a thread to a monitor's wait queue.
+ * 
+ * @note The calling thread must be the current owner of the monitor
+ * @param[in] queue head of the monitor's wait queue
+ * @param[in] thread thread to be added
+ * @return none
+ * 
+ */
+static void
+enqueue_thread (hythread_t * queue, hythread_t thread)
+{
+  hythread_t qthread = *queue;
+
+  ASSERT (thread);
+  /* can't be on two queues at the same time */
+  ASSERT (NULL == thread->next);
+
+  if (qthread != NULL)
+    {
+      while (qthread->next)
+        {
+          qthread = qthread->next;
+        }
+      qthread->next = thread;
+    }
+  else
+    {
+      *queue = thread;
+    }
+
+  ASSERT (*queue != NULL);
+  ASSERT (NULL == thread->next);
+}
+
+#undef CDEV_CURRENT_FUNCTION
+
+#define CDEV_CURRENT_FUNCTION hythread_monitor_wait_timed
+/** 
+ * Wait on a monitor until notified or timed out.
+ *
+ * A timeout of 0 (0ms, 0ns) indicates wait indefinitely.
+ * 
+ * @param[in] monitor a monitor to be waited on
+ * @param[in] millis >=0
+ * @param[in] nanos >=0
+ *
+ * @return  0 the monitor has been waited on, notified, and reobtained<br>
+ * HYTHREAD_INVALID_ARGUMENT millis or nanos is out of range (millis or nanos < 0, or nanos >= 1E6)<br>
+ * HYTHREAD_ILLEGAL_MONITOR_STATE the current thread does not own the monitor<br>
+ * HYTHREAD_TIMED_OUT the timeout expired
+ * 
+ * @see hythread_monitor_wait, hythread_monitor_wait_interruptable, hythread_monitor_enter
+ * 
+ */
+IDATA VMCALL
+hythread_monitor_wait_timed (hythread_monitor_t monitor, I_64 millis,
+                             IDATA nanos)
+{
+  return monitor_wait (monitor, millis, nanos, WAIT_UNINTERRUPTABLE);
+}
+
+#undef CDEV_CURRENT_FUNCTION
+
+#define CDEV_CURRENT_FUNCTION hythread_monitor_dump_trace
+
+#undef CDEV_CURRENT_FUNCTION
+
+#define CDEV_CURRENT_FUNCTION hythread_monitor_dump_all
+
+#undef CDEV_CURRENT_FUNCTION
+
+#define CDEV_CURRENT_FUNCTION hythread_dump_trace
+
+#undef CDEV_CURRENT_FUNCTION
+
+#define CDEV_CURRENT_FUNCTION hythread_global
+/** 
+ * Fetch or create a 'named global'.
+ *
+ * Return a pointer to the data associated with a named global with the specified name.<br>
+ * A new named global is created if a named global with the specified name can't be found.
+ *
+ * @param[in] name name of named global to read/create
+ * @return a pointer to a UDATA associated with name<br>
+ * 0 on failure.
+ * 
+ */
+UDATA *VMCALL
+hythread_global (char *name)
+{
+  HyThreadGlobal *global;
+  hythread_library_t lib = GLOBAL_DATA (default_library);
+
+  MUTEX_ENTER (lib->global_mutex);
+
+  global = lib->globals;
+
+  while (global)
+    {
+      if (strcmp (global->name, name) == 0)
+        {
+          MUTEX_EXIT (lib->global_mutex);
+          return &global->data;
+        }
+      global = global->next;
+    }
+
+  /*
+   * If we got here, we couldn't find it, therefore
+   * we will create a new one
+   */
+
+  global = pool_newElement (lib->global_pool);
+  if (global == NULL)
+    {
+      MUTEX_EXIT (lib->global_mutex);
+      return NULL;
+    }
+
+  global->next = lib->globals;
+  global->name = name;
+  global->data = 0;
+  lib->globals = global;
+
+  MUTEX_EXIT (lib->global_mutex);
+
+  return &global->data;
+}
+
+#undef CDEV_CURRENT_FUNCTION
+
+#define CDEV_CURRENT_FUNCTION hysem_init
+/*
+ * Initialize a semaphore.
+ *
+ * Acquire a semaphore from the threading library.
+ * 
+ * @param[out] sp pointer to semaphore to be initialized
+ * @param[in] initValue initial count value (>=0) for the semaphore
+ * @return  0 on success or negative value on failure
+ *
+ * @deprecated Semaphores are no longer supported.
+ * 
+ * @see hysem_destroy, hysem_init, hysem_post
+ */
+IDATA VMCALL
+hysem_init (hysem_t * sp, I_32 initValue)
+{
+  hysem_t s;
+  IDATA rc = -1;
+
+  (*sp) = s = SEM_CREATE (initValue);
+  if (s)
+    {
+      rc = SEM_INIT (s, 0, initValue);
+    }
+  return rc;
+
+}
+
+#undef CDEV_CURRENT_FUNCTION
+
+#define CDEV_CURRENT_FUNCTION hysem_destroy
+/*
+ * Destroy a semaphore.
+ *
+ * Returns the resources associated with a semaphore back to the Hy threading library.
+ * 
+ * @param[in] s semaphore to be destroyed
+ * @return  0 on success or negative value on failure
+ *
+ * @deprecated Semaphores are no longer supported.
+ * 
+ * @see hysem_init, hysem_wait, hysem_post
+ */
+IDATA VMCALL
+hysem_destroy (hysem_t s)
+{
+  int rval = 0;
+  if (s)
+    {
+      rval = SEM_DESTROY (s);
+      SEM_FREE (s);
+    }
+  return rval;
+
+}
+
+#undef CDEV_CURRENT_FUNCTION
+
+#define CDEV_CURRENT_FUNCTION hysem_post
+/*
+ * Release a semaphore by 1.
+ * 
+ * @param[in] s semaphore to be released by 1
+ * @return  0 on success or negative value on failure
+ *
+ * @deprecated Semaphores are no longer supported.
+ *
+ * @see hysem_init, hysem_destroy, hysem_wait
+ */
+IDATA VMCALL
+hysem_post (hysem_t s)
+{
+  if (s)
+    {
+      return SEM_POST (s);
+    }
+  return -1;
+
+}
+
+#undef CDEV_CURRENT_FUNCTION
+
+#define CDEV_CURRENT_FUNCTION hysem_wait
+/*
+ * Wait on a semaphore.
+ * 
+ * @param[in] s semaphore to be waited on 
+ * @return  0 on success or negative value on failure
+ *
+ * @deprecated Semaphores are no longer supported.
+ *
+ * @see hysem_init, hysem_destroy, hysem_wait
+ *
+ */
+IDATA VMCALL
+hysem_wait (hysem_t s)
+{
+  if (s)
+    {
+      while (SEM_WAIT (s) != 0)
+        {
+          /* loop until success */
+        }
+      return 0;
+    }
+  else
+    {
+      return -1;
+    }
+
+}
+
+#undef CDEV_CURRENT_FUNCTION
+
+#define CDEV_CURRENT_FUNCTION error
+
+#undef CDEV_CURRENT_FUNCTION
+
+#define CDEV_CURRENT_FUNCTION monitor_enter
+/*
+ * Enter a monitor.
+ * 
+ * A thread may enter a monitor it owns multiple times, but must
+ * exit the monitor the same number of times before other threads
+ * waiting on the monitor are permitted to continue
+ * 
+ * @param[in] self current thread
+ * @param[in] monitor monitor to enter
+ * @return 0 on success<br>
+ * HYTHREAD_PRIORITY_INTERRUPTED if the thread was priority 
+ * interrupted while blocked
+ */
+static IDATA
+monitor_enter (hythread_t self, hythread_monitor_t monitor)
+{
+
+  ASSERT (self);
+  ASSERT (0 == self->monitor);
+  ASSERT (monitor);
+  ASSERT (monitor->owner != self);
+  ASSERT (FREE_TAG != monitor->count);
+
+  return monitor_enter_three_tier (self, monitor);
+
+}
+
+#undef CDEV_CURRENT_FUNCTION
+
+#define CDEV_CURRENT_FUNCTION monitor_enter_three_tier
+
+/*
+ * Enter a three-tier monitor.
+ * 
+ * Spin on a spinlock. Block when that fails, and repeat.
+ * 
+ * @param[in] self current thread
+ * @param[in] monitor monitor to enter
+ * @return 0 on success
+ */
+
+static IDATA
+monitor_enter_three_tier (hythread_t self, hythread_monitor_t monitor)
+{
+  int firstTimeBlocking = 1;
+
+  while (1)
+    {
+
+      if (hythread_spinlock_acquire (self, monitor) == 0)
+        {
+          monitor->owner = self;
+          monitor->count = 1;
+          ASSERT (monitor->spinlockState !=
+                  HYTHREAD_MONITOR_SPINLOCK_UNOWNED);
+          break;
+        }
+
+      MONITOR_LOCK (self, monitor, CALLER_MONITOR_ENTER_THREE_TIER1);
+
+      if (HYTHREAD_MONITOR_SPINLOCK_UNOWNED ==
+          hythread_spinlock_swapState (monitor,
+                                       HYTHREAD_MONITOR_SPINLOCK_EXCEEDED))
+        {
+          MONITOR_UNLOCK (self, monitor);
+          monitor->owner = self;
+          monitor->count = 1;
+          ASSERT (monitor->spinlockState !=
+                  HYTHREAD_MONITOR_SPINLOCK_UNOWNED);
+          break;
+        }
+
+      THREAD_LOCK (self, self, CALLER_MONITOR_ENTER_THREE_TIER2);
+      self->flags |= (HYTHREAD_FLAG_BLOCKED);
+      self->monitor = monitor;
+      THREAD_UNLOCK (self, self);
+
+      /* 
+       * First time we've had to block? 
+       * If so, record the info for JLM.
+       */
+      if (IS_JLM_ENABLED (self))
+        {
+          if (firstTimeBlocking)
+            {
+              firstTimeBlocking = 0;
+
+            }
+        }
+
+      enqueue_thread (&monitor->blocking, self);
+      COND_WAIT (self->condition, monitor->mutex);
+      break;
+      COND_WAIT_LOOP ();
+      remove_from_queue (&monitor->blocking, self);
+
+      MONITOR_UNLOCK (self, monitor);
+
+    }
+
+  /* We now own the monitor */
+
+  /*
+   * If the monitor field is set, we must have blocked on it
+   * at some point. We're no longer blocked, so clear this.
+   */
+  if (self->monitor != 0)
+    {
+      THREAD_LOCK (self, self, CALLER_MONITOR_ENTER_THREE_TIER3);
+      self->flags &= ~(HYTHREAD_FLAG_BLOCKED);
+      self->monitor = 0;
+      THREAD_UNLOCK (self, self);
+    }
+
+  /* Did we block? If so, finish up the JLM calcs */
+  /* TODO: this is pretty much the same as in monitor_enter.... */
+  if (IS_JLM_ENABLED (self))
+    {
+      monitor->tracing->enter_count++;
+      if (0 == firstTimeBlocking)
+        {
+          monitor->tracing->slow_count++;
+
+        }
+    }
+
+  ASSERT (!(self->flags & HYTHREAD_FLAG_BLOCKED));
+  ASSERT (0 == self->monitor);
+
+  return 0;
+}
+
+#undef CDEV_CURRENT_FUNCTION
+
+#define CDEV_CURRENT_FUNCTION monitor_exit
+/*
+ * Exit a monitor.
+ * 
+ * If the current thread is not the owner of the monitor, the
+ * mutex is unaffected, and an error is returned. This should be
+ * tested to determine if IllegalMonitorState should be
+ * thrown.
+ * 
+ * @param[in] self current thread
+ * @param[in] monitor monitor to be exited
+ * @return 0 on success<br>
+ * HYTHREAD_ILLEGAL_MONITOR_STATE if the current thread does not 
+ * own the monitor
+ */
+static IDATA
+monitor_exit (hythread_t self, hythread_monitor_t monitor)
+{
+
+  ASSERT (monitor);
+  ASSERT (self);
+  ASSERT (0 == self->monitor);
+
+  if (monitor->owner != self)
+    {
+      ASSERT_DEBUG (0);
+      return HYTHREAD_ILLEGAL_MONITOR_STATE;
+    }
+
+  monitor->count--;
+  ASSERT (monitor->count >= 0);
+
+  if (monitor->count == 0)
+    {
+      monitor->owner = NULL;
+
+      if (HYTHREAD_MONITOR_SPINLOCK_EXCEEDED ==
+          hythread_spinlock_swapState (monitor,
+                                       HYTHREAD_MONITOR_SPINLOCK_UNOWNED))
+        {
+          MONITOR_LOCK (self, monitor, CALLER_MONITOR_EXIT1);
+          unblock_spinlock_threads (self, monitor);
+          MONITOR_UNLOCK (self, monitor);
+        }
+
+    }
+
+  return 0;
+}
+
+#undef CDEV_CURRENT_FUNCTION
+
+#define CDEV_CURRENT_FUNCTION unblock_spinlock_threads
+
+/*
+ * Notify all threads blocked on the monitor's mutex, waiting
+ * to be told that it's ok to try again to get the spinlock.
+ * 
+ * Assumes that the caller already owns the monitor's mutex.
+ *
+ */
+static void
+unblock_spinlock_threads (hythread_t self, hythread_monitor_t monitor)
+{
+  hythread_t queue, next;
+
+  ASSERT (self);
+  ASSERT (monitor);
+
+  next = monitor->blocking;
+  while (next)
+    {
+      queue = next;
+      next = queue->next;
+      COND_NOTIFY_ALL (queue->condition);
+    }
+}
+
+#undef CDEV_CURRENT_FUNCTION
+
+#define CDEV_CURRENT_FUNCTION hythread_reset_tracing
+
+#undef CDEV_CURRENT_FUNCTION
+
+#define CDEV_CURRENT_FUNCTION hythread_monitor_wait_interruptable
+/** 
+ * Wait on a monitor until notified, interrupted (priority or normal), or timed out.
+ *
+ * A timeout of 0 (0ms, 0ns) indicates wait indefinitely.
+ * 
+ * If 'interruptable' is non-zero, the wait may be interrupted by one of the 
+ * interrupt functions. (i.e. hythread_interrupt, hythread_priority_interrupt);
+ *
+ * @param[in] monitor a monitor to be waited on
+ * @param[in] millis >=0
+ * @param[in] nanos >=0
+ * @param[in] interruptable non-zero if the wait is to be interruptable
+ *
+ * @return   0 the monitor has been waited on, notified, and reobtained<br>
+ * HYTHREAD_INVALID_ARGUMENT if millis or nanos is out of range (millis or nanos < 0, or nanos >= 1E6)<br>
+ * HYTHREAD_ILLEGAL_MONITOR_STATE if the current thread does not own the monitor<br>
+ * HYTHREAD_INTERRUPTED if the thread was interrupted while waiting<br>
+ * HYTHREAD_PRIORITY_INTERRUPTED if the thread was priority interrupted while waiting, or while re-obtaining the monitor<br>
+ * HYTHREAD_TIMED_OUT if the timeout expired<br>
+ * 
+ * @see hythread_monitor_wait, hythread_monitor_wait_timed, hythread_monitor_enter
+ * @see hythread_interrupt, hythread_priority_interrupt *
+ */
+IDATA VMCALL
+hythread_monitor_wait_interruptable (hythread_monitor_t monitor, I_64 millis,
+                                     IDATA nanos)
+{
+  return monitor_wait (monitor, millis, nanos, WAIT_INTERRUPTABLE);
+}
+
+#undef CDEV_CURRENT_FUNCTION
+
+#define CDEV_CURRENT_FUNCTION hythread_monitor_num_waiting
+/**
+ * Returns how many threads are currently waiting on a monitor.
+ * 
+ * @note This can only be called by the owner of this monitor.
+ *
+ * @param[in] monitor a monitor
+ * @return number of threads waiting on the monitor (>=0)
+ */
+UDATA VMCALL
+hythread_monitor_num_waiting (hythread_monitor_t monitor)
+{
+  UDATA numWaiting = 0;
+  hythread_t curr;
+  hythread_t self = MACRO_SELF ();
+
+  ASSERT (monitor);
+
+  MONITOR_LOCK (self, monitor, CALLER_MONITOR_NUM_WAITING);
+
+  curr = monitor->waiting;
+  while (curr != NULL)
+    {
+      numWaiting++;
+      curr = curr->next;
+    }
+
+  MONITOR_UNLOCK (self, monitor);
+
+  return numWaiting;
+
+}
+
+#undef CDEV_CURRENT_FUNCTION
+
+#define CDEV_CURRENT_FUNCTION monitor_wait
+/*
+ * 
+ * Wait on a monitor.
+ * 
+ * Release the monitor, wait for a signal (notification), then re-acquire the monitor.
+ * 
+ * In this function, we 'unwind' any recursive hold (monitor->count) the thread has 
+ * on the monitor and release the OS monitor. When the monitor is re-acquired, 
+ * the recursive count is restored to its original value.
+ *
+ * A timeout of 0 (0ms, 0ns) indicates wait indefinitely.
+ * 
+ * If 'interruptable' is non-zero, the wait may be interrupted by one of the 
+ * interrupt functions. (i.e. hythread_interrupt, hythread_priority_interrupt);
+ *
+ * @param[in] monitor monitor to be waited on
+ * @param[in] millis >=0
+ * @param[in] nanos >=0
+ * @param[in] interruptable non-zero if the wait is to be interruptable
+ *
+ * @return HYTHREAD_INVALID_ARGUMENT      - if millis or nanos is out of range (millis or nanos < 0, or nanos >= 1E6)
+ *          HYTHREAD_ILLEGAL_MONITOR_STATE - the current thread does not own the monitor
+ *          0                              - the monitor has been waited on, notified, and reobtained
+ *          HYTHREAD_INTERRUPTED           - the thread was interrupted while waiting
+ *          HYTHREAD_PRIORITY_INTERRUPTED  - if the thread was priority interrupted while waiting, or while re-obtaining the monitor
+ *          HYTHREAD_TIMED_OUT             - the timeout expired
+ * 
+ * @see hythread_monitor_wait, hythread_monitor_wait_interruptable, hythread_monitor_enter
+ * @see hythread_interrupt, hythread_priority_interrupt
+ */
+static IDATA
+monitor_wait (hythread_monitor_t monitor, I_64 millis, IDATA nanos,
+              IDATA interruptable)
+{
+  hythread_t self = MACRO_SELF ();
+  IDATA count = -1;
+  UDATA flags;
+  UDATA interrupted = 0, notified = 0, priorityinterrupted = 0;
+  UDATA timedOut = 0;
+
+  ASSERT (monitor);
+  ASSERT (FREE_TAG != monitor->count);
+
+  if (monitor->owner != self)
+    {
+      ASSERT_DEBUG (0);
+      return HYTHREAD_ILLEGAL_MONITOR_STATE;
+    }
+
+  if ((millis < 0) || (nanos < 0) || (nanos >= 1000000))
+    {
+      ASSERT_DEBUG (0);
+      return HYTHREAD_INVALID_ARGUMENT;
+    }
+
+  count = monitor->count;
+  flags = monitor->flags;
+
+  THREAD_LOCK (self, self, CALLER_MONITOR_WAIT1);
+  ASSERT (0 == self->monitor);
+
+  /*
+   * Before we wait, check if we've already been either interrupted or pri interrupted
+   */
+  if (interruptable && (self->flags & HYTHREAD_FLAG_INTERRUPTED))
+    {
+      self->flags &= ~HYTHREAD_FLAG_INTERRUPTED;
+      THREAD_UNLOCK (self, self);
+      return HYTHREAD_INTERRUPTED;
+    }
+
+  if (interruptable && (self->flags & HYTHREAD_FLAG_PRIORITY_INTERRUPTED))
+    {
+      self->flags &= ~HYTHREAD_FLAG_PRIORITY_INTERRUPTED;
+      THREAD_UNLOCK (self, self);
+      return HYTHREAD_PRIORITY_INTERRUPTED;
+    }
+
+  self->flags |=
+    (HYTHREAD_FLAG_WAITING |
+     (interruptable ? HYTHREAD_FLAG_INTERRUPTABLE : 0));
+  if (millis || nanos)
+    {
+      self->flags |= HYTHREAD_FLAG_TIMER_SET;
+    }
+  self->monitor = monitor;
+  THREAD_UNLOCK (self, self);
+
+  ASSERT (self->flags & HYTHREAD_FLAG_WAITING);
+  monitor->owner = NULL;
+  monitor->count = 0;
+
+  MONITOR_LOCK (self, monitor, CALLER_MONITOR_WAIT);
+  if (HYTHREAD_MONITOR_SPINLOCK_EXCEEDED ==
+      hythread_spinlock_swapState (monitor,
+                                   HYTHREAD_MONITOR_SPINLOCK_UNOWNED))
+    {
+      unblock_spinlock_threads (self, monitor);
+    }
+
+  enqueue_thread (&monitor->waiting, self);
+
+  if (millis || nanos)
+    {
+      IDATA boundedMillis = BOUNDED_I64_TO_IDATA (millis);
+
+      COND_WAIT_IF_TIMEDOUT (self->condition, monitor->mutex, boundedMillis,
+                             nanos)
+      {
+
+        THREAD_LOCK (self, self, CALLER_MONITOR_WAIT2);
+        interrupted = interruptable
+          && ((self->flags & HYTHREAD_FLAG_INTERRUPTED) != 0);
+        priorityinterrupted = interruptable
+          && ((self->flags & HYTHREAD_FLAG_PRIORITY_INTERRUPTED) != 0);
+        notified = self->flags & HYTHREAD_FLAG_NOTIFIED;
+        if (!(interrupted || priorityinterrupted || notified))
+          {
+            timedOut = 1;
+          }
+        break;
+      }
+      else
+      {
+
+        THREAD_LOCK (self, self, CALLER_MONITOR_WAIT2);
+        interrupted = interruptable
+          && ((self->flags & HYTHREAD_FLAG_INTERRUPTED) != 0);
+        priorityinterrupted = interruptable
+          && ((self->flags & HYTHREAD_FLAG_PRIORITY_INTERRUPTED) != 0);
+        notified = self->flags & HYTHREAD_FLAG_NOTIFIED;
+        if (interrupted || priorityinterrupted || notified)
+          {
+            break;
+          }
+        /* must have been spurious */
+        ASSERT_DEBUG (0);
+        THREAD_UNLOCK (self, self);
+      }
+      COND_WAIT_TIMED_LOOP ();
+    }
+  else
+    {
+      /*
+       * WAIT UNTIL NOTIFIED
+       */
+
+      COND_WAIT (self->condition, monitor->mutex);
+
+      THREAD_LOCK (self, self, CALLER_MONITOR_WAIT2);
+      interrupted = interruptable
+        && ((self->flags & HYTHREAD_FLAG_INTERRUPTED) != 0);
+      priorityinterrupted = interruptable
+        && ((self->flags & HYTHREAD_FLAG_PRIORITY_INTERRUPTED) != 0);
+      notified = self->flags & HYTHREAD_FLAG_NOTIFIED;
+      if (interrupted || priorityinterrupted || notified)
+        {
+          break;
+        }
+      /* must have been spurious */
+      ASSERT_DEBUG (0);
+      THREAD_UNLOCK (self, self);
+      COND_WAIT_LOOP ();
+    }
+
+  /* DONE WAITING AT THIS POINT */
+
+  /* we have to remove self from the wait queue */
+  remove_from_queue (&monitor->waiting, self);
+
+  MONITOR_UNLOCK (self, monitor);
+
+  /* at this point, this thread should already be locked */
+  ASSERT (notified || interrupted || priorityinterrupted || timedOut);
+  ASSERT (!interrupted || interruptable);       /* if we were interrupted, then we'd better have been interruptable */
+
+  self->flags &=
+    ~(HYTHREAD_FLAG_WAITING | HYTHREAD_FLAG_NOTIFIED |
+      HYTHREAD_FLAG_PRIORITY_INTERRUPTED | HYTHREAD_FLAG_INTERRUPTABLE |
+      HYTHREAD_FLAG_TIMER_SET);
+
+  if (interrupted && !(notified || priorityinterrupted))
+    self->flags &= ~HYTHREAD_FLAG_INTERRUPTED;
+
+  /* 
+   * Is there an interruptServer thread out there
+   * trying to interrupt us? Its services are 
+   * no longer required.
+   */
+  if (self->interrupter)
+    {
+      ASSERT (interrupted || priorityinterrupted);
+      THREAD_LOCK (self, self->interrupter, CALLER_MONITOR_WAIT2);
+      self->interrupter->flags |= HYTHREAD_FLAG_CANCELED;
+      THREAD_UNLOCK (self, self->interrupter);
+      self->interrupter = NULL;
+    }
+
+  THREAD_UNLOCK (self, self);
+
+  monitor_enter_three_tier (self, monitor);
+
+  monitor->count = count;
+
+  ASSERT (monitor->owner == self);
+  ASSERT (monitor->count == count);
+  ASSERT (monitor->count >= 1);
+  ASSERT (0 == self->monitor);
+  ASSERT (!(monitor->flags & HYTHREAD_FLAG_WAITING));
+  ASSERT (!(monitor->flags & HYTHREAD_FLAG_TIMER_SET));
+  ASSERT (!(monitor->flags & HYTHREAD_FLAG_BLOCKED));
+  ASSERT (!(monitor->flags & HYTHREAD_FLAG_NOTIFIED));
+  ASSERT (!(monitor->flags & HYTHREAD_FLAG_INTERRUPTABLE));
+  ASSERT (NULL == self->next);
+
+  if (priorityinterrupted)
+    return HYTHREAD_PRIORITY_INTERRUPTED;
+  if (notified)
+    return 0;
+  if (interrupted)
+    return HYTHREAD_INTERRUPTED;
+  if (timedOut)
+    return HYTHREAD_TIMED_OUT;
+  ASSERT (0);
+  return 0;
+
+}
+
+#undef CDEV_CURRENT_FUNCTION
+
+#define CDEV_CURRENT_FUNCTION interrupt_thread
+/*
+ * Interrupt a thread.
+ *
+ * If the thread is currently blocked (e.g. waiting on monitor_wait) 
+ * resume the thread and return from the blocking function with
+ * HYTHREAD_INTERRUPTED or HYTHREAD_PRIORITY_INTERRUPTED
+ * 
+ * If it can't be resumed (it's not in an interruptable state)
+ * then just set the appropriate interrupt flag.
+ * 
+ * @param[in] thread thread to be interrupted
+ * @param[in] interruptFlag indicated whether to priority interrupt or just normally interrupt.
+ * @return none
+ */
+static void
+interrupt_thread (hythread_t thread, UDATA interruptFlag)
+{
+  UDATA currFlags, newFlags;
+  hythread_t self = MACRO_SELF ();
+
+  ASSERT (self);
+  ASSERT (thread);
+
+  GLOBAL_LOCK (self, CALLER_INTERRUPT_THREAD);
+  THREAD_LOCK (self, thread, CALLER_INTERRUPT_THREAD);
+  if (thread->flags & interruptFlag)
+    {
+      THREAD_UNLOCK (self, thread);
+      GLOBAL_UNLOCK (self);
+      return;
+    }
+
+  currFlags = thread->flags;
+  newFlags = currFlags | interruptFlag;
+  if (currFlags & HYTHREAD_FLAG_INTERRUPTABLE)
+    {
+      if (currFlags & (HYTHREAD_FLAG_SLEEPING | HYTHREAD_FLAG_PARKED))
+        {
+          COND_NOTIFY_ALL (thread->condition);
+        }
+      else if (currFlags & HYTHREAD_FLAG_WAITING)
+        {
+          if (interrupt_waiting_thread (self, thread))
+            {
+              newFlags |= HYTHREAD_FLAG_BLOCKED;
+            }
+        }
+    }
+
+  thread->flags = newFlags;
+  THREAD_UNLOCK (self, thread);
+  GLOBAL_UNLOCK (self);
+
+}
+
+#undef CDEV_CURRENT_FUNCTION
+
+#define CDEV_CURRENT_FUNCTION interrupt_waiting_thread
+/*
+ * Interrupt a waiting thread.
+ * 
+ * @param[in] self current thread
+ * @param[in] threadToInterrupt
+ * @return 1 if the thread was immediately interrupted<br>
+ * 0 if the thread will be interrupted asap by a special thread.
+ * @note: Assumes caller has locked the global mutex
+ */
+static IDATA
+interrupt_waiting_thread (hythread_t self, hythread_t threadToInterrupt)
+{
+
+  IDATA retVal = 0;
+  hythread_monitor_t monitor;
+
+  ASSERT (self);
+  ASSERT (threadToInterrupt);
+  ASSERT (self != threadToInterrupt);
+  ASSERT (threadToInterrupt->flags & HYTHREAD_FLAG_INTERRUPTABLE);
+  ASSERT (threadToInterrupt->monitor);
+  ASSERT (NULL == threadToInterrupt->interrupter);
+
+#if !defined(ALWAYS_SPAWN_THREAD_TO_INTERRUPT)
+  /*
+   * If we can enter the monitor without blocking, we don't need the
+   * interruptServer thread
+   */
+  monitor = threadToInterrupt->monitor;
+  if (hythread_monitor_try_enter_using_threadId (monitor, self) == 0)
+    {
+      ASSERT (monitor->owner == self);
+      COND_NOTIFY_ALL (threadToInterrupt->condition);
+      hythread_monitor_exit_using_threadId (monitor, self);
+      retVal = 1;
+    }
+  else
+#endif
+
+    {
+      /*
+       * spawn a thread to do it for us, because it's possible that
+       * having this thread lock the waiting thread's monitor may
+       * cause deadlock
+       */
+      create_thread (&threadToInterrupt->interrupter, 0,
+                     HYTHREAD_PRIORITY_NORMAL, 0, interruptServer,
+                     (void *) threadToInterrupt, GLOBAL_IS_LOCKED);
+    }
+  return retVal;
+
+}
+
+#undef CDEV_CURRENT_FUNCTION
+
+#define CDEV_CURRENT_FUNCTION interruptServer
+/*
+ * Interrupt a thread waiting on a monitor.
+ *  
+ * This function serves as the entry point for a 
+ * thread whose sole purpose is to interrupt another
+ * thread.
+ * 
+ * @param[in] entryArg pointer to the thread to interrupt (non-NULL)
+ * @return 0
+ */
+static I_32 HYTHREAD_PROC
+interruptServer (void *entryArg)
+{
+  hythread_t self = MACRO_SELF ();
+  hythread_t threadToInterrupt = (hythread_t) entryArg;
+  hythread_monitor_t monitor;
+
+  ASSERT (threadToInterrupt);
+  ASSERT (self);
+
+  GLOBAL_LOCK (self, CALLER_INTERRUPT_SERVER);
+
+  /*
+   * Did the thread to interrupt die or come out of wait already?
+   * If it did, it cancelled this thread (set our CANCELED bit)
+   */
+  if (self->flags & HYTHREAD_FLAG_CANCELED)
+    {
+      GLOBAL_UNLOCK (self);
+      hythread_exit (NULL);     /* this should not return */
+    }
+
+  THREAD_LOCK (self, threadToInterrupt, CALLER_INTERRUPT_SERVER);
+
+  if (threadToInterrupt->interrupter != self)
+    {
+      THREAD_UNLOCK (self, threadToInterrupt);
+      GLOBAL_UNLOCK (self);
+      hythread_exit (NULL);     /* this should not return */
+    }
+
+  monitor = threadToInterrupt->monitor;
+  ASSERT (monitor);
+  ASSERT (threadToInterrupt->flags & HYTHREAD_FLAG_WAITING);
+
+  hythread_monitor_pin (monitor, self);
+  THREAD_UNLOCK (self, threadToInterrupt);
+  GLOBAL_UNLOCK (self);
+
+  /* try to take the monitor so that we can notify the thread to interrupt */
+  hythread_monitor_enter (monitor);
+
+  GLOBAL_LOCK (self, CALLER_INTERRUPT_SERVER);
+  hythread_monitor_unpin (monitor, self);
+
+  /* Did the thread to interrupt die or come out of wait already? */
+  if (self->flags & HYTHREAD_FLAG_CANCELED)
+    {
+      GLOBAL_UNLOCK (self);
+      hythread_exit (monitor);  /* this should not return */
+      ASSERT (0);
+    }
+
+  THREAD_LOCK (self, threadToInterrupt, CALLER_INTERRUPT_SERVER);
+  if ((threadToInterrupt->interrupter == self)
+      && (threadToInterrupt->flags & HYTHREAD_FLAG_WAITING))
+    {
+      notify_thread (threadToInterrupt, DONT_SET_NOTIFIED_FLAG);
+    }
+  threadToInterrupt->interrupter = NULL;
+  ASSERT (threadToInterrupt->flags & HYTHREAD_FLAG_INTERRUPTED);
+  THREAD_UNLOCK (self, threadToInterrupt);
+
+  GLOBAL_UNLOCK (self);
+  hythread_exit (monitor);
+
+  ASSERT (0);
+  return 0;
+}
+
+#undef CDEV_CURRENT_FUNCTION
+
+#define CDEV_CURRENT_FUNCTION hythread_monitor_exit_using_threadId
+/**
+ * Exit a monitor.
+ * 
+ * This is a slightly faster version of hythread_monitor_exit because
+ * the hythread_t for the current thread doesn't have to be looked up
+ * 
+ * @param[in] monitor a monitor to be exited
+ * @param[in] threadId hythread_t for the current thread
+ * @return 0 on success<br>
+ * HYTHREAD_ILLEGAL_MONITOR_STATE if the current thread does not own the monitor
+ * 
+ * @see hythread_monitor_exit, hythread_monitor_enter, hythread_monitor_enter_using_threadId
+ */
+IDATA VMCALL
+hythread_monitor_exit_using_threadId (hythread_monitor_t monitor,
+                                      hythread_t threadId)
+{
+  ASSERT (threadId == MACRO_SELF ());
+  ASSERT (monitor);
+  ASSERT (FREE_TAG != monitor->count);
+
+  if (monitor->owner != threadId)
+    {
+      ASSERT_DEBUG (0);
+      return HYTHREAD_ILLEGAL_MONITOR_STATE;
+    }
+
+  return monitor_exit (threadId, monitor);
+
+}
+
+#undef CDEV_CURRENT_FUNCTION
+
+#define CDEV_CURRENT_FUNCTION hythread_monitor_enter_using_threadId
+/**
+ * Enter a monitor.
+ * 
+ * This is a slightly faster version of hythread_monitor_enter because
+ * the hythread_t for the current thread doesn't have to be looked up
+ *
+ * @param[in] monitor a monitor to be entered
+ * @param[in] threadId hythread_t for the current thread
+ * @return 0 on success<br>
+ * 				 HYTHREAD_PRIORITY_INTERRUPTED if the thread was priority interrupted while blocked
+ * 
+ * @see hythread_monitor_enter, hythread_monitor_exit, hythread_monitor_exit_using_threadId
+ *
+ */
+IDATA VMCALL
+hythread_monitor_enter_using_threadId (hythread_monitor_t monitor,
+                                       hythread_t threadId)
+{
+  ASSERT (threadId != 0);
+  ASSERT (threadId == MACRO_SELF ());
+  ASSERT (monitor);
+  ASSERT (FREE_TAG != monitor->count);
+
+  if (monitor->owner == threadId)
+    {
+      ASSERT (monitor->count >= 1);
+      monitor->count++;
+
+      if (IS_JLM_ENABLED (threadId))
+        {
+          ASSERT (monitor->tracing);
+          monitor->tracing->recursive_count++;
+          monitor->tracing->enter_count++;
+        }                       /* if (IS_JLM_ENABLED(threadId)) */
+
+      return 0;
+    }
+  return monitor_enter (threadId, monitor);
+}
+
+#undef CDEV_CURRENT_FUNCTION
+
+#define CDEV_CURRENT_FUNCTION hythread_monitor_try_enter_using_threadId
+/** 
+ * Attempt to enter a monitor without blocking.
+ * 
+ * If the thread must block before it enters the monitor this function
+ * returns immediately with a negative value to indicate failure.<br>
+ *  
+ * This is a slightly faster version of hythread_monitor_try_enter because
+ * the current thread's hythread_t doesn't have to be looked up.
+ * 
+ * @param[in] monitor a monitor
+ * @param[in] threadId the current thread
+ * @return  0 on success or negative value on failure
+ *
+ * @see hythread_monitor_try_enter
+ *
+ */
+IDATA VMCALL
+hythread_monitor_try_enter_using_threadId (hythread_monitor_t monitor,
+                                           hythread_t threadId)
+{
+
+  ASSERT (threadId != 0);
+  ASSERT (threadId == MACRO_SELF ());
+  ASSERT (FREE_TAG != monitor->count);
+
+  /* Are we already the owner? */
+  if (monitor->owner == threadId)
+    {
+      ASSERT (monitor->count >= 1);
+      monitor->count++;
+
+      if (IS_JLM_ENABLED (threadId))
+        {
+          monitor->tracing->recursive_count++;
+          monitor->tracing->enter_count++;
+        }                       /* if (IS_JLM_ENABLED(threadId)) */
+
+      return 0;
+    }
+
+  if (hythread_spinlock_acquire (threadId, monitor) == 0)
+
+    {
+      ASSERT (NULL == monitor->owner);
+      ASSERT (0 == monitor->count);
+
+      monitor->owner = threadId;
+      monitor->count = 1;
+
+      if (IS_JLM_ENABLED (threadId))
+        {
+          monitor->tracing->enter_count++;
+
+        }                       /* if (IS_JLM_ENABLED(threadId)) */
+
+      return 0;
+    }
+
+  return -1;
+}
+
+#undef CDEV_CURRENT_FUNCTION
+
+#define CDEV_CURRENT_FUNCTION hythread_probe
+
+#undef CDEV_CURRENT_FUNCTION
+
+#define CDEV_CURRENT_FUNCTION destroy_thread
+/*
+ * Destroy the resources associated with the thread.
+ * 
+ * If the thread is not already dead, the function fails.
+ *
+ * @param[in] thread thread to be destroyed
+ * @param[in] globalAlreadyLocked indicated whether the thread library global mutex is already locked 
+ * @return 0 on success or negative value on failure.
+ */
+static IDATA
+destroy_thread (hythread_t thread, int globalAlreadyLocked)
+{
+
+  hythread_t self = MACRO_SELF ();
+  hythread_library_t lib = self->library;
+
+  ASSERT (thread);
+  ASSERT (lib);
+
+  THREAD_LOCK (self, thread, CALLER_DESTROY);
+  if ((thread->flags & HYTHREAD_FLAG_DEAD) == 0)
+    {
+      THREAD_UNLOCK (self, thread);
+      return -1;
+    }
+  THREAD_UNLOCK (self, thread);
+
+  COND_DESTROY (thread->condition);
+
+  MUTEX_DESTROY (thread->mutex);
+
+#if defined(WIN32)
+  if (thread->flags & HYTHREAD_FLAG_ATTACHED)
+    {
+      CloseHandle (thread->handle);
+    }
+#endif
+
+  free_thread (thread, globalAlreadyLocked);
+  return 0;
+}
+
+#undef CDEV_CURRENT_FUNCTION
+
+#define CDEV_CURRENT_FUNCTION hythread_jlm_thread_init
+
+/*
+ * Initialize and clear a thread's JLM tracing information. 
+ * 
+ * Tracing information for the thread is allocated if not already allocated
+ * The library's thread tracing pool is initialized if not already initialized.
+ * 
+ * @param[in] thread thread to be initialized
+ * @return none
+ *
+ */
+void VMCALL
+hythread_jlm_thread_init (hythread_t thread)
+{
+  hythread_library_t library = thread->library;
+
+  ASSERT (thread);
+  ASSERT (library);
+
+}
+
+#undef CDEV_CURRENT_FUNCTION
+
+#define CDEV_CURRENT_FUNCTION hythread_jlm_thread_clear
+
+/*
+ * Clear (reset) a thread's JLM tracing structure.
+ * 
+ * Assumes the thread's tracing structure has already been allocated.
+ *
+ * @param[in] thread thread to be initialized (non-NULL)
+ * @return none
+ *
+ */
+void VMCALL
+hythread_jlm_thread_clear (hythread_t thread)
+{
+  ASSERT (thread);
+
+}
+
+#undef CDEV_CURRENT_FUNCTION
+
+#define CDEV_CURRENT_FUNCTION hythread_jlm_monitor_init
+
+/*
+ * Initialize and clear a monitor's JLM tracing information. 
+ * 
+ * Tracing information for the monitor is allocated if not already allocated
+ * The library's monitor tracing pool is initialized if not already initialized.
+ * 
+ * @param[in] monitor monitor to be initialized
+ * @return none
+ *
+ */
+void VMCALL
+hythread_jlm_monitor_init (hythread_monitor_t monitor)
+{
+  hythread_t self = MACRO_SELF ();
+  hythread_library_t library;
+  ASSERT (self);
+  ASSERT (monitor);
+  library = self->library;
+  ASSERT (library);
+
+  if (library->monitor_tracing_pool == NULL)
+    {
+      library->monitor_tracing_pool =
+        pool_new (sizeof (HyThreadMonitorTracing), 0, 0, 0, thread_malloc,
+                  thread_free, NULL);
+    }
+
+  if (monitor->tracing == NULL)
+    {
+      /* cannot have been set, so set it now */
+      monitor->tracing = pool_newElement (library->monitor_tracing_pool);
+    }
+
+  hythread_jlm_monitor_clear (monitor);
+}
+
+#undef CDEV_CURRENT_FUNCTION
+
+#define CDEV_CURRENT_FUNCTION hythread_jlm_monitor_clear
+
+/*
+ * Clear (reset) a monitor's JLM tracing structure.
+ * 
+ * Assumes the monitor's tracing structure has already been allocated.
+ *
+ * @param[in] monitor a monitor to be initialized
+ * @return none
+ */
+void VMCALL
+hythread_jlm_monitor_clear (hythread_monitor_t monitor)
+{
+  ASSERT (monitor);
+  ASSERT (monitor->tracing);
+  memset (monitor->tracing, 0, sizeof (*monitor->tracing));
+}
+
+#undef CDEV_CURRENT_FUNCTION
+
+#define CDEV_CURRENT_FUNCTION init_monitor
+/*
+ * Re-initialize the 'simple' fields of a monitor
+ * that has been initialized previously, but is now
+ * being re-used. 
+ *
+ * @param[in] monitor monitor to be initialized
+ * @return 0 on success or negative value on failure.
+ * @see hythread_monitor_init_with_name
+ * 
+ */
+static UDATA
+init_monitor (hythread_monitor_t monitor, UDATA flags)
+{
+  ASSERT (monitor);
+  monitor->count = 0;
+  monitor->owner = NULL;
+  monitor->waiting = NULL;
+  monitor->flags = flags;
+  monitor->userData = 0;
+  monitor->name = 0;
+  monitor->pinCount = 0;
+
+  monitor->proDeflationCount = 0;
+  monitor->antiDeflationCount = 0;
+
+  monitor->blocking = NULL;
+  monitor->spinlockState = HYTHREAD_MONITOR_SPINLOCK_UNOWNED;
+  monitor->lockingWord = 0;
+  /* these numbers are taken from the GC spinlock. They probably need to be tuned more (dynamically?) */
+  /* note that every spinCount must be > 0! */
+
+  monitor->spinCount1 = 256;
+  monitor->spinCount2 = 32;
+  monitor->spinCount3 = 45;
+
+  return 0;
+}
+
+#undef CDEV_CURRENT_FUNCTION
+
+#define CDEV_CURRENT_FUNCTION getCurrentCycles
+/*
+ * Return the cycle count on the current processor. 
+ * 
+ * Units will be platform dependent. 
+ * @todo This will be implmented in builder
+ */
+static hytime_t
+getCurrentCycles (void)
+{
+  return 0;
+}
+
+#undef CDEV_CURRENT_FUNCTION
+
+#define CDEV_CURRENT_FUNCTION hythread_lib_get_flags
+
+/** 
+ * Get threading library global flags.
+ * 
+ * Returns the flags for the threading library associated with the current thread.
+ * 
+ * @note: assumes caller has global lock
+ * 

[... 449 lines stripped ...]