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