BOOL
pthread_win32_thread_detach_np ()
{
  if (ptw32_processInitialized)
    {
      /*
       * Don't use pthread_self() - to avoid creating an implicit POSIX thread handle
       * unnecessarily.
       */
      ptw32_thread_t * sp = (ptw32_thread_t *) pthread_getspecific (ptw32_selfThreadKey);

      if (sp != NULL) // otherwise Win32 thread with no implicit POSIX handle.
	{
	  ptw32_callUserDestroyRoutines (sp->ptHandle);

	  (void) pthread_mutex_lock (&sp->cancelLock);
	  sp->state = PThreadStateLast;
	  /*
	   * If the thread is joinable at this point then it MUST be joined
	   * or detached explicitly by the application.
	   */
	  (void) pthread_mutex_unlock (&sp->cancelLock);

	  if (sp->detachState == PTHREAD_CREATE_DETACHED)
	    {
	      ptw32_threadDestroy (sp->ptHandle);

	      TlsSetValue (ptw32_selfThreadKey->key, NULL);
	    }
	}
    }

  return TRUE;
}
BOOL
pthread_win32_thread_detach_np ()
{
  if (ptw32_processInitialized)
    {
      /*
       * Don't use pthread_self() - to avoid creating an implicit POSIX thread handle
       * unnecessarily.
       */
      ptw32_thread_t * sp = (ptw32_thread_t *) pthread_getspecific (ptw32_selfThreadKey);

      if (sp != NULL) // otherwise Win32 thread with no implicit POSIX handle.
	{
          ptw32_mcs_local_node_t stateLock;
	  ptw32_callUserDestroyRoutines (sp->ptHandle);

	  ptw32_mcs_lock_acquire (&sp->stateLock, &stateLock);
	  sp->state = PThreadStateLast;
	  /*
	   * If the thread is joinable at this point then it MUST be joined
	   * or detached explicitly by the application.
	   */
	  ptw32_mcs_lock_release (&stateLock);

          /*
           * Robust Mutexes
           */
          while (sp->robustMxList != NULL)
            {
              pthread_mutex_t mx = sp->robustMxList->mx;
              ptw32_robust_mutex_remove(&mx, sp);
              (void) PTW32_INTERLOCKED_EXCHANGE_LONG(
                       (PTW32_INTERLOCKED_LONGPTR)&mx->robustNode->stateInconsistent,
                       (PTW32_INTERLOCKED_LONG)-1);
              /*
               * If there are no waiters then the next thread to block will
               * sleep, wake up immediately and then go back to sleep.
               * See pthread_mutex_lock.c.
               */
              SetEvent(mx->event);
            }


	  if (sp->detachState == PTHREAD_CREATE_DETACHED)
	    {
	      ptw32_threadDestroy (sp->ptHandle);

	      if (ptw32_selfThreadKey)
	        {
	    	  TlsSetValue (ptw32_selfThreadKey->key, NULL);
	        }
	    }
	}
    }

  return TRUE;
}
void
ptw32_threadDestroy (pthread_t thread)
{
  struct pthread_t_ threadCopy;

  if (thread != NULL)
    {
      (void) pthread_mutex_lock(&thread->cancelLock);
      thread->state = PThreadStateLast;
      (void) pthread_mutex_unlock(&thread->cancelLock);

      ptw32_callUserDestroyRoutines (thread);

      /*
       * Copy thread state so that the thread can be atomically NULLed.
       */
      memcpy(&threadCopy, thread, sizeof(threadCopy));

      /*
       * Thread ID structs are never freed. They're NULLed and reused.
       * This also sets the thread to PThreadStateInitial (invalid).
       */
      ptw32_threadReusePush(thread);

      /* Now work on the copy. */
      if (threadCopy.cancelEvent != NULL)
	{
	  CloseHandle (threadCopy.cancelEvent);
	}

      (void) pthread_mutex_destroy(&threadCopy.cancelLock);

#if ! defined (__MINGW32__) || defined (__MSVCRT__)
      /*
       * See documentation for endthread vs endthreadex.
       * Don't close the Win32 handle of implicit POSIX threads
       * because the process may want to call GetExitCodeThread().
       */
      if( threadCopy.threadH != 0 && ! threadCopy.implicit )
	{
	  CloseHandle( threadCopy.threadH );
	}
#endif

    }

}				/* ptw32_threadDestroy */
void
ptw32_threadDestroy (pthread_t thread)
{
  if (thread != NULL)
    {
      ptw32_callUserDestroyRoutines (thread);

      if (thread->cancelEvent != NULL)
	{
	  CloseHandle (thread->cancelEvent);
	}

#if ! defined (__MINGW32__) || defined (__MSVCRT__)
      /* See documentation for endthread vs endthreadex. */
      if( thread->threadH != 0 )
	{
	  CloseHandle( thread->threadH );
	}
#endif

      free (thread);
    }

}				/* ptw32_threadDestroy */