2 * Posix Threads library for Microsoft Windows
4 * Use at own risk, there is no implied warranty to this code.
5 * It uses undocumented features of Microsoft Windows that can change
6 * at any time in the future.
8 * (C) 2010 Lockless Inc.
11 * Redistribution and use in source and binary forms, with or without modification,
12 * are permitted provided that the following conditions are met:
15 * * Redistributions of source code must retain the above copyright notice,
16 * this list of conditions and the following disclaimer.
17 * * Redistributions in binary form must reproduce the above copyright notice,
18 * this list of conditions and the following disclaimer in the documentation
19 * and/or other materials provided with the distribution.
20 * * Neither the name of Lockless Inc. nor the names of its contributors may be
21 * used to endorse or promote products derived from this software without
22 * specific prior written permission.
24 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AN
25 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
27 * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
28 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
29 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
30 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
31 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
32 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
33 * OF THE POSSIBILITY OF SUCH DAMAGE.
46 #include <sys/timeb.h>
49 #define PTHREAD_CANCEL_DISABLE 0
50 #define PTHREAD_CANCEL_ENABLE 0x01
52 #define PTHREAD_CANCEL_DEFERRED 0
53 #define PTHREAD_CANCEL_ASYNCHRONOUS 0x02
55 #define PTHREAD_CREATE_JOINABLE 0
56 #define PTHREAD_CREATE_DETACHED 0x04
58 #define PTHREAD_EXPLICT_SCHED 0
59 #define PTHREAD_INHERIT_SCHED 0x08
61 #define PTHREAD_SCOPE_PROCESS 0
62 #define PTHREAD_SCOPE_SYSTEM 0x10
64 #define PTHREAD_DEFAULT_ATTR (PTHREAD_CANCEL_ENABLE)
66 #define PTHREAD_CANCELED ((void *) 0xDEADBEEF)
68 #define PTHREAD_ONCE_INIT 0
69 #define PTHREAD_MUTEX_INITIALIZER {(void*)-1,-1,0,0,0,0}
70 #define PTHREAD_RWLOCK_INITIALIZER {0}
71 #define PTHREAD_COND_INITIALIZER {0}
72 #define PTHREAD_BARRIER_INITIALIZER \
73 {0,0,PTHREAD_MUTEX_INITIALIZER,PTHREAD_COND_INITIALIZER}
74 #define PTHREAD_SPINLOCK_INITIALIZER 0
76 #define PTHREAD_DESTRUCTOR_ITERATIONS 256
77 #define PTHREAD_KEYS_MAX (1<<20)
79 #define PTHREAD_MUTEX_NORMAL 0
80 #define PTHREAD_MUTEX_ERRORCHECK 1
81 #define PTHREAD_MUTEX_RECURSIVE 2
82 #define PTHREAD_MUTEX_DEFAULT 3
83 #define PTHREAD_MUTEX_SHARED 4
84 #define PTHREAD_MUTEX_PRIVATE 0
85 #define PTHREAD_PRIO_NONE 0
86 #define PTHREAD_PRIO_INHERIT 8
87 #define PTHREAD_PRIO_PROTECT 16
88 #define PTHREAD_PRIO_MULT 32
89 #define PTHREAD_PROCESS_SHARED 0
90 #define PTHREAD_PROCESS_PRIVATE 1
92 #define PTHREAD_BARRIER_SERIAL_THREAD 1
95 /* Windows doesn't have this, so declare it ourselves. */
98 /* long long in windows is the same as long in unix for 64bit */
103 typedef struct _pthread_cleanup _pthread_cleanup;
104 struct _pthread_cleanup
106 void (*func)(void *);
108 _pthread_cleanup *next;
114 void *(* func)(void *);
115 _pthread_cleanup *clean;
125 typedef struct _pthread_v *pthread_t;
127 typedef struct pthread_barrier_t pthread_barrier_t;
128 struct pthread_barrier_t
133 CONDITION_VARIABLE cv;
136 typedef struct pthread_attr_t pthread_attr_t;
137 struct pthread_attr_t
144 typedef long pthread_once_t;
145 typedef unsigned pthread_mutexattr_t;
146 typedef SRWLOCK pthread_rwlock_t;
147 typedef CRITICAL_SECTION pthread_mutex_t;
148 typedef unsigned pthread_key_t;
149 typedef void *pthread_barrierattr_t;
150 typedef long pthread_spinlock_t;
151 typedef int pthread_condattr_t;
152 typedef CONDITION_VARIABLE pthread_cond_t;
153 typedef int pthread_rwlockattr_t;
155 volatile long _pthread_cancelling;
159 /* Will default to zero as needed */
160 pthread_once_t _pthread_tls_once;
163 /* Note initializer is zero, so this works */
164 pthread_rwlock_t _pthread_key_lock;
165 unsigned int _pthread_key_max;
166 unsigned int _pthread_key_sch;
167 void (**_pthread_key_dest)(void *);
170 static int pthread_rwlock_unlock(pthread_rwlock_t *l);
173 #define pthread_cleanup_push(F, A)\
175 const _pthread_cleanup _pthread_cup = {(F), (A), pthread_self()->clean};\
176 _ReadWriteBarrier();\
177 pthread_self()->clean = (_pthread_cleanup *) &_pthread_cup;\
180 /* Note that if async cancelling is used, then there is a race here */
181 #define pthread_cleanup_pop(E)\
182 (pthread_self()->clean = _pthread_cup.next, (E?_pthread_cup.func(_pthread_cup.arg):0));}
184 static void _pthread_once_cleanup(pthread_once_t *o)
189 static pthread_t pthread_self(void);
190 static int pthread_once(pthread_once_t *o, void (*func)(void))
200 if (!_InterlockedCompareExchange(o, 2, 0))
203 pthread_cleanup_push(_pthread_once_cleanup, o);
205 pthread_cleanup_pop(0);
226 static int _pthread_once_raw(pthread_once_t *o, void (*func)(void))
236 if (!_InterlockedCompareExchange(o, 2, 0))
259 static int pthread_mutex_lock(pthread_mutex_t *m)
261 EnterCriticalSection(m);
265 static int pthread_mutex_unlock(pthread_mutex_t *m)
267 LeaveCriticalSection(m);
271 static int pthread_mutex_trylock(pthread_mutex_t *m)
273 return TryEnterCriticalSection(m) ? 0 : EBUSY;
276 static int pthread_mutex_init(pthread_mutex_t *m, pthread_mutexattr_t *a)
279 InitializeCriticalSection(m);
284 static int pthread_mutex_destroy(pthread_mutex_t *m)
286 DeleteCriticalSection(m);
290 #define pthread_mutex_getprioceiling(M, P) ENOTSUP
291 #define pthread_mutex_setprioceiling(M, P) ENOTSUP
293 static int pthread_equal(pthread_t t1, pthread_t t2)
298 static void pthread_testcancel(void);
300 static int pthread_rwlock_init(pthread_rwlock_t *l, pthread_rwlockattr_t *a)
303 InitializeSRWLock(l);
308 static int pthread_rwlock_destroy(pthread_rwlock_t *l)
314 static int pthread_rwlock_rdlock(pthread_rwlock_t *l)
316 pthread_testcancel();
317 AcquireSRWLockShared(l);
322 static int pthread_rwlock_wrlock(pthread_rwlock_t *l)
324 pthread_testcancel();
325 AcquireSRWLockExclusive(l);
330 static void pthread_tls_init(void)
332 _pthread_tls = TlsAlloc();
334 /* Cannot continue if out of indexes */
335 if (_pthread_tls == TLS_OUT_OF_INDEXES) abort();
338 static void _pthread_cleanup_dest(pthread_t t)
342 for (j = 0; j < PTHREAD_DESTRUCTOR_ITERATIONS; j++)
346 for (i = 0; i < t->keymax; i++)
348 void *val = t->keyval[i];
352 pthread_rwlock_rdlock(&_pthread_key_lock);
353 if ((uintptr_t) _pthread_key_dest[i] > 1)
355 /* Call destructor */
357 _pthread_key_dest[i](val);
360 pthread_rwlock_unlock(&_pthread_key_lock);
369 static pthread_t pthread_self(void)
373 _pthread_once_raw(&_pthread_tls_once, pthread_tls_init);
375 t = TlsGetValue(_pthread_tls);
380 t = malloc(sizeof(struct _pthread_v));
382 /* If cannot initialize main thread, then the only thing we can do is abort */
389 t->p_state = PTHREAD_DEFAULT_ATTR;
392 t->h = GetCurrentThread();
395 TlsSetValue(_pthread_tls, t);
399 /* Make sure we free ourselves if we are detached */
410 static int pthread_rwlock_unlock(pthread_rwlock_t *l)
412 void *state = *(void **)l;
414 if (state == (void *) 1)
416 /* Known to be an exclusive lock */
417 ReleaseSRWLockExclusive(l);
421 /* A shared unlock will work */
422 ReleaseSRWLockShared(l);
429 static int pthread_rwlock_tryrdlock(pthread_rwlock_t *l)
431 /* Get the current state of the lock */
432 void *state = *(void **) l;
436 /* Unlocked to locked */
437 if (!InterlockedCompareExchangePointer((void *) l, (void *)0x11, NULL)) return 0;
441 /* A single writer exists */
442 if (state == (void *) 1) return EBUSY;
444 /* Multiple writers exist? */
445 if ((uintptr_t) state & 14) return EBUSY;
447 if (InterlockedCompareExchangePointer((void *) l, (void *) ((uintptr_t)state + 16), state) == state) return 0;
452 static int pthread_rwlock_trywrlock(pthread_rwlock_t *l)
454 /* Try to grab lock if it has no users */
455 if (!InterlockedCompareExchangePointer((void *) l, (void *)1, NULL)) return 0;
460 static unsigned long long _pthread_time_in_ms(void)
466 return tb.time * 1000 + tb.millitm;
469 static unsigned long long _pthread_time_in_ms_from_timespec(const struct timespec *ts)
471 unsigned long long t = ts->tv_sec * 1000;
472 t += ts->tv_nsec / 1000000;
477 static unsigned long long _pthread_rel_time_in_ms(const struct timespec *ts)
479 unsigned long long t1 = _pthread_time_in_ms_from_timespec(ts);
480 unsigned long long t2 = _pthread_time_in_ms();
482 /* Prevent underflow */
483 if (t1 < t2) return 1;
487 static int pthread_rwlock_timedrdlock(pthread_rwlock_t *l, const struct timespec *ts)
489 unsigned long long ct = _pthread_time_in_ms();
490 unsigned long long t = _pthread_time_in_ms_from_timespec(ts);
492 pthread_testcancel();
494 /* Use a busy-loop */
497 /* Try to grab lock */
498 if (!pthread_rwlock_tryrdlock(l)) return 0;
500 /* Get current time */
501 ct = _pthread_time_in_ms();
503 /* Have we waited long enough? */
504 if (ct > t) return ETIMEDOUT;
508 static int pthread_rwlock_timedwrlock(pthread_rwlock_t *l, const struct timespec *ts)
510 unsigned long long ct = _pthread_time_in_ms();
511 unsigned long long t = _pthread_time_in_ms_from_timespec(ts);
513 pthread_testcancel();
515 /* Use a busy-loop */
518 /* Try to grab lock */
519 if (!pthread_rwlock_trywrlock(l)) return 0;
521 /* Get current time */
522 ct = _pthread_time_in_ms();
524 /* Have we waited long enough? */
525 if (ct > t) return ETIMEDOUT;
529 static int pthread_get_concurrency(int *val)
531 *val = _pthread_concur;
535 static int pthread_set_concurrency(int val)
537 _pthread_concur = val;
541 #define pthread_getschedparam(T, P, S) ENOTSUP
542 #define pthread_setschedparam(T, P, S) ENOTSUP
543 #define pthread_getcpuclockid(T, C) ENOTSUP
545 static int pthread_exit(void *res)
547 pthread_t t = pthread_self();
551 _pthread_cleanup_dest(t);
557 static void _pthread_invoke_cancel(void)
559 _pthread_cleanup *pcup;
561 _InterlockedDecrement(&_pthread_cancelling);
563 /* Call cancel queue */
564 for (pcup = pthread_self()->clean; pcup; pcup = pcup->next)
566 pcup->func(pcup->arg);
569 pthread_exit(PTHREAD_CANCELED);
572 static void pthread_testcancel(void)
574 if (_pthread_cancelling)
576 pthread_t t = pthread_self();
578 if (t->cancelled && (t->p_state & PTHREAD_CANCEL_ENABLE))
580 _pthread_invoke_cancel();
586 static int pthread_cancel(pthread_t t)
588 if (t->p_state & PTHREAD_CANCEL_ASYNCHRONOUS)
590 /* Dangerous asynchronous cancelling */
594 if (t->cancelled) return ESRCH;
596 ctxt.ContextFlags = CONTEXT_CONTROL;
599 GetThreadContext(t->h, &ctxt);
601 ctxt.Rip = (uintptr_t) _pthread_invoke_cancel;
603 ctxt.Eip = (uintptr_t) _pthread_invoke_cancel;
605 SetThreadContext(t->h, &ctxt);
607 /* Also try deferred Cancelling */
610 /* Notify everyone to look */
611 _InterlockedIncrement(&_pthread_cancelling);
617 /* Safe deferred Cancelling */
620 /* Notify everyone to look */
621 _InterlockedIncrement(&_pthread_cancelling);
627 static unsigned _pthread_get_state(pthread_attr_t *attr, unsigned flag)
629 return attr->p_state & flag;
632 static int _pthread_set_state(pthread_attr_t *attr, unsigned flag, unsigned val)
634 if (~flag & val) return EINVAL;
635 attr->p_state &= ~flag;
636 attr->p_state |= val;
641 static int pthread_attr_init(pthread_attr_t *attr)
643 attr->p_state = PTHREAD_DEFAULT_ATTR;
649 static int pthread_attr_destroy(pthread_attr_t *attr)
651 /* No need to do anything */
656 static int pthread_attr_setdetachstate(pthread_attr_t *a, int flag)
658 return _pthread_set_state(a, PTHREAD_CREATE_DETACHED, flag);
661 static int pthread_attr_getdetachstate(pthread_attr_t *a, int *flag)
663 *flag = _pthread_get_state(a, PTHREAD_CREATE_DETACHED);
667 static int pthread_attr_setinheritsched(pthread_attr_t *a, int flag)
669 return _pthread_set_state(a, PTHREAD_INHERIT_SCHED, flag);
672 static int pthread_attr_getinheritsched(pthread_attr_t *a, int *flag)
674 *flag = _pthread_get_state(a, PTHREAD_INHERIT_SCHED);
678 static int pthread_attr_setscope(pthread_attr_t *a, int flag)
680 return _pthread_set_state(a, PTHREAD_SCOPE_SYSTEM, flag);
683 static int pthread_attr_getscope(pthread_attr_t *a, int *flag)
685 *flag = _pthread_get_state(a, PTHREAD_SCOPE_SYSTEM);
689 static int pthread_attr_getstackaddr(pthread_attr_t *attr, void **stack)
691 *stack = attr->stack;
695 static int pthread_attr_setstackaddr(pthread_attr_t *attr, void *stack)
701 static int pthread_attr_getstacksize(pthread_attr_t *attr, size_t *size)
703 *size = attr->s_size;
707 static int pthread_attr_setstacksize(pthread_attr_t *attr, size_t size)
713 #define pthread_attr_getguardsize(A, S) ENOTSUP
714 #define pthread_attr_setgaurdsize(A, S) ENOTSUP
715 #define pthread_attr_getschedparam(A, S) ENOTSUP
716 #define pthread_attr_setschedparam(A, S) ENOTSUP
717 #define pthread_attr_getschedpolicy(A, S) ENOTSUP
718 #define pthread_attr_setschedpolicy(A, S) ENOTSUP
721 static int pthread_setcancelstate(int state, int *oldstate)
723 pthread_t t = pthread_self();
725 if ((state & PTHREAD_CANCEL_ENABLE) != state) return EINVAL;
726 if (oldstate) *oldstate = t->p_state & PTHREAD_CANCEL_ENABLE;
727 t->p_state &= ~PTHREAD_CANCEL_ENABLE;
733 static int pthread_setcanceltype(int type, int *oldtype)
735 pthread_t t = pthread_self();
737 if ((type & PTHREAD_CANCEL_ASYNCHRONOUS) != type) return EINVAL;
738 if (oldtype) *oldtype = t->p_state & PTHREAD_CANCEL_ASYNCHRONOUS;
739 t->p_state &= ~PTHREAD_CANCEL_ASYNCHRONOUS;
745 static int __stdcall pthread_create_wrapper(void *args)
747 struct _pthread_v *tv = args;
749 _pthread_once_raw(&_pthread_tls_once, pthread_tls_init);
751 TlsSetValue(_pthread_tls, tv);
755 /* Call function and save return value */
756 tv->ret_arg = tv->func(tv->ret_arg);
758 /* Clean up destructors */
759 _pthread_cleanup_dest(tv);
762 /* If we exit too early, then we can race with create */
763 while (tv->h == (HANDLE) -1)
769 /* Make sure we free ourselves if we are detached */
770 if (!tv->h) free(tv);
775 static int pthread_create(pthread_t *th, pthread_attr_t *attr, void *(* func)(void *), void *arg)
777 struct _pthread_v *tv = malloc(sizeof(struct _pthread_v));
784 /* Save data in pthread_t */
789 tv->p_state = PTHREAD_DEFAULT_ATTR;
796 tv->p_state = attr->p_state;
797 ssize = (unsigned int)attr->s_size;
800 /* Make sure tv->h has value of -1 */
803 tv->h = (HANDLE) _beginthreadex(NULL, ssize, pthread_create_wrapper, tv, 0, NULL);
806 if (!tv->h) return 1;
809 if (tv->p_state & PTHREAD_CREATE_DETACHED)
819 static int pthread_join(pthread_t t, void **res)
821 struct _pthread_v *tv = t;
823 pthread_testcancel();
825 WaitForSingleObject(tv->h, INFINITE);
828 /* Obtain return value */
829 if (res) *res = tv->ret_arg;
836 static int pthread_detach(pthread_t t)
838 struct _pthread_v *tv = t;
841 * This can't race with thread exit because
842 * our call would be undefined if called on a dead thread.
852 static int pthread_mutexattr_init(pthread_mutexattr_t *a)
858 static int pthread_mutexattr_destroy(pthread_mutexattr_t *a)
864 static int pthread_mutexattr_gettype(pthread_mutexattr_t *a, int *type)
871 static int pthread_mutexattr_settype(pthread_mutexattr_t *a, int type)
873 if ((unsigned) type > 3) return EINVAL;
880 static int pthread_mutexattr_getpshared(pthread_mutexattr_t *a, int *type)
887 static int pthread_mutexattr_setpshared(pthread_mutexattr_t * a, int type)
889 if ((type & 4) != type) return EINVAL;
897 static int pthread_mutexattr_getprotocol(pthread_mutexattr_t *a, int *type)
899 *type = *a & (8 + 16);
904 static int pthread_mutexattr_setprotocol(pthread_mutexattr_t *a, int type)
906 if ((type & (8 + 16)) != 8 + 16) return EINVAL;
914 static int pthread_mutexattr_getprioceiling(pthread_mutexattr_t *a, int * prio)
916 *prio = *a / PTHREAD_PRIO_MULT;
920 static int pthread_mutexattr_setprioceiling(pthread_mutexattr_t *a, int prio)
922 *a &= (PTHREAD_PRIO_MULT - 1);
923 *a += prio * PTHREAD_PRIO_MULT;
928 static int pthread_mutex_timedlock(pthread_mutex_t *m, struct timespec *ts)
930 unsigned long long t, ct;
932 struct _pthread_crit_t
942 /* Try to lock it without waiting */
943 if (!pthread_mutex_trylock(m)) return 0;
945 ct = _pthread_time_in_ms();
946 t = _pthread_time_in_ms_from_timespec(ts);
950 /* Have we waited long enough? */
951 if (ct > t) return ETIMEDOUT;
953 /* Wait on semaphore within critical section */
954 WaitForSingleObject(((struct _pthread_crit_t *)m)->sem, (DWORD)(t - ct));
956 /* Try to grab lock */
957 if (!pthread_mutex_trylock(m)) return 0;
959 /* Get current time */
960 ct = _pthread_time_in_ms();
964 static int pthread_barrier_destroy(pthread_barrier_t *b)
966 DeleteCriticalSection(&b->m);
972 static int pthread_barrier_init(pthread_barrier_t *b, void *attr, int count)
977 InitializeCriticalSection(&b->m);
978 InitializeConditionVariable(&b->cv);
985 #define _PTHREAD_BARRIER_FLAG (1<<30)
986 static int pthread_barrier_wait(pthread_barrier_t *b)
988 EnterCriticalSection(&b->m);
990 while (b->total > _PTHREAD_BARRIER_FLAG)
992 /* Wait until everyone exits the barrier */
993 SleepConditionVariableCS(&b->cv, &b->m, INFINITE);
996 /* Are we the first to enter? */
997 if (b->total == _PTHREAD_BARRIER_FLAG) b->total = 0;
1001 if (b->total == b->count)
1003 b->total += _PTHREAD_BARRIER_FLAG - 1;
1004 WakeAllConditionVariable(&b->cv);
1006 LeaveCriticalSection(&b->m);
1012 while (b->total < _PTHREAD_BARRIER_FLAG)
1014 /* Wait until enough threads enter the barrier */
1015 SleepConditionVariableCS(&b->cv, &b->m, INFINITE);
1020 /* Get entering threads to wake up */
1021 if (b->total == _PTHREAD_BARRIER_FLAG) WakeAllConditionVariable(&b->cv);
1023 LeaveCriticalSection(&b->m);
1029 static int pthread_barrierattr_init(void **attr)
1035 static int pthread_barrierattr_destroy(void **attr)
1043 static int pthread_barrierattr_setpshared(void **attr, int s)
1049 static int pthread_barrierattr_getpshared(void **attr, int *s)
1051 *s = (int) (size_t) *attr;
1056 static int pthread_key_create(pthread_key_t *key, void (* dest)(void *))
1062 if (!key) return EINVAL;
1064 pthread_rwlock_wrlock(&_pthread_key_lock);
1066 for (i = _pthread_key_sch; i < _pthread_key_max; i++)
1068 if (!_pthread_key_dest[i])
1073 _pthread_key_dest[i] = dest;
1077 _pthread_key_dest[i] = (void(*)(void *))1;
1079 pthread_rwlock_unlock(&_pthread_key_lock);
1085 for (i = 0; i < _pthread_key_sch; i++)
1087 if (!_pthread_key_dest[i])
1092 _pthread_key_dest[i] = dest;
1096 _pthread_key_dest[i] = (void(*)(void *))1;
1098 pthread_rwlock_unlock(&_pthread_key_lock);
1104 if (!_pthread_key_max) _pthread_key_max = 1;
1105 if (_pthread_key_max == PTHREAD_KEYS_MAX)
1107 pthread_rwlock_unlock(&_pthread_key_lock);
1112 nmax = _pthread_key_max * 2;
1113 if (nmax > PTHREAD_KEYS_MAX) nmax = PTHREAD_KEYS_MAX;
1115 /* No spare room anywhere */
1116 d = realloc(_pthread_key_dest, nmax * sizeof(*d));
1119 pthread_rwlock_unlock(&_pthread_key_lock);
1124 /* Clear new region */
1125 memset((void *) &d[_pthread_key_max], 0, (nmax-_pthread_key_max)*sizeof(void *));
1127 /* Use new region */
1128 _pthread_key_dest = d;
1129 _pthread_key_sch = _pthread_key_max + 1;
1130 *key = _pthread_key_max;
1131 _pthread_key_max = nmax;
1135 _pthread_key_dest[*key] = dest;
1139 _pthread_key_dest[*key] = (void(*)(void *))1;
1142 pthread_rwlock_unlock(&_pthread_key_lock);
1147 static int pthread_key_delete(pthread_key_t key)
1149 if (key > _pthread_key_max) return EINVAL;
1150 if (!_pthread_key_dest) return EINVAL;
1152 pthread_rwlock_wrlock(&_pthread_key_lock);
1153 _pthread_key_dest[key] = NULL;
1155 /* Start next search from our location */
1156 if (_pthread_key_sch > key) _pthread_key_sch = key;
1158 pthread_rwlock_unlock(&_pthread_key_lock);
1163 static void *pthread_getspecific(pthread_key_t key)
1165 pthread_t t = pthread_self();
1167 if (key >= t->keymax) return NULL;
1169 return t->keyval[key];
1173 static int pthread_setspecific(pthread_key_t key, const void *value)
1175 pthread_t t = pthread_self();
1177 if (key > t->keymax)
1179 int keymax = (key + 1) * 2;
1180 void **kv = realloc(t->keyval, keymax * sizeof(void *));
1182 if (!kv) return ENOMEM;
1184 /* Clear new region */
1185 memset(&kv[t->keymax], 0, (keymax - t->keymax)*sizeof(void*));
1191 t->keyval[key] = (void *) value;
1197 static int pthread_spin_init(pthread_spinlock_t *l, int pshared)
1205 static int pthread_spin_destroy(pthread_spinlock_t *l)
1211 /* No-fair spinlock due to lack of knowledge of thread number */
1212 static int pthread_spin_lock(pthread_spinlock_t *l)
1214 while (_InterlockedExchange(l, EBUSY))
1216 /* Don't lock the bus whilst waiting */
1221 /* Compiler barrier. Prevent caching of *l */
1222 _ReadWriteBarrier();
1229 static int pthread_spin_trylock(pthread_spinlock_t *l)
1231 return _InterlockedExchange(l, EBUSY);
1234 static int pthread_spin_unlock(pthread_spinlock_t *l)
1236 /* Compiler barrier. The store below acts with release symmantics */
1237 _ReadWriteBarrier();
1244 static int pthread_cond_init(pthread_cond_t *c, pthread_condattr_t *a)
1248 InitializeConditionVariable(c);
1252 static int pthread_cond_signal(pthread_cond_t *c)
1254 WakeConditionVariable(c);
1258 static int pthread_cond_broadcast(pthread_cond_t *c)
1260 WakeAllConditionVariable(c);
1264 static int pthread_cond_wait(pthread_cond_t *c, pthread_mutex_t *m)
1266 pthread_testcancel();
1267 SleepConditionVariableCS(c, m, INFINITE);
1271 static int pthread_cond_destroy(pthread_cond_t *c)
1277 static int pthread_cond_timedwait(pthread_cond_t *c, pthread_mutex_t *m, struct timespec *t)
1279 unsigned long long tm = _pthread_rel_time_in_ms(t);
1281 pthread_testcancel();
1283 if (!SleepConditionVariableCS(c, m, (DWORD) tm)) return ETIMEDOUT;
1285 /* We can have a spurious wakeup after the timeout */
1286 if (!_pthread_rel_time_in_ms(t)) return ETIMEDOUT;
1291 static int pthread_condattr_destroy(pthread_condattr_t *a)
1297 #define pthread_condattr_getclock(A, C) ENOTSUP
1298 #define pthread_condattr_setclock(A, C) ENOTSUP
1300 static int pthread_condattr_init(pthread_condattr_t *a)
1306 static int pthread_condattr_getpshared(pthread_condattr_t *a, int *s)
1312 static int pthread_condattr_setpshared(pthread_condattr_t *a, int s)
1318 static int pthread_rwlockattr_destroy(pthread_rwlockattr_t *a)
1324 static int pthread_rwlockattr_init(pthread_rwlockattr_t *a)
1329 static int pthread_rwlockattr_getpshared(pthread_rwlockattr_t *a, int *s)
1335 static int pthread_rwlockattr_setpshared(pthread_rwlockattr_t *a, int s)
1342 /* No fork() in windows - so ignore this */
1343 #define pthread_atfork(F1,F2,F3) 0
1345 /* Windows has rudimentary signals support */
1346 #define pthread_kill(T, S) 0
1347 #define pthread_sigmask(H, S1, S2) 0
1350 /* Wrap cancellation points */
1351 //FIXME: removed wrappers, some of them caused compilation errors
1353 #endif /* WIN_PTHREADS */