diff options
| author | Nic Gaffney <gaffney_nic@protonmail.com> | 2025-10-13 01:19:27 -0500 |
|---|---|---|
| committer | Nic Gaffney <gaffney_nic@protonmail.com> | 2025-10-13 01:19:27 -0500 |
| commit | 1f9b827badb2de4c4eaae11c0d02242ec90af7f6 (patch) | |
| tree | 27acb295833e6eee730dd71f98db280d54c6a4ad /vendor/zgui/libs/winpthreads/src/thread.c | |
| parent | b5d0c1dcd751f4735d9f6b45c805300000c9d171 (diff) | |
| download | particle-sim-1f9b827badb2de4c4eaae11c0d02242ec90af7f6.tar.gz | |
Updating to zig 0.15.1
Diffstat (limited to 'vendor/zgui/libs/winpthreads/src/thread.c')
| -rw-r--r-- | vendor/zgui/libs/winpthreads/src/thread.c | 1914 |
1 files changed, 0 insertions, 1914 deletions
diff --git a/vendor/zgui/libs/winpthreads/src/thread.c b/vendor/zgui/libs/winpthreads/src/thread.c deleted file mode 100644 index 36ee665..0000000 --- a/vendor/zgui/libs/winpthreads/src/thread.c +++ /dev/null @@ -1,1914 +0,0 @@ -/* - Copyright (c) 2011-2016 mingw-w64 project - - Permission is hereby granted, free of charge, to any person obtaining a - copy of this software and associated documentation files (the "Software"), - to deal in the Software without restriction, including without limitation - the rights to use, copy, modify, merge, publish, distribute, sublicense, - and/or sell copies of the Software, and to permit persons to whom the - Software is furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - DEALINGS IN THE SOFTWARE. -*/ - -#include <windows.h> -#include <strsafe.h> -#include <stdio.h> -#include <stdlib.h> -#include <malloc.h> -#include <signal.h> -#include "pthread.h" -#include "thread.h" -#include "misc.h" -#include "winpthread_internal.h" - -static _pthread_v *__pthread_self_lite (void); - -void (**_pthread_key_dest)(void *) = NULL; - -static volatile long _pthread_cancelling; -static int _pthread_concur; - -/* FIXME Will default to zero as needed */ -static pthread_once_t _pthread_tls_once; -static DWORD _pthread_tls = 0xffffffff; - -static pthread_rwlock_t _pthread_key_lock = PTHREAD_RWLOCK_INITIALIZER; -static unsigned long _pthread_key_max=0L; -static unsigned long _pthread_key_sch=0L; - -static _pthread_v *pthr_root = NULL, *pthr_last = NULL; -static pthread_mutex_t mtx_pthr_locked = PTHREAD_RECURSIVE_MUTEX_INITIALIZER; - -static __pthread_idlist *idList = NULL; -static size_t idListCnt = 0; -static size_t idListMax = 0; -static pthread_t idListNextId = 0; - -#if !defined(_MSC_VER) -#define USE_VEH_FOR_MSC_SETTHREADNAME -#endif -#if !WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) -/* forbidden RemoveVectoredExceptionHandler/AddVectoredExceptionHandler APIs */ -#undef USE_VEH_FOR_MSC_SETTHREADNAME -#endif - -#if defined(USE_VEH_FOR_MSC_SETTHREADNAME) -static void *SetThreadName_VEH_handle = NULL; - -static LONG __stdcall -SetThreadName_VEH (PEXCEPTION_POINTERS ExceptionInfo) -{ - if (ExceptionInfo->ExceptionRecord != NULL && - ExceptionInfo->ExceptionRecord->ExceptionCode == EXCEPTION_SET_THREAD_NAME) - return EXCEPTION_CONTINUE_EXECUTION; - - return EXCEPTION_CONTINUE_SEARCH; -} - -static PVOID (*AddVectoredExceptionHandlerFuncPtr) (ULONG, PVECTORED_EXCEPTION_HANDLER); -static ULONG (*RemoveVectoredExceptionHandlerFuncPtr) (PVOID); - -static void __attribute__((constructor)) -ctor (void) -{ - HMODULE module = GetModuleHandleA("kernel32.dll"); - if (module) { - AddVectoredExceptionHandlerFuncPtr = (__typeof__(AddVectoredExceptionHandlerFuncPtr)) GetProcAddress(module, "AddVectoredExceptionHandler"); - RemoveVectoredExceptionHandlerFuncPtr = (__typeof__(RemoveVectoredExceptionHandlerFuncPtr)) GetProcAddress(module, "RemoveVectoredExceptionHandler"); - } -} -#endif - -typedef struct _THREADNAME_INFO -{ - DWORD dwType; /* must be 0x1000 */ - LPCSTR szName; /* pointer to name (in user addr space) */ - DWORD dwThreadID; /* thread ID (-1=caller thread) */ - DWORD dwFlags; /* reserved for future use, must be zero */ -} THREADNAME_INFO; - -static void -SetThreadName (DWORD dwThreadID, LPCSTR szThreadName) -{ - THREADNAME_INFO info; - DWORD infosize; - - info.dwType = 0x1000; - info.szName = szThreadName; - info.dwThreadID = dwThreadID; - info.dwFlags = 0; - - infosize = sizeof (info) / sizeof (ULONG_PTR); - -#if defined(_MSC_VER) && !defined (USE_VEH_FOR_MSC_SETTHREADNAME) - __try - { - RaiseException (EXCEPTION_SET_THREAD_NAME, 0, infosize, (ULONG_PTR *)&info); - } - __except (EXCEPTION_EXECUTE_HANDLER) - { - } -#else - /* Without a debugger we *must* have an exception handler, - * otherwise raising an exception will crash the process. - */ -#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) - if ((!IsDebuggerPresent ()) && (SetThreadName_VEH_handle == NULL)) -#else - if (!IsDebuggerPresent ()) -#endif - return; - - RaiseException (EXCEPTION_SET_THREAD_NAME, 0, infosize, (ULONG_PTR *) &info); -#endif -} - -/* Search the list idList for an element with identifier ID. If - found, its associated _pthread_v pointer is returned, otherwise - NULL. - NOTE: This method is not locked. */ -static struct _pthread_v * -__pthread_get_pointer (pthread_t id) -{ - size_t l, r, p; - if (!idListCnt) - return NULL; - if (idListCnt == 1) - return (idList[0].id == id ? idList[0].ptr : NULL); - l = 0; r = idListCnt - 1; - while (l <= r) - { - p = (l + r) >> 1; - if (idList[p].id == id) - return idList[p].ptr; - else if (idList[p].id > id) - { - if (p == l) - return NULL; - r = p - 1; - } - else - { - l = p + 1; - } - } - - return NULL; -} - -static void -__pth_remove_use_for_key (pthread_key_t key) -{ - int i; - - pthread_mutex_lock (&mtx_pthr_locked); - for (i = 0; i < idListCnt; i++) - { - if (idList[i].ptr != NULL - && idList[i].ptr->keyval != NULL - && key < idList[i].ptr->keymax) - { - idList[i].ptr->keyval[key] = NULL; - idList[i].ptr->keyval_set[key] = 0; - } - } - pthread_mutex_unlock (&mtx_pthr_locked); -} - -/* Search the list idList for an element with identifier ID. If - found, its associated _pthread_v pointer is returned, otherwise - NULL. - NOTE: This method uses lock mtx_pthr_locked. */ -struct _pthread_v * -__pth_gpointer_locked (pthread_t id) -{ - struct _pthread_v *ret; - if (!id) - return NULL; - pthread_mutex_lock (&mtx_pthr_locked); - ret = __pthread_get_pointer (id); - pthread_mutex_unlock (&mtx_pthr_locked); - return ret; -} - -/* Registers in the list idList an element with _pthread_v pointer - and creates and unique identifier ID. If successful created the - ID of this element is returned, otherwise on failure zero ID gets - returned. - NOTE: This method is not locked. */ -static pthread_t -__pthread_register_pointer (struct _pthread_v *ptr) -{ - __pthread_idlist *e; - size_t i; - - if (!ptr) - return 0; - /* Check if a resize of list is necessary. */ - if (idListCnt >= idListMax) - { - if (!idListCnt) - { - e = (__pthread_idlist *) malloc (sizeof (__pthread_idlist) * 16); - if (!e) - return 0; - idListMax = 16; - idList = e; - } - else - { - e = (__pthread_idlist *) realloc (idList, sizeof (__pthread_idlist) * (idListMax + 16)); - if (!e) - return 0; - idListMax += 16; - idList = e; - } - } - do - { - ++idListNextId; - /* If two MSB are set we reset to id 1. We need to check here bits - to avoid gcc's no-overflow issue on increment. Additionally we - need to handle different size of pthread_t on 32-bit/64-bit. */ - if ((idListNextId & ( ((pthread_t) 1) << ((sizeof (pthread_t) * 8) - 2))) != 0) - idListNextId = 1; - } - while (idListNextId == 0 || __pthread_get_pointer (idListNextId)); - /* We assume insert at end of list. */ - i = idListCnt; - if (i != 0) - { - /* Find position we can actual insert sorted. */ - while (i > 0 && idList[i - 1].id > idListNextId) - --i; - if (i != idListCnt) - memmove (&idList[i + 1], &idList[i], sizeof (__pthread_idlist) * (idListCnt - i)); - } - idList[i].id = idListNextId; - idList[i].ptr = ptr; - ++idListCnt; - return idListNextId; -} - -/* Deregisters in the list idList an element with identifier ID and - returns its _pthread_v pointer on success. Otherwise NULL is returned. - NOTE: This method is not locked. */ -static struct _pthread_v * -__pthread_deregister_pointer (pthread_t id) -{ - size_t l, r, p; - if (!idListCnt) - return NULL; - l = 0; r = idListCnt - 1; - while (l <= r) - { - p = (l + r) >> 1; - if (idList[p].id == id) - { - struct _pthread_v *ret = idList[p].ptr; - p++; - if (p < idListCnt) - memmove (&idList[p - 1], &idList[p], sizeof (__pthread_idlist) * (idListCnt - p)); - --idListCnt; - /* Is this last element in list then free list. */ - if (idListCnt == 0) - { - free (idList); - idListCnt = idListMax = 0; - } - return ret; - } - else if (idList[p].id > id) - { - if (p == l) - return NULL; - r = p - 1; - } - else - { - l = p + 1; - } - } - return NULL; -} - -/* Save a _pthread_v element for reuse in pool. */ -static void -push_pthread_mem (_pthread_v *sv) -{ - if (!sv || sv->next != NULL) - return; - pthread_mutex_lock (&mtx_pthr_locked); - if (sv->x != 0) - __pthread_deregister_pointer (sv->x); - if (sv->keyval) - free (sv->keyval); - if (sv->keyval_set) - free (sv->keyval_set); - if (sv->thread_name) - free (sv->thread_name); - memset (sv, 0, sizeof(struct _pthread_v)); - if (pthr_last == NULL) - pthr_root = pthr_last = sv; - else - { - pthr_last->next = sv; - pthr_last = sv; - } - pthread_mutex_unlock (&mtx_pthr_locked); -} - -/* Get a _pthread_v element from pool, or allocate it. - Note the unique identifier is created for the element here, too. */ -static _pthread_v * -pop_pthread_mem (void) -{ - _pthread_v *r = NULL; - - pthread_mutex_lock (&mtx_pthr_locked); - if ((r = pthr_root) == NULL) - { - if ((r = (_pthread_v *)calloc (1,sizeof(struct _pthread_v))) != NULL) - { - r->x = __pthread_register_pointer (r); - if (r->x == 0) - { - free (r); - r = NULL; - } - } - pthread_mutex_unlock (&mtx_pthr_locked); - return r; - } - r->x = __pthread_register_pointer (r); - if (r->x == 0) - r = NULL; - else - { - if((pthr_root = r->next) == NULL) - pthr_last = NULL; - - r->next = NULL; - } - pthread_mutex_unlock (&mtx_pthr_locked); - return r; -} - -/* Free memory consumed in _pthread_v pointer pool. */ -static void -free_pthread_mem (void) -{ -#if 0 - _pthread_v *t; - - pthread_mutex_lock (&mtx_pthr_locked); - t = pthr_root; - while (t != NULL) - { - _pthread_v *sv = t; - t = t->next; - if (sv->x != 0 && sv->ended == 0 && sv->valid != DEAD_THREAD) - { - pthread_mutex_unlock (&mtx_pthr_locked); - pthread_cancel (t->x); - Sleep (0); - pthread_mutex_lock (&mtx_pthr_locked); - t = pthr_root; - continue; - } - else if (sv->x != 0 && sv->valid != DEAD_THREAD) - { - pthread_mutex_unlock (&mtx_pthr_locked); - Sleep (0); - pthread_mutex_lock (&mtx_pthr_locked); - continue; - } - if (sv->x != 0) - __pthread_deregister_pointer (sv->x); - sv->x = 0; - free (sv); - pthr_root = t; - } - pthread_mutex_unlock (&mtx_pthr_locked); -#endif - return; -} - -static void -replace_spin_keys (pthread_spinlock_t *old, pthread_spinlock_t new) -{ - if (old == NULL) - return; - - if (EPERM == pthread_spin_destroy (old)) - { -#define THREADERR "Error cleaning up spin_keys for thread %lu.\n" - char threaderr[sizeof(THREADERR) + 8] = { 0 }; - snprintf(threaderr, sizeof(threaderr), THREADERR, GetCurrentThreadId()); -#undef THREADERR - OutputDebugStringA (threaderr); - abort (); - } - - *old = new; -} - -/* Hook for TLS-based deregistration/registration of thread. */ -static void WINAPI -__dyn_tls_pthread (HANDLE hDllHandle, DWORD dwReason, LPVOID lpreserved) -{ - _pthread_v *t = NULL; - pthread_spinlock_t new_spin_keys = PTHREAD_SPINLOCK_INITIALIZER; - - if (dwReason == DLL_PROCESS_DETACH) - { -#if defined(USE_VEH_FOR_MSC_SETTHREADNAME) - if (lpreserved == NULL && SetThreadName_VEH_handle != NULL) - { - if (RemoveVectoredExceptionHandlerFuncPtr != NULL) - RemoveVectoredExceptionHandlerFuncPtr (SetThreadName_VEH_handle); - SetThreadName_VEH_handle = NULL; - } -#endif - free_pthread_mem (); - } - else if (dwReason == DLL_PROCESS_ATTACH) - { -#if defined(USE_VEH_FOR_MSC_SETTHREADNAME) - if (AddVectoredExceptionHandlerFuncPtr != NULL) - SetThreadName_VEH_handle = AddVectoredExceptionHandlerFuncPtr (1, &SetThreadName_VEH); - else - SetThreadName_VEH_handle = NULL; - /* Can't do anything on error anyway, check for NULL later */ -#endif - } - else if (dwReason == DLL_THREAD_DETACH) - { - if (_pthread_tls != 0xffffffff) - t = (_pthread_v *)TlsGetValue(_pthread_tls); - if (t && t->thread_noposix != 0) - { - _pthread_cleanup_dest (t->x); - if (t->h != NULL) - { - CloseHandle (t->h); - if (t->evStart) - CloseHandle (t->evStart); - t->evStart = NULL; - t->h = NULL; - } - pthread_mutex_destroy (&t->p_clock); - replace_spin_keys (&t->spin_keys, new_spin_keys); - push_pthread_mem (t); - t = NULL; - TlsSetValue (_pthread_tls, t); - } - else if (t && t->ended == 0) - { - if (t->evStart) - CloseHandle(t->evStart); - t->evStart = NULL; - t->ended = 1; - _pthread_cleanup_dest (t->x); - if ((t->p_state & PTHREAD_CREATE_DETACHED) == PTHREAD_CREATE_DETACHED) - { - t->valid = DEAD_THREAD; - if (t->h != NULL) - CloseHandle (t->h); - t->h = NULL; - pthread_mutex_destroy(&t->p_clock); - replace_spin_keys (&t->spin_keys, new_spin_keys); - push_pthread_mem (t); - t = NULL; - TlsSetValue (_pthread_tls, t); - return; - } - pthread_mutex_destroy(&t->p_clock); - replace_spin_keys (&t->spin_keys, new_spin_keys); - } - else if (t) - { - if (t->evStart) - CloseHandle (t->evStart); - t->evStart = NULL; - pthread_mutex_destroy (&t->p_clock); - replace_spin_keys (&t->spin_keys, new_spin_keys); - } - } -} - -/* TLS-runtime section variable. */ - -#if defined(_MSC_VER) -/* Force a reference to _tls_used to make the linker create the TLS - * directory if it's not already there. (e.g. if __declspec(thread) - * is not used). - * Force a reference to __xl_f to prevent whole program optimization - * from discarding the variable. */ - -/* On x86, symbols are prefixed with an underscore. */ -# if defined(_M_IX86) -# pragma comment(linker, "/include:__tls_used") -# pragma comment(linker, "/include:___xl_f") -# else -# pragma comment(linker, "/include:_tls_used") -# pragma comment(linker, "/include:__xl_f") -# endif - -/* .CRT$XLA to .CRT$XLZ is an array of PIMAGE_TLS_CALLBACK - * pointers. Pick an arbitrary location for our callback. - * - * See VC\...\crt\src\vcruntime\tlssup.cpp for reference. */ - -# pragma section(".CRT$XLF", long, read) -#endif - -WINPTHREADS_ATTRIBUTE((WINPTHREADS_SECTION(".CRT$XLF"))) -extern const PIMAGE_TLS_CALLBACK __xl_f; -const PIMAGE_TLS_CALLBACK __xl_f = __dyn_tls_pthread; - - -#ifdef WINPTHREAD_DBG -static int print_state = 0; -void thread_print_set (int state) -{ - print_state = state; -} - -void -thread_print (volatile pthread_t t, char *txt) -{ - if (!print_state) - return; - if (!t) - printf("T%p %lu %s\n",NULL,GetCurrentThreadId(),txt); - else - { - printf("T%p %lu V=%0X H=%p %s\n", - (void *) __pth_gpointer_locked (t), - GetCurrentThreadId(), - (__pth_gpointer_locked (t))->valid, - (__pth_gpointer_locked (t))->h, - txt - ); - } -} -#endif - -/* Internal collect-once structure. */ -typedef struct collect_once_t { - pthread_once_t *o; - pthread_mutex_t m; - int count; - struct collect_once_t *next; -} collect_once_t; - -static collect_once_t *once_obj = NULL; - -static pthread_spinlock_t once_global = PTHREAD_SPINLOCK_INITIALIZER; - -static collect_once_t * -enterOnceObject (pthread_once_t *o) -{ - collect_once_t *c, *p = NULL; - pthread_spin_lock (&once_global); - c = once_obj; - while (c != NULL && c->o != o) - { - c = (p = c)->next; - } - if (!c) - { - c = (collect_once_t *) calloc(1,sizeof(collect_once_t)); - c->o = o; - c->count = 1; - if (!p) - once_obj = c; - else - p->next = c; - pthread_mutex_init(&c->m, NULL); - } - else - c->count += 1; - pthread_spin_unlock (&once_global); - return c; -} - -static void -leaveOnceObject (collect_once_t *c) -{ - collect_once_t *h, *p = NULL; - if (!c) - return; - pthread_spin_lock (&once_global); - h = once_obj; - while (h != NULL && c != h) - h = (p = h)->next; - - if (h) - { - c->count -= 1; - if (c->count == 0) - { - pthread_mutex_destroy(&c->m); - if (!p) - once_obj = c->next; - else - p->next = c->next; - free (c); - } - } - else - fprintf(stderr, "%p not found?!?!\n", (void *) c); - pthread_spin_unlock (&once_global); -} - -static void -_pthread_once_cleanup (void *o) -{ - collect_once_t *co = (collect_once_t *) o; - pthread_mutex_unlock (&co->m); - leaveOnceObject (co); -} - -static int -_pthread_once_raw (pthread_once_t *o, void (*func)(void)) -{ - collect_once_t *co; - long state = *o; - - CHECK_PTR(o); - CHECK_PTR(func); - - if (state == 1) - return 0; - co = enterOnceObject(o); - pthread_mutex_lock(&co->m); - if (*o == 0) - { - func(); - *o = 1; - } - else if (*o != 1) - fprintf (stderr," once %p is %ld\n", (void *) o, (long) *o); - pthread_mutex_unlock(&co->m); - leaveOnceObject(co); - - /* Done */ - return 0; -} - -/* Unimplemented. */ -void * -pthread_timechange_handler_np(void *dummy) -{ - return NULL; -} - -/* Compatibility routine for pthread-win32. It waits for ellapse of - interval and additionally checks for possible thread-cancelation. */ -int -pthread_delay_np (const struct timespec *interval) -{ - DWORD to = (!interval ? 0 : dwMilliSecs (_pthread_time_in_ms_from_timespec (interval))); - struct _pthread_v *s = __pthread_self_lite (); - - if (!to) - { - pthread_testcancel (); - Sleep (0); - pthread_testcancel (); - return 0; - } - pthread_testcancel (); - if (s->evStart) - _pthread_wait_for_single_object (s->evStart, to); - else - Sleep (to); - pthread_testcancel (); - return 0; -} - -int pthread_delay_np_ms (DWORD to); - -int -pthread_delay_np_ms (DWORD to) -{ - struct _pthread_v *s = __pthread_self_lite (); - - if (!to) - { - pthread_testcancel (); - Sleep (0); - pthread_testcancel (); - return 0; - } - pthread_testcancel (); - if (s->evStart) - _pthread_wait_for_single_object (s->evStart, to); - else - Sleep (to); - pthread_testcancel (); - return 0; -} - -/* Compatibility routine for pthread-win32. It returns the - amount of available CPUs on system. */ -int -pthread_num_processors_np(void) -{ - int r = 0; - DWORD_PTR ProcessAffinityMask, SystemAffinityMask; - - if (GetProcessAffinityMask(GetCurrentProcess(), &ProcessAffinityMask, &SystemAffinityMask)) - { - for(; ProcessAffinityMask != 0; ProcessAffinityMask >>= 1) - r += (ProcessAffinityMask & 1) != 0; - } - /* assume at least 1 */ - return r ? r : 1; -} - -/* Compatiblity routine for pthread-win32. Allows to set amount of used - CPUs for process. */ -int -pthread_set_num_processors_np(int n) -{ - DWORD_PTR ProcessAffinityMask, ProcessNewAffinityMask = 0, SystemAffinityMask; - int r = 0; - /* need at least 1 */ - n = n ? n : 1; - if (GetProcessAffinityMask (GetCurrentProcess (), &ProcessAffinityMask, &SystemAffinityMask)) - { - for (; ProcessAffinityMask != 0; ProcessAffinityMask >>= 1) - { - ProcessNewAffinityMask <<= 1; - if ((ProcessAffinityMask & 1) != 0 && r < n) - { - ProcessNewAffinityMask |= 1; - r++; - } - } - SetProcessAffinityMask (GetCurrentProcess (),ProcessNewAffinityMask); - } - return r; -} - -int -pthread_once (pthread_once_t *o, void (*func)(void)) -{ - collect_once_t *co; - long state = *o; - - CHECK_PTR(o); - CHECK_PTR(func); - - if (state == 1) - return 0; - co = enterOnceObject(o); - pthread_mutex_lock(&co->m); - if (*o == 0) - { - pthread_cleanup_push(_pthread_once_cleanup, co); - func(); - pthread_cleanup_pop(0); - *o = 1; - } - else if (*o != 1) - fprintf (stderr," once %p is %ld\n", (void *) o, (long) *o); - pthread_mutex_unlock(&co->m); - leaveOnceObject(co); - - return 0; -} - -int -pthread_key_create (pthread_key_t *key, void (* dest)(void *)) -{ - unsigned int i; - long nmax; - void (**d)(void *); - - if (!key) - return EINVAL; - - pthread_rwlock_wrlock (&_pthread_key_lock); - - for (i = _pthread_key_sch; i < _pthread_key_max; i++) - { - if (!_pthread_key_dest[i]) - { - *key = i; - if (dest) - _pthread_key_dest[i] = dest; - else - _pthread_key_dest[i] = (void(*)(void *))1; - pthread_rwlock_unlock (&_pthread_key_lock); - return 0; - } - } - - for (i = 0; i < _pthread_key_sch; i++) - { - if (!_pthread_key_dest[i]) - { - *key = i; - if (dest) - _pthread_key_dest[i] = dest; - else - _pthread_key_dest[i] = (void(*)(void *))1; - pthread_rwlock_unlock (&_pthread_key_lock); - - return 0; - } - } - - if (_pthread_key_max == PTHREAD_KEYS_MAX) - { - pthread_rwlock_unlock(&_pthread_key_lock); - return ENOMEM; - } - - nmax = _pthread_key_max * 2; - if (nmax == 0) - nmax = _pthread_key_max + 1; - if (nmax > PTHREAD_KEYS_MAX) - nmax = PTHREAD_KEYS_MAX; - - /* No spare room anywhere */ - d = (void (__cdecl **)(void *))realloc(_pthread_key_dest, nmax * sizeof(*d)); - if (!d) - { - pthread_rwlock_unlock (&_pthread_key_lock); - return ENOMEM; - } - - /* Clear new region */ - memset ((void *) &d[_pthread_key_max], 0, (nmax-_pthread_key_max)*sizeof(void *)); - - /* Use new region */ - _pthread_key_dest = d; - _pthread_key_sch = _pthread_key_max + 1; - *key = _pthread_key_max; - _pthread_key_max = nmax; - - if (dest) - _pthread_key_dest[*key] = dest; - else - _pthread_key_dest[*key] = (void(*)(void *))1; - - pthread_rwlock_unlock (&_pthread_key_lock); - return 0; -} - -int -pthread_key_delete (pthread_key_t key) -{ - if (key >= _pthread_key_max || !_pthread_key_dest) - return EINVAL; - - pthread_rwlock_wrlock (&_pthread_key_lock); - - _pthread_key_dest[key] = NULL; - - /* Start next search from our location */ - if (_pthread_key_sch > key) - _pthread_key_sch = key; - /* So now we need to walk the complete list of threads - and remove key's reference for it. */ - __pth_remove_use_for_key (key); - - pthread_rwlock_unlock (&_pthread_key_lock); - return 0; -} - -void * -pthread_getspecific (pthread_key_t key) -{ - DWORD lasterr = GetLastError (); - void *r; - _pthread_v *t = __pthread_self_lite (); - pthread_spin_lock (&t->spin_keys); - r = (key >= t->keymax || t->keyval_set[key] == 0 ? NULL : t->keyval[key]); - pthread_spin_unlock (&t->spin_keys); - SetLastError (lasterr); - return r; -} - -int -pthread_setspecific (pthread_key_t key, const void *value) -{ - DWORD lasterr = GetLastError (); - _pthread_v *t = __pthread_self_lite (); - - pthread_spin_lock (&t->spin_keys); - - if (key >= t->keymax) - { - int keymax = (key + 1); - void **kv; - unsigned char *kv_set; - - kv = (void **) realloc (t->keyval, keymax * sizeof (void *)); - - if (!kv) - { - pthread_spin_unlock (&t->spin_keys); - return ENOMEM; - } - kv_set = (unsigned char *) realloc (t->keyval_set, keymax); - if (!kv_set) - { - pthread_spin_unlock (&t->spin_keys); - return ENOMEM; - } - - /* Clear new region */ - memset (&kv[t->keymax], 0, (keymax - t->keymax)*sizeof(void *)); - memset (&kv_set[t->keymax], 0, (keymax - t->keymax)); - - t->keyval = kv; - t->keyval_set = kv_set; - t->keymax = keymax; - } - - t->keyval[key] = (void *) value; - t->keyval_set[key] = 1; - pthread_spin_unlock (&t->spin_keys); - SetLastError (lasterr); - - return 0; -} - -int -pthread_equal (pthread_t t1, pthread_t t2) -{ - return (t1 == t2); -} - -void -pthread_tls_init (void) -{ - _pthread_tls = TlsAlloc(); - - /* Cannot continue if out of indexes */ - if (_pthread_tls == TLS_OUT_OF_INDEXES) - abort(); -} - -void -_pthread_cleanup_dest (pthread_t t) -{ - _pthread_v *tv; - unsigned int i, j; - - if (!t) - return; - tv = __pth_gpointer_locked (t); - if (!tv) - return; - - for (j = 0; j < PTHREAD_DESTRUCTOR_ITERATIONS; j++) - { - int flag = 0; - - pthread_spin_lock (&tv->spin_keys); - for (i = 0; i < tv->keymax; i++) - { - void *val = tv->keyval[i]; - - if (tv->keyval_set[i]) - { - pthread_rwlock_rdlock (&_pthread_key_lock); - if ((uintptr_t) _pthread_key_dest[i] > 1) - { - /* Call destructor */ - tv->keyval[i] = NULL; - tv->keyval_set[i] = 0; - pthread_spin_unlock (&tv->spin_keys); - _pthread_key_dest[i](val); - pthread_spin_lock (&tv->spin_keys); - flag = 1; - } - else - { - tv->keyval[i] = NULL; - tv->keyval_set[i] = 0; - } - pthread_rwlock_unlock(&_pthread_key_lock); - } - } - pthread_spin_unlock (&tv->spin_keys); - /* Nothing to do? */ - if (!flag) - return; - } -} - -static _pthread_v * -__pthread_self_lite (void) -{ - _pthread_v *t; - pthread_spinlock_t new_spin_keys = PTHREAD_SPINLOCK_INITIALIZER; - - _pthread_once_raw (&_pthread_tls_once, pthread_tls_init); - - t = (_pthread_v *) TlsGetValue (_pthread_tls); - if (t) - return t; - /* Main thread? */ - t = (struct _pthread_v *) pop_pthread_mem (); - - /* If cannot initialize main thread, then the only thing we can do is return null pthread_t */ - if (!__xl_f || !t) - return 0; - - t->p_state = PTHREAD_DEFAULT_ATTR /*| PTHREAD_CREATE_DETACHED*/; - t->tid = GetCurrentThreadId(); - t->evStart = CreateEvent (NULL, 1, 0, NULL); - t->p_clock = PTHREAD_MUTEX_INITIALIZER; - replace_spin_keys (&t->spin_keys, new_spin_keys); - t->sched_pol = SCHED_OTHER; - t->h = NULL; //GetCurrentThread(); - if (!DuplicateHandle(GetCurrentProcess(), GetCurrentThread(), GetCurrentProcess(), &t->h, 0, FALSE, DUPLICATE_SAME_ACCESS)) - abort (); - t->sched.sched_priority = GetThreadPriority(t->h); - t->ended = 0; - t->thread_noposix = 1; - - /* Save for later */ - if (!TlsSetValue(_pthread_tls, t)) - abort (); - return t; -} - -pthread_t -pthread_self (void) -{ - _pthread_v *t = __pthread_self_lite (); - - if (!t) - return 0; - return t->x; -} - -/* Internal helper for getting event handle of thread T. */ -void * -pthread_getevent (void) -{ - _pthread_v *t = __pthread_self_lite (); - return (!t ? NULL : t->evStart); -} - -/* Internal helper for getting thread handle of thread T. */ -void * -pthread_gethandle (pthread_t t) -{ - struct _pthread_v *tv = __pth_gpointer_locked (t); - return (!tv ? NULL : tv->h); -} - -/* Internal helper for getting pointer of clean of current thread. */ -struct _pthread_cleanup ** -pthread_getclean (void) -{ - struct _pthread_v *t = __pthread_self_lite (); - if (!t) return NULL; - return &t->clean; -} - -int -pthread_get_concurrency (int *val) -{ - *val = _pthread_concur; - return 0; -} - -int -pthread_set_concurrency (int val) -{ - _pthread_concur = val; - return 0; -} - -void -pthread_exit (void *res) -{ - _pthread_v *t = NULL; - unsigned rslt = (unsigned) ((intptr_t) res); - struct _pthread_v *id = __pthread_self_lite (); - - id->ret_arg = res; - - _pthread_cleanup_dest (id->x); - if (id->thread_noposix == 0) - longjmp(id->jb, 1); - - /* Make sure we free ourselves if we are detached */ - if ((t = (_pthread_v *)TlsGetValue(_pthread_tls)) != NULL) - { - if (!t->h) - { - t->valid = DEAD_THREAD; - if (t->evStart) - CloseHandle (t->evStart); - t->evStart = NULL; - rslt = (unsigned) (size_t) t->ret_arg; - push_pthread_mem(t); - t = NULL; - TlsSetValue (_pthread_tls, t); - } - else - { - rslt = (unsigned) (size_t) t->ret_arg; - t->ended = 1; - if (t->evStart) - CloseHandle (t->evStart); - t->evStart = NULL; - if ((t->p_state & PTHREAD_CREATE_DETACHED) == PTHREAD_CREATE_DETACHED) - { - t->valid = DEAD_THREAD; - CloseHandle (t->h); - t->h = NULL; - push_pthread_mem(t); - t = NULL; - TlsSetValue(_pthread_tls, t); - } - } - } - /* Time to die */ - _endthreadex(rslt); -} - -void -_pthread_invoke_cancel (void) -{ - _pthread_cleanup *pcup; - struct _pthread_v *se = __pthread_self_lite (); - se->in_cancel = 1; - _pthread_setnobreak (1); - InterlockedDecrement(&_pthread_cancelling); - - /* Call cancel queue */ - for (pcup = se->clean; pcup; pcup = pcup->next) - { - pcup->func((pthread_once_t *)pcup->arg); - } - - _pthread_setnobreak (0); - pthread_exit(PTHREAD_CANCELED); -} - -int -__pthread_shallcancel (void) -{ - struct _pthread_v *t; - if (!_pthread_cancelling) - return 0; - t = __pthread_self_lite (); - if (t == NULL) - return 0; - if (t->nobreak <= 0 && t->cancelled && (t->p_state & PTHREAD_CANCEL_ENABLE)) - return 1; - return 0; -} - -void -_pthread_setnobreak (int v) -{ - struct _pthread_v *t = __pthread_self_lite (); - if (t == NULL) - return; - if (v > 0) - InterlockedIncrement ((long*)&t->nobreak); - else - InterlockedDecrement((long*)&t->nobreak); -} - -void -pthread_testcancel (void) -{ - struct _pthread_v *self = __pthread_self_lite (); - - if (!self || self->in_cancel) - return; - if (!_pthread_cancelling) - return; - pthread_mutex_lock (&self->p_clock); - - if (self->cancelled && (self->p_state & PTHREAD_CANCEL_ENABLE) && self->nobreak <= 0) - { - self->in_cancel = 1; - self->p_state &= ~PTHREAD_CANCEL_ENABLE; - if (self->evStart) - ResetEvent (self->evStart); - pthread_mutex_unlock (&self->p_clock); - _pthread_invoke_cancel (); - } - pthread_mutex_unlock (&self->p_clock); -} - -int -pthread_cancel (pthread_t t) -{ - struct _pthread_v *tv = __pth_gpointer_locked (t); - - if (tv == NULL) - return ESRCH; - CHECK_OBJECT(tv, ESRCH); - /*if (tv->ended) return ESRCH;*/ - pthread_mutex_lock(&tv->p_clock); - if (pthread_equal(pthread_self(), t)) - { - if(tv->cancelled) - { - pthread_mutex_unlock(&tv->p_clock); - return (tv->in_cancel ? ESRCH : 0); - } - tv->cancelled = 1; - InterlockedIncrement(&_pthread_cancelling); - if(tv->evStart) SetEvent(tv->evStart); - if ((tv->p_state & PTHREAD_CANCEL_ASYNCHRONOUS) != 0 && (tv->p_state & PTHREAD_CANCEL_ENABLE) != 0) - { - tv->p_state &= ~PTHREAD_CANCEL_ENABLE; - tv->in_cancel = 1; - pthread_mutex_unlock(&tv->p_clock); - _pthread_invoke_cancel(); - } - else - pthread_mutex_unlock(&tv->p_clock); - return 0; - } - - if ((tv->p_state & PTHREAD_CANCEL_ASYNCHRONOUS) != 0 && (tv->p_state & PTHREAD_CANCEL_ENABLE) != 0) - { - /* Dangerous asynchronous cancelling */ - CONTEXT ctxt; - - if(tv->in_cancel) - { - pthread_mutex_unlock(&tv->p_clock); - return (tv->in_cancel ? ESRCH : 0); - } - /* Already done? */ - if(tv->cancelled || tv->in_cancel) - { - /* ??? pthread_mutex_unlock (&tv->p_clock); */ - return ESRCH; - } - - ctxt.ContextFlags = CONTEXT_CONTROL; - - SuspendThread (tv->h); - if (WaitForSingleObject (tv->h, 0) == WAIT_TIMEOUT) - { - GetThreadContext(tv->h, &ctxt); -#ifdef _M_X64 - ctxt.Rip = (uintptr_t) _pthread_invoke_cancel; -#elif defined(_M_IX86) - ctxt.Eip = (uintptr_t) _pthread_invoke_cancel; -#elif defined(_M_ARM) || defined(_M_ARM64) - ctxt.Pc = (uintptr_t) _pthread_invoke_cancel; -#else -#error Unsupported architecture -#endif -#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) - SetThreadContext (tv->h, &ctxt); -#endif - - /* Also try deferred Cancelling */ - tv->cancelled = 1; - tv->p_state &= ~PTHREAD_CANCEL_ENABLE; - tv->in_cancel = 1; - - /* Notify everyone to look */ - InterlockedIncrement (&_pthread_cancelling); - if (tv->evStart) - SetEvent (tv->evStart); - pthread_mutex_unlock (&tv->p_clock); - - ResumeThread (tv->h); - } - } - else - { - if (tv->cancelled == 0) - { - /* Safe deferred Cancelling */ - tv->cancelled = 1; - - /* Notify everyone to look */ - InterlockedIncrement (&_pthread_cancelling); - if (tv->evStart) - SetEvent (tv->evStart); - } - else - { - pthread_mutex_unlock (&tv->p_clock); - return (tv->in_cancel ? ESRCH : 0); - } - } - pthread_mutex_unlock (&tv->p_clock); - return 0; -} - -/* half-stubbed version as we don't really well support signals */ -int -pthread_kill (pthread_t t, int sig) -{ - struct _pthread_v *tv; - - pthread_mutex_lock (&mtx_pthr_locked); - tv = __pthread_get_pointer (t); - if (!tv || t != tv->x || tv->in_cancel || tv->ended || tv->h == NULL - || tv->h == INVALID_HANDLE_VALUE) - { - pthread_mutex_unlock (&mtx_pthr_locked); - return ESRCH; - } - pthread_mutex_unlock (&mtx_pthr_locked); - if (!sig) - return 0; - if (sig < SIGINT || sig > NSIG) - return EINVAL; - return pthread_cancel(t); -} - -unsigned -_pthread_get_state (const pthread_attr_t *attr, unsigned flag) -{ - return (attr->p_state & flag); -} - -int -_pthread_set_state (pthread_attr_t *attr, unsigned flag, unsigned val) -{ - if (~flag & val) - return EINVAL; - attr->p_state &= ~flag; - attr->p_state |= val; - - return 0; -} - -int -pthread_attr_init (pthread_attr_t *attr) -{ - memset (attr, 0, sizeof (pthread_attr_t)); - attr->p_state = PTHREAD_DEFAULT_ATTR; - attr->stack = NULL; - attr->s_size = 0; - return 0; -} - -int -pthread_attr_destroy (pthread_attr_t *attr) -{ - /* No need to do anything */ - memset (attr, 0, sizeof(pthread_attr_t)); - return 0; -} - -int -pthread_attr_setdetachstate (pthread_attr_t *a, int flag) -{ - return _pthread_set_state(a, PTHREAD_CREATE_DETACHED, flag); -} - -int -pthread_attr_getdetachstate (const pthread_attr_t *a, int *flag) -{ - *flag = _pthread_get_state(a, PTHREAD_CREATE_DETACHED); - return 0; -} - -int -pthread_attr_setinheritsched (pthread_attr_t *a, int flag) -{ - if (!a || (flag != PTHREAD_INHERIT_SCHED && flag != PTHREAD_EXPLICIT_SCHED)) - return EINVAL; - return _pthread_set_state(a, PTHREAD_INHERIT_SCHED, flag); -} - -int -pthread_attr_getinheritsched (const pthread_attr_t *a, int *flag) -{ - *flag = _pthread_get_state(a, PTHREAD_INHERIT_SCHED); - return 0; -} - -int -pthread_attr_setscope (pthread_attr_t *a, int flag) -{ - return _pthread_set_state(a, PTHREAD_SCOPE_SYSTEM, flag); -} - -int -pthread_attr_getscope (const pthread_attr_t *a, int *flag) -{ - *flag = _pthread_get_state(a, PTHREAD_SCOPE_SYSTEM); - return 0; -} - -int -pthread_attr_getstack (const pthread_attr_t *attr, void **stack, size_t *size) -{ - *stack = (char *) attr->stack - attr->s_size; - *size = attr->s_size; - return 0; -} - -int -pthread_attr_setstack (pthread_attr_t *attr, void *stack, size_t size) -{ - attr->s_size = size; - attr->stack = (char *) stack + size; - return 0; -} - -int -pthread_attr_getstackaddr (const pthread_attr_t *attr, void **stack) -{ - *stack = attr->stack; - return 0; -} - -int -pthread_attr_setstackaddr (pthread_attr_t *attr, void *stack) -{ - attr->stack = stack; - return 0; -} - -int -pthread_attr_getstacksize (const pthread_attr_t *attr, size_t *size) -{ - *size = attr->s_size; - return 0; -} - -int -pthread_attr_setstacksize (pthread_attr_t *attr, size_t size) -{ - attr->s_size = size; - return 0; -} - -static void -test_cancel_locked (pthread_t t) -{ - struct _pthread_v *tv = __pth_gpointer_locked (t); - - if (!tv || tv->in_cancel || tv->ended != 0 || (tv->p_state & PTHREAD_CANCEL_ENABLE) == 0) - return; - if ((tv->p_state & PTHREAD_CANCEL_ASYNCHRONOUS) == 0) - return; - if (WaitForSingleObject(tv->evStart, 0) != WAIT_OBJECT_0) - return; - pthread_mutex_unlock (&tv->p_clock); - _pthread_invoke_cancel(); -} - -int -pthread_setcancelstate (int state, int *oldstate) -{ - _pthread_v *t = __pthread_self_lite (); - - if (!t || (state & PTHREAD_CANCEL_ENABLE) != state) - return EINVAL; - - pthread_mutex_lock (&t->p_clock); - if (oldstate) - *oldstate = t->p_state & PTHREAD_CANCEL_ENABLE; - t->p_state &= ~PTHREAD_CANCEL_ENABLE; - t->p_state |= state; - test_cancel_locked (t->x); - pthread_mutex_unlock (&t->p_clock); - - return 0; -} - -int -pthread_setcanceltype (int type, int *oldtype) -{ - _pthread_v *t = __pthread_self_lite (); - - if (!t || (type & PTHREAD_CANCEL_ASYNCHRONOUS) != type) - return EINVAL; - - pthread_mutex_lock (&t->p_clock); - if (oldtype) - *oldtype = t->p_state & PTHREAD_CANCEL_ASYNCHRONOUS; - t->p_state &= ~PTHREAD_CANCEL_ASYNCHRONOUS; - t->p_state |= type; - test_cancel_locked (t->x); - pthread_mutex_unlock (&t->p_clock); - - return 0; -} - -void _fpreset (void); - -#if defined(__i386__) -/* Align ESP on 16-byte boundaries. */ -# if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 2) -__attribute__((force_align_arg_pointer)) -# endif -#endif -unsigned __stdcall -pthread_create_wrapper (void *args) -{ - unsigned rslt = 0; - struct _pthread_v *tv = (struct _pthread_v *)args; - - _fpreset(); - - pthread_mutex_lock (&mtx_pthr_locked); - pthread_mutex_lock (&tv->p_clock); - _pthread_once_raw(&_pthread_tls_once, pthread_tls_init); - TlsSetValue(_pthread_tls, tv); - tv->tid = GetCurrentThreadId(); - pthread_mutex_unlock (&tv->p_clock); - - - if (!setjmp(tv->jb)) - { - intptr_t trslt = (intptr_t) 128; - /* Provide to this thread a default exception handler. */ - #ifdef __SEH__ - asm ("\t.tl_start:\n"); - #endif /* Call function and save return value */ - pthread_mutex_unlock (&mtx_pthr_locked); - if (tv->func) - trslt = (intptr_t) tv->func(tv->ret_arg); - #ifdef __SEH__ - asm ("\tnop\n\t.tl_end: nop\n" -#ifdef __arm__ - "\t.seh_handler __C_specific_handler, %except\n" -#else - "\t.seh_handler __C_specific_handler, @except\n" -#endif - "\t.seh_handlerdata\n" - "\t.long 1\n" - "\t.rva .tl_start, .tl_end, _gnu_exception_handler ,.tl_end\n" - "\t.text" - ); - #endif - pthread_mutex_lock (&mtx_pthr_locked); - tv->ret_arg = (void*) trslt; - /* Clean up destructors */ - _pthread_cleanup_dest(tv->x); - } - else - pthread_mutex_lock (&mtx_pthr_locked); - - pthread_mutex_lock (&tv->p_clock); - rslt = (unsigned) (size_t) tv->ret_arg; - /* Make sure we free ourselves if we are detached */ - if (tv->evStart) - CloseHandle (tv->evStart); - tv->evStart = NULL; - if (!tv->h) - { - tv->valid = DEAD_THREAD; - pthread_mutex_unlock (&tv->p_clock); - pthread_mutex_destroy (&tv->p_clock); - push_pthread_mem (tv); - tv = NULL; - TlsSetValue (_pthread_tls, tv); - } - else - { - pthread_mutex_unlock (&tv->p_clock); - pthread_mutex_destroy (&tv->p_clock); - /* Reinitialise p_clock, since there may be attempts at - destroying it again in __dyn_tls_thread later on. */ - tv->p_clock = PTHREAD_MUTEX_INITIALIZER; - tv->ended = 1; - } - while (pthread_mutex_unlock (&mtx_pthr_locked) == 0) - Sleep (0); - _endthreadex (rslt); - return rslt; -} - -int -pthread_create (pthread_t *th, const pthread_attr_t *attr, void *(* func)(void *), void *arg) -{ - HANDLE thrd = NULL; - int redo = 0; - struct _pthread_v *tv; - unsigned int ssize = 0; - pthread_spinlock_t new_spin_keys = PTHREAD_SPINLOCK_INITIALIZER; - - if (attr && attr->s_size > UINT_MAX) - return EINVAL; - - if ((tv = pop_pthread_mem ()) == NULL) - return EAGAIN; - - if (th) - *th = tv->x; - - /* Save data in pthread_t */ - tv->ended = 0; - tv->ret_arg = arg; - tv->func = func; - tv->p_state = PTHREAD_DEFAULT_ATTR; - tv->h = INVALID_HANDLE_VALUE; - /* We retry it here a few times, as events are a limited resource ... */ - do - { - tv->evStart = CreateEvent (NULL, 1, 0, NULL); - if (tv->evStart != NULL) - break; - Sleep ((!redo ? 0 : 20)); - } - while (++redo <= 4); - - tv->p_clock = PTHREAD_MUTEX_INITIALIZER; - replace_spin_keys (&tv->spin_keys, new_spin_keys); - tv->valid = LIFE_THREAD; - tv->sched.sched_priority = THREAD_PRIORITY_NORMAL; - tv->sched_pol = SCHED_OTHER; - if (tv->evStart == NULL) - { - if (th) - memset (th, 0, sizeof (pthread_t)); - push_pthread_mem (tv); - return EAGAIN; - } - - if (attr) - { - int inh = 0; - tv->p_state = attr->p_state; - ssize = (unsigned int)attr->s_size; - pthread_attr_getinheritsched (attr, &inh); - if (inh) - { - tv->sched.sched_priority = __pthread_self_lite ()->sched.sched_priority; - } - else - tv->sched.sched_priority = attr->param.sched_priority; - } - - /* Make sure tv->h has value of INVALID_HANDLE_VALUE */ - _ReadWriteBarrier(); - - thrd = (HANDLE) _beginthreadex(NULL, ssize, pthread_create_wrapper, tv, 0x4/*CREATE_SUSPEND*/, NULL); - if (thrd == INVALID_HANDLE_VALUE) - thrd = 0; - /* Failed */ - if (!thrd) - { - if (tv->evStart) - CloseHandle (tv->evStart); - pthread_mutex_destroy (&tv->p_clock); - replace_spin_keys (&tv->spin_keys, new_spin_keys); - tv->evStart = NULL; - tv->h = 0; - if (th) - memset (th, 0, sizeof (pthread_t)); - push_pthread_mem (tv); - return EAGAIN; - } - { - int pr = tv->sched.sched_priority; - if (pr <= THREAD_PRIORITY_IDLE) { - pr = THREAD_PRIORITY_IDLE; - } else if (pr <= THREAD_PRIORITY_LOWEST) { - pr = THREAD_PRIORITY_LOWEST; - } else if (pr >= THREAD_PRIORITY_TIME_CRITICAL) { - pr = THREAD_PRIORITY_TIME_CRITICAL; - } else if (pr >= THREAD_PRIORITY_HIGHEST) { - pr = THREAD_PRIORITY_HIGHEST; - } - SetThreadPriority (thrd, pr); - } - ResetEvent (tv->evStart); - if ((tv->p_state & PTHREAD_CREATE_DETACHED) != 0) - { - tv->h = 0; - ResumeThread (thrd); - CloseHandle (thrd); - } - else - { - tv->h = thrd; - ResumeThread (thrd); - } - Sleep (0); - return 0; -} - -int -pthread_join (pthread_t t, void **res) -{ - DWORD dwFlags; - struct _pthread_v *tv = __pth_gpointer_locked (t); - pthread_spinlock_t new_spin_keys = PTHREAD_SPINLOCK_INITIALIZER; - - if (!tv || tv->h == NULL || !GetHandleInformation(tv->h, &dwFlags)) - return ESRCH; - if ((tv->p_state & PTHREAD_CREATE_DETACHED) != 0) - return EINVAL; - if (pthread_equal(pthread_self(), t)) - return EDEADLK; - - /* pthread_testcancel (); */ - if (tv->ended == 0 || (tv->h != NULL && tv->h != INVALID_HANDLE_VALUE)) - WaitForSingleObject (tv->h, INFINITE); - CloseHandle (tv->h); - if (tv->evStart) - CloseHandle (tv->evStart); - tv->evStart = NULL; - /* Obtain return value */ - if (res) - *res = tv->ret_arg; - pthread_mutex_destroy (&tv->p_clock); - replace_spin_keys (&tv->spin_keys, new_spin_keys); - push_pthread_mem (tv); - - return 0; -} - -int -_pthread_tryjoin (pthread_t t, void **res) -{ - DWORD dwFlags; - struct _pthread_v *tv; - pthread_spinlock_t new_spin_keys = PTHREAD_SPINLOCK_INITIALIZER; - - pthread_mutex_lock (&mtx_pthr_locked); - tv = __pthread_get_pointer (t); - - if (!tv || tv->h == NULL || !GetHandleInformation(tv->h, &dwFlags)) - { - pthread_mutex_unlock (&mtx_pthr_locked); - return ESRCH; - } - - if ((tv->p_state & PTHREAD_CREATE_DETACHED) != 0) - { - pthread_mutex_unlock (&mtx_pthr_locked); - return EINVAL; - } - if (pthread_equal(pthread_self(), t)) - { - pthread_mutex_unlock (&mtx_pthr_locked); - return EDEADLK; - } - if(tv->ended == 0 && WaitForSingleObject(tv->h, 0)) - { - if (tv->ended == 0) - { - pthread_mutex_unlock (&mtx_pthr_locked); - /* pthread_testcancel (); */ - return EBUSY; - } - } - CloseHandle (tv->h); - if (tv->evStart) - CloseHandle (tv->evStart); - tv->evStart = NULL; - - /* Obtain return value */ - if (res) - *res = tv->ret_arg; - pthread_mutex_destroy (&tv->p_clock); - replace_spin_keys (&tv->spin_keys, new_spin_keys); - - push_pthread_mem (tv); - - pthread_mutex_unlock (&mtx_pthr_locked); - /* pthread_testcancel (); */ - return 0; -} - -int -pthread_detach (pthread_t t) -{ - int r = 0; - DWORD dwFlags; - struct _pthread_v *tv = __pth_gpointer_locked (t); - HANDLE dw; - pthread_spinlock_t new_spin_keys = PTHREAD_SPINLOCK_INITIALIZER; - - pthread_mutex_lock (&mtx_pthr_locked); - if (!tv || tv->h == NULL || !GetHandleInformation(tv->h, &dwFlags)) - { - pthread_mutex_unlock (&mtx_pthr_locked); - return ESRCH; - } - if ((tv->p_state & PTHREAD_CREATE_DETACHED) != 0) - { - pthread_mutex_unlock (&mtx_pthr_locked); - return EINVAL; - } - /* if (tv->ended) r = ESRCH; */ - dw = tv->h; - tv->h = 0; - tv->p_state |= PTHREAD_CREATE_DETACHED; - _ReadWriteBarrier(); - if (dw) - { - CloseHandle (dw); - if (tv->ended) - { - if (tv->evStart) - CloseHandle (tv->evStart); - tv->evStart = NULL; - pthread_mutex_destroy (&tv->p_clock); - replace_spin_keys (&tv->spin_keys, new_spin_keys); - push_pthread_mem (tv); - } - } - pthread_mutex_unlock (&mtx_pthr_locked); - - return r; -} - -static int dummy_concurrency_level = 0; - -int -pthread_getconcurrency (void) -{ - return dummy_concurrency_level; -} - -int -pthread_setconcurrency (int new_level) -{ - dummy_concurrency_level = new_level; - return 0; -} - -int -pthread_setname_np (pthread_t thread, const char *name) -{ - struct _pthread_v *tv; - char *stored_name; - - if (name == NULL) - return EINVAL; - - tv = __pth_gpointer_locked (thread); - if (!tv || thread != tv->x || tv->in_cancel || tv->ended || tv->h == NULL - || tv->h == INVALID_HANDLE_VALUE) - return ESRCH; - - stored_name = strdup (name); - if (stored_name == NULL) - return ENOMEM; - - if (tv->thread_name != NULL) - free (tv->thread_name); - - tv->thread_name = stored_name; - SetThreadName (tv->tid, name); - return 0; -} - -int -pthread_getname_np (pthread_t thread, char *name, size_t len) -{ - HRESULT result; - struct _pthread_v *tv; - - if (name == NULL) - return EINVAL; - - tv = __pth_gpointer_locked (thread); - if (!tv || thread != tv->x || tv->in_cancel || tv->ended || tv->h == NULL - || tv->h == INVALID_HANDLE_VALUE) - return ESRCH; - - if (len < 1) - return ERANGE; - - if (tv->thread_name == NULL) - { - name[0] = '\0'; - return 0; - } - - if (strlen (tv->thread_name) >= len) - return ERANGE; - - result = StringCchCopyNA (name, len, tv->thread_name, len - 1); - if (SUCCEEDED (result)) - return 0; - - return ERANGE; -} |
