1 /*
2  * implement.h
3  *
4  * Definitions that don't need to be public.
5  *
6  * Keeps all the internals out of pthread.h
7  *
8  * --------------------------------------------------------------------------
9  *
10  *      Pthreads4w - POSIX Threads for Windows
11  *      Copyright 1998 John E. Bossom
12  *      Copyright 1999-2018, Pthreads4w contributors
13  *
14  *      Homepage: https://sourceforge.net/projects/pthreads4w/
15  *
16  *      The current list of contributors is contained
17  *      in the file CONTRIBUTORS included with the source
18  *      code distribution. The list can also be seen at the
19  *      following World Wide Web location:
20  *
21  *      https://sourceforge.net/p/pthreads4w/wiki/Contributors/
22  *
23  * Licensed under the Apache License, Version 2.0 (the "License");
24  * you may not use this file except in compliance with the License.
25  * You may obtain a copy of the License at
26  *
27  *     http://www.apache.org/licenses/LICENSE-2.0
28  *
29  * Unless required by applicable law or agreed to in writing, software
30  * distributed under the License is distributed on an "AS IS" BASIS,
31  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
32  * See the License for the specific language governing permissions and
33  * limitations under the License.
34  */
35 
36 #if !defined(_IMPLEMENT_H)
37 #define _IMPLEMENT_H
38 
39 #if !defined (__PTW32_CONFIG_H)
40 # error "config.h was not #included"
41 #endif
42 
43 #include <_ptw32.h>
44 
45 #if !defined(_WIN32_WINNT)
46 # define _WIN32_WINNT 0x0400
47 #endif
48 
49 #define WIN32_LEAN_AND_MEAN
50 
51 #include <windows.h>
52 #include <sys/types.h>
53 /*
54  * In case windows.h doesn't define it (e.g. WinCE perhaps)
55  */
56 #if defined(WINCE)
57 typedef VOID (APIENTRY *PAPCFUNC)(DWORD dwParam);
58 #endif
59 
60 /*
61  * Designed to allow error values to be set and retrieved in builds where
62  * MSCRT libraries are statically linked to DLLs.
63  *
64  * This does not handle the case where a static pthreads4w lib is linked
65  * to a static linked app. Compiling and linking pthreads.c with app.c
66  * as one does work with the right macros defined. See tests/Makefile
67  * for clues or just "cd tests && nmake clean VC-static".
68  */
69 #if ! defined(WINCE) && \
70     (( defined(__MINGW32__) && __MSVCRT_VERSION__ >= 0x0800 ) || \
71     ( defined(_MSC_VER) && _MSC_VER >= 1400 ))  /* MSVC8+ */
72 #  if defined(__MINGW32__)
73 __attribute__((unused))
74 #  endif
__ptw32_get_errno(void)75 static int __ptw32_get_errno(void) { int err = 0; _get_errno(&err); return err; }
76 #  define __PTW32_GET_ERRNO() __ptw32_get_errno()
77 #  if defined(__MINGW32__)
78 __attribute__((unused))
79 #  endif
__ptw32_set_errno(int err)80 static void __ptw32_set_errno(int err) { _set_errno(err); SetLastError(err); }
81 #    define __PTW32_SET_ERRNO(err) __ptw32_set_errno(err)
82 #else
83 #  define __PTW32_GET_ERRNO() (errno)
84 #  if defined(__MINGW32__)
85 __attribute__((unused))
86 #  endif
__ptw32_set_errno(int err)87 static void __ptw32_set_errno(int err) { errno = err; SetLastError(err); }
88 #    define __PTW32_SET_ERRNO(err) __ptw32_set_errno(err)
89 #endif
90 
91 #if !defined(malloc)
92 # include <malloc.h>
93 #endif
94 
95 #if defined(__PTW32_CLEANUP_C)
96 # include <setjmp.h>
97 #endif
98 
99 #if !defined(INT_MAX)
100 # include <limits.h>
101 #endif
102 
103 /* use local include files during development */
104 #include "semaphore.h"
105 #include "sched.h"
106 
107 /* MSVC 7.1 doesn't like complex #if expressions */
108 #define INLINE
109 #if defined (__PTW32_BUILD_INLINED)
110 #  if defined(HAVE_C_INLINE) || defined(__cplusplus)
111 #    undef INLINE
112 #    define INLINE inline
113 #  endif
114 #endif
115 
116 #if defined (__PTW32_CONFIG_MSVC6)
117 # define  __PTW32_INTERLOCKED_VOLATILE
118 #else
119 # define  __PTW32_INTERLOCKED_VOLATILE volatile
120 #endif
121 
122 #define  __PTW32_INTERLOCKED_LONG long
123 #define  __PTW32_INTERLOCKED_PVOID PVOID
124 #define  __PTW32_INTERLOCKED_LONGPTR  __PTW32_INTERLOCKED_VOLATILE long*
125 #define  __PTW32_INTERLOCKED_PVOID_PTR  __PTW32_INTERLOCKED_VOLATILE PVOID*
126 #if defined(_WIN64)
127 #  define  __PTW32_INTERLOCKED_SIZE LONGLONG
128 #  define  __PTW32_INTERLOCKED_SIZEPTR  __PTW32_INTERLOCKED_VOLATILE LONGLONG*
129 #else
130 #  define  __PTW32_INTERLOCKED_SIZE long
131 #  define  __PTW32_INTERLOCKED_SIZEPTR  __PTW32_INTERLOCKED_VOLATILE long*
132 #endif
133 
134 /*
135  * Don't allow the linker to optimize away dll.obj (dll.o) in static builds.
136  */
137 #if defined (__PTW32_STATIC_LIB) && defined (__PTW32_BUILD) && !defined (__PTW32_TEST_SNEAK_PEEK)
138 __PTW32_BEGIN_C_DECLS
139   void __ptw32_autostatic_anchor(void);
140 # if defined(__GNUC__)
141     __attribute__((unused, used))
142 # endif
143   static void (*local_autostatic_anchor)(void) = __ptw32_autostatic_anchor;
144 __PTW32_END_C_DECLS
145 #endif
146 
147 typedef enum
148 {
149   /*
150    * This enumeration represents the state of the thread;
151    * The thread is still valid if the numeric value of the
152    * state is greater or equal "PThreadStateRunning".
153    */
154   PThreadStateInitial = 0,	/* Thread not running                   */
155   PThreadStateReuse,            /* In reuse pool.                       */
156   PThreadStateRunning,		/* Thread alive & kicking               */
157   PThreadStateSuspended,	/* Thread alive but suspended           */
158   PThreadStateCancelPending,	/* Thread alive but                     */
159                                 /* has cancellation pending.            */
160   PThreadStateCanceling,	/* Thread alive but is                  */
161                                 /* in the process of terminating        */
162                                 /* due to a cancellation request        */
163   PThreadStateExiting,		/* Thread alive but exiting             */
164                                 /* due to an exception                  */
165   PThreadStateLast              /* All handlers have been run and now   */
166                                 /* final cleanup can be done.           */
167 }
168 PThreadState;
169 
170 typedef struct __ptw32_mcs_node_t_     __ptw32_mcs_local_node_t;
171 typedef struct __ptw32_mcs_node_t_*    __ptw32_mcs_lock_t;
172 typedef struct __ptw32_robust_node_t_  __ptw32_robust_node_t;
173 typedef struct __ptw32_thread_t_       __ptw32_thread_t;
174 
175 struct __ptw32_thread_t_
176 {
177   unsigned __int64 seqNumber;	/* Process-unique thread sequence number */
178   HANDLE threadH;		/* Win32 thread handle - POSIX thread is invalid if threadH == 0 */
179   pthread_t ptHandle;		/* This thread's permanent pthread_t handle */
180   __ptw32_thread_t * prevReuse;	/* Links threads on reuse stack */
181   volatile PThreadState state;
182   __ptw32_mcs_lock_t threadLock;	/* Used for serialised access to public thread state */
183   __ptw32_mcs_lock_t stateLock;	/* Used for async-cancel safety */
184   HANDLE cancelEvent;
185   void *exitStatus;
186   void *parms;
187   void *keys;
188   void *nextAssoc;
189 #if defined(__PTW32_CLEANUP_C)
190   jmp_buf start_mark;		/* Jump buffer follows void* so should be aligned */
191 #endif				/* __PTW32_CLEANUP_C */
192 #if defined(HAVE_SIGSET_T)
193   sigset_t sigmask;
194 #endif				/* HAVE_SIGSET_T */
195   __ptw32_mcs_lock_t
196               robustMxListLock; /* robustMxList lock */
197   __ptw32_robust_node_t*
198                   robustMxList; /* List of currenty held robust mutexes */
199   int ptErrno;
200   int detachState;
201   int sched_priority;		/* As set, not as currently is */
202   int cancelState;
203   int cancelType;
204   int implicit:1;
205   DWORD thread;			/* Windows thread ID */
206 #if defined(HAVE_CPU_AFFINITY)
207   size_t cpuset;		/* Thread CPU affinity set */
208 #endif
209   char * name;                  /* Thread name */
210 #if defined(_UWIN)
211   DWORD dummy[5];
212 #endif
213   size_t align;			/* Force alignment if this struct is packed */
214 };
215 
216 
217 /*
218  * Special value to mark attribute objects as valid.
219  */
220 #define  __PTW32_ATTR_VALID ((unsigned long) 0xC4C0FFEE)
221 
222 struct pthread_attr_t_
223 {
224   unsigned long valid;
225   void *stackaddr;
226   size_t stacksize;
227   int detachstate;
228   struct sched_param param;
229   int inheritsched;
230   int contentionscope;
231   size_t cpuset;
232   char * thrname;
233 #if defined(HAVE_SIGSET_T)
234   sigset_t sigmask;
235 #endif				/* HAVE_SIGSET_T */
236 };
237 
238 
239 /*
240  * ====================
241  * ====================
242  * Semaphores, Mutexes and Condition Variables
243  * ====================
244  * ====================
245  */
246 
247 struct sem_t_
248 {
249   int value;
250   __ptw32_mcs_lock_t lock;
251   HANDLE sem;
252 #if defined(NEED_SEM)
253   int leftToUnblock;
254 #endif
255 };
256 
257 #define  __PTW32_OBJECT_AUTO_INIT ((void *)(size_t) -1)
258 #define  __PTW32_OBJECT_INVALID   NULL
259 
260 struct pthread_mutex_t_
261 {
262   LONG lock_idx;		/* Provides exclusive access to mutex state
263 				   via the Interlocked* mechanism.
264 				    0: unlocked/free.
265 				    1: locked - no other waiters.
266 				   -1: locked - with possible other waiters.
267 				*/
268   int recursive_count;		/* Number of unlocks a thread needs to perform
269 				   before the lock is released (recursive
270 				   mutexes only). */
271   int kind;			/* Mutex type. */
272   pthread_t ownerThread;
273   HANDLE event;			/* Mutex release notification to waiting
274 				   threads. */
275   __ptw32_robust_node_t*
276                     robustNode; /* Extra state for robust mutexes  */
277 };
278 
279 enum __ptw32_robust_state_t_
280 {
281    __PTW32_ROBUST_CONSISTENT,
282    __PTW32_ROBUST_INCONSISTENT,
283    __PTW32_ROBUST_NOTRECOVERABLE
284 };
285 
286 typedef enum __ptw32_robust_state_t_   __ptw32_robust_state_t;
287 
288 /*
289  * Node used to manage per-thread lists of currently-held robust mutexes.
290  */
291 struct __ptw32_robust_node_t_
292 {
293   pthread_mutex_t mx;
294   __ptw32_robust_state_t stateInconsistent;
295   __ptw32_robust_node_t* prev;
296   __ptw32_robust_node_t* next;
297 };
298 
299 struct pthread_mutexattr_t_
300 {
301   int pshared;
302   int kind;
303   int robustness;
304 };
305 
306 /*
307  * Possible values, other than  __PTW32_OBJECT_INVALID,
308  * for the "interlock" element in a spinlock.
309  *
310  * In this implementation, when a spinlock is initialised,
311  * the number of cpus available to the process is checked.
312  * If there is only one cpu then "interlock" is set equal to
313  *  __PTW32_SPIN_USE_MUTEX and u.mutex is an initialised mutex.
314  * If the number of cpus is greater than 1 then "interlock"
315  * is set equal to  __PTW32_SPIN_UNLOCKED and the number is
316  * stored in u.cpus. This arrangement allows the spinlock
317  * routines to attempt an InterlockedCompareExchange on "interlock"
318  * immediately and, if that fails, to try the inferior mutex.
319  *
320  * "u.cpus" isn't used for anything yet, but could be used at
321  * some point to optimise spinlock behaviour.
322  */
323 #define  __PTW32_SPIN_INVALID     (0)
324 #define  __PTW32_SPIN_UNLOCKED    (1)
325 #define  __PTW32_SPIN_LOCKED      (2)
326 #define  __PTW32_SPIN_USE_MUTEX   (3)
327 
328 struct pthread_spinlock_t_
329 {
330   long interlock;		/* Locking element for multi-cpus. */
331   union
332   {
333     int cpus;			/* No. of cpus if multi cpus, or   */
334     pthread_mutex_t mutex;	/* mutex if single cpu.            */
335   } u;
336 };
337 
338 /*
339  * MCS lock queue node - see ptw32_MCS_lock.c
340  */
341 struct __ptw32_mcs_node_t_
342 {
343   struct __ptw32_mcs_node_t_ **lock;        /* ptr to tail of queue */
344   struct __ptw32_mcs_node_t_  *next;        /* ptr to successor in queue */
345   HANDLE                     readyFlag;   /* set after lock is released by
346                                              predecessor */
347   HANDLE                     nextFlag;    /* set after 'next' ptr is set by
348                                              successor */
349 };
350 
351 
352 struct pthread_barrier_t_
353 {
354   unsigned int nCurrentBarrierHeight;
355   unsigned int nInitialBarrierHeight;
356   int pshared;
357   sem_t semBarrierBreeched;
358   __ptw32_mcs_lock_t lock;
359   __ptw32_mcs_local_node_t proxynode;
360 };
361 
362 struct pthread_barrierattr_t_
363 {
364   int pshared;
365 };
366 
367 struct pthread_key_t_
368 {
369   DWORD key;
370   void  (__PTW32_CDECL *destructor) (void *);
371   __ptw32_mcs_lock_t keyLock;
372   void *threads;
373 };
374 
375 
376 typedef struct ThreadParms ThreadParms;
377 
378 struct ThreadParms
379 {
380   pthread_t tid;
381   void * (__PTW32_CDECL *start) (void *);
382   void *arg;
383 };
384 
385 
386 struct pthread_cond_t_
387 {
388   long nWaitersBlocked;		/* Number of threads blocked            */
389   long nWaitersGone;		/* Number of threads timed out          */
390   long nWaitersToUnblock;	/* Number of threads to unblock         */
391   sem_t semBlockQueue;		/* Queue up threads waiting for the     */
392   /*   condition to become signalled      */
393   sem_t semBlockLock;		/* Semaphore that guards access to      */
394   /* | waiters blocked count/block queue  */
395   /* +-> Mandatory Sync.LEVEL-1           */
396   pthread_mutex_t mtxUnblockLock;	/* Mutex that guards access to          */
397   /* | waiters (to)unblock(ed) counts     */
398   /* +-> Optional* Sync.LEVEL-2           */
399   pthread_cond_t next;		/* Doubly linked list                   */
400   pthread_cond_t prev;
401 };
402 
403 
404 struct pthread_condattr_t_
405 {
406   int pshared;
407 };
408 
409 #define  __PTW32_RWLOCK_MAGIC 0xfacade2
410 
411 struct pthread_rwlock_t_
412 {
413   pthread_mutex_t mtxExclusiveAccess;
414   pthread_mutex_t mtxSharedAccessCompleted;
415   pthread_cond_t cndSharedAccessCompleted;
416   int nSharedAccessCount;
417   int nExclusiveAccessCount;
418   int nCompletedSharedAccessCount;
419   int nMagic;
420 };
421 
422 struct pthread_rwlockattr_t_
423 {
424   int pshared;
425 };
426 
427 typedef union
428 {
429   char cpuset[CPU_SETSIZE/8];
430   size_t _cpuset;
431 } _sched_cpu_set_vector_;
432 
433 typedef struct ThreadKeyAssoc ThreadKeyAssoc;
434 
435 struct ThreadKeyAssoc
436 {
437   /*
438    * Purpose:
439    *      This structure creates an association between a thread and a key.
440    *      It is used to implement the implicit invocation of a user defined
441    *      destroy routine for thread specific data registered by a user upon
442    *      exiting a thread.
443    *
444    *      Graphically, the arrangement is as follows, where:
445    *
446    *         K - Key with destructor
447    *            (head of chain is key->threads)
448    *         T - Thread that has called pthread_setspecific(Kn)
449    *            (head of chain is thread->keys)
450    *         A - Association. Each association is a node at the
451    *             intersection of two doubly-linked lists.
452    *
453    *                 T1    T2    T3
454    *                 |     |     |
455    *                 |     |     |
456    *         K1 -----+-----A-----A----->
457    *                 |     |     |
458    *                 |     |     |
459    *         K2 -----A-----A-----+----->
460    *                 |     |     |
461    *                 |     |     |
462    *         K3 -----A-----+-----A----->
463    *                 |     |     |
464    *                 |     |     |
465    *                 V     V     V
466    *
467    *      Access to the association is guarded by two locks: the key's
468    *      general lock (guarding the row) and the thread's general
469    *      lock (guarding the column). This avoids the need for a
470    *      dedicated lock for each association, which not only consumes
471    *      more handles but requires that the lock resources persist
472    *      until both the key is deleted and the thread has called the
473    *      destructor. The two-lock arrangement allows those resources
474    *      to be freed as soon as either thread or key is concluded.
475    *
476    *      To avoid deadlock, whenever both locks are required both the
477    *      key and thread locks are acquired consistently in the order
478    *      "key lock then thread lock". An exception to this exists
479    *      when a thread calls the destructors, however, this is done
480    *      carefully (but inelegantly) to avoid deadlock.
481    *
482    *      An association is created when a thread first calls
483    *      pthread_setspecific() on a key that has a specified
484    *      destructor.
485    *
486    *      An association is destroyed either immediately after the
487    *      thread calls the key destructor function on thread exit, or
488    *      when the key is deleted.
489    *
490    * Attributes:
491    *      thread
492    *              reference to the thread that owns the
493    *              association. This is actually the pointer to the
494    *              thread struct itself. Since the association is
495    *              destroyed before the thread exits, this can never
496    *              point to a different logical thread to the one that
497    *              created the assoc, i.e. after thread struct reuse.
498    *
499    *      key
500    *              reference to the key that owns the association.
501    *
502    *      nextKey
503    *              The pthread_t->keys attribute is the head of a
504    *              chain of associations that runs through the nextKey
505    *              link. This chain provides the 1 to many relationship
506    *              between a pthread_t and all pthread_key_t on which
507    *              it called pthread_setspecific.
508    *
509    *      prevKey
510    *              Similarly.
511    *
512    *      nextThread
513    *              The pthread_key_t->threads attribute is the head of
514    *              a chain of associations that runs through the
515    *              nextThreads link. This chain provides the 1 to many
516    *              relationship between a pthread_key_t and all the
517    *              PThreads that have called pthread_setspecific for
518    *              this pthread_key_t.
519    *
520    *      prevThread
521    *              Similarly.
522    *
523    * Notes:
524    *      1)      As soon as either the key or the thread is no longer
525    *              referencing the association, it can be destroyed. The
526    *              association will be removed from both chains.
527    *
528    *      2)      Under WIN32, an association is only created by
529    *              pthread_setspecific if the user provided a
530    *              destroyRoutine when they created the key.
531    *
532    *
533    */
534   __ptw32_thread_t * thread;
535   pthread_key_t key;
536   ThreadKeyAssoc *nextKey;
537   ThreadKeyAssoc *nextThread;
538   ThreadKeyAssoc *prevKey;
539   ThreadKeyAssoc *prevThread;
540 };
541 
542 
543 #if defined(__PTW32_CLEANUP_SEH)
544 /*
545  * --------------------------------------------------------------
546  * MAKE_SOFTWARE_EXCEPTION
547  *      This macro constructs a software exception code following
548  *      the same format as the standard Win32 error codes as defined
549  *      in WINERROR.H
550  *  Values are 32 bit values laid out as follows:
551  *
552  *   1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
553  *  +---+-+-+-----------------------+-------------------------------+
554  *  |Sev|C|R|     Facility          |               Code            |
555  *  +---+-+-+-----------------------+-------------------------------+
556  *
557  * Severity Values:
558  */
559 #define SE_SUCCESS              0x00
560 #define SE_INFORMATION          0x01
561 #define SE_WARNING              0x02
562 #define SE_ERROR                0x03
563 
564 #define MAKE_SOFTWARE_EXCEPTION( _severity, _facility, _exception ) \
565 ( (DWORD) ( ( (_severity) << 30 ) |     /* Severity code        */ \
566             ( 1 << 29 ) |               /* MS=0, User=1         */ \
567             ( 0 << 28 ) |               /* Reserved             */ \
568             ( (_facility) << 16 ) |     /* Facility Code        */ \
569             ( (_exception) <<  0 )      /* Exception Code       */ \
570             ) )
571 
572 /*
573  * We choose one specific Facility/Error code combination to
574  * identify our software exceptions vs. WIN32 exceptions.
575  * We store our actual component and error code within
576  * the optional information array.
577  */
578 #define EXCEPTION_PTW32_SERVICES        \
579      MAKE_SOFTWARE_EXCEPTION( SE_ERROR, \
580                                __PTW32_SERVICES_FACILITY, \
581                                __PTW32_SERVICES_ERROR )
582 
583 #define  __PTW32_SERVICES_FACILITY         0xBAD
584 #define  __PTW32_SERVICES_ERROR            0xDEED
585 
586 #endif /* __PTW32_CLEANUP_SEH */
587 
588 /*
589  * Services available through EXCEPTION_PTW32_SERVICES
590  * and also used [as parameters to __ptw32_throw()] as
591  * generic exception selectors.
592  */
593 
594 #define  __PTW32_EPS_EXIT                  (1)
595 #define  __PTW32_EPS_CANCEL                (2)
596 
597 
598 /* Useful macros */
599 #define  __PTW32_MAX(a,b)  ((a)<(b)?(b):(a))
600 #define  __PTW32_MIN(a,b)  ((a)>(b)?(b):(a))
601 
602 
603 /* Declared in pthread_cancel.c */
604 extern DWORD (*__ptw32_register_cancellation) (PAPCFUNC, HANDLE, DWORD);
605 
606 /* Thread Reuse stack bottom marker. Must not be NULL or any valid pointer to memory. */
607 #define  __PTW32_THREAD_REUSE_EMPTY ((__ptw32_thread_t *)(size_t) 1)
608 
609 extern int __ptw32_processInitialized;
610 extern __ptw32_thread_t * __ptw32_threadReuseTop;
611 extern __ptw32_thread_t * __ptw32_threadReuseBottom;
612 extern pthread_key_t __ptw32_selfThreadKey;
613 extern pthread_key_t __ptw32_cleanupKey;
614 extern pthread_cond_t __ptw32_cond_list_head;
615 extern pthread_cond_t __ptw32_cond_list_tail;
616 
617 extern int __ptw32_mutex_default_kind;
618 
619 extern unsigned __int64 __ptw32_threadSeqNumber;
620 
621 extern int __ptw32_concurrency;
622 
623 extern int __ptw32_features;
624 
625 extern __ptw32_mcs_lock_t __ptw32_thread_reuse_lock;
626 extern __ptw32_mcs_lock_t __ptw32_mutex_test_init_lock;
627 extern __ptw32_mcs_lock_t __ptw32_cond_list_lock;
628 extern __ptw32_mcs_lock_t __ptw32_cond_test_init_lock;
629 extern __ptw32_mcs_lock_t __ptw32_rwlock_test_init_lock;
630 extern __ptw32_mcs_lock_t __ptw32_spinlock_test_init_lock;
631 
632 #if defined(_UWIN)
633 extern int pthread_count;
634 #endif
635 
636 __PTW32_BEGIN_C_DECLS
637 
638 /*
639  * =====================
640  * =====================
641  * Forward Declarations
642  * =====================
643  * =====================
644  */
645 
646   int __ptw32_is_attr (const pthread_attr_t * attr);
647 
648   int __ptw32_cond_check_need_init (pthread_cond_t * cond);
649   int __ptw32_mutex_check_need_init (pthread_mutex_t * mutex);
650   int __ptw32_rwlock_check_need_init (pthread_rwlock_t * rwlock);
651   int __ptw32_spinlock_check_need_init (pthread_spinlock_t * lock);
652 
653   int __ptw32_robust_mutex_inherit(pthread_mutex_t * mutex);
654   void __ptw32_robust_mutex_add(pthread_mutex_t* mutex, pthread_t self);
655   void __ptw32_robust_mutex_remove(pthread_mutex_t* mutex, __ptw32_thread_t* otp);
656 
657   DWORD
658     __ptw32_Registercancellation (PAPCFUNC callback,
659 			       HANDLE threadH, DWORD callback_arg);
660 
661   int __ptw32_processInitialize (void);
662 
663   void __ptw32_processTerminate (void);
664 
665   void __ptw32_threadDestroy (pthread_t tid);
666 
667   void __ptw32_pop_cleanup_all (int execute);
668 
669   pthread_t __ptw32_new (void);
670 
671   pthread_t __ptw32_threadReusePop (void);
672 
673   void __ptw32_threadReusePush (pthread_t thread);
674 
675   int __ptw32_getprocessors (int *count);
676 
677   int __ptw32_setthreadpriority (pthread_t thread, int policy, int priority);
678 
679   void __ptw32_rwlock_cancelwrwait (void *arg);
680 
681 #if ! defined (__MINGW32__) || (defined (__MSVCRT__) && ! defined (__DMC__))
682   unsigned __stdcall
683 #else
684   void
685 #endif
686     __ptw32_threadStart (void *vthreadParms);
687 
688   void __ptw32_callUserDestroyRoutines (pthread_t thread);
689 
690   int __ptw32_tkAssocCreate (__ptw32_thread_t * thread, pthread_key_t key);
691 
692   void __ptw32_tkAssocDestroy (ThreadKeyAssoc * assoc);
693 
694   int __ptw32_semwait (sem_t * sem);
695 
696   DWORD __ptw32_relmillisecs (const struct timespec * abstime);
697 
698   void __ptw32_mcs_lock_acquire (__ptw32_mcs_lock_t * lock, __ptw32_mcs_local_node_t * node);
699 
700   int __ptw32_mcs_lock_try_acquire (__ptw32_mcs_lock_t * lock, __ptw32_mcs_local_node_t * node);
701 
702   void __ptw32_mcs_lock_release (__ptw32_mcs_local_node_t * node);
703 
704   void __ptw32_mcs_node_transfer (__ptw32_mcs_local_node_t * new_node, __ptw32_mcs_local_node_t * old_node);
705 
706   void __ptw32_timespec_to_filetime (const struct timespec *ts, FILETIME * ft);
707 
708   void __ptw32_filetime_to_timespec (const FILETIME * ft, struct timespec *ts);
709 
710 /* Declared in pthw32_calloc.c */
711 #if defined(NEED_CALLOC)
712 #define calloc(n, s) __ptw32_calloc(n, s)
713   void *__ptw32_calloc (size_t n, size_t s);
714 #endif
715 
716 /* Declared in ptw32_throw.c */
717 void __ptw32_throw (DWORD exception);
718 
719 __PTW32_END_C_DECLS
720 
721 #if defined(_UWIN_)
722 #   if defined(_MT)
723 
724 __PTW32_BEGIN_C_DECLS
725 
726   _CRTIMP unsigned long __cdecl _beginthread (void (__cdecl *) (void *),
727 					      unsigned, void *);
728   _CRTIMP void __cdecl _endthread (void);
729   _CRTIMP unsigned long __cdecl _beginthreadex (void *, unsigned,
730 						unsigned (__stdcall *) (void *),
731 						void *, unsigned, unsigned *);
732   _CRTIMP void __cdecl _endthreadex (unsigned);
733 
734 __PTW32_END_C_DECLS
735 
736 #   endif
737 #else
738 #   if ! defined(WINCE)
739 #     include <process.h>
740 #   endif
741 #endif
742 
743 
744 /*
745  * Use intrinsic versions wherever possible. VC will do this
746  * automatically where possible and GCC define these if available:
747  * __GCC_HAVE_SYNC_COMPARE_AND_SWAP_1
748  * __GCC_HAVE_SYNC_COMPARE_AND_SWAP_2
749  * __GCC_HAVE_SYNC_COMPARE_AND_SWAP_4
750  * __GCC_HAVE_SYNC_COMPARE_AND_SWAP_8
751  * __GCC_HAVE_SYNC_COMPARE_AND_SWAP_16
752  *
753  * The full set of Interlocked intrinsics in GCC are (check versions):
754  * type __sync_fetch_and_add (type *ptr, type value, ...)
755  * type __sync_fetch_and_sub (type *ptr, type value, ...)
756  * type __sync_fetch_and_or (type *ptr, type value, ...)
757  * type __sync_fetch_and_and (type *ptr, type value, ...)
758  * type __sync_fetch_and_xor (type *ptr, type value, ...)
759  * type __sync_fetch_and_nand (type *ptr, type value, ...)
760  * type __sync_add_and_fetch (type *ptr, type value, ...)
761  * type __sync_sub_and_fetch (type *ptr, type value, ...)
762  * type __sync_or_and_fetch (type *ptr, type value, ...)
763  * type __sync_and_and_fetch (type *ptr, type value, ...)
764  * type __sync_xor_and_fetch (type *ptr, type value, ...)
765  * type __sync_nand_and_fetch (type *ptr, type value, ...)
766  * bool __sync_bool_compare_and_swap (type *ptr, type oldval type newval, ...)
767  * type __sync_val_compare_and_swap (type *ptr, type oldval type newval, ...)
768  * __sync_synchronize (...) // Full memory barrier
769  * type __sync_lock_test_and_set (type *ptr, type value, ...) // Acquire barrier
770  * void __sync_lock_release (type *ptr, ...) // Release barrier
771  *
772  * These are all overloaded and take 1,2,4,8 byte scalar or pointer types.
773  *
774  * The above aren't available in Mingw32 as of gcc 4.5.2 so define our own.
775  */
776 #if defined(__cplusplus)
777 # define  __PTW32_TO_VLONG64PTR(ptr) reinterpret_cast<volatile LONG64 *>(ptr)
778 #else
779 # define  __PTW32_TO_VLONG64PTR(ptr) (ptr)
780 #endif
781 
782 #if defined(__GNUC__)
783 # if defined(_WIN64)
784 # define  __PTW32_INTERLOCKED_COMPARE_EXCHANGE_64(location, value, comparand) \
785     ({                                                                     \
786       __typeof (value) _result;                                            \
787       __asm__ __volatile__                                                 \
788       (                                                                    \
789         "lock\n\t"                                                         \
790         "cmpxchgq      %2,(%1)"                                            \
791         :"=a" (_result)                                                    \
792         :"r"  (location), "r" (value), "a" (comparand)                     \
793         :"memory", "cc");                                                  \
794       _result;                                                             \
795     })
796 # define  __PTW32_INTERLOCKED_EXCHANGE_64(location, value)                    \
797     ({                                                                     \
798       __typeof (value) _result;                                            \
799       __asm__ __volatile__                                                 \
800       (                                                                    \
801         "xchgq	 %0,(%1)"                                                  \
802         :"=r" (_result)                                                    \
803         :"r" (location), "0" (value)                                       \
804         :"memory", "cc");                                                  \
805       _result;                                                             \
806     })
807 # define  __PTW32_INTERLOCKED_EXCHANGE_ADD_64(location, value)                \
808     ({                                                                     \
809       __typeof (value) _result;                                            \
810       __asm__ __volatile__                                                 \
811       (                                                                    \
812         "lock\n\t"                                                         \
813         "xaddq	 %0,(%1)"                                                  \
814         :"=r" (_result)                                                    \
815         :"r" (location), "0" (value)                                       \
816         :"memory", "cc");                                                  \
817       _result;                                                             \
818     })
819 # define  __PTW32_INTERLOCKED_INCREMENT_64(location)                          \
820     ({                                                                     \
821        __PTW32_INTERLOCKED_LONG _temp = 1;                                    \
822       __asm__ __volatile__                                                 \
823       (                                                                    \
824         "lock\n\t"                                                         \
825         "xaddq	 %0,(%1)"                                                  \
826         :"+r" (_temp)                                                      \
827         :"r" (location)                                                    \
828         :"memory", "cc");                                                  \
829       ++_temp;                                                             \
830     })
831 # define  __PTW32_INTERLOCKED_DECREMENT_64(location)                          \
832     ({                                                                     \
833        __PTW32_INTERLOCKED_LONG _temp = -1;                                   \
834       __asm__ __volatile__                                                 \
835       (                                                                    \
836         "lock\n\t"                                                         \
837         "xaddq	 %2,(%1)"                                                  \
838         :"+r" (_temp)                                                      \
839         :"r" (location)                                                    \
840         :"memory", "cc");                                                  \
841       --_temp;                                                             \
842     })
843 #endif
844 # define  __PTW32_INTERLOCKED_COMPARE_EXCHANGE_LONG(location, value, comparand) \
845     ({                                                                     \
846       __typeof (value) _result;                                            \
847       __asm__ __volatile__                                                 \
848       (                                                                    \
849         "lock\n\t"                                                         \
850         "cmpxchgl       %2,(%1)"                                           \
851         :"=a" (_result)                                                    \
852         :"r"  (location), "r" (value), "a" (comparand)                     \
853         :"memory", "cc");                                                  \
854       _result;                                                             \
855     })
856 # define  __PTW32_INTERLOCKED_EXCHANGE_LONG(location, value)                  \
857     ({                                                                     \
858       __typeof (value) _result;                                            \
859       __asm__ __volatile__                                                 \
860       (                                                                    \
861         "xchgl	 %0,(%1)"                                                  \
862         :"=r" (_result)                                                    \
863         :"r" (location), "0" (value)                                       \
864         :"memory", "cc");                                                  \
865       _result;                                                             \
866     })
867 # define  __PTW32_INTERLOCKED_EXCHANGE_ADD_LONG(location, value)              \
868     ({                                                                     \
869       __typeof (value) _result;                                            \
870       __asm__ __volatile__                                                 \
871       (                                                                    \
872         "lock\n\t"                                                         \
873         "xaddl	 %0,(%1)"                                                  \
874         :"=r" (_result)                                                    \
875         :"r" (location), "0" (value)                                       \
876         :"memory", "cc");                                                  \
877       _result;                                                             \
878     })
879 # define  __PTW32_INTERLOCKED_INCREMENT_LONG(location)                        \
880     ({                                                                     \
881        __PTW32_INTERLOCKED_LONG _temp = 1;                                    \
882       __asm__ __volatile__                                                 \
883       (                                                                    \
884         "lock\n\t"                                                         \
885         "xaddl	 %0,(%1)"                                                  \
886         :"+r" (_temp)                                                      \
887         :"r" (location)                                                    \
888         :"memory", "cc");                                                  \
889       ++_temp;                                                             \
890     })
891 # define  __PTW32_INTERLOCKED_DECREMENT_LONG(location)                        \
892     ({                                                                     \
893        __PTW32_INTERLOCKED_LONG _temp = -1;                                   \
894       __asm__ __volatile__                                                 \
895       (                                                                    \
896         "lock\n\t"                                                         \
897         "xaddl	 %0,(%1)"                                                  \
898         :"+r" (_temp)                                                      \
899         :"r" (location)                                                    \
900         :"memory", "cc");                                                  \
901       --_temp;                                                             \
902     })
903 # define  __PTW32_INTERLOCKED_COMPARE_EXCHANGE_PTR(location, value, comparand) \
904      __PTW32_INTERLOCKED_COMPARE_EXCHANGE_SIZE ((__PTW32_INTERLOCKED_SIZEPTR)location, \
905                                              (__PTW32_INTERLOCKED_SIZE)value, \
906                                              (__PTW32_INTERLOCKED_SIZE)comparand)
907 # define  __PTW32_INTERLOCKED_EXCHANGE_PTR(location, value) \
908      __PTW32_INTERLOCKED_EXCHANGE_SIZE ((__PTW32_INTERLOCKED_SIZEPTR)location, \
909                                      (__PTW32_INTERLOCKED_SIZE)value)
910 #else
911 # if defined(_WIN64)
912 #   define  __PTW32_INTERLOCKED_COMPARE_EXCHANGE_64(p,v,c) InterlockedCompareExchange64 (__PTW32_TO_VLONG64PTR(p),(v),(c))
913 #   define  __PTW32_INTERLOCKED_EXCHANGE_64(p,v) InterlockedExchange64 (__PTW32_TO_VLONG64PTR(p),(v))
914 #   define  __PTW32_INTERLOCKED_EXCHANGE_ADD_64(p,v) InterlockedExchangeAdd64 (__PTW32_TO_VLONG64PTR(p),(v))
915 #   define  __PTW32_INTERLOCKED_INCREMENT_64(p) InterlockedIncrement64 (__PTW32_TO_VLONG64PTR(p))
916 #   define  __PTW32_INTERLOCKED_DECREMENT_64(p) InterlockedDecrement64 (__PTW32_TO_VLONG64PTR(p))
917 # endif
918 # if defined (__PTW32_CONFIG_MSVC6) && !defined(_WIN64)
919 #  define  __PTW32_INTERLOCKED_COMPARE_EXCHANGE_LONG(location, value, comparand) \
920       ((LONG)InterlockedCompareExchange((PVOID *)(location), (PVOID)(value), (PVOID)(comparand)))
921 # else
922 #  define  __PTW32_INTERLOCKED_COMPARE_EXCHANGE_LONG InterlockedCompareExchange
923 # endif
924 # define  __PTW32_INTERLOCKED_EXCHANGE_LONG(p,v) InterlockedExchange((p),(v))
925 # define  __PTW32_INTERLOCKED_EXCHANGE_ADD_LONG(p,v) InterlockedExchangeAdd((p),(v))
926 # define  __PTW32_INTERLOCKED_INCREMENT_LONG(p) InterlockedIncrement((p))
927 # define  __PTW32_INTERLOCKED_DECREMENT_LONG(p) InterlockedDecrement((p))
928 # if defined (__PTW32_CONFIG_MSVC6) && !defined(_WIN64)
929 #  define  __PTW32_INTERLOCKED_COMPARE_EXCHANGE_PTR InterlockedCompareExchange
930 #  define  __PTW32_INTERLOCKED_EXCHANGE_PTR(location, value) \
931     ((PVOID)InterlockedExchange((LPLONG)(location), (LONG)(value)))
932 # else
933 #  define  __PTW32_INTERLOCKED_COMPARE_EXCHANGE_PTR(p,v,c) InterlockedCompareExchangePointer((p),(v),(c))
934 #  define  __PTW32_INTERLOCKED_EXCHANGE_PTR(p,v) InterlockedExchangePointer((p),(v))
935 # endif
936 #endif
937 #if defined(_WIN64)
938 #   define  __PTW32_INTERLOCKED_COMPARE_EXCHANGE_SIZE(p,v,c)  __PTW32_INTERLOCKED_COMPARE_EXCHANGE_64 (__PTW32_TO_VLONG64PTR(p),(v),(c))
939 #   define  __PTW32_INTERLOCKED_EXCHANGE_SIZE(p,v)  __PTW32_INTERLOCKED_EXCHANGE_64 (__PTW32_TO_VLONG64PTR(p),(v))
940 #   define  __PTW32_INTERLOCKED_EXCHANGE_ADD_SIZE(p,v)  __PTW32_INTERLOCKED_EXCHANGE_ADD_64 (__PTW32_TO_VLONG64PTR(p),(v))
941 #   define  __PTW32_INTERLOCKED_INCREMENT_SIZE(p)  __PTW32_INTERLOCKED_INCREMENT_64 (__PTW32_TO_VLONG64PTR(p))
942 #   define  __PTW32_INTERLOCKED_DECREMENT_SIZE(p)  __PTW32_INTERLOCKED_DECREMENT_64 (__PTW32_TO_VLONG64PTR(p))
943 #else
944 #   define  __PTW32_INTERLOCKED_COMPARE_EXCHANGE_SIZE(p,v,c)  __PTW32_INTERLOCKED_COMPARE_EXCHANGE_LONG((p),(v),(c))
945 #   define  __PTW32_INTERLOCKED_EXCHANGE_SIZE(p,v)  __PTW32_INTERLOCKED_EXCHANGE_LONG((p),(v))
946 #   define  __PTW32_INTERLOCKED_EXCHANGE_ADD_SIZE(p,v)  __PTW32_INTERLOCKED_EXCHANGE_ADD_LONG((p),(v))
947 #   define  __PTW32_INTERLOCKED_INCREMENT_SIZE(p)  __PTW32_INTERLOCKED_INCREMENT_LONG((p))
948 #   define  __PTW32_INTERLOCKED_DECREMENT_SIZE(p)  __PTW32_INTERLOCKED_DECREMENT_LONG((p))
949 #endif
950 
951 #if defined(NEED_CREATETHREAD)
952 
953 /*
954  * Macro uses args so we can cast start_proc to LPTHREAD_START_ROUTINE
955  * in order to avoid warnings because of return type
956  */
957 
958 #define _beginthreadex(security, \
959                        stack_size, \
960                        start_proc, \
961                        arg, \
962                        flags, \
963                        pid) \
964         CreateThread(security, \
965                      stack_size, \
966                      (LPTHREAD_START_ROUTINE) start_proc, \
967                      arg, \
968                      flags, \
969                      pid)
970 
971 #define _endthreadex ExitThread
972 
973 #endif				/* NEED_CREATETHREAD */
974 
975 
976 #endif				/* _IMPLEMENT_H */
977