source: win32/libpthreads-w32-2.8.0/include/implement.h @ 273

Last change on this file since 273 was 191, checked in by tim, 15 years ago

updated scons build scripts to handle MinGW
added binaries for MinGW build dependencies

File size: 20.4 KB
RevLine 
[191]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
52typedef 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
101typedef 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}
120PThreadState;
121
122
123typedef struct ptw32_thread_t_ ptw32_thread_t;
124
125struct 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
162struct 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
185struct 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
198struct 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
215struct 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
242struct 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
252struct 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
261struct pthread_barrierattr_t_
262{
263  int pshared;
264};
265
266struct pthread_key_t_
267{
268  DWORD key;
269  void (*destructor) (void *);
270  pthread_mutex_t keyLock;
271  void *threads;
272};
273
274
275typedef struct ThreadParms ThreadParms;
276typedef struct ThreadKeyAssoc ThreadKeyAssoc;
277
278struct ThreadParms
279{
280  pthread_t tid;
281  void *(*start) (void *);
282  void *arg;
283};
284
285
286struct 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
304struct pthread_condattr_t_
305{
306  int pshared;
307};
308
309#define PTW32_RWLOCK_MAGIC 0xfacade2
310
311struct 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
322struct pthread_rwlockattr_t_
323{
324  int pshared;
325};
326
327/*
328 * MCS lock queue node - see ptw32_MCS_lock.c
329 */
330struct 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
340typedef struct ptw32_mcs_node_t_   ptw32_mcs_local_node_t;
341typedef struct ptw32_mcs_node_t_  *ptw32_mcs_lock_t;
342
343
344struct 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 */
514extern 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 */
519extern 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
524extern int ptw32_processInitialized;
525extern ptw32_thread_t * ptw32_threadReuseTop;
526extern ptw32_thread_t * ptw32_threadReuseBottom;
527extern pthread_key_t ptw32_selfThreadKey;
528extern pthread_key_t ptw32_cleanupKey;
529extern pthread_cond_t ptw32_cond_list_head;
530extern pthread_cond_t ptw32_cond_list_tail;
531
532extern int ptw32_mutex_default_kind;
533
534extern int ptw32_concurrency;
535
536extern int ptw32_features;
537
538extern BOOL ptw32_smp_system;  /* True: SMP system, False: Uni-processor system */
539
540extern CRITICAL_SECTION ptw32_thread_reuse_lock;
541extern CRITICAL_SECTION ptw32_mutex_test_init_lock;
542extern CRITICAL_SECTION ptw32_cond_list_lock;
543extern CRITICAL_SECTION ptw32_cond_test_init_lock;
544extern CRITICAL_SECTION ptw32_rwlock_test_init_lock;
545extern CRITICAL_SECTION ptw32_spinlock_test_init_lock;
546
547#ifdef _UWIN
548extern int pthread_count;
549#endif
550
551#ifdef __cplusplus
552extern "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
646extern "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 */
Note: See TracBrowser for help on using the repository browser.