4
* Definitions that don't need to be public.
6
* Keeps all the internals out of pthread.h
8
* --------------------------------------------------------------------------
10
* Pthreads-win32 - POSIX Threads Library for Win32
11
* Copyright(C) 1998 John E. Bossom
12
* Copyright(C) 1999,2005 Pthreads-win32 contributors
14
* Contact Email: rpj@callisto.canberra.edu.au
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
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.
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.
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
44
#define _WIN32_WINNT 0x400
49
* In case windows.h doesn't define it (e.g. WinCE perhaps)
52
typedef VOID (APIENTRY *PAPCFUNC)(DWORD dwParam);
56
* note: ETIMEDOUT is correctly defined in winsock.h
61
* In case ETIMEDOUT hasn't been defined above somehow.
64
# define ETIMEDOUT 10060 /* This is the value in winsock.h. */
75
/* use local include files during development */
76
#include "semaphore.h"
79
#if defined(HAVE_C_INLINE) || defined(__cplusplus)
85
#if defined (__MINGW32__) || (_MSC_VER >= 1300)
86
#define PTW32_INTERLOCKED_LONG long
87
#define PTW32_INTERLOCKED_LPLONG long*
89
#define PTW32_INTERLOCKED_LONG PVOID
90
#define PTW32_INTERLOCKED_LPLONG PVOID*
93
#if defined(__MINGW32__)
95
#elif defined(__BORLANDC__)
96
#define int64_t ULONGLONG
98
#define int64_t _int64
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".
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 */
123
typedef struct ptw32_thread_t_ ptw32_thread_t;
125
struct ptw32_thread_t_
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;
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 */
147
#endif /* __CLEANUP_C */
150
#endif /* HAVE_SIGSET_T */
158
* Special value to mark attribute objects as valid.
160
#define PTW32_ATTR_VALID ((unsigned long) 0xC4C0FFEE)
162
struct pthread_attr_t_
168
struct sched_param param;
173
#endif /* HAVE_SIGSET_T */
178
* ====================
179
* ====================
180
* Semaphores, Mutexes and Condition Variables
181
* ====================
182
* ====================
188
pthread_mutex_t lock;
195
#define PTW32_OBJECT_AUTO_INIT ((void *) -1)
196
#define PTW32_OBJECT_INVALID NULL
198
struct pthread_mutex_t_
200
LONG lock_idx; /* Provides exclusive access to mutex state
201
via the Interlocked* mechanism.
203
1: locked - no other waiters.
204
-1: locked - with possible other waiters.
206
int recursive_count; /* Number of unlocks a thread needs to perform
207
before the lock is released (recursive
209
int kind; /* Mutex type. */
210
pthread_t ownerThread;
211
HANDLE event; /* Mutex release notification to waiting
215
struct pthread_mutexattr_t_
222
* Possible values, other than PTW32_OBJECT_INVALID,
223
* for the "interlock" element in a spinlock.
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.
235
* "u.cpus" isn't used for anything yet, but could be used at
236
* some point to optimise spinlock behaviour.
238
#define PTW32_SPIN_UNLOCKED (1)
239
#define PTW32_SPIN_LOCKED (2)
240
#define PTW32_SPIN_USE_MUTEX (3)
242
struct pthread_spinlock_t_
244
long interlock; /* Locking element for multi-cpus. */
247
int cpus; /* No. of cpus if multi cpus, or */
248
pthread_mutex_t mutex; /* mutex if single cpu. */
252
struct pthread_barrier_t_
254
unsigned int nCurrentBarrierHeight;
255
unsigned int nInitialBarrierHeight;
258
sem_t semBarrierBreeched[2];
261
struct pthread_barrierattr_t_
266
struct pthread_key_t_
269
void (*destructor) (void *);
270
pthread_mutex_t keyLock;
275
typedef struct ThreadParms ThreadParms;
276
typedef struct ThreadKeyAssoc ThreadKeyAssoc;
281
void *(*start) (void *);
286
struct pthread_cond_t_
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 */
304
struct pthread_condattr_t_
309
#define PTW32_RWLOCK_MAGIC 0xfacade2
311
struct pthread_rwlock_t_
313
pthread_mutex_t mtxExclusiveAccess;
314
pthread_mutex_t mtxSharedAccessCompleted;
315
pthread_cond_t cndSharedAccessCompleted;
316
int nSharedAccessCount;
317
int nExclusiveAccessCount;
318
int nCompletedSharedAccessCount;
322
struct pthread_rwlockattr_t_
328
* MCS lock queue node - see ptw32_MCS_lock.c
330
struct ptw32_mcs_node_t_
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
336
LONG nextFlag; /* set after 'next' ptr is set by
340
typedef struct ptw32_mcs_node_t_ ptw32_mcs_local_node_t;
341
typedef struct ptw32_mcs_node_t_ *ptw32_mcs_lock_t;
344
struct ThreadKeyAssoc
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
353
* Graphically, the arrangement is as follows, where:
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.
365
* K1 -----+-----A-----A----->
368
* K2 -----A-----A-----+----->
371
* K3 -----A-----+-----A----->
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
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
392
* An association is created when a thread first calls
393
* pthread_setspecific() on a key that has a specified
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.
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.
410
* reference to the key that owns the association.
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.
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.
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.
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.
444
ptw32_thread_t * thread;
446
ThreadKeyAssoc *nextKey;
447
ThreadKeyAssoc *nextThread;
448
ThreadKeyAssoc *prevKey;
449
ThreadKeyAssoc *prevThread;
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
460
* Values are 32 bit values layed out as follows:
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
* +---+-+-+-----------------------+-------------------------------+
469
#define SE_SUCCESS 0x00
470
#define SE_INFORMATION 0x01
471
#define SE_WARNING 0x02
472
#define SE_ERROR 0x03
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 */ \
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.
488
#define EXCEPTION_PTW32_SERVICES \
489
MAKE_SOFTWARE_EXCEPTION( SE_ERROR, \
490
PTW32_SERVICES_FACILITY, \
491
PTW32_SERVICES_ERROR )
493
#define PTW32_SERVICES_FACILITY 0xBAD
494
#define PTW32_SERVICES_ERROR 0xDEED
496
#endif /* __CLEANUP_SEH */
499
* Services available through EXCEPTION_PTW32_SERVICES
500
* and also used [as parameters to ptw32_throw()] as
501
* generic exception selectors.
504
#define PTW32_EPS_EXIT (1)
505
#define PTW32_EPS_CANCEL (2)
509
#define PTW32_MAX(a,b) ((a)<(b)?(b):(a))
510
#define PTW32_MIN(a,b) ((a)>(b)?(b):(a))
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);
518
/* Declared in pthread_cancel.c */
519
extern DWORD (*ptw32_register_cancelation) (PAPCFUNC, HANDLE, DWORD);
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)
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;
532
extern int ptw32_mutex_default_kind;
534
extern int ptw32_concurrency;
536
extern int ptw32_features;
538
extern BOOL ptw32_smp_system; /* True: SMP system, False: Uni-processor system */
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;
548
extern int pthread_count;
554
#endif /* __cplusplus */
557
* =====================
558
* =====================
559
* Forward Declarations
560
* =====================
561
* =====================
564
int ptw32_is_attr (const pthread_attr_t * attr);
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
int ptw32_spinlock_check_need_init (pthread_spinlock_t * spinlock);
571
PTW32_INTERLOCKED_LONG WINAPI
572
ptw32_InterlockedCompareExchange (PTW32_INTERLOCKED_LPLONG location,
573
PTW32_INTERLOCKED_LONG value,
574
PTW32_INTERLOCKED_LONG comparand);
577
ptw32_InterlockedExchange (LPLONG location,
581
ptw32_RegisterCancelation (PAPCFUNC callback,
582
HANDLE threadH, DWORD callback_arg);
584
int ptw32_processInitialize (void);
586
void ptw32_processTerminate (void);
588
void ptw32_threadDestroy (pthread_t tid);
590
void ptw32_pop_cleanup_all (int execute);
592
pthread_t ptw32_new (void);
594
pthread_t ptw32_threadReusePop (void);
596
void ptw32_threadReusePush (pthread_t thread);
598
int ptw32_getprocessors (int *count);
600
int ptw32_setthreadpriority (pthread_t thread, int policy, int priority);
602
void ptw32_rwlock_cancelwrwait (void *arg);
604
#if ! defined (__MINGW32__) || defined (__MSVCRT__)
609
ptw32_threadStart (void *vthreadParms);
611
void ptw32_callUserDestroyRoutines (pthread_t thread);
613
int ptw32_tkAssocCreate (ptw32_thread_t * thread, pthread_key_t key);
615
void ptw32_tkAssocDestroy (ThreadKeyAssoc * assoc);
617
int ptw32_semwait (sem_t * sem);
619
DWORD ptw32_relmillisecs (const struct timespec * abstime);
621
void ptw32_mcs_lock_acquire (ptw32_mcs_lock_t * lock, ptw32_mcs_local_node_t * node);
623
void ptw32_mcs_lock_release (ptw32_mcs_local_node_t * node);
626
void ptw32_timespec_to_filetime (const struct timespec *ts, FILETIME * ft);
627
void ptw32_filetime_to_timespec (const FILETIME * ft, struct timespec *ts);
630
/* Declared in misc.c */
632
#define calloc(n, s) ptw32_calloc(n, s)
633
void *ptw32_calloc (size_t n, size_t s);
636
/* Declared in private.c */
637
void ptw32_throw (DWORD exception);
641
#endif /* __cplusplus */
650
_CRTIMP unsigned long __cdecl _beginthread (void (__cdecl *) (void *),
652
_CRTIMP void __cdecl _endthread (void);
653
_CRTIMP unsigned long __cdecl _beginthreadex (void *, unsigned,
654
unsigned (__stdcall *) (void *),
655
void *, unsigned, unsigned *);
656
_CRTIMP void __cdecl _endthreadex (unsigned);
663
# include <process.h>
669
* Defaults. Could be overridden when building the inlined version of the dll.
670
* See ptw32_InterlockedCompareExchange.c
672
#ifndef PTW32_INTERLOCKED_COMPARE_EXCHANGE
675
* InterlockedCompareExchange is an intrinsic function in Win64.
677
# define PTW32_INTERLOCKED_COMPARE_EXCHANGE _InterlockedCompareExchange
680
* The routine pthread_win32_process_attach_np() in pthread_win32_attach_detach_np.c
681
* checks at runtime that InterlockedCompareExchange is supported within
682
* KERNEL32.DLL (or COREDLL.DLL for WinCE). This allows the same
683
* dll to run on all Win32 versions from Win95 onwards. Not sure if this
684
* is required for WinCE, but should work just the same anyway.
686
# define PTW32_INTERLOCKED_COMPARE_EXCHANGE ptw32_interlocked_compare_exchange
690
#ifndef PTW32_INTERLOCKED_EXCHANGE
691
#define PTW32_INTERLOCKED_EXCHANGE InterlockedExchange
696
* Check for old and new versions of cygwin. See the FAQ file:
698
* Question 1 - How do I get pthreads-win32 to link under Cygwin or Mingw32?
700
* Patch by Anders Norlander <anorland@hem2.passagen.se>
702
#if defined(__CYGWIN32__) || defined(__CYGWIN__) || defined(NEED_CREATETHREAD)
705
* Macro uses args so we can cast start_proc to LPTHREAD_START_ROUTINE
706
* in order to avoid warnings because of return type
709
#define _beginthreadex(security, \
715
CreateThread(security, \
717
(LPTHREAD_START_ROUTINE) start_proc, \
722
#define _endthreadex ExitThread
724
#endif /* __CYGWIN32__ || __CYGWIN__ || NEED_CREATETHREAD */
727
#endif /* _IMPLEMENT_H */