implement.h 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692
  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: rpj@callisto.canberra.edu.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. #ifndef _IMPLEMENT_H
  38. #define _IMPLEMENT_H
  39. #ifdef _WIN32_WINNT
  40. #undef _WIN32_WINNT
  41. #endif
  42. #define _WIN32_WINNT 0x400
  43. #include <windows.h>
  44. /*
  45. * In case windows.h doesn't define it (e.g. WinCE perhaps)
  46. */
  47. #ifdef WINCE
  48. typedef VOID (APIENTRY *PAPCFUNC)(DWORD dwParam);
  49. #endif
  50. /*
  51. * note: ETIMEDOUT is correctly defined in winsock.h
  52. */
  53. #include <winsock.h>
  54. /*
  55. * In case ETIMEDOUT hasn't been defined above somehow.
  56. */
  57. #ifndef ETIMEDOUT
  58. # define ETIMEDOUT 10060 /* This is the value in winsock.h. */
  59. #endif
  60. #if !defined(malloc)
  61. #include <malloc.h>
  62. #endif
  63. #if !defined(INT_MAX)
  64. #include <limits.h>
  65. #endif
  66. /* use local include files during development */
  67. #include "semaphore.h"
  68. #include "sched.h"
  69. #if defined(HAVE_C_INLINE) || defined(__cplusplus)
  70. #define INLINE inline
  71. #else
  72. #define INLINE
  73. #endif
  74. #if defined (__MINGW32__) || (_MSC_VER >= 1300)
  75. #define PTW32_INTERLOCKED_LONG long
  76. #define PTW32_INTERLOCKED_LPLONG long*
  77. #else
  78. #define PTW32_INTERLOCKED_LONG PVOID
  79. #define PTW32_INTERLOCKED_LPLONG PVOID*
  80. #endif
  81. #if defined(__MINGW32__)
  82. #include <stdint.h>
  83. #elif defined(__BORLANDC__)
  84. #define int64_t ULONGLONG
  85. #else
  86. #define int64_t _int64
  87. #endif
  88. typedef enum {
  89. /*
  90. * This enumeration represents the state of the thread;
  91. * The thread is still "alive" if the numeric value of the
  92. * state is greater or equal "PThreadStateRunning".
  93. */
  94. PThreadStateInitial = 0, /* Thread not running */
  95. PThreadStateRunning, /* Thread alive & kicking */
  96. PThreadStateSuspended, /* Thread alive but suspended */
  97. PThreadStateCancelPending, /* Thread alive but is */
  98. /* has cancelation pending. */
  99. PThreadStateCanceling, /* Thread alive but is */
  100. /* in the process of terminating */
  101. /* due to a cancellation request */
  102. PThreadStateException, /* Thread alive but exiting */
  103. /* due to an exception */
  104. PThreadStateLast
  105. }
  106. PThreadState;
  107. typedef struct ptw32_thread_t_ ptw32_thread_t;
  108. struct ptw32_thread_t_ {
  109. #ifdef _UWIN
  110. DWORD dummy[5];
  111. #endif
  112. DWORD thread;
  113. HANDLE threadH; /* Win32 thread handle - POSIX thread is invalid if threadH == 0 */
  114. pthread_t ptHandle; /* This thread's permanent pthread_t handle */
  115. ptw32_thread_t * prevReuse; /* Links threads on reuse stack */
  116. volatile PThreadState state;
  117. void *exitStatus;
  118. void *parms;
  119. int ptErrno;
  120. int detachState;
  121. pthread_mutex_t threadLock; /* Used for serialised access to public thread state */
  122. int sched_priority; /* As set, not as currently is */
  123. pthread_mutex_t cancelLock; /* Used for async-cancel safety */
  124. int cancelState;
  125. int cancelType;
  126. HANDLE cancelEvent;
  127. #ifdef __CLEANUP_C
  128. jmp_buf start_mark;
  129. #endif /* __CLEANUP_C */
  130. #if HAVE_SIGSET_T
  131. sigset_t sigmask;
  132. #endif /* HAVE_SIGSET_T */
  133. int implicit:1;
  134. void *keys;
  135. void *nextAssoc;
  136. };
  137. /*
  138. * Special value to mark attribute objects as valid.
  139. */
  140. #define PTW32_ATTR_VALID ((unsigned long) 0xC4C0FFEE)
  141. struct pthread_attr_t_ {
  142. unsigned long valid;
  143. void *stackaddr;
  144. size_t stacksize;
  145. int detachstate;
  146. struct sched_param param;
  147. int inheritsched;
  148. int contentionscope;
  149. #if HAVE_SIGSET_T
  150. sigset_t sigmask;
  151. #endif /* HAVE_SIGSET_T */
  152. };
  153. /*
  154. * ====================
  155. * ====================
  156. * Semaphores, Mutexes and Condition Variables
  157. * ====================
  158. * ====================
  159. */
  160. struct sem_t_ {
  161. int value;
  162. pthread_mutex_t lock;
  163. HANDLE sem;
  164. #ifdef NEED_SEM
  165. int leftToUnblock;
  166. #endif
  167. };
  168. #define PTW32_OBJECT_AUTO_INIT ((void *) -1)
  169. #define PTW32_OBJECT_INVALID NULL
  170. struct pthread_mutex_t_ {
  171. LONG lock_idx; /* Provides exclusive access to mutex state
  172. via the Interlocked* mechanism.
  173. 0: unlocked/free.
  174. 1: locked - no other waiters.
  175. -1: locked - with possible other waiters.
  176. */
  177. int recursive_count; /* Number of unlocks a thread needs to perform
  178. before the lock is released (recursive
  179. mutexes only). */
  180. int kind; /* Mutex type. */
  181. pthread_t ownerThread;
  182. HANDLE event; /* Mutex release notification to waiting
  183. threads. */
  184. };
  185. struct pthread_mutexattr_t_ {
  186. int pshared;
  187. int kind;
  188. };
  189. /*
  190. * Possible values, other than PTW32_OBJECT_INVALID,
  191. * for the "interlock" element in a spinlock.
  192. *
  193. * In this implementation, when a spinlock is initialised,
  194. * the number of cpus available to the process is checked.
  195. * If there is only one cpu then "interlock" is set equal to
  196. * PTW32_SPIN_USE_MUTEX and u.mutex is a initialised mutex.
  197. * If the number of cpus is greater than 1 then "interlock"
  198. * is set equal to PTW32_SPIN_UNLOCKED and the number is
  199. * stored in u.cpus. This arrangement allows the spinlock
  200. * routines to attempt an InterlockedCompareExchange on "interlock"
  201. * immediately and, if that fails, to try the inferior mutex.
  202. *
  203. * "u.cpus" isn't used for anything yet, but could be used at
  204. * some point to optimise spinlock behaviour.
  205. */
  206. #define PTW32_SPIN_UNLOCKED (1)
  207. #define PTW32_SPIN_LOCKED (2)
  208. #define PTW32_SPIN_USE_MUTEX (3)
  209. struct pthread_spinlock_t_ {
  210. long interlock; /* Locking element for multi-cpus. */
  211. union {
  212. int cpus; /* No. of cpus if multi cpus, or */
  213. pthread_mutex_t mutex; /* mutex if single cpu. */
  214. } u;
  215. };
  216. struct pthread_barrier_t_ {
  217. unsigned int nCurrentBarrierHeight;
  218. unsigned int nInitialBarrierHeight;
  219. int iStep;
  220. int pshared;
  221. sem_t semBarrierBreeched[2];
  222. };
  223. struct pthread_barrierattr_t_ {
  224. int pshared;
  225. };
  226. struct pthread_key_t_ {
  227. DWORD key;
  228. void (*destructor) (void *);
  229. pthread_mutex_t keyLock;
  230. void *threads;
  231. };
  232. typedef struct ThreadParms ThreadParms;
  233. typedef struct ThreadKeyAssoc ThreadKeyAssoc;
  234. struct ThreadParms {
  235. pthread_t tid;
  236. void *(*start) (void *);
  237. void *arg;
  238. };
  239. struct pthread_cond_t_ {
  240. long nWaitersBlocked; /* Number of threads blocked */
  241. long nWaitersGone; /* Number of threads timed out */
  242. long nWaitersToUnblock; /* Number of threads to unblock */
  243. sem_t semBlockQueue; /* Queue up threads waiting for the */
  244. /* condition to become signalled */
  245. sem_t semBlockLock; /* Semaphore that guards access to */
  246. /* | waiters blocked count/block queue */
  247. /* +-> Mandatory Sync.LEVEL-1 */
  248. pthread_mutex_t mtxUnblockLock; /* Mutex that guards access to */
  249. /* | waiters (to)unblock(ed) counts */
  250. /* +-> Optional* Sync.LEVEL-2 */
  251. pthread_cond_t next; /* Doubly linked list */
  252. pthread_cond_t prev;
  253. };
  254. struct pthread_condattr_t_ {
  255. int pshared;
  256. };
  257. #define PTW32_RWLOCK_MAGIC 0xfacade2
  258. struct pthread_rwlock_t_ {
  259. pthread_mutex_t mtxExclusiveAccess;
  260. pthread_mutex_t mtxSharedAccessCompleted;
  261. pthread_cond_t cndSharedAccessCompleted;
  262. int nSharedAccessCount;
  263. int nExclusiveAccessCount;
  264. int nCompletedSharedAccessCount;
  265. int nMagic;
  266. };
  267. struct pthread_rwlockattr_t_ {
  268. int pshared;
  269. };
  270. /*
  271. * MCS lock queue node - see ptw32_MCS_lock.c
  272. */
  273. struct ptw32_mcs_node_t_ {
  274. struct ptw32_mcs_node_t_ **lock; /* ptr to tail of queue */
  275. struct ptw32_mcs_node_t_ *next; /* ptr to successor in queue */
  276. LONG readyFlag; /* set after lock is released by
  277. predecessor */
  278. LONG nextFlag; /* set after 'next' ptr is set by
  279. successor */
  280. };
  281. typedef struct ptw32_mcs_node_t_ ptw32_mcs_local_node_t;
  282. typedef struct ptw32_mcs_node_t_ *ptw32_mcs_lock_t;
  283. struct ThreadKeyAssoc {
  284. /*
  285. * Purpose:
  286. * This structure creates an association between a thread and a key.
  287. * It is used to implement the implicit invocation of a user defined
  288. * destroy routine for thread specific data registered by a user upon
  289. * exiting a thread.
  290. *
  291. * Graphically, the arrangement is as follows, where:
  292. *
  293. * K - Key with destructor
  294. * (head of chain is key->threads)
  295. * T - Thread that has called pthread_setspecific(Kn)
  296. * (head of chain is thread->keys)
  297. * A - Association. Each association is a node at the
  298. * intersection of two doubly-linked lists.
  299. *
  300. * T1 T2 T3
  301. * | | |
  302. * | | |
  303. * K1 -----+-----A-----A----->
  304. * | | |
  305. * | | |
  306. * K2 -----A-----A-----+----->
  307. * | | |
  308. * | | |
  309. * K3 -----A-----+-----A----->
  310. * | | |
  311. * | | |
  312. * V V V
  313. *
  314. * Access to the association is guarded by two locks: the key's
  315. * general lock (guarding the row) and the thread's general
  316. * lock (guarding the column). This avoids the need for a
  317. * dedicated lock for each association, which not only consumes
  318. * more handles but requires that: before the lock handle can
  319. * be released - both the key must be deleted and the thread
  320. * must have called the destructor. The two-lock arrangement
  321. * allows the resources to be freed as soon as either thread or
  322. * key is concluded.
  323. *
  324. * To avoid deadlock: whenever both locks are required, the key
  325. * and thread locks are always acquired in the order: key lock
  326. * then thread lock. An exception to this exists when a thread
  327. * calls the destructors, however this is done carefully to
  328. * avoid deadlock.
  329. *
  330. * An association is created when a thread first calls
  331. * pthread_setspecific() on a key that has a specified
  332. * destructor.
  333. *
  334. * An association is destroyed either immediately after the
  335. * thread calls the key destructor function on thread exit, or
  336. * when the key is deleted.
  337. *
  338. * Attributes:
  339. * thread
  340. * reference to the thread that owns the
  341. * association. This is actually the pointer to the
  342. * thread struct itself. Since the association is
  343. * destroyed before the thread exits, this can never
  344. * point to a different logical thread to the one that
  345. * created the assoc, i.e. after thread struct reuse.
  346. *
  347. * key
  348. * reference to the key that owns the association.
  349. *
  350. * nextKey
  351. * The pthread_t->keys attribute is the head of a
  352. * chain of associations that runs through the nextKey
  353. * link. This chain provides the 1 to many relationship
  354. * between a pthread_t and all pthread_key_t on which
  355. * it called pthread_setspecific.
  356. *
  357. * prevKey
  358. * Similarly.
  359. *
  360. * nextThread
  361. * The pthread_key_t->threads attribute is the head of
  362. * a chain of assoctiations that runs through the
  363. * nextThreads link. This chain provides the 1 to many
  364. * relationship between a pthread_key_t and all the
  365. * PThreads that have called pthread_setspecific for
  366. * this pthread_key_t.
  367. *
  368. * prevThread
  369. * Similarly.
  370. *
  371. * Notes:
  372. * 1) As soon as either the key or the thread is no longer
  373. * referencing the association, it can be destroyed. The
  374. * association will be removed from both chains.
  375. *
  376. * 2) Under WIN32, an association is only created by
  377. * pthread_setspecific if the user provided a
  378. * destroyRoutine when they created the key.
  379. *
  380. *
  381. */
  382. ptw32_thread_t * thread;
  383. pthread_key_t key;
  384. ThreadKeyAssoc *nextKey;
  385. ThreadKeyAssoc *nextThread;
  386. ThreadKeyAssoc *prevKey;
  387. ThreadKeyAssoc *prevThread;
  388. };
  389. #ifdef __CLEANUP_SEH
  390. /*
  391. * --------------------------------------------------------------
  392. * MAKE_SOFTWARE_EXCEPTION
  393. * This macro constructs a software exception code following
  394. * the same format as the standard Win32 error codes as defined
  395. * in WINERROR.H
  396. * Values are 32 bit values layed out as follows:
  397. *
  398. * 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
  399. * +---+-+-+-----------------------+-------------------------------+
  400. * |Sev|C|R| Facility | Code |
  401. * +---+-+-+-----------------------+-------------------------------+
  402. *
  403. * Severity Values:
  404. */
  405. #define SE_SUCCESS 0x00
  406. #define SE_INFORMATION 0x01
  407. #define SE_WARNING 0x02
  408. #define SE_ERROR 0x03
  409. #define MAKE_SOFTWARE_EXCEPTION( _severity, _facility, _exception ) \
  410. ( (DWORD) ( ( (_severity) << 30 ) | /* Severity code */ \
  411. ( 1 << 29 ) | /* MS=0, User=1 */ \
  412. ( 0 << 28 ) | /* Reserved */ \
  413. ( (_facility) << 16 ) | /* Facility Code */ \
  414. ( (_exception) << 0 ) /* Exception Code */ \
  415. ) )
  416. /*
  417. * We choose one specific Facility/Error code combination to
  418. * identify our software exceptions vs. WIN32 exceptions.
  419. * We store our actual component and error code within
  420. * the optional information array.
  421. */
  422. #define EXCEPTION_PTW32_SERVICES \
  423. MAKE_SOFTWARE_EXCEPTION( SE_ERROR, \
  424. PTW32_SERVICES_FACILITY, \
  425. PTW32_SERVICES_ERROR )
  426. #define PTW32_SERVICES_FACILITY 0xBAD
  427. #define PTW32_SERVICES_ERROR 0xDEED
  428. #endif /* __CLEANUP_SEH */
  429. /*
  430. * Services available through EXCEPTION_PTW32_SERVICES
  431. * and also used [as parameters to ptw32_throw()] as
  432. * generic exception selectors.
  433. */
  434. #define PTW32_EPS_EXIT (1)
  435. #define PTW32_EPS_CANCEL (2)
  436. /* Useful macros */
  437. #define PTW32_MAX(a,b) ((a)<(b)?(b):(a))
  438. #define PTW32_MIN(a,b) ((a)>(b)?(b):(a))
  439. /* Declared in global.c */
  440. extern PTW32_INTERLOCKED_LONG (WINAPI *
  441. ptw32_interlocked_compare_exchange)
  442. (PTW32_INTERLOCKED_LPLONG, PTW32_INTERLOCKED_LONG, PTW32_INTERLOCKED_LONG);
  443. /* Declared in pthread_cancel.c */
  444. extern DWORD (*ptw32_register_cancelation) (PAPCFUNC, HANDLE, DWORD);
  445. /* Thread Reuse stack bottom marker. Must not be NULL or any valid pointer to memory. */
  446. #define PTW32_THREAD_REUSE_EMPTY ((ptw32_thread_t *) 1)
  447. extern int ptw32_processInitialized;
  448. extern ptw32_thread_t * ptw32_threadReuseTop;
  449. extern ptw32_thread_t * ptw32_threadReuseBottom;
  450. extern pthread_key_t ptw32_selfThreadKey;
  451. extern pthread_key_t ptw32_cleanupKey;
  452. extern pthread_cond_t ptw32_cond_list_head;
  453. extern pthread_cond_t ptw32_cond_list_tail;
  454. extern int ptw32_mutex_default_kind;
  455. extern int ptw32_concurrency;
  456. extern int ptw32_features;
  457. extern BOOL ptw32_smp_system; /* True: SMP system, False: Uni-processor system */
  458. extern CRITICAL_SECTION ptw32_thread_reuse_lock;
  459. extern CRITICAL_SECTION ptw32_mutex_test_init_lock;
  460. extern CRITICAL_SECTION ptw32_cond_list_lock;
  461. extern CRITICAL_SECTION ptw32_cond_test_init_lock;
  462. extern CRITICAL_SECTION ptw32_rwlock_test_init_lock;
  463. extern CRITICAL_SECTION ptw32_spinlock_test_init_lock;
  464. #ifdef _UWIN
  465. extern int pthread_count;
  466. #endif
  467. #ifdef __cplusplus
  468. extern "C"
  469. {
  470. #endif /* __cplusplus */
  471. /*
  472. * =====================
  473. * =====================
  474. * Forward Declarations
  475. * =====================
  476. * =====================
  477. */
  478. int ptw32_is_attr (const pthread_attr_t * attr);
  479. int ptw32_cond_check_need_init (pthread_cond_t * cond);
  480. int ptw32_mutex_check_need_init (pthread_mutex_t * mutex);
  481. int ptw32_rwlock_check_need_init (pthread_rwlock_t * rwlock);
  482. PTW32_INTERLOCKED_LONG WINAPI
  483. ptw32_InterlockedCompareExchange (PTW32_INTERLOCKED_LPLONG location,
  484. PTW32_INTERLOCKED_LONG value,
  485. PTW32_INTERLOCKED_LONG comparand);
  486. LONG WINAPI
  487. ptw32_InterlockedExchange (LPLONG location,
  488. LONG value);
  489. DWORD
  490. ptw32_RegisterCancelation (PAPCFUNC callback,
  491. HANDLE threadH, DWORD callback_arg);
  492. int ptw32_processInitialize (void);
  493. void ptw32_processTerminate (void);
  494. void ptw32_threadDestroy (pthread_t tid);
  495. void ptw32_pop_cleanup_all (int execute);
  496. pthread_t ptw32_new (void);
  497. pthread_t ptw32_threadReusePop (void);
  498. void ptw32_threadReusePush (pthread_t thread);
  499. int ptw32_getprocessors (int *count);
  500. int ptw32_setthreadpriority (pthread_t thread, int policy, int priority);
  501. void ptw32_rwlock_cancelwrwait (void *arg);
  502. #if ! defined (__MINGW32__) || defined (__MSVCRT__)
  503. unsigned __stdcall
  504. #else
  505. void
  506. #endif
  507. ptw32_threadStart (void *vthreadParms);
  508. void ptw32_callUserDestroyRoutines (pthread_t thread);
  509. int ptw32_tkAssocCreate (ptw32_thread_t * thread, pthread_key_t key);
  510. void ptw32_tkAssocDestroy (ThreadKeyAssoc * assoc);
  511. int ptw32_semwait (sem_t * sem);
  512. DWORD ptw32_relmillisecs (const struct timespec * abstime);
  513. void ptw32_mcs_lock_acquire (ptw32_mcs_lock_t * lock, ptw32_mcs_local_node_t * node);
  514. void ptw32_mcs_lock_release (ptw32_mcs_local_node_t * node);
  515. #ifdef NEED_FTIME
  516. void ptw32_timespec_to_filetime (const struct timespec *ts, FILETIME * ft);
  517. void ptw32_filetime_to_timespec (const FILETIME * ft, struct timespec *ts);
  518. #endif
  519. /* Declared in misc.c */
  520. #ifdef NEED_CALLOC
  521. #define calloc(n, s) ptw32_calloc(n, s)
  522. void *ptw32_calloc (size_t n, size_t s);
  523. #endif
  524. /* Declared in private.c */
  525. void ptw32_throw (DWORD exception);
  526. #ifdef __cplusplus
  527. }
  528. #endif /* __cplusplus */
  529. #ifdef _UWIN_
  530. # ifdef _MT
  531. # ifdef __cplusplus
  532. extern "C"
  533. {
  534. # endif
  535. _CRTIMP unsigned long __cdecl _beginthread (void (__cdecl *) (void *),
  536. unsigned, void *);
  537. _CRTIMP void __cdecl _endthread (void);
  538. _CRTIMP unsigned long __cdecl _beginthreadex (void *, unsigned,
  539. unsigned (__stdcall *) (void *),
  540. void *, unsigned, unsigned *);
  541. _CRTIMP void __cdecl _endthreadex (unsigned);
  542. # ifdef __cplusplus
  543. }
  544. # endif
  545. # endif
  546. #else
  547. # include <process.h>
  548. #endif
  549. /*
  550. * Defaults. Could be overridden when building the inlined version of the dll.
  551. * See ptw32_InterlockedCompareExchange.c
  552. */
  553. #ifndef PTW32_INTERLOCKED_COMPARE_EXCHANGE
  554. #define PTW32_INTERLOCKED_COMPARE_EXCHANGE ptw32_interlocked_compare_exchange
  555. #endif
  556. #ifndef PTW32_INTERLOCKED_EXCHANGE
  557. #define PTW32_INTERLOCKED_EXCHANGE InterlockedExchange
  558. #endif
  559. /*
  560. * Check for old and new versions of cygwin. See the FAQ file:
  561. *
  562. * Question 1 - How do I get pthreads-win32 to link under Cygwin or Mingw32?
  563. *
  564. * Patch by Anders Norlander <anorland@hem2.passagen.se>
  565. */
  566. #if defined(__CYGWIN32__) || defined(__CYGWIN__) || defined(NEED_CREATETHREAD)
  567. /*
  568. * Macro uses args so we can cast start_proc to LPTHREAD_START_ROUTINE
  569. * in order to avoid warnings because of return type
  570. */
  571. #define _beginthreadex(security, \
  572. stack_size, \
  573. start_proc, \
  574. arg, \
  575. flags, \
  576. pid) \
  577. CreateThread(security, \
  578. stack_size, \
  579. (LPTHREAD_START_ROUTINE) start_proc, \
  580. arg, \
  581. flags, \
  582. pid)
  583. #define _endthreadex ExitThread
  584. #endif /* __CYGWIN32__ || __CYGWIN__ || NEED_CREATETHREAD */
  585. #endif /* _IMPLEMENT_H */