/[pcsx2_0.9.7]/trunk/3rdparty/w32pthreads/include/implement.h
ViewVC logotype

Contents of /trunk/3rdparty/w32pthreads/include/implement.h

Parent Directory Parent Directory | Revision Log Revision Log


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

  ViewVC Help
Powered by ViewVC 1.1.22