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  *      Pthreads-win32 - POSIX Threads Library for Win32
11  *      Copyright(C) 1998 John E. Bossom
12  *      Copyright(C) 1999,2005 Pthreads-win32 contributors
13  *
14  *      Contact Email: Ross.Johnson@homemail.com.au
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  *      http://sources.redhat.com/pthreads-win32/contributors.html
21  *
22  *      This library is free software; you can redistribute it and/or
23  *      modify it under the terms of the GNU Lesser General Public
24  *      License as published by the Free Software Foundation; either
25  *      version 2 of the License, or (at your option) any later version.
26  *
27  *      This library is distributed in the hope that it will be useful,
28  *      but WITHOUT ANY WARRANTY; without even the implied warranty of
29  *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
30  *      Lesser General Public License for more details.
31  *
32  *      You should have received a copy of the GNU Lesser General Public
33  *      License along with this library in the file COPYING.LIB;
34  *      if not, write to the Free Software Foundation, Inc.,
35  *      51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
36  */
37 
38 #if !defined(_IMPLEMENT_H)
39 #define _IMPLEMENT_H
40 
41 #if !defined(_WIN32_WINNT)
42 #define _WIN32_WINNT 0x0400
43 #endif
44 
45 #include <windows.h>
46 
47 /*
48  * In case windows.h doesn't define it (e.g. WinCE perhaps)
49  */
50 #if defined(WINCE)
51 typedef VOID (APIENTRY *PAPCFUNC)(DWORD dwParam);
52 #endif
53 
54 /*
55  * note: ETIMEDOUT is correctly defined in winsock.h
56  */
57 #include <winsock.h>
58 
59 /*
60  * In case ETIMEDOUT hasn't been defined above somehow.
61  */
62 #if !defined(ETIMEDOUT)
63 #  define ETIMEDOUT 10060	/* This is the value in winsock.h. */
64 #endif
65 
66 #if !defined(malloc)
67 #include <malloc.h>
68 #endif
69 
70 #if defined(__CLEANUP_C)
71 # include <setjmp.h>
72 #endif
73 
74 #if !defined(INT_MAX)
75 #include <limits.h>
76 #endif
77 
78 /* use local include files during development */
79 #include "semaphore.h"
80 #include "sched.h"
81 
82 #if defined(HAVE_C_INLINE) || defined(__cplusplus)
83 #define INLINE inline
84 #else
85 #define INLINE
86 #endif
87 
88 #if defined(_MSC_VER) && _MSC_VER < 1300
89 /*
90  * MSVC 6 does not use the "volatile" qualifier
91  */
92 #define PTW32_INTERLOCKED_VOLATILE
93 #else
94 #define PTW32_INTERLOCKED_VOLATILE volatile
95 #endif
96 #define PTW32_INTERLOCKED_LONG long
97 #define PTW32_INTERLOCKED_SIZE size_t
98 #define PTW32_INTERLOCKED_PVOID PVOID
99 #define PTW32_INTERLOCKED_LONGPTR PTW32_INTERLOCKED_VOLATILE long*
100 #define PTW32_INTERLOCKED_SIZEPTR PTW32_INTERLOCKED_VOLATILE size_t*
101 #define PTW32_INTERLOCKED_PVOID_PTR PTW32_INTERLOCKED_VOLATILE PVOID*
102 
103 #if defined(__MINGW64__) || defined(__MINGW32__)
104 #  include <stdint.h>
105 #elif defined(__BORLANDC__)
106 #  define int64_t ULONGLONG
107 #else
108 #  define int64_t _int64
109 #  if defined(_MSC_VER) && _MSC_VER < 1300
110      typedef long intptr_t;
111 #  endif
112 #endif
113 
114 typedef enum
115 {
116   /*
117    * This enumeration represents the state of the thread;
118    * The thread is still "alive" if the numeric value of the
119    * state is greater or equal "PThreadStateRunning".
120    */
121   PThreadStateInitial = 0,	/* Thread not running                   */
122   PThreadStateRunning,		/* Thread alive & kicking               */
123   PThreadStateSuspended,	/* Thread alive but suspended           */
124   PThreadStateCancelPending,	/* Thread alive but                     */
125                                 /* has cancelation pending.             */
126   PThreadStateCanceling,	/* Thread alive but is                  */
127                                 /* in the process of terminating        */
128                                 /* due to a cancellation request        */
129   PThreadStateExiting,		/* Thread alive but exiting             */
130                                 /* due to an exception                  */
131   PThreadStateLast,             /* All handlers have been run and now   */
132                                 /* final cleanup can be done.           */
133   PThreadStateReuse             /* In reuse pool.                       */
134 }
135 PThreadState;
136 
137 typedef struct ptw32_mcs_node_t_     ptw32_mcs_local_node_t;
138 typedef struct ptw32_mcs_node_t_*    ptw32_mcs_lock_t;
139 typedef struct ptw32_robust_node_t_  ptw32_robust_node_t;
140 typedef struct ptw32_thread_t_       ptw32_thread_t;
141 
142 
143 struct ptw32_thread_t_
144 {
145   unsigned __int64 seqNumber;	/* Process-unique thread sequence number */
146   HANDLE threadH;		/* Win32 thread handle - POSIX thread is invalid if threadH == 0 */
147   pthread_t ptHandle;		/* This thread's permanent pthread_t handle */
148   ptw32_thread_t * prevReuse;	/* Links threads on reuse stack */
149   volatile PThreadState state;
150   ptw32_mcs_lock_t threadLock;	/* Used for serialised access to public thread state */
151   ptw32_mcs_lock_t stateLock;	/* Used for async-cancel safety */
152   HANDLE cancelEvent;
153   void *exitStatus;
154   void *parms;
155   void *keys;
156   void *nextAssoc;
157 #if defined(__CLEANUP_C)
158   jmp_buf start_mark;		/* Jump buffer follows void* so should be aligned */
159 #endif				/* __CLEANUP_C */
160 #if defined(HAVE_SIGSET_T)
161   sigset_t sigmask;
162 #endif				/* HAVE_SIGSET_T */
163   ptw32_mcs_lock_t
164               robustMxListLock; /* robustMxList lock */
165   ptw32_robust_node_t*
166                   robustMxList; /* List of currenty held robust mutexes */
167   int ptErrno;
168   int detachState;
169   int sched_priority;		/* As set, not as currently is */
170   int cancelState;
171   int cancelType;
172   int implicit:1;
173   DWORD thread;			/* Win32 thread ID */
174 #if defined(_UWIN)
175   DWORD dummy[5];
176 #endif
177   size_t align;			/* Force alignment if this struct is packed */
178 };
179 
180 
181 /*
182  * Special value to mark attribute objects as valid.
183  */
184 #define PTW32_ATTR_VALID ((unsigned long) 0xC4C0FFEE)
185 
186 struct pthread_attr_t_
187 {
188   unsigned long valid;
189   void *stackaddr;
190   size_t stacksize;
191   int detachstate;
192   struct sched_param param;
193   int inheritsched;
194   int contentionscope;
195 #if defined(HAVE_SIGSET_T)
196   sigset_t sigmask;
197 #endif				/* HAVE_SIGSET_T */
198 };
199 
200 
201 /*
202  * ====================
203  * ====================
204  * Semaphores, Mutexes and Condition Variables
205  * ====================
206  * ====================
207  */
208 
209 struct sem_t_
210 {
211   int value;
212   pthread_mutex_t lock;
213   HANDLE sem;
214 #if defined(NEED_SEM)
215   int leftToUnblock;
216 #endif
217 };
218 
219 #define PTW32_OBJECT_AUTO_INIT ((void *)(size_t) -1)
220 #define PTW32_OBJECT_INVALID   NULL
221 
222 struct pthread_mutex_t_
223 {
224   LONG lock_idx;		/* Provides exclusive access to mutex state
225 				   via the Interlocked* mechanism.
226 				    0: unlocked/free.
227 				    1: locked - no other waiters.
228 				   -1: locked - with possible other waiters.
229 				*/
230   int recursive_count;		/* Number of unlocks a thread needs to perform
231 				   before the lock is released (recursive
232 				   mutexes only). */
233   int kind;			/* Mutex type. */
234   pthread_t ownerThread;
235   HANDLE event;			/* Mutex release notification to waiting
236 				   threads. */
237   ptw32_robust_node_t*
238                     robustNode; /* Extra state for robust mutexes  */
239 };
240 
241 enum ptw32_robust_state_t_
242 {
243   PTW32_ROBUST_CONSISTENT,
244   PTW32_ROBUST_INCONSISTENT,
245   PTW32_ROBUST_NOTRECOVERABLE
246 };
247 
248 typedef enum ptw32_robust_state_t_   ptw32_robust_state_t;
249 
250 /*
251  * Node used to manage per-thread lists of currently-held robust mutexes.
252  */
253 struct ptw32_robust_node_t_
254 {
255   pthread_mutex_t mx;
256   ptw32_robust_state_t stateInconsistent;
257   ptw32_robust_node_t* prev;
258   ptw32_robust_node_t* next;
259 };
260 
261 struct pthread_mutexattr_t_
262 {
263   int pshared;
264   int kind;
265   int robustness;
266 };
267 
268 /*
269  * Possible values, other than PTW32_OBJECT_INVALID,
270  * for the "interlock" element in a spinlock.
271  *
272  * In this implementation, when a spinlock is initialised,
273  * the number of cpus available to the process is checked.
274  * If there is only one cpu then "interlock" is set equal to
275  * PTW32_SPIN_USE_MUTEX and u.mutex is an initialised mutex.
276  * If the number of cpus is greater than 1 then "interlock"
277  * is set equal to PTW32_SPIN_UNLOCKED and the number is
278  * stored in u.cpus. This arrangement allows the spinlock
279  * routines to attempt an InterlockedCompareExchange on "interlock"
280  * immediately and, if that fails, to try the inferior mutex.
281  *
282  * "u.cpus" isn't used for anything yet, but could be used at
283  * some point to optimise spinlock behaviour.
284  */
285 #define PTW32_SPIN_INVALID     (0)
286 #define PTW32_SPIN_UNLOCKED    (1)
287 #define PTW32_SPIN_LOCKED      (2)
288 #define PTW32_SPIN_USE_MUTEX   (3)
289 
290 struct pthread_spinlock_t_
291 {
292   long interlock;		/* Locking element for multi-cpus. */
293   union
294   {
295     int cpus;			/* No. of cpus if multi cpus, or   */
296     pthread_mutex_t mutex;	/* mutex if single cpu.            */
297   } u;
298 };
299 
300 /*
301  * MCS lock queue node - see ptw32_MCS_lock.c
302  */
303 struct ptw32_mcs_node_t_
304 {
305   struct ptw32_mcs_node_t_ **lock;        /* ptr to tail of queue */
306   struct ptw32_mcs_node_t_  *next;        /* ptr to successor in queue */
307   HANDLE                     readyFlag;   /* set after lock is released by
308                                              predecessor */
309   HANDLE                     nextFlag;    /* set after 'next' ptr is set by
310                                              successor */
311 };
312 
313 
314 struct pthread_barrier_t_
315 {
316   unsigned int nCurrentBarrierHeight;
317   unsigned int nInitialBarrierHeight;
318   int pshared;
319   sem_t semBarrierBreeched;
320   ptw32_mcs_lock_t lock;
321   ptw32_mcs_local_node_t proxynode;
322 };
323 
324 struct pthread_barrierattr_t_
325 {
326   int pshared;
327 };
328 
329 struct pthread_key_t_
330 {
331   DWORD key;
332   void (PTW32_CDECL *destructor) (void *);
333   ptw32_mcs_lock_t keyLock;
334   void *threads;
335 };
336 
337 
338 typedef struct ThreadParms ThreadParms;
339 
340 struct ThreadParms
341 {
342   pthread_t tid;
343   void *(PTW32_CDECL *start) (void *);
344   void *arg;
345 };
346 
347 
348 struct pthread_cond_t_
349 {
350   long nWaitersBlocked;		/* Number of threads blocked            */
351   long nWaitersGone;		/* Number of threads timed out          */
352   long nWaitersToUnblock;	/* Number of threads to unblock         */
353   sem_t semBlockQueue;		/* Queue up threads waiting for the     */
354   /*   condition to become signalled      */
355   sem_t semBlockLock;		/* Semaphore that guards access to      */
356   /* | waiters blocked count/block queue  */
357   /* +-> Mandatory Sync.LEVEL-1           */
358   pthread_mutex_t mtxUnblockLock;	/* Mutex that guards access to          */
359   /* | waiters (to)unblock(ed) counts     */
360   /* +-> Optional* Sync.LEVEL-2           */
361   pthread_cond_t next;		/* Doubly linked list                   */
362   pthread_cond_t prev;
363 };
364 
365 
366 struct pthread_condattr_t_
367 {
368   int pshared;
369 };
370 
371 #define PTW32_RWLOCK_MAGIC 0xfacade2
372 
373 struct pthread_rwlock_t_
374 {
375   pthread_mutex_t mtxExclusiveAccess;
376   pthread_mutex_t mtxSharedAccessCompleted;
377   pthread_cond_t cndSharedAccessCompleted;
378   int nSharedAccessCount;
379   int nExclusiveAccessCount;
380   int nCompletedSharedAccessCount;
381   int nMagic;
382 };
383 
384 struct pthread_rwlockattr_t_
385 {
386   int pshared;
387 };
388 
389 typedef struct ThreadKeyAssoc ThreadKeyAssoc;
390 
391 struct ThreadKeyAssoc
392 {
393   /*
394    * Purpose:
395    *      This structure creates an association between a thread and a key.
396    *      It is used to implement the implicit invocation of a user defined
397    *      destroy routine for thread specific data registered by a user upon
398    *      exiting a thread.
399    *
400    *      Graphically, the arrangement is as follows, where:
401    *
402    *         K - Key with destructor
403    *            (head of chain is key->threads)
404    *         T - Thread that has called pthread_setspecific(Kn)
405    *            (head of chain is thread->keys)
406    *         A - Association. Each association is a node at the
407    *             intersection of two doubly-linked lists.
408    *
409    *                 T1    T2    T3
410    *                 |     |     |
411    *                 |     |     |
412    *         K1 -----+-----A-----A----->
413    *                 |     |     |
414    *                 |     |     |
415    *         K2 -----A-----A-----+----->
416    *                 |     |     |
417    *                 |     |     |
418    *         K3 -----A-----+-----A----->
419    *                 |     |     |
420    *                 |     |     |
421    *                 V     V     V
422    *
423    *      Access to the association is guarded by two locks: the key's
424    *      general lock (guarding the row) and the thread's general
425    *      lock (guarding the column). This avoids the need for a
426    *      dedicated lock for each association, which not only consumes
427    *      more handles but requires that the lock resources persist
428    *      until both the key is deleted and the thread has called the
429    *      destructor. The two-lock arrangement allows those resources
430    *      to be freed as soon as either thread or key is concluded.
431    *
432    *      To avoid deadlock, whenever both locks are required both the
433    *      key and thread locks are acquired consistently in the order
434    *      "key lock then thread lock". An exception to this exists
435    *      when a thread calls the destructors, however, this is done
436    *      carefully (but inelegantly) to avoid deadlock.
437    *
438    *      An association is created when a thread first calls
439    *      pthread_setspecific() on a key that has a specified
440    *      destructor.
441    *
442    *      An association is destroyed either immediately after the
443    *      thread calls the key destructor function on thread exit, or
444    *      when the key is deleted.
445    *
446    * Attributes:
447    *      thread
448    *              reference to the thread that owns the
449    *              association. This is actually the pointer to the
450    *              thread struct itself. Since the association is
451    *              destroyed before the thread exits, this can never
452    *              point to a different logical thread to the one that
453    *              created the assoc, i.e. after thread struct reuse.
454    *
455    *      key
456    *              reference to the key that owns the association.
457    *
458    *      nextKey
459    *              The pthread_t->keys attribute is the head of a
460    *              chain of associations that runs through the nextKey
461    *              link. This chain provides the 1 to many relationship
462    *              between a pthread_t and all pthread_key_t on which
463    *              it called pthread_setspecific.
464    *
465    *      prevKey
466    *              Similarly.
467    *
468    *      nextThread
469    *              The pthread_key_t->threads attribute is the head of
470    *              a chain of associations that runs through the
471    *              nextThreads link. This chain provides the 1 to many
472    *              relationship between a pthread_key_t and all the
473    *              PThreads that have called pthread_setspecific for
474    *              this pthread_key_t.
475    *
476    *      prevThread
477    *              Similarly.
478    *
479    * Notes:
480    *      1)      As soon as either the key or the thread is no longer
481    *              referencing the association, it can be destroyed. The
482    *              association will be removed from both chains.
483    *
484    *      2)      Under WIN32, an association is only created by
485    *              pthread_setspecific if the user provided a
486    *              destroyRoutine when they created the key.
487    *
488    *
489    */
490   ptw32_thread_t * thread;
491   pthread_key_t key;
492   ThreadKeyAssoc *nextKey;
493   ThreadKeyAssoc *nextThread;
494   ThreadKeyAssoc *prevKey;
495   ThreadKeyAssoc *prevThread;
496 };
497 
498 
499 #if defined(__CLEANUP_SEH)
500 /*
501  * --------------------------------------------------------------
502  * MAKE_SOFTWARE_EXCEPTION
503  *      This macro constructs a software exception code following
504  *      the same format as the standard Win32 error codes as defined
505  *      in WINERROR.H
506  *  Values are 32 bit values laid out as follows:
507  *
508  *   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
509  *  +---+-+-+-----------------------+-------------------------------+
510  *  |Sev|C|R|     Facility          |               Code            |
511  *  +---+-+-+-----------------------+-------------------------------+
512  *
513  * Severity Values:
514  */
515 #define SE_SUCCESS              0x00
516 #define SE_INFORMATION          0x01
517 #define SE_WARNING              0x02
518 #define SE_ERROR                0x03
519 
520 #define MAKE_SOFTWARE_EXCEPTION( _severity, _facility, _exception ) \
521 ( (DWORD) ( ( (_severity) << 30 ) |     /* Severity code        */ \
522             ( 1 << 29 ) |               /* MS=0, User=1         */ \
523             ( 0 << 28 ) |               /* Reserved             */ \
524             ( (_facility) << 16 ) |     /* Facility Code        */ \
525             ( (_exception) <<  0 )      /* Exception Code       */ \
526             ) )
527 
528 /*
529  * We choose one specific Facility/Error code combination to
530  * identify our software exceptions vs. WIN32 exceptions.
531  * We store our actual component and error code within
532  * the optional information array.
533  */
534 #define EXCEPTION_PTW32_SERVICES        \
535      MAKE_SOFTWARE_EXCEPTION( SE_ERROR, \
536                               PTW32_SERVICES_FACILITY, \
537                               PTW32_SERVICES_ERROR )
538 
539 #define PTW32_SERVICES_FACILITY         0xBAD
540 #define PTW32_SERVICES_ERROR            0xDEED
541 
542 #endif /* __CLEANUP_SEH */
543 
544 /*
545  * Services available through EXCEPTION_PTW32_SERVICES
546  * and also used [as parameters to ptw32_throw()] as
547  * generic exception selectors.
548  */
549 
550 #define PTW32_EPS_EXIT                  (1)
551 #define PTW32_EPS_CANCEL                (2)
552 
553 
554 /* Useful macros */
555 #define PTW32_MAX(a,b)  ((a)<(b)?(b):(a))
556 #define PTW32_MIN(a,b)  ((a)>(b)?(b):(a))
557 
558 
559 /* Declared in pthread_cancel.c */
560 extern DWORD (*ptw32_register_cancelation) (PAPCFUNC, HANDLE, DWORD);
561 
562 /* Thread Reuse stack bottom marker. Must not be NULL or any valid pointer to memory. */
563 #define PTW32_THREAD_REUSE_EMPTY ((ptw32_thread_t *)(size_t) 1)
564 
565 extern int ptw32_processInitialized;
566 extern ptw32_thread_t * ptw32_threadReuseTop;
567 extern ptw32_thread_t * ptw32_threadReuseBottom;
568 extern pthread_key_t ptw32_selfThreadKey;
569 extern pthread_key_t ptw32_cleanupKey;
570 extern pthread_cond_t ptw32_cond_list_head;
571 extern pthread_cond_t ptw32_cond_list_tail;
572 
573 extern int ptw32_mutex_default_kind;
574 
575 extern unsigned __int64 ptw32_threadSeqNumber;
576 
577 extern int ptw32_concurrency;
578 
579 extern int ptw32_features;
580 
581 extern ptw32_mcs_lock_t ptw32_thread_reuse_lock;
582 extern ptw32_mcs_lock_t ptw32_mutex_test_init_lock;
583 extern ptw32_mcs_lock_t ptw32_cond_list_lock;
584 extern ptw32_mcs_lock_t ptw32_cond_test_init_lock;
585 extern ptw32_mcs_lock_t ptw32_rwlock_test_init_lock;
586 extern ptw32_mcs_lock_t ptw32_spinlock_test_init_lock;
587 
588 #if defined(_UWIN)
589 extern int pthread_count;
590 #endif
591 
592 #if defined(__cplusplus)
593 extern "C"
594 {
595 #endif				/* __cplusplus */
596 
597 /*
598  * =====================
599  * =====================
600  * Forward Declarations
601  * =====================
602  * =====================
603  */
604 
605   int ptw32_is_attr (const pthread_attr_t * attr);
606 
607   int ptw32_cond_check_need_init (pthread_cond_t * cond);
608   int ptw32_mutex_check_need_init (pthread_mutex_t * mutex);
609   int ptw32_rwlock_check_need_init (pthread_rwlock_t * rwlock);
610 
611   int ptw32_robust_mutex_inherit(pthread_mutex_t * mutex);
612   void ptw32_robust_mutex_add(pthread_mutex_t* mutex, pthread_t self);
613   void ptw32_robust_mutex_remove(pthread_mutex_t* mutex, ptw32_thread_t* otp);
614 
615   DWORD
616     ptw32_RegisterCancelation (PAPCFUNC callback,
617 			       HANDLE threadH, DWORD callback_arg);
618 
619   int ptw32_processInitialize (void);
620 
621   void ptw32_processTerminate (void);
622 
623   void ptw32_threadDestroy (pthread_t tid);
624 
625   void ptw32_pop_cleanup_all (int execute);
626 
627   pthread_t ptw32_new (void);
628 
629   pthread_t ptw32_threadReusePop (void);
630 
631   void ptw32_threadReusePush (pthread_t thread);
632 
633   int ptw32_getprocessors (int *count);
634 
635   int ptw32_setthreadpriority (pthread_t thread, int policy, int priority);
636 
637   void ptw32_rwlock_cancelwrwait (void *arg);
638 
639 #if ! (defined (__MINGW64__) || defined(__MINGW32__)) || (defined(__MSVCRT__) && ! defined(__DMC__))
640   unsigned __stdcall
641 #else
642   void
643 #endif
644     ptw32_threadStart (void *vthreadParms);
645 
646   void ptw32_callUserDestroyRoutines (pthread_t thread);
647 
648   int ptw32_tkAssocCreate (ptw32_thread_t * thread, pthread_key_t key);
649 
650   void ptw32_tkAssocDestroy (ThreadKeyAssoc * assoc);
651 
652   int ptw32_semwait (sem_t * sem);
653 
654   DWORD ptw32_relmillisecs (const struct timespec * abstime);
655 
656   void ptw32_mcs_lock_acquire (ptw32_mcs_lock_t * lock, ptw32_mcs_local_node_t * node);
657 
658   int ptw32_mcs_lock_try_acquire (ptw32_mcs_lock_t * lock, ptw32_mcs_local_node_t * node);
659 
660   void ptw32_mcs_lock_release (ptw32_mcs_local_node_t * node);
661 
662   void ptw32_mcs_node_transfer (ptw32_mcs_local_node_t * new_node, ptw32_mcs_local_node_t * old_node);
663 
664 #if defined(NEED_FTIME)
665   void ptw32_timespec_to_filetime (const struct timespec *ts, FILETIME * ft);
666   void ptw32_filetime_to_timespec (const FILETIME * ft, struct timespec *ts);
667 #endif
668 
669 /* Declared in misc.c */
670 #if defined(NEED_CALLOC)
671 #define calloc(n, s) ptw32_calloc(n, s)
672   void *ptw32_calloc (size_t n, size_t s);
673 #endif
674 
675 /* Declared in private.c */
676 #if defined(_MSC_VER)
677 /*
678  * Ignore the warning:
679  * "C++ exception specification ignored except to indicate that
680  * the function is not __declspec(nothrow)."
681  */
682 #pragma warning(disable:4290)
683 #endif
684   void ptw32_throw (DWORD exception)
685 #if defined(__CLEANUP_CXX)
686     throw(ptw32_exception_cancel,ptw32_exception_exit)
687 #endif
688 ;
689 
690 #if defined(__cplusplus)
691 }
692 #endif				/* __cplusplus */
693 
694 
695 #if defined(_UWIN_)
696 #   if defined(_MT)
697 #       if defined(__cplusplus)
698 extern "C"
699 {
700 #       endif
701   _CRTIMP unsigned long __cdecl _beginthread (void (__cdecl *) (void *),
702 					      unsigned, void *);
703   _CRTIMP void __cdecl _endthread (void);
704   _CRTIMP unsigned long __cdecl _beginthreadex (void *, unsigned,
705 						unsigned (__stdcall *) (void *),
706 						void *, unsigned, unsigned *);
707   _CRTIMP void __cdecl _endthreadex (unsigned);
708 #       if defined(__cplusplus)
709 }
710 #       endif
711 #   endif
712 #else
713 #       include <process.h>
714 #   endif
715 
716 
717 /*
718  * Use intrinsic versions wherever possible. VC will do this
719  * automatically where possible and GCC define these if available:
720  * __GCC_HAVE_SYNC_COMPARE_AND_SWAP_1
721  * __GCC_HAVE_SYNC_COMPARE_AND_SWAP_2
722  * __GCC_HAVE_SYNC_COMPARE_AND_SWAP_4
723  * __GCC_HAVE_SYNC_COMPARE_AND_SWAP_8
724  * __GCC_HAVE_SYNC_COMPARE_AND_SWAP_16
725  *
726  * The full set of Interlocked intrinsics in GCC are (check versions):
727  * type __sync_fetch_and_add (type *ptr, type value, ...)
728  * type __sync_fetch_and_sub (type *ptr, type value, ...)
729  * type __sync_fetch_and_or (type *ptr, type value, ...)
730  * type __sync_fetch_and_and (type *ptr, type value, ...)
731  * type __sync_fetch_and_xor (type *ptr, type value, ...)
732  * type __sync_fetch_and_nand (type *ptr, type value, ...)
733  * type __sync_add_and_fetch (type *ptr, type value, ...)
734  * type __sync_sub_and_fetch (type *ptr, type value, ...)
735  * type __sync_or_and_fetch (type *ptr, type value, ...)
736  * type __sync_and_and_fetch (type *ptr, type value, ...)
737  * type __sync_xor_and_fetch (type *ptr, type value, ...)
738  * type __sync_nand_and_fetch (type *ptr, type value, ...)
739  * bool __sync_bool_compare_and_swap (type *ptr, type oldval type newval, ...)
740  * type __sync_val_compare_and_swap (type *ptr, type oldval type newval, ...)
741  * __sync_synchronize (...) // Full memory barrier
742  * type __sync_lock_test_and_set (type *ptr, type value, ...) // Acquire barrier
743  * void __sync_lock_release (type *ptr, ...) // Release barrier
744  *
745  * These are all overloaded and take 1,2,4,8 byte scalar or pointer types.
746  *
747  * The above aren't available in Mingw32 as of gcc 4.5.2 so define our own.
748  */
749 #if defined(__GNUC__)
750 # if defined(_WIN64)
751 # define PTW32_INTERLOCKED_COMPARE_EXCHANGE_64(location, value, comparand)    \
752     ({                                                                     \
753       __typeof (value) _result;                                            \
754       __asm__ __volatile__                                                 \
755       (                                                                    \
756         "lock\n\t"                                                         \
757         "cmpxchgq      %2,(%1)"                                            \
758         :"=a" (_result)                                                    \
759         :"r"  (location), "r" (value), "a" (comparand)                     \
760         :"memory", "cc");                                                  \
761       _result;                                                             \
762     })
763 # define PTW32_INTERLOCKED_EXCHANGE_64(location, value)                    \
764     ({                                                                     \
765       __typeof (value) _result;                                            \
766       __asm__ __volatile__                                                 \
767       (                                                                    \
768         "xchgq	 %0,(%1)"                                                  \
769         :"=r" (_result)                                                    \
770         :"r" (location), "0" (value)                                       \
771         :"memory", "cc");                                                  \
772       _result;                                                             \
773     })
774 # define PTW32_INTERLOCKED_EXCHANGE_ADD_64(location, value)                \
775     ({                                                                     \
776       __typeof (value) _result;                                            \
777       __asm__ __volatile__                                                 \
778       (                                                                    \
779         "lock\n\t"                                                         \
780         "xaddq	 %0,(%1)"                                                  \
781         :"=r" (_result)                                                    \
782         :"r" (location), "0" (value)                                       \
783         :"memory", "cc");                                                  \
784       _result;                                                             \
785     })
786 # define PTW32_INTERLOCKED_INCREMENT_64(location)                          \
787     ({                                                                     \
788       PTW32_INTERLOCKED_LONG _temp = 1;                                   \
789       __asm__ __volatile__                                                 \
790       (                                                                    \
791         "lock\n\t"                                                         \
792         "xaddq	 %0,(%1)"                                                  \
793         :"+r" (_temp)                                                      \
794         :"r" (location)                                                    \
795         :"memory", "cc");                                                  \
796       ++_temp;                                                             \
797     })
798 # define PTW32_INTERLOCKED_DECREMENT_64(location)                          \
799     ({                                                                     \
800       PTW32_INTERLOCKED_LONG _temp = -1;                                  \
801       __asm__ __volatile__                                                 \
802       (                                                                    \
803         "lock\n\t"                                                         \
804         "xaddq	 %2,(%1)"                                                  \
805         :"+r" (_temp)                                                      \
806         :"r" (location)                                                    \
807         :"memory", "cc");                                                  \
808       --_temp;                                                             \
809     })
810 #endif
811 # define PTW32_INTERLOCKED_COMPARE_EXCHANGE_LONG(location, value, comparand)    \
812     ({                                                                     \
813       __typeof (value) _result;                                            \
814       __asm__ __volatile__                                                 \
815       (                                                                    \
816         "lock\n\t"                                                         \
817         "cmpxchgl       %2,(%1)"                                           \
818         :"=a" (_result)                                                    \
819         :"r"  (location), "r" (value), "a" (comparand)                     \
820         :"memory", "cc");                                                  \
821       _result;                                                             \
822     })
823 # define PTW32_INTERLOCKED_EXCHANGE_LONG(location, value)                  \
824     ({                                                                     \
825       __typeof (value) _result;                                            \
826       __asm__ __volatile__                                                 \
827       (                                                                    \
828         "xchgl	 %0,(%1)"                                                  \
829         :"=r" (_result)                                                    \
830         :"r" (location), "0" (value)                                       \
831         :"memory", "cc");                                                  \
832       _result;                                                             \
833     })
834 # define PTW32_INTERLOCKED_EXCHANGE_ADD_LONG(location, value)              \
835     ({                                                                     \
836       __typeof (value) _result;                                            \
837       __asm__ __volatile__                                                 \
838       (                                                                    \
839         "lock\n\t"                                                         \
840         "xaddl	 %0,(%1)"                                                  \
841         :"=r" (_result)                                                    \
842         :"r" (location), "0" (value)                                       \
843         :"memory", "cc");                                                  \
844       _result;                                                             \
845     })
846 # define PTW32_INTERLOCKED_INCREMENT_LONG(location)                        \
847     ({                                                                     \
848       PTW32_INTERLOCKED_LONG _temp = 1;                                   \
849       __asm__ __volatile__                                                 \
850       (                                                                    \
851         "lock\n\t"                                                         \
852         "xaddl	 %0,(%1)"                                                  \
853         :"+r" (_temp)                                                      \
854         :"r" (location)                                                    \
855         :"memory", "cc");                                                  \
856       ++_temp;                                                             \
857     })
858 # define PTW32_INTERLOCKED_DECREMENT_LONG(location)                        \
859     ({                                                                     \
860       PTW32_INTERLOCKED_LONG _temp = -1;                                  \
861       __asm__ __volatile__                                                 \
862       (                                                                    \
863         "lock\n\t"                                                         \
864         "xaddl	 %0,(%1)"                                                  \
865         :"+r" (_temp)                                                      \
866         :"r" (location)                                                    \
867         :"memory", "cc");                                                  \
868       --_temp;                                                             \
869     })
870 # define PTW32_INTERLOCKED_COMPARE_EXCHANGE_PTR(location, value, comparand) \
871     PTW32_INTERLOCKED_COMPARE_EXCHANGE_SIZE((PTW32_INTERLOCKED_SIZEPTR)location, \
872                                             (PTW32_INTERLOCKED_SIZE)value, \
873                                             (PTW32_INTERLOCKED_SIZE)comparand)
874 # define PTW32_INTERLOCKED_EXCHANGE_PTR(location, value) \
875     PTW32_INTERLOCKED_EXCHANGE_SIZE((PTW32_INTERLOCKED_SIZEPTR)location, \
876                                     (PTW32_INTERLOCKED_SIZE)value)
877 #else
878 # if defined(_WIN64)
879 #   define PTW32_INTERLOCKED_COMPARE_EXCHANGE_64 InterlockedCompareExchange64
880 #   define PTW32_INTERLOCKED_EXCHANGE_64 InterlockedExchange64
881 #   define PTW32_INTERLOCKED_EXCHANGE_ADD_64 InterlockedExchangeAdd64
882 #   define PTW32_INTERLOCKED_INCREMENT_64 InterlockedIncrement64
883 #   define PTW32_INTERLOCKED_DECREMENT_64 InterlockedDecrement64
884 # endif
885 # if defined(_MSC_VER) && _MSC_VER < 1300 && !defined(_WIN64) /* MSVC 6 */
886 #  define PTW32_INTERLOCKED_COMPARE_EXCHANGE_LONG(location, value, comparand) \
887       ((LONG)InterlockedCompareExchange((PVOID *)(location), (PVOID)(value), (PVOID)(comparand)))
888 # else
889 #  define PTW32_INTERLOCKED_COMPARE_EXCHANGE_LONG InterlockedCompareExchange
890 # endif
891 # define PTW32_INTERLOCKED_EXCHANGE_LONG InterlockedExchange
892 # define PTW32_INTERLOCKED_EXCHANGE_ADD_LONG InterlockedExchangeAdd
893 # define PTW32_INTERLOCKED_INCREMENT_LONG InterlockedIncrement
894 # define PTW32_INTERLOCKED_DECREMENT_LONG InterlockedDecrement
895 # if defined(_MSC_VER) && _MSC_VER < 1300 && !defined(_WIN64) /* MSVC 6 */
896 #  define PTW32_INTERLOCKED_COMPARE_EXCHANGE_PTR InterlockedCompareExchange
897 #  define PTW32_INTERLOCKED_EXCHANGE_PTR(location, value) \
898     ((PVOID)InterlockedExchange((LPLONG)(location), (LONG)(value)))
899 # else
900 #  define PTW32_INTERLOCKED_COMPARE_EXCHANGE_PTR InterlockedCompareExchangePointer
901 #  define PTW32_INTERLOCKED_EXCHANGE_PTR InterlockedExchangePointer
902 # endif
903 #endif
904 #if defined(_WIN64)
905 #   define PTW32_INTERLOCKED_COMPARE_EXCHANGE_SIZE PTW32_INTERLOCKED_COMPARE_EXCHANGE_64
906 #   define PTW32_INTERLOCKED_EXCHANGE_SIZE PTW32_INTERLOCKED_EXCHANGE_64
907 #   define PTW32_INTERLOCKED_EXCHANGE_ADD_SIZE PTW32_INTERLOCKED_EXCHANGE_ADD_64
908 #   define PTW32_INTERLOCKED_INCREMENT_SIZE PTW32_INTERLOCKED_INCREMENT_64
909 #   define PTW32_INTERLOCKED_DECREMENT_SIZE PTW32_INTERLOCKED_DECREMENT_64
910 #else
911 #   define PTW32_INTERLOCKED_COMPARE_EXCHANGE_SIZE PTW32_INTERLOCKED_COMPARE_EXCHANGE_LONG
912 #   define PTW32_INTERLOCKED_EXCHANGE_SIZE PTW32_INTERLOCKED_EXCHANGE_LONG
913 #   define PTW32_INTERLOCKED_EXCHANGE_ADD_SIZE PTW32_INTERLOCKED_EXCHANGE_ADD_LONG
914 #   define PTW32_INTERLOCKED_INCREMENT_SIZE PTW32_INTERLOCKED_INCREMENT_LONG
915 #   define PTW32_INTERLOCKED_DECREMENT_SIZE PTW32_INTERLOCKED_DECREMENT_LONG
916 #endif
917 
918 #if defined(NEED_CREATETHREAD)
919 
920 /*
921  * Macro uses args so we can cast start_proc to LPTHREAD_START_ROUTINE
922  * in order to avoid warnings because of return type
923  */
924 
925 #define _beginthreadex(security, \
926                        stack_size, \
927                        start_proc, \
928                        arg, \
929                        flags, \
930                        pid) \
931         CreateThread(security, \
932                      stack_size, \
933                      (LPTHREAD_START_ROUTINE) start_proc, \
934                      arg, \
935                      flags, \
936                      pid)
937 
938 #define _endthreadex ExitThread
939 
940 #endif				/* NEED_CREATETHREAD */
941 
942 
943 #endif				/* _IMPLEMENT_H */
944