Eneboo - Documentación para desarrolladores
|
00001 /* 00002 * implement.h 00003 * 00004 * Definitions that don't need to be public. 00005 * 00006 * Keeps all the internals out of pthread.h 00007 * 00008 * -------------------------------------------------------------------------- 00009 * 00010 * Pthreads-win32 - POSIX Threads Library for Win32 00011 * Copyright(C) 1998 John E. Bossom 00012 * Copyright(C) 1999,2005 Pthreads-win32 contributors 00013 * 00014 * Contact Email: rpj@callisto.canberra.edu.au 00015 * 00016 * The current list of contributors is contained 00017 * in the file CONTRIBUTORS included with the source 00018 * code distribution. The list can also be seen at the 00019 * following World Wide Web location: 00020 * http://sources.redhat.com/pthreads-win32/contributors.html 00021 * 00022 * This library is free software; you can redistribute it and/or 00023 * modify it under the terms of the GNU Lesser General Public 00024 * License as published by the Free Software Foundation; either 00025 * version 2 of the License, or (at your option) any later version. 00026 * 00027 * This library is distributed in the hope that it will be useful, 00028 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00029 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00030 * Lesser General Public License for more details. 00031 * 00032 * You should have received a copy of the GNU Lesser General Public 00033 * License along with this library in the file COPYING.LIB; 00034 * if not, write to the Free Software Foundation, Inc., 00035 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA 00036 */ 00037 00038 #ifndef _IMPLEMENT_H 00039 #define _IMPLEMENT_H 00040 00041 #ifdef _WIN32_WINNT 00042 #undef _WIN32_WINNT 00043 #endif 00044 #define _WIN32_WINNT 0x400 00045 00046 #include <windows.h> 00047 00048 /* 00049 * In case windows.h doesn't define it (e.g. WinCE perhaps) 00050 */ 00051 #ifdef WINCE 00052 typedef VOID (APIENTRY *PAPCFUNC)(DWORD dwParam); 00053 #endif 00054 00055 /* 00056 * note: ETIMEDOUT is correctly defined in winsock.h 00057 */ 00058 #include <winsock.h> 00059 00060 /* 00061 * In case ETIMEDOUT hasn't been defined above somehow. 00062 */ 00063 #ifndef ETIMEDOUT 00064 # define ETIMEDOUT 10060 /* This is the value in winsock.h. */ 00065 #endif 00066 00067 #if !defined(malloc) 00068 #include <malloc.h> 00069 #endif 00070 00071 #if !defined(INT_MAX) 00072 #include <limits.h> 00073 #endif 00074 00075 /* use local include files during development */ 00076 #include "semaphore.h" 00077 #include "sched.h" 00078 00079 #if defined(HAVE_C_INLINE) || defined(__cplusplus) 00080 #define INLINE 00081 #else 00082 #define INLINE 00083 #endif 00084 00085 #if defined (__MINGW32__) || (_MSC_VER >= 1300) 00086 #define PTW32_INTERLOCKED_LONG long 00087 #define PTW32_INTERLOCKED_LPLONG long* 00088 #else 00089 #define PTW32_INTERLOCKED_LONG PVOID 00090 #define PTW32_INTERLOCKED_LPLONG PVOID* 00091 #endif 00092 00093 #if defined(__MINGW32__) 00094 #include <stdint.h> 00095 #elif defined(__BORLANDC__) 00096 #define int64_t ULONGLONG 00097 #else 00098 #define int64_t _int64 00099 #endif 00100 00101 typedef enum 00102 { 00103 /* 00104 * This enumeration represents the state of the thread; 00105 * The thread is still "alive" if the numeric value of the 00106 * state is greater or equal "PThreadStateRunning". 00107 */ 00108 PThreadStateInitial = 0, /* Thread not running */ 00109 PThreadStateRunning, /* Thread alive & kicking */ 00110 PThreadStateSuspended, /* Thread alive but suspended */ 00111 PThreadStateCancelPending, /* Thread alive but is */ 00112 /* has cancelation pending. */ 00113 PThreadStateCanceling, /* Thread alive but is */ 00114 /* in the process of terminating */ 00115 /* due to a cancellation request */ 00116 PThreadStateException, /* Thread alive but exiting */ 00117 /* due to an exception */ 00118 PThreadStateLast 00119 } 00120 PThreadState; 00121 00122 00123 typedef struct ptw32_thread_t_ ptw32_thread_t; 00124 00125 struct ptw32_thread_t_ 00126 { 00127 #ifdef _UWIN 00128 DWORD dummy[5]; 00129 #endif 00130 DWORD thread; 00131 HANDLE threadH; /* Win32 thread handle - POSIX thread is invalid if threadH == 0 */ 00132 pthread_t ptHandle; /* This thread's permanent pthread_t handle */ 00133 ptw32_thread_t * prevReuse; /* Links threads on reuse stack */ 00134 volatile PThreadState state; 00135 void *exitStatus; 00136 void *parms; 00137 int ptErrno; 00138 int detachState; 00139 pthread_mutex_t threadLock; /* Used for serialised access to public thread state */ 00140 int sched_priority; /* As set, not as currently is */ 00141 pthread_mutex_t cancelLock; /* Used for async-cancel safety */ 00142 int cancelState; 00143 int cancelType; 00144 HANDLE cancelEvent; 00145 #ifdef __CLEANUP_C 00146 jmp_buf start_mark; 00147 #endif /* __CLEANUP_C */ 00148 #if HAVE_SIGSET_T 00149 sigset_t sigmask; 00150 #endif /* HAVE_SIGSET_T */ 00151 int implicit:1; 00152 void *keys; 00153 void *nextAssoc; 00154 }; 00155 00156 00157 /* 00158 * Special value to mark attribute objects as valid. 00159 */ 00160 #define PTW32_ATTR_VALID ((unsigned long) 0xC4C0FFEE) 00161 00162 struct pthread_attr_t_ 00163 { 00164 unsigned long valid; 00165 void *stackaddr; 00166 size_t stacksize; 00167 int detachstate; 00168 struct sched_param param; 00169 int inheritsched; 00170 int contentionscope; 00171 #if HAVE_SIGSET_T 00172 sigset_t sigmask; 00173 #endif /* HAVE_SIGSET_T */ 00174 }; 00175 00176 00177 /* 00178 * ==================== 00179 * ==================== 00180 * Semaphores, Mutexes and Condition Variables 00181 * ==================== 00182 * ==================== 00183 */ 00184 00185 struct sem_t_ 00186 { 00187 int value; 00188 pthread_mutex_t lock; 00189 HANDLE sem; 00190 #ifdef NEED_SEM 00191 int leftToUnblock; 00192 #endif 00193 }; 00194 00195 #define PTW32_OBJECT_AUTO_INIT ((void *) -1) 00196 #define PTW32_OBJECT_INVALID NULL 00197 00198 struct pthread_mutex_t_ 00199 { 00200 LONG lock_idx; /* Provides exclusive access to mutex state 00201 via the Interlocked* mechanism. 00202 0: unlocked/free. 00203 1: locked - no other waiters. 00204 -1: locked - with possible other waiters. 00205 */ 00206 int recursive_count; /* Number of unlocks a thread needs to perform 00207 before the lock is released (recursive 00208 mutexes only). */ 00209 int kind; /* Mutex type. */ 00210 pthread_t ownerThread; 00211 HANDLE event; /* Mutex release notification to waiting 00212 threads. */ 00213 }; 00214 00215 struct pthread_mutexattr_t_ 00216 { 00217 int pshared; 00218 int kind; 00219 }; 00220 00221 /* 00222 * Possible values, other than PTW32_OBJECT_INVALID, 00223 * for the "interlock" element in a spinlock. 00224 * 00225 * In this implementation, when a spinlock is initialised, 00226 * the number of cpus available to the process is checked. 00227 * If there is only one cpu then "interlock" is set equal to 00228 * PTW32_SPIN_USE_MUTEX and u.mutex is a initialised mutex. 00229 * If the number of cpus is greater than 1 then "interlock" 00230 * is set equal to PTW32_SPIN_UNLOCKED and the number is 00231 * stored in u.cpus. This arrangement allows the spinlock 00232 * routines to attempt an InterlockedCompareExchange on "interlock" 00233 * immediately and, if that fails, to try the inferior mutex. 00234 * 00235 * "u.cpus" isn't used for anything yet, but could be used at 00236 * some point to optimise spinlock behaviour. 00237 */ 00238 #define PTW32_SPIN_UNLOCKED (1) 00239 #define PTW32_SPIN_LOCKED (2) 00240 #define PTW32_SPIN_USE_MUTEX (3) 00241 00242 struct pthread_spinlock_t_ 00243 { 00244 long interlock; /* Locking element for multi-cpus. */ 00245 union 00246 { 00247 int cpus; /* No. of cpus if multi cpus, or */ 00248 pthread_mutex_t mutex; /* mutex if single cpu. */ 00249 } u; 00250 }; 00251 00252 struct pthread_barrier_t_ 00253 { 00254 unsigned int nCurrentBarrierHeight; 00255 unsigned int nInitialBarrierHeight; 00256 int iStep; 00257 int pshared; 00258 sem_t semBarrierBreeched[2]; 00259 }; 00260 00261 struct pthread_barrierattr_t_ 00262 { 00263 int pshared; 00264 }; 00265 00266 struct pthread_key_t_ 00267 { 00268 DWORD key; 00269 void (*destructor) (void *); 00270 pthread_mutex_t keyLock; 00271 void *threads; 00272 }; 00273 00274 00275 typedef struct ThreadParms ThreadParms; 00276 typedef struct ThreadKeyAssoc ThreadKeyAssoc; 00277 00278 struct ThreadParms 00279 { 00280 pthread_t tid; 00281 void *(*start) (void *); 00282 void *arg; 00283 }; 00284 00285 00286 struct pthread_cond_t_ 00287 { 00288 long nWaitersBlocked; /* Number of threads blocked */ 00289 long nWaitersGone; /* Number of threads timed out */ 00290 long nWaitersToUnblock; /* Number of threads to unblock */ 00291 sem_t semBlockQueue; /* Queue up threads waiting for the */ 00292 /* condition to become signalled */ 00293 sem_t semBlockLock; /* Semaphore that guards access to */ 00294 /* | waiters blocked count/block queue */ 00295 /* +-> Mandatory Sync.LEVEL-1 */ 00296 pthread_mutex_t mtxUnblockLock; /* Mutex that guards access to */ 00297 /* | waiters (to)unblock(ed) counts */ 00298 /* +-> Optional* Sync.LEVEL-2 */ 00299 pthread_cond_t next; /* Doubly linked list */ 00300 pthread_cond_t prev; 00301 }; 00302 00303 00304 struct pthread_condattr_t_ 00305 { 00306 int pshared; 00307 }; 00308 00309 #define PTW32_RWLOCK_MAGIC 0xfacade2 00310 00311 struct pthread_rwlock_t_ 00312 { 00313 pthread_mutex_t mtxExclusiveAccess; 00314 pthread_mutex_t mtxSharedAccessCompleted; 00315 pthread_cond_t cndSharedAccessCompleted; 00316 int nSharedAccessCount; 00317 int nExclusiveAccessCount; 00318 int nCompletedSharedAccessCount; 00319 int nMagic; 00320 }; 00321 00322 struct pthread_rwlockattr_t_ 00323 { 00324 int pshared; 00325 }; 00326 00327 /* 00328 * MCS lock queue node - see ptw32_MCS_lock.c 00329 */ 00330 struct ptw32_mcs_node_t_ 00331 { 00332 struct ptw32_mcs_node_t_ **lock; /* ptr to tail of queue */ 00333 struct ptw32_mcs_node_t_ *next; /* ptr to successor in queue */ 00334 LONG readyFlag; /* set after lock is released by 00335 predecessor */ 00336 LONG nextFlag; /* set after 'next' ptr is set by 00337 successor */ 00338 }; 00339 00340 typedef struct ptw32_mcs_node_t_ ptw32_mcs_local_node_t; 00341 typedef struct ptw32_mcs_node_t_ *ptw32_mcs_lock_t; 00342 00343 00344 struct ThreadKeyAssoc 00345 { 00346 /* 00347 * Purpose: 00348 * This structure creates an association between a thread and a key. 00349 * It is used to implement the implicit invocation of a user defined 00350 * destroy routine for thread specific data registered by a user upon 00351 * exiting a thread. 00352 * 00353 * Graphically, the arrangement is as follows, where: 00354 * 00355 * K - Key with destructor 00356 * (head of chain is key->threads) 00357 * T - Thread that has called pthread_setspecific(Kn) 00358 * (head of chain is thread->keys) 00359 * A - Association. Each association is a node at the 00360 * intersection of two doubly-linked lists. 00361 * 00362 * T1 T2 T3 00363 * | | | 00364 * | | | 00365 * K1 -----+-----A-----A-----> 00366 * | | | 00367 * | | | 00368 * K2 -----A-----A-----+-----> 00369 * | | | 00370 * | | | 00371 * K3 -----A-----+-----A-----> 00372 * | | | 00373 * | | | 00374 * V V V 00375 * 00376 * Access to the association is guarded by two locks: the key's 00377 * general lock (guarding the row) and the thread's general 00378 * lock (guarding the column). This avoids the need for a 00379 * dedicated lock for each association, which not only consumes 00380 * more handles but requires that: before the lock handle can 00381 * be released - both the key must be deleted and the thread 00382 * must have called the destructor. The two-lock arrangement 00383 * allows the resources to be freed as soon as either thread or 00384 * key is concluded. 00385 * 00386 * To avoid deadlock: whenever both locks are required, the key 00387 * and thread locks are always acquired in the order: key lock 00388 * then thread lock. An exception to this exists when a thread 00389 * calls the destructors, however this is done carefully to 00390 * avoid deadlock. 00391 * 00392 * An association is created when a thread first calls 00393 * pthread_setspecific() on a key that has a specified 00394 * destructor. 00395 * 00396 * An association is destroyed either immediately after the 00397 * thread calls the key destructor function on thread exit, or 00398 * when the key is deleted. 00399 * 00400 * Attributes: 00401 * thread 00402 * reference to the thread that owns the 00403 * association. This is actually the pointer to the 00404 * thread struct itself. Since the association is 00405 * destroyed before the thread exits, this can never 00406 * point to a different logical thread to the one that 00407 * created the assoc, i.e. after thread struct reuse. 00408 * 00409 * key 00410 * reference to the key that owns the association. 00411 * 00412 * nextKey 00413 * The pthread_t->keys attribute is the head of a 00414 * chain of associations that runs through the nextKey 00415 * link. This chain provides the 1 to many relationship 00416 * between a pthread_t and all pthread_key_t on which 00417 * it called pthread_setspecific. 00418 * 00419 * prevKey 00420 * Similarly. 00421 * 00422 * nextThread 00423 * The pthread_key_t->threads attribute is the head of 00424 * a chain of assoctiations that runs through the 00425 * nextThreads link. This chain provides the 1 to many 00426 * relationship between a pthread_key_t and all the 00427 * PThreads that have called pthread_setspecific for 00428 * this pthread_key_t. 00429 * 00430 * prevThread 00431 * Similarly. 00432 * 00433 * Notes: 00434 * 1) As soon as either the key or the thread is no longer 00435 * referencing the association, it can be destroyed. The 00436 * association will be removed from both chains. 00437 * 00438 * 2) Under WIN32, an association is only created by 00439 * pthread_setspecific if the user provided a 00440 * destroyRoutine when they created the key. 00441 * 00442 * 00443 */ 00444 ptw32_thread_t * thread; 00445 pthread_key_t key; 00446 ThreadKeyAssoc *nextKey; 00447 ThreadKeyAssoc *nextThread; 00448 ThreadKeyAssoc *prevKey; 00449 ThreadKeyAssoc *prevThread; 00450 }; 00451 00452 00453 #ifdef __CLEANUP_SEH 00454 /* 00455 * -------------------------------------------------------------- 00456 * MAKE_SOFTWARE_EXCEPTION 00457 * This macro constructs a software exception code following 00458 * the same format as the standard Win32 error codes as defined 00459 * in WINERROR.H 00460 * Values are 32 bit values layed out as follows: 00461 * 00462 * 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 00463 * +---+-+-+-----------------------+-------------------------------+ 00464 * |Sev|C|R| Facility | Code | 00465 * +---+-+-+-----------------------+-------------------------------+ 00466 * 00467 * Severity Values: 00468 */ 00469 #define SE_SUCCESS 0x00 00470 #define SE_INFORMATION 0x01 00471 #define SE_WARNING 0x02 00472 #define SE_ERROR 0x03 00473 00474 #define MAKE_SOFTWARE_EXCEPTION( _severity, _facility, _exception ) \ 00475 ( (DWORD) ( ( (_severity) << 30 ) | /* Severity code */ \ 00476 ( 1 << 29 ) | /* MS=0, User=1 */ \ 00477 ( 0 << 28 ) | /* Reserved */ \ 00478 ( (_facility) << 16 ) | /* Facility Code */ \ 00479 ( (_exception) << 0 ) /* Exception Code */ \ 00480 ) ) 00481 00482 /* 00483 * We choose one specific Facility/Error code combination to 00484 * identify our software exceptions vs. WIN32 exceptions. 00485 * We store our actual component and error code within 00486 * the optional information array. 00487 */ 00488 #define EXCEPTION_PTW32_SERVICES \ 00489 MAKE_SOFTWARE_EXCEPTION( SE_ERROR, \ 00490 PTW32_SERVICES_FACILITY, \ 00491 PTW32_SERVICES_ERROR ) 00492 00493 #define PTW32_SERVICES_FACILITY 0xBAD 00494 #define PTW32_SERVICES_ERROR 0xDEED 00495 00496 #endif /* __CLEANUP_SEH */ 00497 00498 /* 00499 * Services available through EXCEPTION_PTW32_SERVICES 00500 * and also used [as parameters to ptw32_throw()] as 00501 * generic exception selectors. 00502 */ 00503 00504 #define PTW32_EPS_EXIT (1) 00505 #define PTW32_EPS_CANCEL (2) 00506 00507 00508 /* Useful macros */ 00509 #define PTW32_MAX(a,b) ((a)<(b)?(b):(a)) 00510 #define PTW32_MIN(a,b) ((a)>(b)?(b):(a)) 00511 00512 00513 /* Declared in global.c */ 00514 extern PTW32_INTERLOCKED_LONG (WINAPI * 00515 ptw32_interlocked_compare_exchange) 00516 (PTW32_INTERLOCKED_LPLONG, PTW32_INTERLOCKED_LONG, PTW32_INTERLOCKED_LONG); 00517 00518 /* Declared in pthread_cancel.c */ 00519 extern DWORD (*ptw32_register_cancelation) (PAPCFUNC, HANDLE, DWORD); 00520 00521 /* Thread Reuse stack bottom marker. Must not be NULL or any valid pointer to memory. */ 00522 #define PTW32_THREAD_REUSE_EMPTY ((ptw32_thread_t *) 1) 00523 00524 extern int ptw32_processInitialized; 00525 extern ptw32_thread_t * ptw32_threadReuseTop; 00526 extern ptw32_thread_t * ptw32_threadReuseBottom; 00527 extern pthread_key_t ptw32_selfThreadKey; 00528 extern pthread_key_t ptw32_cleanupKey; 00529 extern pthread_cond_t ptw32_cond_list_head; 00530 extern pthread_cond_t ptw32_cond_list_tail; 00531 00532 extern int ptw32_mutex_default_kind; 00533 00534 extern int ptw32_concurrency; 00535 00536 extern int ptw32_features; 00537 00538 extern BOOL ptw32_smp_system; /* True: SMP system, False: Uni-processor system */ 00539 00540 extern CRITICAL_SECTION ptw32_thread_reuse_lock; 00541 extern CRITICAL_SECTION ptw32_mutex_test_init_lock; 00542 extern CRITICAL_SECTION ptw32_cond_list_lock; 00543 extern CRITICAL_SECTION ptw32_cond_test_init_lock; 00544 extern CRITICAL_SECTION ptw32_rwlock_test_init_lock; 00545 extern CRITICAL_SECTION ptw32_spinlock_test_init_lock; 00546 00547 #ifdef _UWIN 00548 extern int pthread_count; 00549 #endif 00550 00551 #ifdef __cplusplus 00552 extern "C" 00553 { 00554 #endif /* __cplusplus */ 00555 00556 /* 00557 * ===================== 00558 * ===================== 00559 * Forward Declarations 00560 * ===================== 00561 * ===================== 00562 */ 00563 00564 int ptw32_is_attr (const pthread_attr_t * attr); 00565 00566 int ptw32_cond_check_need_init (pthread_cond_t * cond); 00567 int ptw32_mutex_check_need_init (pthread_mutex_t * mutex); 00568 int ptw32_rwlock_check_need_init (pthread_rwlock_t * rwlock); 00569 00570 PTW32_INTERLOCKED_LONG WINAPI 00571 ptw32_InterlockedCompareExchange (PTW32_INTERLOCKED_LPLONG location, 00572 PTW32_INTERLOCKED_LONG value, 00573 PTW32_INTERLOCKED_LONG comparand); 00574 00575 LONG WINAPI 00576 ptw32_InterlockedExchange (LPLONG location, 00577 LONG value); 00578 00579 DWORD 00580 ptw32_RegisterCancelation (PAPCFUNC callback, 00581 HANDLE threadH, DWORD callback_arg); 00582 00583 int ptw32_processInitialize (void); 00584 00585 void ptw32_processTerminate (void); 00586 00587 void ptw32_threadDestroy (pthread_t tid); 00588 00589 void ptw32_pop_cleanup_all (int execute); 00590 00591 pthread_t ptw32_new (void); 00592 00593 pthread_t ptw32_threadReusePop (void); 00594 00595 void ptw32_threadReusePush (pthread_t thread); 00596 00597 int ptw32_getprocessors (int *count); 00598 00599 int ptw32_setthreadpriority (pthread_t thread, int policy, int priority); 00600 00601 void ptw32_rwlock_cancelwrwait (void *arg); 00602 00603 #if ! defined (__MINGW32__) || defined (__MSVCRT__) 00604 unsigned __stdcall 00605 #else 00606 void 00607 #endif 00608 ptw32_threadStart (void *vthreadParms); 00609 00610 void ptw32_callUserDestroyRoutines (pthread_t thread); 00611 00612 int ptw32_tkAssocCreate (ptw32_thread_t * thread, pthread_key_t key); 00613 00614 void ptw32_tkAssocDestroy (ThreadKeyAssoc * assoc); 00615 00616 int ptw32_semwait (sem_t * sem); 00617 00618 DWORD ptw32_relmillisecs (const struct timespec * abstime); 00619 00620 void ptw32_mcs_lock_acquire (ptw32_mcs_lock_t * lock, ptw32_mcs_local_node_t * node); 00621 00622 void ptw32_mcs_lock_release (ptw32_mcs_local_node_t * node); 00623 00624 #ifdef NEED_FTIME 00625 void ptw32_timespec_to_filetime (const struct timespec *ts, FILETIME * ft); 00626 void ptw32_filetime_to_timespec (const FILETIME * ft, struct timespec *ts); 00627 #endif 00628 00629 /* Declared in misc.c */ 00630 #ifdef NEED_CALLOC 00631 #define calloc(n, s) ptw32_calloc(n, s) 00632 void *ptw32_calloc (size_t n, size_t s); 00633 #endif 00634 00635 /* Declared in private.c */ 00636 void ptw32_throw (DWORD exception); 00637 00638 #ifdef __cplusplus 00639 } 00640 #endif /* __cplusplus */ 00641 00642 00643 #ifdef _UWIN_ 00644 # ifdef _MT 00645 # ifdef __cplusplus 00646 extern "C" 00647 { 00648 # endif 00649 _CRTIMP unsigned long __cdecl _beginthread (void (__cdecl *) (void *), 00650 unsigned, void *); 00651 _CRTIMP void __cdecl _endthread (void); 00652 _CRTIMP unsigned long __cdecl _beginthreadex (void *, unsigned, 00653 unsigned (__stdcall *) (void *), 00654 void *, unsigned, unsigned *); 00655 _CRTIMP void __cdecl _endthreadex (unsigned); 00656 # ifdef __cplusplus 00657 } 00658 # endif 00659 # endif 00660 #else 00661 # include <process.h> 00662 #endif 00663 00664 00665 /* 00666 * Defaults. Could be overridden when building the inlined version of the dll. 00667 * See ptw32_InterlockedCompareExchange.c 00668 */ 00669 #ifndef PTW32_INTERLOCKED_COMPARE_EXCHANGE 00670 #define PTW32_INTERLOCKED_COMPARE_EXCHANGE ptw32_interlocked_compare_exchange 00671 #endif 00672 00673 #ifndef PTW32_INTERLOCKED_EXCHANGE 00674 #define PTW32_INTERLOCKED_EXCHANGE InterlockedExchange 00675 #endif 00676 00677 00678 /* 00679 * Check for old and new versions of cygwin. See the FAQ file: 00680 * 00681 * Question 1 - How do I get pthreads-win32 to link under Cygwin or Mingw32? 00682 * 00683 * Patch by Anders Norlander <anorland@hem2.passagen.se> 00684 */ 00685 #if defined(__CYGWIN32__) || defined(__CYGWIN__) || defined(NEED_CREATETHREAD) 00686 00687 /* 00688 * Macro uses args so we can cast start_proc to LPTHREAD_START_ROUTINE 00689 * in order to avoid warnings because of return type 00690 */ 00691 00692 #define _beginthreadex(security, \ 00693 stack_size, \ 00694 start_proc, \ 00695 arg, \ 00696 flags, \ 00697 pid) \ 00698 CreateThread(security, \ 00699 stack_size, \ 00700 (LPTHREAD_START_ROUTINE) start_proc, \ 00701 arg, \ 00702 flags, \ 00703 pid) 00704 00705 #define _endthreadex ExitThread 00706 00707 #endif /* __CYGWIN32__ || __CYGWIN__ || NEED_CREATETHREAD */ 00708 00709 00710 #endif /* _IMPLEMENT_H */