Home | History | Annotate | Download | only in pthreads-win32
      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 (at) 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