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