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