Tizen 2.1 base
[platform/upstream/gcd.git] / pthread_workqueue-0.8.2 / src / windows / winpthreads.h
1 /*
2  * Posix Threads library for Microsoft Windows
3  *
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.
7  *
8  * (C) 2010 Lockless Inc.
9  * All rights reserved.
10  *
11  * Redistribution and use in source and binary forms, with or without modification,
12  * are permitted provided that the following conditions are met:
13  *
14  *
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.
23  *
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.
34  */
35
36 #ifndef WIN_PTHREADS
37 #define WIN_PTHREADS
38
39 #include <stdlib.h>
40 #include <malloc.h>
41 #include <errno.h>
42 #include <process.h>
43 #include <windows.h>
44 #include <setjmp.h>
45 #include <errno.h>
46 #include <sys/timeb.h>
47
48 #
49 #define PTHREAD_CANCEL_DISABLE 0
50 #define PTHREAD_CANCEL_ENABLE 0x01
51
52 #define PTHREAD_CANCEL_DEFERRED 0
53 #define PTHREAD_CANCEL_ASYNCHRONOUS 0x02
54
55 #define PTHREAD_CREATE_JOINABLE 0
56 #define PTHREAD_CREATE_DETACHED 0x04
57
58 #define PTHREAD_EXPLICT_SCHED 0
59 #define PTHREAD_INHERIT_SCHED 0x08
60
61 #define PTHREAD_SCOPE_PROCESS 0
62 #define PTHREAD_SCOPE_SYSTEM 0x10
63
64 #define PTHREAD_DEFAULT_ATTR (PTHREAD_CANCEL_ENABLE)
65
66 #define PTHREAD_CANCELED ((void *) 0xDEADBEEF)
67
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
75
76 #define PTHREAD_DESTRUCTOR_ITERATIONS 256
77 #define PTHREAD_KEYS_MAX (1<<20)
78
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
91
92 #define PTHREAD_BARRIER_SERIAL_THREAD 1
93
94
95 /* Windows doesn't have this, so declare it ourselves. */
96 struct timespec
97 {
98         /* long long in windows is the same as long in unix for 64bit */
99         long long tv_sec;
100         long long tv_nsec;
101 };
102
103 typedef struct _pthread_cleanup _pthread_cleanup;
104 struct _pthread_cleanup
105 {
106         void (*func)(void *);
107         void *arg;
108         _pthread_cleanup *next;
109 };
110
111 struct _pthread_v
112 {
113         void *ret_arg;
114         void *(* func)(void *);
115         _pthread_cleanup *clean;
116         HANDLE h;
117         int cancelled;
118         unsigned p_state;
119         unsigned int keymax;
120         void **keyval;
121         
122         jmp_buf jb;
123 };
124
125 typedef struct _pthread_v *pthread_t;
126
127 typedef struct pthread_barrier_t pthread_barrier_t;
128 struct pthread_barrier_t
129 {
130         int count;
131         int total;
132         CRITICAL_SECTION m;
133         CONDITION_VARIABLE cv;
134 };
135
136 typedef struct pthread_attr_t pthread_attr_t;
137 struct pthread_attr_t
138 {
139         unsigned p_state;
140         void *stack;
141         size_t s_size;
142 };
143
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;
154
155 volatile long _pthread_cancelling;
156
157 int _pthread_concur;
158
159 /* Will default to zero as needed */
160 pthread_once_t _pthread_tls_once;
161 DWORD _pthread_tls;
162
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 *);
168
169 /* Prototypes */
170 static int pthread_rwlock_unlock(pthread_rwlock_t *l);
171
172
173 #define pthread_cleanup_push(F, A)\
174 {\
175         const _pthread_cleanup _pthread_cup = {(F), (A), pthread_self()->clean};\
176         _ReadWriteBarrier();\
177         pthread_self()->clean = (_pthread_cleanup *) &_pthread_cup;\
178         _ReadWriteBarrier()
179         
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));}
183
184 static void _pthread_once_cleanup(pthread_once_t *o)
185 {
186         *o = 0;
187 }
188
189 static pthread_t pthread_self(void);
190 static int pthread_once(pthread_once_t *o, void (*func)(void))
191 {
192         long state = *o;
193
194         _ReadWriteBarrier();
195         
196         while (state != 1)
197         {
198                 if (!state)
199                 {
200                         if (!_InterlockedCompareExchange(o, 2, 0))
201                         {
202                                 /* Success */
203                                 pthread_cleanup_push(_pthread_once_cleanup, o);
204                                 func();
205                                 pthread_cleanup_pop(0);
206                                 
207                                 /* Mark as done */
208                                 *o = 1;
209                                 
210                                 return 0;
211                         }
212                 }
213                 
214                 YieldProcessor();
215                 
216                 _ReadWriteBarrier();
217                 
218                 state = *o;
219         }
220         
221         /* Done */
222         return 0;
223         
224 }
225
226 static int _pthread_once_raw(pthread_once_t *o, void (*func)(void))
227 {
228         long state = *o;
229
230         _ReadWriteBarrier();
231         
232         while (state != 1)
233         {
234                 if (!state)
235                 {
236                         if (!_InterlockedCompareExchange(o, 2, 0))
237                         {
238                                 /* Success */
239                                 func();
240                                 
241                                 /* Mark as done */
242                                 *o = 1;
243                                 
244                                 return 0;
245                         }
246                 }
247                 
248                 YieldProcessor();
249                 
250                 _ReadWriteBarrier();
251                 
252                 state = *o;
253         }
254         
255         /* Done */
256         return 0;
257 }
258
259 static int pthread_mutex_lock(pthread_mutex_t *m)
260 {
261         EnterCriticalSection(m);
262         return 0;
263 }
264
265 static int pthread_mutex_unlock(pthread_mutex_t *m)
266 {
267         LeaveCriticalSection(m);
268         return 0;
269 }
270         
271 static int pthread_mutex_trylock(pthread_mutex_t *m)
272 {
273         return TryEnterCriticalSection(m) ? 0 : EBUSY; 
274 }
275
276 static int pthread_mutex_init(pthread_mutex_t *m, pthread_mutexattr_t *a)
277 {
278         (void) a;
279         InitializeCriticalSection(m);
280         
281         return 0;
282 }
283
284 static int pthread_mutex_destroy(pthread_mutex_t *m)
285 {
286         DeleteCriticalSection(m);
287         return 0;
288 }
289
290 #define pthread_mutex_getprioceiling(M, P) ENOTSUP
291 #define pthread_mutex_setprioceiling(M, P) ENOTSUP
292
293 static int pthread_equal(pthread_t t1, pthread_t t2)
294 {
295         return t1 == t2;
296 }
297
298 static void pthread_testcancel(void);
299
300 static int pthread_rwlock_init(pthread_rwlock_t *l, pthread_rwlockattr_t *a)
301 {
302         (void) a;
303         InitializeSRWLock(l);
304         
305         return 0;
306 }
307
308 static int pthread_rwlock_destroy(pthread_rwlock_t *l)
309 {
310         (void) *l;
311         return 0;
312 }
313
314 static int pthread_rwlock_rdlock(pthread_rwlock_t *l)
315 {
316         pthread_testcancel();
317         AcquireSRWLockShared(l);
318         
319         return 0;
320 }
321
322 static int pthread_rwlock_wrlock(pthread_rwlock_t *l)
323 {
324         pthread_testcancel();
325         AcquireSRWLockExclusive(l);
326         
327         return 0;
328 }
329
330 static void pthread_tls_init(void)
331 {
332         _pthread_tls = TlsAlloc();
333         
334         /* Cannot continue if out of indexes */
335         if (_pthread_tls == TLS_OUT_OF_INDEXES) abort();
336 }
337
338 static void _pthread_cleanup_dest(pthread_t t)
339 {
340         unsigned int i, j;
341         
342         for (j = 0; j < PTHREAD_DESTRUCTOR_ITERATIONS; j++)
343         {
344                 int flag = 0;
345         
346                 for (i = 0; i < t->keymax; i++)
347                 {
348                         void *val = t->keyval[i];
349                         
350                         if (val)
351                         {
352                                 pthread_rwlock_rdlock(&_pthread_key_lock);
353                                 if ((uintptr_t) _pthread_key_dest[i] > 1)
354                                 {
355                                         /* Call destructor */
356                                         t->keyval[i] = NULL;
357                                         _pthread_key_dest[i](val);
358                                         flag = 1;
359                                 }
360                                 pthread_rwlock_unlock(&_pthread_key_lock);
361                         }
362                 }
363         
364                 /* Nothing to do? */
365                 if (!flag) return;
366         }
367 }
368
369 static pthread_t pthread_self(void)
370 {
371         pthread_t t;
372         
373         _pthread_once_raw(&_pthread_tls_once, pthread_tls_init);
374         
375         t = TlsGetValue(_pthread_tls);
376         
377         /* Main thread? */
378         if (!t)
379         {
380                 t = malloc(sizeof(struct _pthread_v));
381                 
382                 /* If cannot initialize main thread, then the only thing we can do is abort */
383                 if (!t) abort();
384         
385                 t->ret_arg = NULL;
386                 t->func = NULL;
387                 t->clean = NULL;
388                 t->cancelled = 0;
389                 t->p_state = PTHREAD_DEFAULT_ATTR;
390                 t->keymax = 0;
391                 t->keyval = NULL;
392                 t->h = GetCurrentThread();
393                 
394                 /* Save for later */
395                 TlsSetValue(_pthread_tls, t);
396                 
397                 if (setjmp(t->jb))
398                 {
399                         /* Make sure we free ourselves if we are detached */
400                         if (!t->h) free(t);
401                         
402                         /* Time to die */
403                         _endthreadex(0);
404                 }
405         }
406         
407         return t;
408 }
409
410 static int pthread_rwlock_unlock(pthread_rwlock_t *l)
411 {
412         void *state = *(void **)l;
413         
414         if (state == (void *) 1)
415         {
416                 /* Known to be an exclusive lock */
417                 ReleaseSRWLockExclusive(l);
418         }
419         else
420         {
421                 /* A shared unlock will work */
422                 ReleaseSRWLockShared(l);
423         }
424         
425         return 0;
426 }
427
428
429 static int pthread_rwlock_tryrdlock(pthread_rwlock_t *l)
430 {
431         /* Get the current state of the lock */
432         void *state = *(void **) l;
433         
434         if (!state)
435         {
436                 /* Unlocked to locked */
437                 if (!InterlockedCompareExchangePointer((void *) l, (void *)0x11, NULL)) return 0;
438                 return EBUSY;
439         }
440         
441         /* A single writer exists */
442         if (state == (void *) 1) return EBUSY;
443         
444         /* Multiple writers exist? */
445         if ((uintptr_t) state & 14) return EBUSY;
446         
447         if (InterlockedCompareExchangePointer((void *) l, (void *) ((uintptr_t)state + 16), state) == state) return 0;
448         
449         return EBUSY;
450 }
451
452 static int pthread_rwlock_trywrlock(pthread_rwlock_t *l)
453 {
454         /* Try to grab lock if it has no users */
455         if (!InterlockedCompareExchangePointer((void *) l, (void *)1, NULL)) return 0;
456         
457         return EBUSY;
458 }
459
460 static unsigned long long _pthread_time_in_ms(void)
461 {
462         struct __timeb64 tb;
463         
464         _ftime64_s(&tb);
465         
466         return tb.time * 1000 + tb.millitm;
467 }
468
469 static unsigned long long _pthread_time_in_ms_from_timespec(const struct timespec *ts)
470 {
471         unsigned long long t = ts->tv_sec * 1000;
472         t += ts->tv_nsec / 1000000;
473
474         return t;
475 }
476
477 static unsigned long long _pthread_rel_time_in_ms(const struct timespec *ts)
478 {
479         unsigned long long t1 = _pthread_time_in_ms_from_timespec(ts);
480         unsigned long long t2 = _pthread_time_in_ms();
481         
482         /* Prevent underflow */
483         if (t1 < t2) return 1;
484         return t1 - t2;
485 }
486
487 static int pthread_rwlock_timedrdlock(pthread_rwlock_t *l, const struct timespec *ts)
488 {
489         unsigned long long ct = _pthread_time_in_ms();
490         unsigned long long t = _pthread_time_in_ms_from_timespec(ts);
491
492         pthread_testcancel();
493         
494         /* Use a busy-loop */
495         while (1)
496         {
497                 /* Try to grab lock */
498                 if (!pthread_rwlock_tryrdlock(l)) return 0;
499                 
500                 /* Get current time */
501                 ct = _pthread_time_in_ms();
502                 
503                 /* Have we waited long enough? */
504                 if (ct > t) return ETIMEDOUT;
505         }
506 }
507
508 static int pthread_rwlock_timedwrlock(pthread_rwlock_t *l, const struct timespec *ts)
509 {
510         unsigned long long ct = _pthread_time_in_ms();
511         unsigned long long t = _pthread_time_in_ms_from_timespec(ts);
512
513         pthread_testcancel();
514         
515         /* Use a busy-loop */
516         while (1)
517         {
518                 /* Try to grab lock */
519                 if (!pthread_rwlock_trywrlock(l)) return 0;
520                 
521                 /* Get current time */
522                 ct = _pthread_time_in_ms();
523                 
524                 /* Have we waited long enough? */
525                 if (ct > t) return ETIMEDOUT;
526         }
527 }
528         
529 static int pthread_get_concurrency(int *val)
530 {
531         *val = _pthread_concur;
532         return 0;
533 }
534
535 static int pthread_set_concurrency(int val)
536 {
537         _pthread_concur = val;
538         return 0;
539 }
540
541 #define pthread_getschedparam(T, P, S) ENOTSUP
542 #define pthread_setschedparam(T, P, S) ENOTSUP
543 #define pthread_getcpuclockid(T, C) ENOTSUP
544
545 static int pthread_exit(void *res)
546 {
547         pthread_t t = pthread_self();
548
549         t->ret_arg = res;
550         
551         _pthread_cleanup_dest(t);
552         
553         longjmp(t->jb, 1);
554 }
555
556
557 static void _pthread_invoke_cancel(void)
558 {
559         _pthread_cleanup *pcup;
560         
561         _InterlockedDecrement(&_pthread_cancelling);
562         
563         /* Call cancel queue */
564         for (pcup = pthread_self()->clean; pcup; pcup = pcup->next)
565         {
566                 pcup->func(pcup->arg);
567         }
568                 
569         pthread_exit(PTHREAD_CANCELED);
570 }
571
572 static void pthread_testcancel(void)
573 {
574         if (_pthread_cancelling)
575         {
576                 pthread_t t = pthread_self();
577                 
578                 if (t->cancelled && (t->p_state & PTHREAD_CANCEL_ENABLE))
579                 {
580                         _pthread_invoke_cancel();
581                 }
582         }
583 }
584
585
586 static int pthread_cancel(pthread_t t)
587 {
588         if (t->p_state & PTHREAD_CANCEL_ASYNCHRONOUS)
589         {
590                 /* Dangerous asynchronous cancelling */
591                 CONTEXT ctxt;
592                 
593                 /* Already done? */
594                 if (t->cancelled) return ESRCH;
595                 
596                 ctxt.ContextFlags = CONTEXT_CONTROL;
597                 
598                 SuspendThread(t->h);
599                 GetThreadContext(t->h, &ctxt);
600 #ifdef _M_X64
601                 ctxt.Rip = (uintptr_t) _pthread_invoke_cancel;
602 #else
603                 ctxt.Eip = (uintptr_t) _pthread_invoke_cancel;
604 #endif
605                 SetThreadContext(t->h, &ctxt);
606                 
607                 /* Also try deferred Cancelling */
608                 t->cancelled = 1;
609         
610                 /* Notify everyone to look */
611                 _InterlockedIncrement(&_pthread_cancelling);
612                 
613                 ResumeThread(t->h);
614         }
615         else
616         {
617                 /* Safe deferred Cancelling */
618                 t->cancelled = 1;
619         
620                 /* Notify everyone to look */
621                 _InterlockedIncrement(&_pthread_cancelling);
622         }
623         
624         return 0;
625 }
626
627 static unsigned _pthread_get_state(pthread_attr_t *attr, unsigned flag)
628 {
629         return attr->p_state & flag;
630 }
631
632 static int _pthread_set_state(pthread_attr_t *attr, unsigned flag, unsigned val)
633 {
634         if (~flag & val) return EINVAL;
635         attr->p_state &= ~flag;
636         attr->p_state |= val;
637         
638         return 0;
639 }
640
641 static int pthread_attr_init(pthread_attr_t *attr)
642 {
643         attr->p_state = PTHREAD_DEFAULT_ATTR;
644         attr->stack = NULL;
645         attr->s_size = 0;
646         return 0;
647 }
648
649 static int pthread_attr_destroy(pthread_attr_t *attr)
650 {
651         /* No need to do anything */
652         return 0;
653 }
654
655
656 static int pthread_attr_setdetachstate(pthread_attr_t *a, int flag)
657 {
658         return _pthread_set_state(a, PTHREAD_CREATE_DETACHED, flag);
659 }
660
661 static int pthread_attr_getdetachstate(pthread_attr_t *a, int *flag)
662 {
663         *flag = _pthread_get_state(a, PTHREAD_CREATE_DETACHED);
664         return 0;
665 }
666
667 static int pthread_attr_setinheritsched(pthread_attr_t *a, int flag)
668 {
669         return _pthread_set_state(a, PTHREAD_INHERIT_SCHED, flag);
670 }
671
672 static int pthread_attr_getinheritsched(pthread_attr_t *a, int *flag)
673 {
674         *flag = _pthread_get_state(a, PTHREAD_INHERIT_SCHED);
675         return 0;
676 }
677
678 static int pthread_attr_setscope(pthread_attr_t *a, int flag)
679 {
680         return _pthread_set_state(a, PTHREAD_SCOPE_SYSTEM, flag);
681 }
682
683 static int pthread_attr_getscope(pthread_attr_t *a, int *flag)
684 {
685         *flag = _pthread_get_state(a, PTHREAD_SCOPE_SYSTEM);
686         return 0;
687 }
688
689 static int pthread_attr_getstackaddr(pthread_attr_t *attr, void **stack)
690 {
691         *stack = attr->stack;
692         return 0;
693 }
694
695 static int pthread_attr_setstackaddr(pthread_attr_t *attr, void *stack)
696 {
697         attr->stack = stack;
698         return 0;
699 }
700
701 static int pthread_attr_getstacksize(pthread_attr_t *attr, size_t *size)
702 {
703         *size = attr->s_size;
704         return 0;
705 }
706
707 static int pthread_attr_setstacksize(pthread_attr_t *attr, size_t size)
708 {
709         attr->s_size = size;
710         return 0;
711 }
712
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
719
720
721 static int pthread_setcancelstate(int state, int *oldstate)
722 {
723         pthread_t t = pthread_self();
724         
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;
728         t->p_state |= state;
729         
730         return 0;
731 }
732
733 static int pthread_setcanceltype(int type, int *oldtype)
734 {
735         pthread_t t = pthread_self();
736         
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;
740         t->p_state |= type;
741         
742         return 0;
743 }
744
745 static int __stdcall pthread_create_wrapper(void *args)
746 {
747         struct _pthread_v *tv = args;
748         
749         _pthread_once_raw(&_pthread_tls_once, pthread_tls_init);
750         
751         TlsSetValue(_pthread_tls, tv);
752                 
753         if (!setjmp(tv->jb))
754         {
755                 /* Call function and save return value */
756                 tv->ret_arg = tv->func(tv->ret_arg);
757                 
758                 /* Clean up destructors */
759                 _pthread_cleanup_dest(tv);
760         }
761         
762         /* If we exit too early, then we can race with create */
763         while (tv->h == (HANDLE) -1)
764         {
765                 YieldProcessor();
766                 _ReadWriteBarrier();
767         }
768         
769         /* Make sure we free ourselves if we are detached */
770         if (!tv->h) free(tv);
771         
772         return 0;
773 }
774
775 static int pthread_create(pthread_t *th, pthread_attr_t *attr, void *(* func)(void *), void *arg)
776 {
777         struct _pthread_v *tv = malloc(sizeof(struct _pthread_v));
778         unsigned ssize = 0;
779         
780         if (!tv) return 1;
781         
782         *th = tv;
783         
784         /* Save data in pthread_t */
785         tv->ret_arg = arg;
786         tv->func = func;
787         tv->clean = NULL;
788         tv->cancelled = 0;
789         tv->p_state = PTHREAD_DEFAULT_ATTR;
790         tv->keymax = 0;
791         tv->keyval = NULL;
792         tv->h = (HANDLE) -1;
793         
794         if (attr)
795         {
796                 tv->p_state = attr->p_state;
797                 ssize = (unsigned int)attr->s_size;
798         }
799         
800         /* Make sure tv->h has value of -1 */
801         _ReadWriteBarrier();
802
803         tv->h = (HANDLE) _beginthreadex(NULL, ssize, pthread_create_wrapper, tv, 0, NULL);
804         
805         /* Failed */
806         if (!tv->h) return 1;
807         
808         
809         if (tv->p_state & PTHREAD_CREATE_DETACHED)
810         {
811                 CloseHandle(tv->h);
812                 _ReadWriteBarrier();
813                 tv->h = 0;
814         }
815
816         return 0;
817 }
818
819 static int pthread_join(pthread_t t, void **res)
820 {
821         struct _pthread_v *tv = t;
822         
823         pthread_testcancel();
824         
825         WaitForSingleObject(tv->h, INFINITE);
826         CloseHandle(tv->h);
827         
828         /* Obtain return value */
829         if (res) *res = tv->ret_arg;
830         
831         free(tv);
832
833         return 0;
834 }
835
836 static int pthread_detach(pthread_t t)
837 {
838         struct _pthread_v *tv = t;
839         
840         /*
841          * This can't race with thread exit because
842          * our call would be undefined if called on a dead thread.
843          */
844         
845         CloseHandle(tv->h);
846         _ReadWriteBarrier();
847         tv->h = 0;
848         
849         return 0;
850 }
851
852 static int pthread_mutexattr_init(pthread_mutexattr_t *a)
853 {
854         *a = 0;
855         return 0;
856 }
857
858 static int pthread_mutexattr_destroy(pthread_mutexattr_t *a)
859 {
860         (void) a;
861         return 0;
862 }
863
864 static int pthread_mutexattr_gettype(pthread_mutexattr_t *a, int *type)
865 {
866         *type = *a & 3;
867
868         return 0;
869 }
870
871 static int pthread_mutexattr_settype(pthread_mutexattr_t *a, int type)
872 {
873         if ((unsigned) type > 3) return EINVAL;
874         *a &= ~3;
875         *a |= type;
876         
877         return 0;
878 }
879
880 static int pthread_mutexattr_getpshared(pthread_mutexattr_t *a, int *type)
881 {
882         *type = *a & 4;
883         
884         return 0;
885 }
886
887 static int pthread_mutexattr_setpshared(pthread_mutexattr_t * a, int type)
888 {
889         if ((type & 4) != type) return EINVAL;
890         
891         *a &= ~4;
892         *a |= type;
893         
894         return 0;
895 }
896
897 static int pthread_mutexattr_getprotocol(pthread_mutexattr_t *a, int *type)
898 {
899         *type = *a & (8 + 16);
900         
901         return 0;
902 }
903
904 static int pthread_mutexattr_setprotocol(pthread_mutexattr_t *a, int type)
905 {
906         if ((type & (8 + 16)) != 8 + 16) return EINVAL;
907         
908         *a &= ~(8 + 16);
909         *a |= type;
910         
911         return 0;
912 }
913
914 static int pthread_mutexattr_getprioceiling(pthread_mutexattr_t *a, int * prio)
915 {
916         *prio = *a / PTHREAD_PRIO_MULT;
917         return 0;
918 }
919
920 static int pthread_mutexattr_setprioceiling(pthread_mutexattr_t *a, int prio)
921 {
922         *a &= (PTHREAD_PRIO_MULT - 1);
923         *a += prio * PTHREAD_PRIO_MULT;
924         
925         return 0;
926 }
927
928 static int pthread_mutex_timedlock(pthread_mutex_t *m, struct timespec *ts)
929 {
930         unsigned long long t, ct;
931         
932         struct _pthread_crit_t
933         {
934                 void *debug;
935                 LONG count;
936                 LONG r_count;
937                 HANDLE owner;
938                 HANDLE sem;
939                 ULONG_PTR spin;
940         };
941         
942         /* Try to lock it without waiting */
943         if (!pthread_mutex_trylock(m)) return 0;
944         
945         ct = _pthread_time_in_ms();
946         t = _pthread_time_in_ms_from_timespec(ts);
947         
948         while (1)
949         {
950                 /* Have we waited long enough? */
951                 if (ct > t) return ETIMEDOUT;
952                 
953                 /* Wait on semaphore within critical section */
954                 WaitForSingleObject(((struct _pthread_crit_t *)m)->sem, (DWORD)(t - ct));
955                 
956                 /* Try to grab lock */
957                 if (!pthread_mutex_trylock(m)) return 0;
958                 
959                 /* Get current time */
960                 ct = _pthread_time_in_ms();
961         }
962 }
963
964 static int pthread_barrier_destroy(pthread_barrier_t *b)
965 {
966         DeleteCriticalSection(&b->m);
967         
968         return 0;
969
970 }
971
972 static int pthread_barrier_init(pthread_barrier_t *b, void *attr, int count)
973 {
974         /* Ignore attr */
975         (void) attr;
976         
977         InitializeCriticalSection(&b->m);
978         InitializeConditionVariable(&b->cv);
979         b->count = count;
980         b->total = 0;
981         
982         return 0;
983 }
984
985 #define _PTHREAD_BARRIER_FLAG (1<<30)
986 static int pthread_barrier_wait(pthread_barrier_t *b)
987 {
988         EnterCriticalSection(&b->m);
989         
990         while (b->total > _PTHREAD_BARRIER_FLAG)
991         {
992                 /* Wait until everyone exits the barrier */
993                 SleepConditionVariableCS(&b->cv, &b->m, INFINITE);
994         }
995         
996         /* Are we the first to enter? */
997         if (b->total == _PTHREAD_BARRIER_FLAG) b->total = 0;
998         
999         b->total++;
1000         
1001         if (b->total == b->count)
1002         {
1003                 b->total += _PTHREAD_BARRIER_FLAG - 1;
1004                 WakeAllConditionVariable(&b->cv);
1005                 
1006                 LeaveCriticalSection(&b->m);
1007                 
1008                 return 1;
1009         }
1010         else
1011         {
1012                 while (b->total < _PTHREAD_BARRIER_FLAG)
1013                 {
1014                         /* Wait until enough threads enter the barrier */
1015                         SleepConditionVariableCS(&b->cv, &b->m, INFINITE);
1016                 }
1017                 
1018                 b->total--;
1019                 
1020                 /* Get entering threads to wake up */
1021                 if (b->total == _PTHREAD_BARRIER_FLAG) WakeAllConditionVariable(&b->cv);
1022                 
1023                 LeaveCriticalSection(&b->m);
1024                 
1025                 return 0;
1026         }
1027 }
1028
1029 static int pthread_barrierattr_init(void **attr)
1030 {
1031         *attr = NULL;
1032         return 0;
1033 }
1034
1035 static int pthread_barrierattr_destroy(void **attr)
1036 {
1037         /* Ignore attr */
1038         (void) attr;
1039         
1040         return 0;
1041 }
1042
1043 static int pthread_barrierattr_setpshared(void **attr, int s)
1044 {
1045         *attr = (void *) s;
1046         return 0;
1047 }
1048
1049 static int pthread_barrierattr_getpshared(void **attr, int *s)
1050 {
1051         *s = (int) (size_t) *attr;
1052
1053         return 0;
1054 }
1055
1056 static int pthread_key_create(pthread_key_t *key, void (* dest)(void *))
1057 {
1058         unsigned int i;
1059         long nmax;
1060         void (**d)(void *);
1061
1062         if (!key) return EINVAL;
1063         
1064         pthread_rwlock_wrlock(&_pthread_key_lock);
1065         
1066         for (i = _pthread_key_sch; i < _pthread_key_max; i++)
1067         {
1068                 if (!_pthread_key_dest[i])
1069                 {
1070                         *key = i;
1071                         if (dest)
1072                         {
1073                                 _pthread_key_dest[i] = dest;
1074                         }
1075                         else
1076                         {
1077                                 _pthread_key_dest[i] = (void(*)(void *))1;
1078                         }
1079                         pthread_rwlock_unlock(&_pthread_key_lock);
1080                         
1081                         return 0;
1082                 }
1083         }
1084         
1085         for (i = 0; i < _pthread_key_sch; i++)
1086         {
1087                 if (!_pthread_key_dest[i])
1088                 {
1089                         *key = i;
1090                         if (dest)
1091                         {
1092                                 _pthread_key_dest[i] = dest;
1093                         }
1094                         else
1095                         {
1096                                 _pthread_key_dest[i] = (void(*)(void *))1;
1097                         }
1098                         pthread_rwlock_unlock(&_pthread_key_lock);
1099                         
1100                         return 0;
1101                 }
1102         }
1103         
1104         if (!_pthread_key_max) _pthread_key_max = 1;
1105         if (_pthread_key_max == PTHREAD_KEYS_MAX)
1106         {
1107                 pthread_rwlock_unlock(&_pthread_key_lock);
1108                 
1109                 return ENOMEM;
1110         }
1111         
1112         nmax = _pthread_key_max * 2;
1113         if (nmax > PTHREAD_KEYS_MAX) nmax = PTHREAD_KEYS_MAX;
1114         
1115         /* No spare room anywhere */
1116         d = realloc(_pthread_key_dest, nmax * sizeof(*d));
1117         if (!d)
1118         {
1119                 pthread_rwlock_unlock(&_pthread_key_lock);
1120                 
1121                 return ENOMEM;
1122         }
1123         
1124         /* Clear new region */
1125         memset((void *) &d[_pthread_key_max], 0, (nmax-_pthread_key_max)*sizeof(void *));
1126         
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;
1132         
1133         if (dest)
1134         {
1135                 _pthread_key_dest[*key] = dest;
1136         }
1137         else
1138         {
1139                 _pthread_key_dest[*key] = (void(*)(void *))1;
1140         }
1141
1142         pthread_rwlock_unlock(&_pthread_key_lock);
1143         
1144         return 0;
1145 }
1146
1147 static int pthread_key_delete(pthread_key_t key)
1148 {
1149         if (key > _pthread_key_max) return EINVAL;
1150         if (!_pthread_key_dest) return EINVAL;
1151         
1152         pthread_rwlock_wrlock(&_pthread_key_lock);
1153         _pthread_key_dest[key] = NULL;
1154         
1155         /* Start next search from our location */
1156         if (_pthread_key_sch > key) _pthread_key_sch = key;
1157         
1158         pthread_rwlock_unlock(&_pthread_key_lock);
1159         
1160         return 0;
1161 }
1162
1163 static void *pthread_getspecific(pthread_key_t key)
1164 {
1165         pthread_t t = pthread_self();
1166         
1167         if (key >= t->keymax) return NULL;
1168         
1169         return t->keyval[key];
1170
1171 }
1172
1173 static int pthread_setspecific(pthread_key_t key, const void *value)
1174 {
1175         pthread_t t = pthread_self();
1176
1177         if (key > t->keymax)
1178         {
1179                 int keymax = (key + 1) * 2;
1180                 void **kv = realloc(t->keyval, keymax * sizeof(void *));
1181                 
1182                 if (!kv) return ENOMEM;
1183                 
1184                 /* Clear new region */
1185                 memset(&kv[t->keymax], 0, (keymax - t->keymax)*sizeof(void*));
1186                 
1187                 t->keyval = kv;
1188                 t->keymax = keymax;
1189         }
1190         
1191         t->keyval[key] = (void *) value;
1192         
1193         return 0;
1194 }
1195
1196
1197 static int pthread_spin_init(pthread_spinlock_t *l, int pshared)
1198 {
1199         (void) pshared;
1200         
1201         *l = 0;
1202         return 0;
1203 }
1204
1205 static int pthread_spin_destroy(pthread_spinlock_t *l)
1206 {
1207         (void) l;
1208         return 0;
1209 }
1210
1211 /* No-fair spinlock due to lack of knowledge of thread number */
1212 static int pthread_spin_lock(pthread_spinlock_t *l)
1213 {
1214         while (_InterlockedExchange(l, EBUSY))
1215         {
1216                 /* Don't lock the bus whilst waiting */
1217                 while (*l)
1218                 {
1219                         YieldProcessor();
1220                         
1221                         /* Compiler barrier.  Prevent caching of *l */
1222                         _ReadWriteBarrier();
1223                 }
1224         }
1225         
1226         return 0;
1227 }
1228
1229 static int pthread_spin_trylock(pthread_spinlock_t *l)
1230 {
1231         return _InterlockedExchange(l, EBUSY);
1232 }
1233
1234 static int pthread_spin_unlock(pthread_spinlock_t *l)
1235 {
1236         /* Compiler barrier.  The store below acts with release symmantics */
1237         _ReadWriteBarrier();
1238         
1239         *l = 0;
1240         
1241         return 0;
1242 }
1243
1244 static int pthread_cond_init(pthread_cond_t *c, pthread_condattr_t *a)
1245 {
1246         (void) a;
1247         
1248         InitializeConditionVariable(c);
1249         return 0;
1250 }
1251
1252 static int pthread_cond_signal(pthread_cond_t *c)
1253 {
1254         WakeConditionVariable(c);
1255         return 0;
1256 }
1257
1258 static int pthread_cond_broadcast(pthread_cond_t *c)
1259 {
1260         WakeAllConditionVariable(c);
1261         return 0;
1262 }
1263
1264 static int pthread_cond_wait(pthread_cond_t *c, pthread_mutex_t *m)
1265 {
1266         pthread_testcancel();
1267         SleepConditionVariableCS(c, m, INFINITE);
1268         return 0;
1269 }
1270
1271 static int pthread_cond_destroy(pthread_cond_t *c)
1272 {
1273         (void) c;
1274         return 0;
1275 }
1276
1277 static int pthread_cond_timedwait(pthread_cond_t *c, pthread_mutex_t *m, struct timespec *t)
1278 {
1279         unsigned long long tm = _pthread_rel_time_in_ms(t);
1280         
1281         pthread_testcancel();
1282         
1283         if (!SleepConditionVariableCS(c, m, (DWORD) tm)) return ETIMEDOUT;
1284         
1285         /* We can have a spurious wakeup after the timeout */
1286         if (!_pthread_rel_time_in_ms(t)) return ETIMEDOUT;
1287         
1288         return 0;
1289 }
1290
1291 static int pthread_condattr_destroy(pthread_condattr_t *a)
1292 {
1293         (void) a;
1294         return 0;
1295 }
1296
1297 #define pthread_condattr_getclock(A, C) ENOTSUP
1298 #define pthread_condattr_setclock(A, C) ENOTSUP
1299
1300 static int pthread_condattr_init(pthread_condattr_t *a)
1301 {
1302         *a = 0;
1303         return 0;
1304 }
1305
1306 static int pthread_condattr_getpshared(pthread_condattr_t *a, int *s)
1307 {
1308         *s = *a;
1309         return 0;
1310 }
1311
1312 static int pthread_condattr_setpshared(pthread_condattr_t *a, int s)
1313 {
1314         *a = s;
1315         return 0;
1316 }
1317
1318 static int pthread_rwlockattr_destroy(pthread_rwlockattr_t *a)
1319 {
1320         (void) a;
1321         return 0;
1322 }
1323
1324 static int pthread_rwlockattr_init(pthread_rwlockattr_t *a)
1325 {
1326         *a = 0;
1327 }
1328
1329 static int pthread_rwlockattr_getpshared(pthread_rwlockattr_t *a, int *s)
1330 {
1331         *s = *a;
1332         return 0;
1333 }
1334
1335 static int pthread_rwlockattr_setpshared(pthread_rwlockattr_t *a, int s)
1336 {
1337         *a = s;
1338         return 0;
1339 }
1340
1341
1342 /* No fork() in windows - so ignore this */
1343 #define pthread_atfork(F1,F2,F3) 0
1344
1345 /* Windows has rudimentary signals support */
1346 #define pthread_kill(T, S) 0
1347 #define pthread_sigmask(H, S1, S2) 0
1348
1349
1350 /* Wrap cancellation points */
1351 //FIXME: removed wrappers, some of them caused compilation errors
1352
1353 #endif /* WIN_PTHREADS */