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 * Pthreads4w - POSIX Threads for Windows
11 * Copyright 1998 John E. Bossom
12 * Copyright 1999-2018, Pthreads4w contributors
13 *
14 * Homepage: https://sourceforge.net/projects/pthreads4w/
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 *
21 * https://sourceforge.net/p/pthreads4w/wiki/Contributors/
22 *
23 * Licensed under the Apache License, Version 2.0 (the "License");
24 * you may not use this file except in compliance with the License.
25 * You may obtain a copy of the License at
26 *
27 * http://www.apache.org/licenses/LICENSE-2.0
28 *
29 * Unless required by applicable law or agreed to in writing, software
30 * distributed under the License is distributed on an "AS IS" BASIS,
31 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
32 * See the License for the specific language governing permissions and
33 * limitations under the License.
34 */
35
36 #if !defined(_IMPLEMENT_H)
37 #define _IMPLEMENT_H
38
39 #if !defined (__PTW32_CONFIG_H)
40 # error "config.h was not #included"
41 #endif
42
43 #include <_ptw32.h>
44
45 #if !defined(_WIN32_WINNT)
46 # define _WIN32_WINNT 0x0400
47 #endif
48
49 #define WIN32_LEAN_AND_MEAN
50
51 #include <windows.h>
52 #include <sys/types.h>
53 /*
54 * In case windows.h doesn't define it (e.g. WinCE perhaps)
55 */
56 #if defined(WINCE)
57 typedef VOID (APIENTRY *PAPCFUNC)(DWORD dwParam);
58 #endif
59
60 /*
61 * Designed to allow error values to be set and retrieved in builds where
62 * MSCRT libraries are statically linked to DLLs.
63 *
64 * This does not handle the case where a static pthreads4w lib is linked
65 * to a static linked app. Compiling and linking pthreads.c with app.c
66 * as one does work with the right macros defined. See tests/Makefile
67 * for clues or just "cd tests && nmake clean VC-static".
68 */
69 #if ! defined(WINCE) && \
70 (( defined(__MINGW32__) && __MSVCRT_VERSION__ >= 0x0800 ) || \
71 ( defined(_MSC_VER) && _MSC_VER >= 1400 )) /* MSVC8+ */
72 # if defined(__MINGW32__)
73 __attribute__((unused))
74 # endif
__ptw32_get_errno(void)75 static int __ptw32_get_errno(void) { int err = 0; _get_errno(&err); return err; }
76 # define __PTW32_GET_ERRNO() __ptw32_get_errno()
77 # if defined(__MINGW32__)
78 __attribute__((unused))
79 # endif
__ptw32_set_errno(int err)80 static void __ptw32_set_errno(int err) { _set_errno(err); SetLastError(err); }
81 # define __PTW32_SET_ERRNO(err) __ptw32_set_errno(err)
82 #else
83 # define __PTW32_GET_ERRNO() (errno)
84 # if defined(__MINGW32__)
85 __attribute__((unused))
86 # endif
__ptw32_set_errno(int err)87 static void __ptw32_set_errno(int err) { errno = err; SetLastError(err); }
88 # define __PTW32_SET_ERRNO(err) __ptw32_set_errno(err)
89 #endif
90
91 #if !defined(malloc)
92 # include <malloc.h>
93 #endif
94
95 #if defined(__PTW32_CLEANUP_C)
96 # include <setjmp.h>
97 #endif
98
99 #if !defined(INT_MAX)
100 # include <limits.h>
101 #endif
102
103 /* use local include files during development */
104 #include "semaphore.h"
105 #include "sched.h"
106
107 /* MSVC 7.1 doesn't like complex #if expressions */
108 #define INLINE
109 #if defined (__PTW32_BUILD_INLINED)
110 # if defined(HAVE_C_INLINE) || defined(__cplusplus)
111 # undef INLINE
112 # define INLINE inline
113 # endif
114 #endif
115
116 #if defined (__PTW32_CONFIG_MSVC6)
117 # define __PTW32_INTERLOCKED_VOLATILE
118 #else
119 # define __PTW32_INTERLOCKED_VOLATILE volatile
120 #endif
121
122 #define __PTW32_INTERLOCKED_LONG long
123 #define __PTW32_INTERLOCKED_PVOID PVOID
124 #define __PTW32_INTERLOCKED_LONGPTR __PTW32_INTERLOCKED_VOLATILE long*
125 #define __PTW32_INTERLOCKED_PVOID_PTR __PTW32_INTERLOCKED_VOLATILE PVOID*
126 #if defined(_WIN64)
127 # define __PTW32_INTERLOCKED_SIZE LONGLONG
128 # define __PTW32_INTERLOCKED_SIZEPTR __PTW32_INTERLOCKED_VOLATILE LONGLONG*
129 #else
130 # define __PTW32_INTERLOCKED_SIZE long
131 # define __PTW32_INTERLOCKED_SIZEPTR __PTW32_INTERLOCKED_VOLATILE long*
132 #endif
133
134 /*
135 * Don't allow the linker to optimize away dll.obj (dll.o) in static builds.
136 */
137 #if defined (__PTW32_STATIC_LIB) && defined (__PTW32_BUILD) && !defined (__PTW32_TEST_SNEAK_PEEK)
138 __PTW32_BEGIN_C_DECLS
139 void __ptw32_autostatic_anchor(void);
140 # if defined(__GNUC__)
141 __attribute__((unused, used))
142 # endif
143 static void (*local_autostatic_anchor)(void) = __ptw32_autostatic_anchor;
144 __PTW32_END_C_DECLS
145 #endif
146
147 typedef enum
148 {
149 /*
150 * This enumeration represents the state of the thread;
151 * The thread is still valid if the numeric value of the
152 * state is greater or equal "PThreadStateRunning".
153 */
154 PThreadStateInitial = 0, /* Thread not running */
155 PThreadStateReuse, /* In reuse pool. */
156 PThreadStateRunning, /* Thread alive & kicking */
157 PThreadStateSuspended, /* Thread alive but suspended */
158 PThreadStateCancelPending, /* Thread alive but */
159 /* has cancellation pending. */
160 PThreadStateCanceling, /* Thread alive but is */
161 /* in the process of terminating */
162 /* due to a cancellation request */
163 PThreadStateExiting, /* Thread alive but exiting */
164 /* due to an exception */
165 PThreadStateLast /* All handlers have been run and now */
166 /* final cleanup can be done. */
167 }
168 PThreadState;
169
170 typedef struct __ptw32_mcs_node_t_ __ptw32_mcs_local_node_t;
171 typedef struct __ptw32_mcs_node_t_* __ptw32_mcs_lock_t;
172 typedef struct __ptw32_robust_node_t_ __ptw32_robust_node_t;
173 typedef struct __ptw32_thread_t_ __ptw32_thread_t;
174
175 struct __ptw32_thread_t_
176 {
177 unsigned __int64 seqNumber; /* Process-unique thread sequence number */
178 HANDLE threadH; /* Win32 thread handle - POSIX thread is invalid if threadH == 0 */
179 pthread_t ptHandle; /* This thread's permanent pthread_t handle */
180 __ptw32_thread_t * prevReuse; /* Links threads on reuse stack */
181 volatile PThreadState state;
182 __ptw32_mcs_lock_t threadLock; /* Used for serialised access to public thread state */
183 __ptw32_mcs_lock_t stateLock; /* Used for async-cancel safety */
184 HANDLE cancelEvent;
185 void *exitStatus;
186 void *parms;
187 void *keys;
188 void *nextAssoc;
189 #if defined(__PTW32_CLEANUP_C)
190 jmp_buf start_mark; /* Jump buffer follows void* so should be aligned */
191 #endif /* __PTW32_CLEANUP_C */
192 #if defined(HAVE_SIGSET_T)
193 sigset_t sigmask;
194 #endif /* HAVE_SIGSET_T */
195 __ptw32_mcs_lock_t
196 robustMxListLock; /* robustMxList lock */
197 __ptw32_robust_node_t*
198 robustMxList; /* List of currenty held robust mutexes */
199 int ptErrno;
200 int detachState;
201 int sched_priority; /* As set, not as currently is */
202 int cancelState;
203 int cancelType;
204 int implicit:1;
205 DWORD thread; /* Windows thread ID */
206 #if defined(HAVE_CPU_AFFINITY)
207 size_t cpuset; /* Thread CPU affinity set */
208 #endif
209 char * name; /* Thread name */
210 #if defined(_UWIN)
211 DWORD dummy[5];
212 #endif
213 size_t align; /* Force alignment if this struct is packed */
214 };
215
216
217 /*
218 * Special value to mark attribute objects as valid.
219 */
220 #define __PTW32_ATTR_VALID ((unsigned long) 0xC4C0FFEE)
221
222 struct pthread_attr_t_
223 {
224 unsigned long valid;
225 void *stackaddr;
226 size_t stacksize;
227 int detachstate;
228 struct sched_param param;
229 int inheritsched;
230 int contentionscope;
231 size_t cpuset;
232 char * thrname;
233 #if defined(HAVE_SIGSET_T)
234 sigset_t sigmask;
235 #endif /* HAVE_SIGSET_T */
236 };
237
238
239 /*
240 * ====================
241 * ====================
242 * Semaphores, Mutexes and Condition Variables
243 * ====================
244 * ====================
245 */
246
247 struct sem_t_
248 {
249 int value;
250 __ptw32_mcs_lock_t lock;
251 HANDLE sem;
252 #if defined(NEED_SEM)
253 int leftToUnblock;
254 #endif
255 };
256
257 #define __PTW32_OBJECT_AUTO_INIT ((void *)(size_t) -1)
258 #define __PTW32_OBJECT_INVALID NULL
259
260 struct pthread_mutex_t_
261 {
262 LONG lock_idx; /* Provides exclusive access to mutex state
263 via the Interlocked* mechanism.
264 0: unlocked/free.
265 1: locked - no other waiters.
266 -1: locked - with possible other waiters.
267 */
268 int recursive_count; /* Number of unlocks a thread needs to perform
269 before the lock is released (recursive
270 mutexes only). */
271 int kind; /* Mutex type. */
272 pthread_t ownerThread;
273 HANDLE event; /* Mutex release notification to waiting
274 threads. */
275 __ptw32_robust_node_t*
276 robustNode; /* Extra state for robust mutexes */
277 };
278
279 enum __ptw32_robust_state_t_
280 {
281 __PTW32_ROBUST_CONSISTENT,
282 __PTW32_ROBUST_INCONSISTENT,
283 __PTW32_ROBUST_NOTRECOVERABLE
284 };
285
286 typedef enum __ptw32_robust_state_t_ __ptw32_robust_state_t;
287
288 /*
289 * Node used to manage per-thread lists of currently-held robust mutexes.
290 */
291 struct __ptw32_robust_node_t_
292 {
293 pthread_mutex_t mx;
294 __ptw32_robust_state_t stateInconsistent;
295 __ptw32_robust_node_t* prev;
296 __ptw32_robust_node_t* next;
297 };
298
299 struct pthread_mutexattr_t_
300 {
301 int pshared;
302 int kind;
303 int robustness;
304 };
305
306 /*
307 * Possible values, other than __PTW32_OBJECT_INVALID,
308 * for the "interlock" element in a spinlock.
309 *
310 * In this implementation, when a spinlock is initialised,
311 * the number of cpus available to the process is checked.
312 * If there is only one cpu then "interlock" is set equal to
313 * __PTW32_SPIN_USE_MUTEX and u.mutex is an initialised mutex.
314 * If the number of cpus is greater than 1 then "interlock"
315 * is set equal to __PTW32_SPIN_UNLOCKED and the number is
316 * stored in u.cpus. This arrangement allows the spinlock
317 * routines to attempt an InterlockedCompareExchange on "interlock"
318 * immediately and, if that fails, to try the inferior mutex.
319 *
320 * "u.cpus" isn't used for anything yet, but could be used at
321 * some point to optimise spinlock behaviour.
322 */
323 #define __PTW32_SPIN_INVALID (0)
324 #define __PTW32_SPIN_UNLOCKED (1)
325 #define __PTW32_SPIN_LOCKED (2)
326 #define __PTW32_SPIN_USE_MUTEX (3)
327
328 struct pthread_spinlock_t_
329 {
330 long interlock; /* Locking element for multi-cpus. */
331 union
332 {
333 int cpus; /* No. of cpus if multi cpus, or */
334 pthread_mutex_t mutex; /* mutex if single cpu. */
335 } u;
336 };
337
338 /*
339 * MCS lock queue node - see ptw32_MCS_lock.c
340 */
341 struct __ptw32_mcs_node_t_
342 {
343 struct __ptw32_mcs_node_t_ **lock; /* ptr to tail of queue */
344 struct __ptw32_mcs_node_t_ *next; /* ptr to successor in queue */
345 HANDLE readyFlag; /* set after lock is released by
346 predecessor */
347 HANDLE nextFlag; /* set after 'next' ptr is set by
348 successor */
349 };
350
351
352 struct pthread_barrier_t_
353 {
354 unsigned int nCurrentBarrierHeight;
355 unsigned int nInitialBarrierHeight;
356 int pshared;
357 sem_t semBarrierBreeched;
358 __ptw32_mcs_lock_t lock;
359 __ptw32_mcs_local_node_t proxynode;
360 };
361
362 struct pthread_barrierattr_t_
363 {
364 int pshared;
365 };
366
367 struct pthread_key_t_
368 {
369 DWORD key;
370 void (__PTW32_CDECL *destructor) (void *);
371 __ptw32_mcs_lock_t keyLock;
372 void *threads;
373 };
374
375
376 typedef struct ThreadParms ThreadParms;
377
378 struct ThreadParms
379 {
380 pthread_t tid;
381 void * (__PTW32_CDECL *start) (void *);
382 void *arg;
383 };
384
385
386 struct pthread_cond_t_
387 {
388 long nWaitersBlocked; /* Number of threads blocked */
389 long nWaitersGone; /* Number of threads timed out */
390 long nWaitersToUnblock; /* Number of threads to unblock */
391 sem_t semBlockQueue; /* Queue up threads waiting for the */
392 /* condition to become signalled */
393 sem_t semBlockLock; /* Semaphore that guards access to */
394 /* | waiters blocked count/block queue */
395 /* +-> Mandatory Sync.LEVEL-1 */
396 pthread_mutex_t mtxUnblockLock; /* Mutex that guards access to */
397 /* | waiters (to)unblock(ed) counts */
398 /* +-> Optional* Sync.LEVEL-2 */
399 pthread_cond_t next; /* Doubly linked list */
400 pthread_cond_t prev;
401 };
402
403
404 struct pthread_condattr_t_
405 {
406 int pshared;
407 };
408
409 #define __PTW32_RWLOCK_MAGIC 0xfacade2
410
411 struct pthread_rwlock_t_
412 {
413 pthread_mutex_t mtxExclusiveAccess;
414 pthread_mutex_t mtxSharedAccessCompleted;
415 pthread_cond_t cndSharedAccessCompleted;
416 int nSharedAccessCount;
417 int nExclusiveAccessCount;
418 int nCompletedSharedAccessCount;
419 int nMagic;
420 };
421
422 struct pthread_rwlockattr_t_
423 {
424 int pshared;
425 };
426
427 typedef union
428 {
429 char cpuset[CPU_SETSIZE/8];
430 size_t _cpuset;
431 } _sched_cpu_set_vector_;
432
433 typedef struct ThreadKeyAssoc ThreadKeyAssoc;
434
435 struct ThreadKeyAssoc
436 {
437 /*
438 * Purpose:
439 * This structure creates an association between a thread and a key.
440 * It is used to implement the implicit invocation of a user defined
441 * destroy routine for thread specific data registered by a user upon
442 * exiting a thread.
443 *
444 * Graphically, the arrangement is as follows, where:
445 *
446 * K - Key with destructor
447 * (head of chain is key->threads)
448 * T - Thread that has called pthread_setspecific(Kn)
449 * (head of chain is thread->keys)
450 * A - Association. Each association is a node at the
451 * intersection of two doubly-linked lists.
452 *
453 * T1 T2 T3
454 * | | |
455 * | | |
456 * K1 -----+-----A-----A----->
457 * | | |
458 * | | |
459 * K2 -----A-----A-----+----->
460 * | | |
461 * | | |
462 * K3 -----A-----+-----A----->
463 * | | |
464 * | | |
465 * V V V
466 *
467 * Access to the association is guarded by two locks: the key's
468 * general lock (guarding the row) and the thread's general
469 * lock (guarding the column). This avoids the need for a
470 * dedicated lock for each association, which not only consumes
471 * more handles but requires that the lock resources persist
472 * until both the key is deleted and the thread has called the
473 * destructor. The two-lock arrangement allows those resources
474 * to be freed as soon as either thread or key is concluded.
475 *
476 * To avoid deadlock, whenever both locks are required both the
477 * key and thread locks are acquired consistently in the order
478 * "key lock then thread lock". An exception to this exists
479 * when a thread calls the destructors, however, this is done
480 * carefully (but inelegantly) to avoid deadlock.
481 *
482 * An association is created when a thread first calls
483 * pthread_setspecific() on a key that has a specified
484 * destructor.
485 *
486 * An association is destroyed either immediately after the
487 * thread calls the key destructor function on thread exit, or
488 * when the key is deleted.
489 *
490 * Attributes:
491 * thread
492 * reference to the thread that owns the
493 * association. This is actually the pointer to the
494 * thread struct itself. Since the association is
495 * destroyed before the thread exits, this can never
496 * point to a different logical thread to the one that
497 * created the assoc, i.e. after thread struct reuse.
498 *
499 * key
500 * reference to the key that owns the association.
501 *
502 * nextKey
503 * The pthread_t->keys attribute is the head of a
504 * chain of associations that runs through the nextKey
505 * link. This chain provides the 1 to many relationship
506 * between a pthread_t and all pthread_key_t on which
507 * it called pthread_setspecific.
508 *
509 * prevKey
510 * Similarly.
511 *
512 * nextThread
513 * The pthread_key_t->threads attribute is the head of
514 * a chain of associations that runs through the
515 * nextThreads link. This chain provides the 1 to many
516 * relationship between a pthread_key_t and all the
517 * PThreads that have called pthread_setspecific for
518 * this pthread_key_t.
519 *
520 * prevThread
521 * Similarly.
522 *
523 * Notes:
524 * 1) As soon as either the key or the thread is no longer
525 * referencing the association, it can be destroyed. The
526 * association will be removed from both chains.
527 *
528 * 2) Under WIN32, an association is only created by
529 * pthread_setspecific if the user provided a
530 * destroyRoutine when they created the key.
531 *
532 *
533 */
534 __ptw32_thread_t * thread;
535 pthread_key_t key;
536 ThreadKeyAssoc *nextKey;
537 ThreadKeyAssoc *nextThread;
538 ThreadKeyAssoc *prevKey;
539 ThreadKeyAssoc *prevThread;
540 };
541
542
543 #if defined(__PTW32_CLEANUP_SEH)
544 /*
545 * --------------------------------------------------------------
546 * MAKE_SOFTWARE_EXCEPTION
547 * This macro constructs a software exception code following
548 * the same format as the standard Win32 error codes as defined
549 * in WINERROR.H
550 * Values are 32 bit values laid out as follows:
551 *
552 * 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
553 * +---+-+-+-----------------------+-------------------------------+
554 * |Sev|C|R| Facility | Code |
555 * +---+-+-+-----------------------+-------------------------------+
556 *
557 * Severity Values:
558 */
559 #define SE_SUCCESS 0x00
560 #define SE_INFORMATION 0x01
561 #define SE_WARNING 0x02
562 #define SE_ERROR 0x03
563
564 #define MAKE_SOFTWARE_EXCEPTION( _severity, _facility, _exception ) \
565 ( (DWORD) ( ( (_severity) << 30 ) | /* Severity code */ \
566 ( 1 << 29 ) | /* MS=0, User=1 */ \
567 ( 0 << 28 ) | /* Reserved */ \
568 ( (_facility) << 16 ) | /* Facility Code */ \
569 ( (_exception) << 0 ) /* Exception Code */ \
570 ) )
571
572 /*
573 * We choose one specific Facility/Error code combination to
574 * identify our software exceptions vs. WIN32 exceptions.
575 * We store our actual component and error code within
576 * the optional information array.
577 */
578 #define EXCEPTION_PTW32_SERVICES \
579 MAKE_SOFTWARE_EXCEPTION( SE_ERROR, \
580 __PTW32_SERVICES_FACILITY, \
581 __PTW32_SERVICES_ERROR )
582
583 #define __PTW32_SERVICES_FACILITY 0xBAD
584 #define __PTW32_SERVICES_ERROR 0xDEED
585
586 #endif /* __PTW32_CLEANUP_SEH */
587
588 /*
589 * Services available through EXCEPTION_PTW32_SERVICES
590 * and also used [as parameters to __ptw32_throw()] as
591 * generic exception selectors.
592 */
593
594 #define __PTW32_EPS_EXIT (1)
595 #define __PTW32_EPS_CANCEL (2)
596
597
598 /* Useful macros */
599 #define __PTW32_MAX(a,b) ((a)<(b)?(b):(a))
600 #define __PTW32_MIN(a,b) ((a)>(b)?(b):(a))
601
602
603 /* Declared in pthread_cancel.c */
604 extern DWORD (*__ptw32_register_cancellation) (PAPCFUNC, HANDLE, DWORD);
605
606 /* Thread Reuse stack bottom marker. Must not be NULL or any valid pointer to memory. */
607 #define __PTW32_THREAD_REUSE_EMPTY ((__ptw32_thread_t *)(size_t) 1)
608
609 extern int __ptw32_processInitialized;
610 extern __ptw32_thread_t * __ptw32_threadReuseTop;
611 extern __ptw32_thread_t * __ptw32_threadReuseBottom;
612 extern pthread_key_t __ptw32_selfThreadKey;
613 extern pthread_key_t __ptw32_cleanupKey;
614 extern pthread_cond_t __ptw32_cond_list_head;
615 extern pthread_cond_t __ptw32_cond_list_tail;
616
617 extern int __ptw32_mutex_default_kind;
618
619 extern unsigned __int64 __ptw32_threadSeqNumber;
620
621 extern int __ptw32_concurrency;
622
623 extern int __ptw32_features;
624
625 extern __ptw32_mcs_lock_t __ptw32_thread_reuse_lock;
626 extern __ptw32_mcs_lock_t __ptw32_mutex_test_init_lock;
627 extern __ptw32_mcs_lock_t __ptw32_cond_list_lock;
628 extern __ptw32_mcs_lock_t __ptw32_cond_test_init_lock;
629 extern __ptw32_mcs_lock_t __ptw32_rwlock_test_init_lock;
630 extern __ptw32_mcs_lock_t __ptw32_spinlock_test_init_lock;
631
632 #if defined(_UWIN)
633 extern int pthread_count;
634 #endif
635
636 __PTW32_BEGIN_C_DECLS
637
638 /*
639 * =====================
640 * =====================
641 * Forward Declarations
642 * =====================
643 * =====================
644 */
645
646 int __ptw32_is_attr (const pthread_attr_t * attr);
647
648 int __ptw32_cond_check_need_init (pthread_cond_t * cond);
649 int __ptw32_mutex_check_need_init (pthread_mutex_t * mutex);
650 int __ptw32_rwlock_check_need_init (pthread_rwlock_t * rwlock);
651 int __ptw32_spinlock_check_need_init (pthread_spinlock_t * lock);
652
653 int __ptw32_robust_mutex_inherit(pthread_mutex_t * mutex);
654 void __ptw32_robust_mutex_add(pthread_mutex_t* mutex, pthread_t self);
655 void __ptw32_robust_mutex_remove(pthread_mutex_t* mutex, __ptw32_thread_t* otp);
656
657 DWORD
658 __ptw32_Registercancellation (PAPCFUNC callback,
659 HANDLE threadH, DWORD callback_arg);
660
661 int __ptw32_processInitialize (void);
662
663 void __ptw32_processTerminate (void);
664
665 void __ptw32_threadDestroy (pthread_t tid);
666
667 void __ptw32_pop_cleanup_all (int execute);
668
669 pthread_t __ptw32_new (void);
670
671 pthread_t __ptw32_threadReusePop (void);
672
673 void __ptw32_threadReusePush (pthread_t thread);
674
675 int __ptw32_getprocessors (int *count);
676
677 int __ptw32_setthreadpriority (pthread_t thread, int policy, int priority);
678
679 void __ptw32_rwlock_cancelwrwait (void *arg);
680
681 #if ! defined (__MINGW32__) || (defined (__MSVCRT__) && ! defined (__DMC__))
682 unsigned __stdcall
683 #else
684 void
685 #endif
686 __ptw32_threadStart (void *vthreadParms);
687
688 void __ptw32_callUserDestroyRoutines (pthread_t thread);
689
690 int __ptw32_tkAssocCreate (__ptw32_thread_t * thread, pthread_key_t key);
691
692 void __ptw32_tkAssocDestroy (ThreadKeyAssoc * assoc);
693
694 int __ptw32_semwait (sem_t * sem);
695
696 DWORD __ptw32_relmillisecs (const struct timespec * abstime);
697
698 void __ptw32_mcs_lock_acquire (__ptw32_mcs_lock_t * lock, __ptw32_mcs_local_node_t * node);
699
700 int __ptw32_mcs_lock_try_acquire (__ptw32_mcs_lock_t * lock, __ptw32_mcs_local_node_t * node);
701
702 void __ptw32_mcs_lock_release (__ptw32_mcs_local_node_t * node);
703
704 void __ptw32_mcs_node_transfer (__ptw32_mcs_local_node_t * new_node, __ptw32_mcs_local_node_t * old_node);
705
706 void __ptw32_timespec_to_filetime (const struct timespec *ts, FILETIME * ft);
707
708 void __ptw32_filetime_to_timespec (const FILETIME * ft, struct timespec *ts);
709
710 /* Declared in pthw32_calloc.c */
711 #if defined(NEED_CALLOC)
712 #define calloc(n, s) __ptw32_calloc(n, s)
713 void *__ptw32_calloc (size_t n, size_t s);
714 #endif
715
716 /* Declared in ptw32_throw.c */
717 void __ptw32_throw (DWORD exception);
718
719 __PTW32_END_C_DECLS
720
721 #if defined(_UWIN_)
722 # if defined(_MT)
723
724 __PTW32_BEGIN_C_DECLS
725
726 _CRTIMP unsigned long __cdecl _beginthread (void (__cdecl *) (void *),
727 unsigned, void *);
728 _CRTIMP void __cdecl _endthread (void);
729 _CRTIMP unsigned long __cdecl _beginthreadex (void *, unsigned,
730 unsigned (__stdcall *) (void *),
731 void *, unsigned, unsigned *);
732 _CRTIMP void __cdecl _endthreadex (unsigned);
733
734 __PTW32_END_C_DECLS
735
736 # endif
737 #else
738 # if ! defined(WINCE)
739 # include <process.h>
740 # endif
741 #endif
742
743
744 /*
745 * Use intrinsic versions wherever possible. VC will do this
746 * automatically where possible and GCC define these if available:
747 * __GCC_HAVE_SYNC_COMPARE_AND_SWAP_1
748 * __GCC_HAVE_SYNC_COMPARE_AND_SWAP_2
749 * __GCC_HAVE_SYNC_COMPARE_AND_SWAP_4
750 * __GCC_HAVE_SYNC_COMPARE_AND_SWAP_8
751 * __GCC_HAVE_SYNC_COMPARE_AND_SWAP_16
752 *
753 * The full set of Interlocked intrinsics in GCC are (check versions):
754 * type __sync_fetch_and_add (type *ptr, type value, ...)
755 * type __sync_fetch_and_sub (type *ptr, type value, ...)
756 * type __sync_fetch_and_or (type *ptr, type value, ...)
757 * type __sync_fetch_and_and (type *ptr, type value, ...)
758 * type __sync_fetch_and_xor (type *ptr, type value, ...)
759 * type __sync_fetch_and_nand (type *ptr, type value, ...)
760 * type __sync_add_and_fetch (type *ptr, type value, ...)
761 * type __sync_sub_and_fetch (type *ptr, type value, ...)
762 * type __sync_or_and_fetch (type *ptr, type value, ...)
763 * type __sync_and_and_fetch (type *ptr, type value, ...)
764 * type __sync_xor_and_fetch (type *ptr, type value, ...)
765 * type __sync_nand_and_fetch (type *ptr, type value, ...)
766 * bool __sync_bool_compare_and_swap (type *ptr, type oldval type newval, ...)
767 * type __sync_val_compare_and_swap (type *ptr, type oldval type newval, ...)
768 * __sync_synchronize (...) // Full memory barrier
769 * type __sync_lock_test_and_set (type *ptr, type value, ...) // Acquire barrier
770 * void __sync_lock_release (type *ptr, ...) // Release barrier
771 *
772 * These are all overloaded and take 1,2,4,8 byte scalar or pointer types.
773 *
774 * The above aren't available in Mingw32 as of gcc 4.5.2 so define our own.
775 */
776 #if defined(__cplusplus)
777 # define __PTW32_TO_VLONG64PTR(ptr) reinterpret_cast<volatile LONG64 *>(ptr)
778 #else
779 # define __PTW32_TO_VLONG64PTR(ptr) (ptr)
780 #endif
781
782 #if defined(__GNUC__)
783 # if defined(_WIN64)
784 # define __PTW32_INTERLOCKED_COMPARE_EXCHANGE_64(location, value, comparand) \
785 ({ \
786 __typeof (value) _result; \
787 __asm__ __volatile__ \
788 ( \
789 "lock\n\t" \
790 "cmpxchgq %2,(%1)" \
791 :"=a" (_result) \
792 :"r" (location), "r" (value), "a" (comparand) \
793 :"memory", "cc"); \
794 _result; \
795 })
796 # define __PTW32_INTERLOCKED_EXCHANGE_64(location, value) \
797 ({ \
798 __typeof (value) _result; \
799 __asm__ __volatile__ \
800 ( \
801 "xchgq %0,(%1)" \
802 :"=r" (_result) \
803 :"r" (location), "0" (value) \
804 :"memory", "cc"); \
805 _result; \
806 })
807 # define __PTW32_INTERLOCKED_EXCHANGE_ADD_64(location, value) \
808 ({ \
809 __typeof (value) _result; \
810 __asm__ __volatile__ \
811 ( \
812 "lock\n\t" \
813 "xaddq %0,(%1)" \
814 :"=r" (_result) \
815 :"r" (location), "0" (value) \
816 :"memory", "cc"); \
817 _result; \
818 })
819 # define __PTW32_INTERLOCKED_INCREMENT_64(location) \
820 ({ \
821 __PTW32_INTERLOCKED_LONG _temp = 1; \
822 __asm__ __volatile__ \
823 ( \
824 "lock\n\t" \
825 "xaddq %0,(%1)" \
826 :"+r" (_temp) \
827 :"r" (location) \
828 :"memory", "cc"); \
829 ++_temp; \
830 })
831 # define __PTW32_INTERLOCKED_DECREMENT_64(location) \
832 ({ \
833 __PTW32_INTERLOCKED_LONG _temp = -1; \
834 __asm__ __volatile__ \
835 ( \
836 "lock\n\t" \
837 "xaddq %2,(%1)" \
838 :"+r" (_temp) \
839 :"r" (location) \
840 :"memory", "cc"); \
841 --_temp; \
842 })
843 #endif
844 # define __PTW32_INTERLOCKED_COMPARE_EXCHANGE_LONG(location, value, comparand) \
845 ({ \
846 __typeof (value) _result; \
847 __asm__ __volatile__ \
848 ( \
849 "lock\n\t" \
850 "cmpxchgl %2,(%1)" \
851 :"=a" (_result) \
852 :"r" (location), "r" (value), "a" (comparand) \
853 :"memory", "cc"); \
854 _result; \
855 })
856 # define __PTW32_INTERLOCKED_EXCHANGE_LONG(location, value) \
857 ({ \
858 __typeof (value) _result; \
859 __asm__ __volatile__ \
860 ( \
861 "xchgl %0,(%1)" \
862 :"=r" (_result) \
863 :"r" (location), "0" (value) \
864 :"memory", "cc"); \
865 _result; \
866 })
867 # define __PTW32_INTERLOCKED_EXCHANGE_ADD_LONG(location, value) \
868 ({ \
869 __typeof (value) _result; \
870 __asm__ __volatile__ \
871 ( \
872 "lock\n\t" \
873 "xaddl %0,(%1)" \
874 :"=r" (_result) \
875 :"r" (location), "0" (value) \
876 :"memory", "cc"); \
877 _result; \
878 })
879 # define __PTW32_INTERLOCKED_INCREMENT_LONG(location) \
880 ({ \
881 __PTW32_INTERLOCKED_LONG _temp = 1; \
882 __asm__ __volatile__ \
883 ( \
884 "lock\n\t" \
885 "xaddl %0,(%1)" \
886 :"+r" (_temp) \
887 :"r" (location) \
888 :"memory", "cc"); \
889 ++_temp; \
890 })
891 # define __PTW32_INTERLOCKED_DECREMENT_LONG(location) \
892 ({ \
893 __PTW32_INTERLOCKED_LONG _temp = -1; \
894 __asm__ __volatile__ \
895 ( \
896 "lock\n\t" \
897 "xaddl %0,(%1)" \
898 :"+r" (_temp) \
899 :"r" (location) \
900 :"memory", "cc"); \
901 --_temp; \
902 })
903 # define __PTW32_INTERLOCKED_COMPARE_EXCHANGE_PTR(location, value, comparand) \
904 __PTW32_INTERLOCKED_COMPARE_EXCHANGE_SIZE ((__PTW32_INTERLOCKED_SIZEPTR)location, \
905 (__PTW32_INTERLOCKED_SIZE)value, \
906 (__PTW32_INTERLOCKED_SIZE)comparand)
907 # define __PTW32_INTERLOCKED_EXCHANGE_PTR(location, value) \
908 __PTW32_INTERLOCKED_EXCHANGE_SIZE ((__PTW32_INTERLOCKED_SIZEPTR)location, \
909 (__PTW32_INTERLOCKED_SIZE)value)
910 #else
911 # if defined(_WIN64)
912 # define __PTW32_INTERLOCKED_COMPARE_EXCHANGE_64(p,v,c) InterlockedCompareExchange64 (__PTW32_TO_VLONG64PTR(p),(v),(c))
913 # define __PTW32_INTERLOCKED_EXCHANGE_64(p,v) InterlockedExchange64 (__PTW32_TO_VLONG64PTR(p),(v))
914 # define __PTW32_INTERLOCKED_EXCHANGE_ADD_64(p,v) InterlockedExchangeAdd64 (__PTW32_TO_VLONG64PTR(p),(v))
915 # define __PTW32_INTERLOCKED_INCREMENT_64(p) InterlockedIncrement64 (__PTW32_TO_VLONG64PTR(p))
916 # define __PTW32_INTERLOCKED_DECREMENT_64(p) InterlockedDecrement64 (__PTW32_TO_VLONG64PTR(p))
917 # endif
918 # if defined (__PTW32_CONFIG_MSVC6) && !defined(_WIN64)
919 # define __PTW32_INTERLOCKED_COMPARE_EXCHANGE_LONG(location, value, comparand) \
920 ((LONG)InterlockedCompareExchange((PVOID *)(location), (PVOID)(value), (PVOID)(comparand)))
921 # else
922 # define __PTW32_INTERLOCKED_COMPARE_EXCHANGE_LONG InterlockedCompareExchange
923 # endif
924 # define __PTW32_INTERLOCKED_EXCHANGE_LONG(p,v) InterlockedExchange((p),(v))
925 # define __PTW32_INTERLOCKED_EXCHANGE_ADD_LONG(p,v) InterlockedExchangeAdd((p),(v))
926 # define __PTW32_INTERLOCKED_INCREMENT_LONG(p) InterlockedIncrement((p))
927 # define __PTW32_INTERLOCKED_DECREMENT_LONG(p) InterlockedDecrement((p))
928 # if defined (__PTW32_CONFIG_MSVC6) && !defined(_WIN64)
929 # define __PTW32_INTERLOCKED_COMPARE_EXCHANGE_PTR InterlockedCompareExchange
930 # define __PTW32_INTERLOCKED_EXCHANGE_PTR(location, value) \
931 ((PVOID)InterlockedExchange((LPLONG)(location), (LONG)(value)))
932 # else
933 # define __PTW32_INTERLOCKED_COMPARE_EXCHANGE_PTR(p,v,c) InterlockedCompareExchangePointer((p),(v),(c))
934 # define __PTW32_INTERLOCKED_EXCHANGE_PTR(p,v) InterlockedExchangePointer((p),(v))
935 # endif
936 #endif
937 #if defined(_WIN64)
938 # define __PTW32_INTERLOCKED_COMPARE_EXCHANGE_SIZE(p,v,c) __PTW32_INTERLOCKED_COMPARE_EXCHANGE_64 (__PTW32_TO_VLONG64PTR(p),(v),(c))
939 # define __PTW32_INTERLOCKED_EXCHANGE_SIZE(p,v) __PTW32_INTERLOCKED_EXCHANGE_64 (__PTW32_TO_VLONG64PTR(p),(v))
940 # define __PTW32_INTERLOCKED_EXCHANGE_ADD_SIZE(p,v) __PTW32_INTERLOCKED_EXCHANGE_ADD_64 (__PTW32_TO_VLONG64PTR(p),(v))
941 # define __PTW32_INTERLOCKED_INCREMENT_SIZE(p) __PTW32_INTERLOCKED_INCREMENT_64 (__PTW32_TO_VLONG64PTR(p))
942 # define __PTW32_INTERLOCKED_DECREMENT_SIZE(p) __PTW32_INTERLOCKED_DECREMENT_64 (__PTW32_TO_VLONG64PTR(p))
943 #else
944 # define __PTW32_INTERLOCKED_COMPARE_EXCHANGE_SIZE(p,v,c) __PTW32_INTERLOCKED_COMPARE_EXCHANGE_LONG((p),(v),(c))
945 # define __PTW32_INTERLOCKED_EXCHANGE_SIZE(p,v) __PTW32_INTERLOCKED_EXCHANGE_LONG((p),(v))
946 # define __PTW32_INTERLOCKED_EXCHANGE_ADD_SIZE(p,v) __PTW32_INTERLOCKED_EXCHANGE_ADD_LONG((p),(v))
947 # define __PTW32_INTERLOCKED_INCREMENT_SIZE(p) __PTW32_INTERLOCKED_INCREMENT_LONG((p))
948 # define __PTW32_INTERLOCKED_DECREMENT_SIZE(p) __PTW32_INTERLOCKED_DECREMENT_LONG((p))
949 #endif
950
951 #if defined(NEED_CREATETHREAD)
952
953 /*
954 * Macro uses args so we can cast start_proc to LPTHREAD_START_ROUTINE
955 * in order to avoid warnings because of return type
956 */
957
958 #define _beginthreadex(security, \
959 stack_size, \
960 start_proc, \
961 arg, \
962 flags, \
963 pid) \
964 CreateThread(security, \
965 stack_size, \
966 (LPTHREAD_START_ROUTINE) start_proc, \
967 arg, \
968 flags, \
969 pid)
970
971 #define _endthreadex ExitThread
972
973 #endif /* NEED_CREATETHREAD */
974
975
976 #endif /* _IMPLEMENT_H */
977