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

Last change on this file was 191, checked in by tim, 14 years ago

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

File size: 20.4 KB
Line 
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.