41 #include "winpthreads.h" 42 #include <sys/timeb.h> 58 void *(* func)(
void *);
69 volatile long _pthread_cancelling;
74 pthread_once_t _pthread_tls_once;
78 pthread_rwlock_t _pthread_key_lock;
79 unsigned _pthread_key_max;
80 unsigned _pthread_key_sch;
81 void (**_pthread_key_dest)(
void *);
84 #define pthread_cleanup_push(F, A)\ 86 const _pthread_cleanup _pthread_cup = {(F), (A), pthread_self()->clean};\ 88 pthread_self()->clean = (_pthread_cleanup *) &_pthread_cup;\ 92 #define pthread_cleanup_pop(E)\ 93 (pthread_self()->clean = _pthread_cup.next, (E ? _pthread_cup.func(_pthread_cup.arg) : 0));} 95 static void _pthread_once_cleanup(pthread_once_t *o)
100 int pthread_once(pthread_once_t *o,
void (*func)(
void))
110 if (!_InterlockedCompareExchange(o, 2, 0))
113 pthread_cleanup_push((
void(*)(
void*))_pthread_once_cleanup, o);
115 pthread_cleanup_pop(0);
135 static int _pthread_once_raw(pthread_once_t *o,
void (*func)(
void))
145 if (!_InterlockedCompareExchange(o, 2, 0))
168 int pthread_mutex_lock(pthread_mutex_t *m)
170 EnterCriticalSection(m);
174 int pthread_mutex_unlock(pthread_mutex_t *m)
176 LeaveCriticalSection(m);
180 int pthread_mutex_trylock(pthread_mutex_t *m)
182 return TryEnterCriticalSection(m) ? 0 : EBUSY;
185 int pthread_mutex_init(pthread_mutex_t *m, pthread_mutexattr_t *a)
188 InitializeCriticalSection(m);
193 int pthread_mutex_destroy(pthread_mutex_t *m)
195 DeleteCriticalSection(m);
204 int pthread_rwlock_init(pthread_rwlock_t *l, pthread_rwlockattr_t *a)
207 InitializeSRWLock(l);
212 int pthread_rwlock_destroy(pthread_rwlock_t *l)
218 int pthread_rwlock_rdlock(pthread_rwlock_t *l)
220 pthread_testcancel();
221 AcquireSRWLockShared(l);
226 int pthread_rwlock_wrlock(pthread_rwlock_t *l)
228 pthread_testcancel();
229 AcquireSRWLockExclusive(l);
234 int pthread_rwlock_unlock(pthread_rwlock_t *l)
236 void *state = *(
void **)l;
238 if (state == (
void *)1)
241 ReleaseSRWLockExclusive(l);
246 ReleaseSRWLockShared(l);
252 int pthread_rwlock_tryrdlock(pthread_rwlock_t *l)
255 void *state = *(
void **)l;
260 if (!_InterlockedCompareExchangePointer((
void *
volatile *)l, (
void *)0x11, NULL))
return 0;
265 if (state == (
void *)1)
return EBUSY;
268 if ((uintptr_t)state & 14)
return EBUSY;
270 if (_InterlockedCompareExchangePointer((
void *
volatile *)l, (
void *)((uintptr_t)state + 16), state) == state)
return 0;
275 int pthread_rwlock_trywrlock(pthread_rwlock_t *l)
278 if (!_InterlockedCompareExchangePointer((
void *
volatile *)l, (
void *)1, NULL))
return 0;
283 void pthread_tls_init(
void)
285 _pthread_tls = TlsAlloc();
288 if (_pthread_tls == TLS_OUT_OF_INDEXES) abort();
291 static void _pthread_cleanup_dest(
pthread_t t)
295 for (j = 0; j < PTHREAD_DESTRUCTOR_ITERATIONS; j++)
299 for (i = 0; i < t->keymax; i++)
301 void *val = t->keyval[i];
305 pthread_rwlock_rdlock(&_pthread_key_lock);
306 if ((uintptr_t) _pthread_key_dest[i] > 1)
310 _pthread_key_dest[i](val);
313 pthread_rwlock_unlock(&_pthread_key_lock);
326 _pthread_once_raw(&_pthread_tls_once, pthread_tls_init);
328 t = (
struct _pthread_v*)TlsGetValue(_pthread_tls);
341 t->p_state = PTHREAD_DEFAULT_ATTR;
344 t->h = GetCurrentThread();
347 TlsSetValue(_pthread_tls, t);
362 static unsigned long long _pthread_time_in_ms(
void)
368 return tb.time * 1000 + tb.millitm;
371 static unsigned long long _pthread_time_in_ms_from_timespec(
const struct timespec *ts)
373 unsigned long long t = ts->tv_sec * 1000;
374 t += ts->tv_nsec / 1000000;
379 static unsigned long long _pthread_rel_time_in_ms(
const struct timespec *ts)
381 unsigned long long t1 = _pthread_time_in_ms_from_timespec(ts);
382 unsigned long long t2 = _pthread_time_in_ms();
385 if (t1 < t2)
return 0;
389 int pthread_rwlock_timedrdlock(pthread_rwlock_t *l,
const struct timespec *ts)
391 unsigned long long ct = _pthread_time_in_ms();
392 unsigned long long t = _pthread_time_in_ms_from_timespec(ts);
394 pthread_testcancel();
400 if (!pthread_rwlock_tryrdlock(l))
return 0;
403 ct = _pthread_time_in_ms();
406 if (ct > t)
return ETIMEDOUT;
410 int pthread_rwlock_timedwrlock(pthread_rwlock_t *l,
const struct timespec *ts)
412 unsigned long long ct = _pthread_time_in_ms();
413 unsigned long long t = _pthread_time_in_ms_from_timespec(ts);
415 pthread_testcancel();
421 if (!pthread_rwlock_trywrlock(l))
return 0;
424 ct = _pthread_time_in_ms();
427 if (ct > t)
return ETIMEDOUT;
431 int pthread_get_concurrency(
int *val)
433 *val = _pthread_concur;
437 int pthread_set_concurrency(
int val)
439 _pthread_concur = val;
443 int pthread_exit(
void *res)
449 _pthread_cleanup_dest(t);
455 static void _pthread_invoke_cancel(
void)
459 _InterlockedDecrement(&_pthread_cancelling);
462 for (pcup = pthread_self()->clean; pcup; pcup = pcup->next)
464 pcup->func(pcup->arg);
467 pthread_exit(PTHREAD_CANCELED);
470 void pthread_testcancel(
void)
472 if (_pthread_cancelling)
476 if (t->cancelled && (t->p_state & PTHREAD_CANCEL_ENABLE))
478 _pthread_invoke_cancel();
486 #if !defined(WINAPI_FAMILY) || (WINAPI_FAMILY != WINAPI_FAMILY_APP) 487 if (t->p_state & PTHREAD_CANCEL_ASYNCHRONOUS)
493 if (t->cancelled)
return ESRCH;
495 ctxt.ContextFlags = CONTEXT_CONTROL;
498 GetThreadContext(t->h, &ctxt);
500 ctxt.Rip = (uintptr_t) _pthread_invoke_cancel;
502 ctxt.Eip = (uintptr_t) _pthread_invoke_cancel;
504 SetThreadContext(t->h, &ctxt);
510 _InterlockedIncrement(&_pthread_cancelling);
521 _InterlockedIncrement(&_pthread_cancelling);
527 static unsigned _pthread_get_state(
pthread_attr_t *attr,
unsigned flag)
529 return attr->p_state & flag;
532 static int _pthread_set_state(
pthread_attr_t *attr,
unsigned flag,
unsigned val)
534 if (~flag & val)
return EINVAL;
535 attr->p_state &= ~flag;
536 attr->p_state |= val;
543 attr->p_state = PTHREAD_DEFAULT_ATTR;
558 return _pthread_set_state(a, PTHREAD_CREATE_DETACHED, flag);
563 *flag = _pthread_get_state(a, PTHREAD_CREATE_DETACHED);
569 return _pthread_set_state(a, PTHREAD_INHERIT_SCHED, flag);
574 *flag = _pthread_get_state(a, PTHREAD_INHERIT_SCHED);
580 return _pthread_set_state(a, PTHREAD_SCOPE_SYSTEM, flag);
585 *flag = _pthread_get_state(a, PTHREAD_SCOPE_SYSTEM);
591 *stack = attr->stack;
603 *size = attr->s_size;
613 #define pthread_attr_getguardsize(A, S) ENOTSUP 614 #define pthread_attr_setgaurdsize(A, S) ENOTSUP 615 #define pthread_attr_getschedparam(A, S) ENOTSUP 616 #define pthread_attr_setschedparam(A, S) ENOTSUP 617 #define pthread_attr_getschedpolicy(A, S) ENOTSUP 618 #define pthread_attr_setschedpolicy(A, S) ENOTSUP 621 int pthread_setcancelstate(
int state,
int *oldstate)
625 if ((state & PTHREAD_CANCEL_ENABLE) != state)
return EINVAL;
626 if (oldstate) *oldstate = t->p_state & PTHREAD_CANCEL_ENABLE;
627 t->p_state &= ~PTHREAD_CANCEL_ENABLE;
633 int pthread_setcanceltype(
int type,
int *oldtype)
637 if ((type & PTHREAD_CANCEL_ASYNCHRONOUS) != type)
return EINVAL;
638 if (oldtype) *oldtype = t->p_state & PTHREAD_CANCEL_ASYNCHRONOUS;
639 t->p_state &= ~PTHREAD_CANCEL_ASYNCHRONOUS;
645 unsigned __stdcall pthread_create_wrapper(
void *args)
649 _pthread_once_raw(&_pthread_tls_once, pthread_tls_init);
651 TlsSetValue(_pthread_tls, tv);
656 tv->ret_arg = tv->func(tv->ret_arg);
659 _pthread_cleanup_dest(tv);
663 while (tv->h == (HANDLE) -1)
670 if (!tv->h) free(tv);
689 tv->p_state = PTHREAD_DEFAULT_ATTR;
696 tv->p_state = attr->p_state;
697 ssize = (unsigned) attr->s_size;
703 tv->h = (HANDLE) _beginthreadex(NULL, ssize, pthread_create_wrapper, tv, 0, NULL);
706 if (!tv->h)
return 1;
708 if (tv->p_state & PTHREAD_CREATE_DETACHED)
718 int pthread_join(
pthread_t t,
void **res)
722 pthread_testcancel();
724 WaitForSingleObject(tv->h, INFINITE);
728 if (res) *res = tv->ret_arg;
751 int pthread_mutexattr_init(pthread_mutexattr_t *a)
757 int pthread_mutexattr_destroy(pthread_mutexattr_t *a)
763 int pthread_mutexattr_gettype(pthread_mutexattr_t *a,
int *type)
770 int pthread_mutexattr_settype(pthread_mutexattr_t *a,
int type)
772 if ((
unsigned) type > 3)
return EINVAL;
779 int pthread_mutexattr_getpshared(pthread_mutexattr_t *a,
int *type)
786 int pthread_mutexattr_setpshared(pthread_mutexattr_t * a,
int type)
788 if ((type & 4) != type)
return EINVAL;
796 int pthread_mutexattr_getprotocol(pthread_mutexattr_t *a,
int *type)
798 *type = *a & (8 + 16);
803 int pthread_mutexattr_setprotocol(pthread_mutexattr_t *a,
int type)
805 if ((type & (8 + 16)) != 8 + 16)
return EINVAL;
813 int pthread_mutexattr_getprioceiling(pthread_mutexattr_t *a,
int * prio)
815 *prio = *a / PTHREAD_PRIO_MULT;
819 int pthread_mutexattr_setprioceiling(pthread_mutexattr_t *a,
int prio)
821 *a &= (PTHREAD_PRIO_MULT - 1);
822 *a += prio * PTHREAD_PRIO_MULT;
827 int pthread_mutex_timedlock(pthread_mutex_t *m,
struct timespec *ts)
829 unsigned long long t, ct;
831 struct _pthread_crit_t
842 if (!pthread_mutex_trylock(m))
return 0;
844 ct = _pthread_time_in_ms();
845 t = _pthread_time_in_ms_from_timespec(ts);
850 if (ct > t)
return ETIMEDOUT;
853 WaitForSingleObject(((
struct _pthread_crit_t *)m)->sem, (DWORD)(t - ct));
856 if (!pthread_mutex_trylock(m))
return 0;
859 ct = _pthread_time_in_ms();
863 #define _PTHREAD_BARRIER_FLAG (1<<30) 867 EnterCriticalSection(&b->m);
869 while (b->total > _PTHREAD_BARRIER_FLAG)
872 SleepConditionVariableCS(&b->cv, &b->m, INFINITE);
875 LeaveCriticalSection(&b->m);
877 DeleteCriticalSection(&b->m);
890 InitializeCriticalSection(&b->m);
891 InitializeConditionVariable(&b->cv);
898 EnterCriticalSection(&b->m);
900 while (b->total > _PTHREAD_BARRIER_FLAG)
903 SleepConditionVariableCS(&b->cv, &b->m, INFINITE);
907 if (b->total == _PTHREAD_BARRIER_FLAG) b->total = 0;
911 if (b->total == b->count)
913 b->total += _PTHREAD_BARRIER_FLAG - 1;
914 WakeAllConditionVariable(&b->cv);
916 LeaveCriticalSection(&b->m);
922 while (b->total < _PTHREAD_BARRIER_FLAG)
925 SleepConditionVariableCS(&b->cv, &b->m, INFINITE);
931 if (b->total == _PTHREAD_BARRIER_FLAG) WakeAllConditionVariable(&b->cv);
933 LeaveCriticalSection(&b->m);
939 int pthread_barrierattr_init(
void **attr)
945 int pthread_barrierattr_destroy(
void **attr)
953 int pthread_barrierattr_setpshared(
void **attr,
int s)
959 int pthread_barrierattr_getpshared(
void **attr,
int *s)
961 *s = (int) (
size_t) *attr;
966 int pthread_key_create(pthread_key_t *key,
void (* dest)(
void *))
972 if (!key)
return EINVAL;
974 pthread_rwlock_wrlock(&_pthread_key_lock);
976 for (i = _pthread_key_sch; i < _pthread_key_max; i++)
978 if (!_pthread_key_dest[i])
983 _pthread_key_dest[i] = dest;
987 _pthread_key_dest[i] = (void(*)(
void *))1;
989 pthread_rwlock_unlock(&_pthread_key_lock);
995 for (i = 0; i < _pthread_key_sch; i++)
997 if (!_pthread_key_dest[i])
1002 _pthread_key_dest[i] = dest;
1006 _pthread_key_dest[i] = (void(*)(
void *))1;
1008 pthread_rwlock_unlock(&_pthread_key_lock);
1014 if (!_pthread_key_max) _pthread_key_max = 1;
1015 if (_pthread_key_max == PTHREAD_KEYS_MAX)
1017 pthread_rwlock_unlock(&_pthread_key_lock);
1022 nmax = _pthread_key_max * 2;
1023 if (nmax > PTHREAD_KEYS_MAX) nmax = PTHREAD_KEYS_MAX;
1026 d = (void (**)(
void*))realloc(_pthread_key_dest, nmax *
sizeof(*d));
1029 pthread_rwlock_unlock(&_pthread_key_lock);
1035 memset((
void *) &d[_pthread_key_max], 0, (nmax-_pthread_key_max)*
sizeof(
void *));
1038 _pthread_key_dest = d;
1039 _pthread_key_sch = _pthread_key_max + 1;
1040 *key = _pthread_key_max;
1041 _pthread_key_max = nmax;
1045 _pthread_key_dest[*key] = dest;
1049 _pthread_key_dest[*key] = (void(*)(
void *))1;
1052 pthread_rwlock_unlock(&_pthread_key_lock);
1057 int pthread_key_delete(pthread_key_t key)
1059 if (key > _pthread_key_max)
return EINVAL;
1060 if (!_pthread_key_dest)
return EINVAL;
1062 pthread_rwlock_wrlock(&_pthread_key_lock);
1063 _pthread_key_dest[key] = NULL;
1066 if (_pthread_key_sch > key) _pthread_key_sch = key;
1068 pthread_rwlock_unlock(&_pthread_key_lock);
1073 void *pthread_getspecific(pthread_key_t key)
1077 if (key >= t->keymax)
return NULL;
1079 return t->keyval[key];
1083 int pthread_setspecific(pthread_key_t key,
const void *value)
1087 if (key > t->keymax)
1089 int keymax = (key + 1) * 2;
1090 void **kv = (
void**)realloc(t->keyval, keymax *
sizeof(
void *));
1092 if (!kv)
return ENOMEM;
1095 memset(&kv[t->keymax], 0, (keymax - t->keymax)*
sizeof(
void*));
1101 t->keyval[key] = (
void *) value;
1107 int pthread_spin_init(pthread_spinlock_t *l,
int pshared)
1115 int pthread_spin_destroy(pthread_spinlock_t *l)
1122 int pthread_spin_lock(pthread_spinlock_t *l)
1124 while (_InterlockedExchange(l, EBUSY))
1132 _ReadWriteBarrier();
1139 int pthread_spin_trylock(pthread_spinlock_t *l)
1141 return _InterlockedExchange(l, EBUSY);
1144 int pthread_spin_unlock(pthread_spinlock_t *l)
1147 _ReadWriteBarrier();
1154 int pthread_cond_init(pthread_cond_t *c, pthread_condattr_t *a)
1158 InitializeConditionVariable(c);
1162 int pthread_cond_signal(pthread_cond_t *c)
1164 WakeConditionVariable(c);
1168 int pthread_cond_broadcast(pthread_cond_t *c)
1170 WakeAllConditionVariable(c);
1174 int pthread_cond_wait(pthread_cond_t *c, pthread_mutex_t *m)
1176 pthread_testcancel();
1177 SleepConditionVariableCS(c, m, INFINITE);
1181 int pthread_cond_destroy(pthread_cond_t *c)
1187 int pthread_cond_timedwait(pthread_cond_t *c, pthread_mutex_t *m,
struct timespec *t)
1189 unsigned long long tm = _pthread_rel_time_in_ms(t);
1191 pthread_testcancel();
1193 if (!SleepConditionVariableCS(c, m, (DWORD)tm))
return ETIMEDOUT;
1196 if (!_pthread_rel_time_in_ms(t))
return ETIMEDOUT;
1201 int pthread_condattr_destroy(pthread_condattr_t *a)
1207 int pthread_condattr_init(pthread_condattr_t *a)
1213 int pthread_condattr_getpshared(pthread_condattr_t *a,
int *s)
1219 int pthread_condattr_setpshared(pthread_condattr_t *a,
int s)
1225 int pthread_rwlockattr_destroy(pthread_rwlockattr_t *a)
1231 int pthread_rwlockattr_init(pthread_rwlockattr_t *a)
1237 int pthread_rwlockattr_getpshared(pthread_rwlockattr_t *a,
int *s)
1243 int pthread_rwlockattr_setpshared(pthread_rwlockattr_t *a,
int s)