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