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 */