]> sourceware.org Git - newlib-cygwin.git/blame - winsup/cygwin/thread.h
libiberty/ChangeLog:
[newlib-cygwin.git] / winsup / cygwin / thread.h
CommitLineData
1fd5e000
CF
1/* thread.h: Locking and threading module definitions
2
e136dbc2 3 Copyright 1998, 1999, 2000, 2001, 2002, 2003 Red Hat, Inc.
1fd5e000
CF
4
5 Written by Marco Fuykschot <marco@ddi.nl>
9a08b2c0 6 Major update 2001 Robert Collins <rbtcollins@hotmail.com>
462f4eff 7
1fd5e000
CF
8This file is part of Cygwin.
9
10This software is a copyrighted work licensed under the terms of the
11Cygwin license. Please consult the file "CYGWIN_LICENSE" for
12details. */
13
14#ifndef _CYGNUS_THREADS_
15#define _CYGNUS_THREADS_
16
17#define LOCK_FD_LIST 1
18#define LOCK_MEMORY_LIST 2
19#define LOCK_MMAP_LIST 3
20#define LOCK_DLL_LIST 4
1fd5e000
CF
21
22#define WRITE_LOCK 1
23#define READ_LOCK 2
24
25extern "C"
26{
27#if defined (_CYG_THREAD_FAILSAFE) && defined (_MT_SAFE)
5c83f260 28 void AssertResourceOwner (int, int);
1fd5e000 29#else
f2aeff27 30#define AssertResourceOwner(i,ii)
1fd5e000
CF
31#endif
32}
33
34#ifndef _MT_SAFE
35
36#define SetResourceLock(i,n,c)
37#define ReleaseResourceLock(i,n,c)
38
39#else
40
5c83f260 41#include <pthread.h>
2ff03dc2
TP
42#include <limits.h>
43#include <errno.h>
9a08b2c0 44#include <signal.h>
1fd5e000
CF
45#include <pwd.h>
46#include <grp.h>
bccd5e0d 47#define _NOMNTENT_FUNCS
1fd5e000 48#include <mntent.h>
1fd5e000 49
9a08b2c0 50extern "C"
1fd5e000 51{
9a08b2c0 52
f2aeff27
CF
53struct _winsup_t
54{
55 /*
5c83f260
RC
56 Needed for the group functions
57 */
de4e0d30 58 struct __group16 _grp;
f2aeff27
CF
59 char *_namearray[2];
60 int _grp_pos;
61
62 /* console.cc */
63 unsigned _rarg;
64
65 /* dlfcn.cc */
66 int _dl_error;
67 char _dl_buffer[256];
68
69 /* passwd.cc */
70 struct passwd _res;
71 char _pass[_PASSWORD_LEN];
72 int _pw_pos;
73
74 /* path.cc */
75 struct mntent mntbuf;
76 int _iteration;
77 DWORD available_drives;
f97adf98
CF
78 char mnt_type[80];
79 char mnt_opts[80];
80 char mnt_fsname[MAX_PATH];
81 char mnt_dir[MAX_PATH];
f2aeff27
CF
82
83 /* strerror */
84 char _strerror_buf[20];
85
86 /* sysloc.cc */
87 char *_process_ident;
88 int _process_logopt;
89 int _process_facility;
90 int _process_logmask;
91
92 /* times.cc */
93 char timezone_buf[20];
94 struct tm _localtime_buf;
95
96 /* uinfo.cc */
17db1105 97 char _username[UNLEN + 1];
cb19ccf4
CV
98
99 /* net.cc */
100 char *_ntoa_buf;
101 struct protoent *_protoent_buf;
102 struct servent *_servent_buf;
103 struct hostent *_hostent_buf;
f2aeff27
CF
104};
105
106
107struct __reent_t
108{
109 struct _reent *_clib;
110 struct _winsup_t *_winsup;
111};
1fd5e000 112
f2aeff27
CF
113_reent *_reent_clib ();
114_winsup_t *_reent_winsup ();
115void SetResourceLock (int, int, const char *) __attribute__ ((regparm (3)));
116void ReleaseResourceLock (int, int, const char *)
117 __attribute__ ((regparm (3)));
1fd5e000
CF
118
119#ifdef _CYG_THREAD_FAILSAFE
f2aeff27 120void AssertResourceOwner (int, int);
1fd5e000
CF
121#else
122#define AssertResourceOwner(i,ii)
123#endif
124}
125
15648790 126class native_mutex
ed9fe455
TP
127{
128public:
129 bool init ();
130 bool lock ();
131 void unlock ();
132private:
133 HANDLE theHandle;
134};
135
1fd5e000
CF
136class per_process;
137class pinfo;
138
139class ResourceLocks
140{
141public:
5c83f260
RC
142 ResourceLocks ()
143 {
144 }
1dc16fc7
CF
145 LPCRITICAL_SECTION Lock (int);
146 void Init ();
147 void Delete ();
1fd5e000 148#ifdef _CYG_THREAD_FAILSAFE
1dc16fc7
CF
149 DWORD owner;
150 DWORD count;
1fd5e000 151#endif
9a08b2c0 152private:
1dc16fc7
CF
153 CRITICAL_SECTION lock;
154 bool inited;
1fd5e000
CF
155};
156
9a08b2c0
CF
157#define PTHREAD_MAGIC 0xdf0df045
158#define PTHREAD_MUTEX_MAGIC PTHREAD_MAGIC+1
159#define PTHREAD_KEY_MAGIC PTHREAD_MAGIC+2
160#define PTHREAD_ATTR_MAGIC PTHREAD_MAGIC+3
161#define PTHREAD_MUTEXATTR_MAGIC PTHREAD_MAGIC+4
162#define PTHREAD_COND_MAGIC PTHREAD_MAGIC+5
163#define PTHREAD_CONDATTR_MAGIC PTHREAD_MAGIC+6
164#define SEM_MAGIC PTHREAD_MAGIC+7
2ff03dc2 165#define PTHREAD_ONCE_MAGIC PTHREAD_MAGIC+8
00d296a3
TP
166#define PTHREAD_RWLOCK_MAGIC PTHREAD_MAGIC+9
167#define PTHREAD_RWLOCKATTR_MAGIC PTHREAD_MAGIC+10
5c83f260 168
2ff03dc2 169#define MUTEX_OWNER_ANONYMOUS ((pthread_t) -1)
5d68d1de 170
5c83f260 171/* verifyable_object should not be defined here - it's a general purpose class */
1fd5e000 172
9a08b2c0
CF
173class verifyable_object
174{
175public:
176 long magic;
1fd5e000 177
aea1f301
CF
178 verifyable_object (long);
179 virtual ~verifyable_object ();
9a08b2c0
CF
180};
181
9c510edc 182typedef enum
86336f4f
RC
183{
184 VALID_OBJECT,
185 INVALID_OBJECT,
186 VALID_STATIC_OBJECT
187} verifyable_object_state;
188
189verifyable_object_state verifyable_object_isvalid (void const *, long);
190verifyable_object_state verifyable_object_isvalid (void const *, long, void *);
1fd5e000 191
15648790 192template <class list_node> class List {
af428c1e 193public:
9306ba2e
TP
194 List() : head(NULL)
195 {
196 }
197
15648790 198 void insert (list_node *node)
9306ba2e 199 {
15648790 200 if (!node)
9306ba2e 201 return;
15648790 202 node->next = (list_node *) InterlockedExchangePointer (&head, node);
9306ba2e
TP
203 }
204
15648790 205 list_node *remove ( list_node *node)
9306ba2e 206 {
15648790 207 if (!node || !head)
9306ba2e 208 return NULL;
15648790
TP
209 if (node == head)
210 return pop ();
211
212 list_node *result_prev = head;
213 while (result_prev && result_prev->next && !(node == result_prev->next))
214 result_prev = result_prev->next;
215 if (result_prev)
216 return (list_node *)InterlockedExchangePointer (&result_prev->next, result_prev->next->next);
9306ba2e
TP
217 return NULL;
218 }
219
15648790 220 list_node *pop ()
9306ba2e 221 {
15648790 222 return (list_node *) InterlockedExchangePointer (&head, head->next);
9306ba2e
TP
223 }
224
225 /* poor mans generic programming. */
15648790 226 void for_each (void (list_node::*callback) ())
9306ba2e 227 {
15648790
TP
228 list_node *node = head;
229 while (node)
9306ba2e 230 {
15648790
TP
231 (node->*callback) ();
232 node = node->next;
9306ba2e
TP
233 }
234 }
235
af428c1e 236protected:
15648790 237 list_node *head;
af428c1e
RC
238};
239
5c83f260
RC
240class pthread_key:public verifyable_object
241{
242public:
15648790
TP
243 static bool is_good_object (pthread_key_t const *);
244 DWORD tls_index;
f1f13795 245
5c83f260 246 int set (const void *);
20b94ee9 247 void *get () const;
5c83f260 248
20b94ee9 249 pthread_key (void (*)(void *));
aea1f301 250 ~pthread_key ();
9306ba2e
TP
251 static void fixup_before_fork()
252 {
15648790 253 keys.for_each (&pthread_key::save_key_to_buffer);
9306ba2e
TP
254 }
255
256 static void fixup_after_fork()
257 {
15648790 258 keys.for_each (&pthread_key::recreate_key_from_buffer);
9306ba2e
TP
259 }
260
15648790 261 static void run_all_destructors ()
9306ba2e 262 {
15648790 263 keys.for_each (&pthread_key::run_destructor);
9306ba2e 264 }
af428c1e
RC
265
266 /* List support calls */
267 class pthread_key *next;
f1f13795 268private:
af428c1e 269 static List<pthread_key> keys;
15648790
TP
270 void save_key_to_buffer ();
271 void recreate_key_from_buffer ();
20b94ee9 272 void (*destructor) (void *);
15648790 273 void run_destructor ();
af428c1e 274 void *fork_buf;
5c83f260
RC
275};
276
9a08b2c0 277class pthread_attr:public verifyable_object
1fd5e000 278{
9a08b2c0 279public:
15648790 280 static bool is_good_object(pthread_attr_t const *);
9a08b2c0 281 int joinable;
5c83f260
RC
282 int contentionscope;
283 int inheritsched;
284 struct sched_param schedparam;
9a08b2c0
CF
285 size_t stacksize;
286
aea1f301
CF
287 pthread_attr ();
288 ~pthread_attr ();
1fd5e000
CF
289};
290
43c3c4e3
RC
291class pthread_mutexattr:public verifyable_object
292{
293public:
15648790 294 static bool is_good_object(pthread_mutexattr_t const *);
43c3c4e3
RC
295 int pshared;
296 int mutextype;
aea1f301
CF
297 pthread_mutexattr ();
298 ~pthread_mutexattr ();
43c3c4e3
RC
299};
300
301class pthread_mutex:public verifyable_object
302{
303public:
15648790
TP
304 static bool is_good_object (pthread_mutex_t const *);
305 static bool is_good_initializer (pthread_mutex_t const *);
306 static bool is_good_initializer_or_object (pthread_mutex_t const *);
307 static bool is_good_initializer_or_bad_object (pthread_mutex_t const *mutex);
308 static bool can_be_unlocked (pthread_mutex_t const *mutex);
309 static void init_mutex ();
eb208df0 310 static int init (pthread_mutex_t *, const pthread_mutexattr_t *);
9d1e72a1 311
2ff03dc2 312 unsigned long lock_counter;
43c3c4e3 313 HANDLE win32_obj_id;
5d68d1de 314 unsigned int recursion_counter;
43c3c4e3 315 LONG condwaits;
5d68d1de
TP
316 pthread_t owner;
317 int type;
43c3c4e3 318 int pshared;
43c3c4e3 319
15648790 320 pthread_t get_pthread_self () const
2ff03dc2
TP
321 {
322 return PTHREAD_MUTEX_NORMAL == type ? MUTEX_OWNER_ANONYMOUS :
323 ::pthread_self ();
324 }
325
15648790 326 int lock ()
2ff03dc2 327 {
15648790 328 return _lock (get_pthread_self ());
2ff03dc2 329 }
15648790 330 int trylock ()
2ff03dc2 331 {
15648790 332 return _trylock (get_pthread_self ());
2ff03dc2 333 }
15648790 334 int unlock ()
2ff03dc2 335 {
15648790 336 return _unlock (get_pthread_self ());
2ff03dc2 337 }
15648790 338 int destroy ()
2ff03dc2 339 {
15648790 340 return _destroy (get_pthread_self ());
2ff03dc2
TP
341 }
342
15648790 343 void set_owner (pthread_t self)
2ff03dc2
TP
344 {
345 recursion_counter = 1;
346 owner = self;
347 }
348
15648790 349 int lock_recursive ()
2ff03dc2
TP
350 {
351 if (UINT_MAX == recursion_counter)
352 return EAGAIN;
353 ++recursion_counter;
354 return 0;
355 }
356
43c3c4e3
RC
357 pthread_mutex (pthread_mutexattr * = NULL);
358 pthread_mutex (pthread_mutex_t *, pthread_mutexattr *);
359 ~pthread_mutex ();
ed9fe455 360
9306ba2e
TP
361 class pthread_mutex * next;
362 static void fixup_after_fork ()
363 {
15648790 364 mutexes.for_each (&pthread_mutex::_fixup_after_fork);
9306ba2e
TP
365 }
366
eb208df0 367private:
15648790
TP
368 int _lock (pthread_t self);
369 int _trylock (pthread_t self);
370 int _unlock (pthread_t self);
371 int _destroy (pthread_t self);
372
373 void _fixup_after_fork ();
2ff03dc2 374
9306ba2e 375 static List<pthread_mutex> mutexes;
15648790 376 static native_mutex mutex_initialization_lock;
43c3c4e3
RC
377};
378
09cbb9d6
TP
379#define WAIT_CANCELED (WAIT_OBJECT_0 + 1)
380
9a08b2c0 381class pthread:public verifyable_object
1fd5e000
CF
382{
383public:
9a08b2c0
CF
384 HANDLE win32_obj_id;
385 class pthread_attr attr;
386 void *(*function) (void *);
1dc16fc7
CF
387 void *arg;
388 void *return_ptr;
389 bool suspended;
5c83f260 390 int cancelstate, canceltype;
d288c1c7 391 HANDLE cancel_event;
e9259cb2 392 pthread_t joiner;
5c83f260
RC
393 // int joinable;
394
1dc16fc7
CF
395 /* signal handling */
396 struct sigaction *sigs;
397 sigset_t *sigmask;
398 LONG *sigtodo;
4e786173
RC
399 virtual void create (void *(*)(void *), pthread_attr *, void *);
400
aea1f301
CF
401 pthread ();
402 virtual ~pthread ();
9a08b2c0 403
15648790
TP
404 static void init_mainthread (bool);
405 static bool is_good_object(pthread_t const *);
aea1f301
CF
406 static void atforkprepare();
407 static void atforkparent();
408 static void atforkchild();
9a08b2c0 409
aea1f301
CF
410 /* API calls */
411 static int cancel (pthread_t);
412 static int join (pthread_t * thread, void **return_val);
413 static int detach (pthread_t * thread);
414 static int create (pthread_t * thread, const pthread_attr_t * attr,
01f58e41 415 void *(*start_routine) (void *), void *arg);
aea1f301
CF
416 static int once (pthread_once_t *, void (*)(void));
417 static int atfork(void (*)(void), void (*)(void), void (*)(void));
418 static int suspend (pthread_t * thread);
419 static int resume (pthread_t * thread);
01f58e41 420
aea1f301 421 virtual void exit (void *value_ptr);
d288c1c7 422
aea1f301 423 virtual int cancel ();
9d1e72a1 424
aea1f301
CF
425 virtual void testcancel ();
426 static void static_cancel_self ();
d288c1c7 427
09cbb9d6
TP
428 static DWORD cancelable_wait (HANDLE object, DWORD timeout, const bool do_cancel = true);
429
aea1f301
CF
430 virtual int setcancelstate (int state, int *oldstate);
431 virtual int setcanceltype (int type, int *oldtype);
d288c1c7 432
aea1f301
CF
433 virtual void push_cleanup_handler (__pthread_cleanup_handler *handler);
434 virtual void pop_cleanup_handler (int const execute);
007276b3 435
aea1f301
CF
436 static pthread* self ();
437 static void *thread_init_wrapper (void *);
007276b3 438
aea1f301 439 virtual unsigned long getsequence_np();
4e786173 440
a4cea440
TP
441 static int equal (pthread_t t1, pthread_t t2)
442 {
443 return t1 == t2;
444 }
445
9a08b2c0 446private:
aea1f301
CF
447 DWORD thread_id;
448 __pthread_cleanup_handler *cleanup_stack;
449 pthread_mutex mutex;
450
451 void pop_all_cleanup_handlers (void);
452 void precreate (pthread_attr *);
453 void postcreate ();
15648790
TP
454 void set_thread_id_to_current ();
455 static void set_tls_self_pointer (pthread *);
456 static pthread *get_tls_self_pointer ();
aea1f301 457 void cancel_self ();
15648790
TP
458 DWORD get_thread_id ();
459 void init_current_thread ();
4e786173
RC
460};
461
15648790 462class pthread_null : public pthread
4e786173 463{
d04cf16c 464 public:
15648790
TP
465 static pthread *get_null_pthread();
466 ~pthread_null();
aea1f301
CF
467
468 /* From pthread These should never get called
469 * as the ojbect is not verifyable
470 */
471 void create (void *(*)(void *), pthread_attr *, void *);
472 void exit (void *value_ptr);
473 int cancel ();
474 void testcancel ();
475 int setcancelstate (int state, int *oldstate);
476 int setcanceltype (int type, int *oldtype);
477 void push_cleanup_handler (__pthread_cleanup_handler *handler);
478 void pop_cleanup_handler (int const execute);
479 unsigned long getsequence_np();
4e786173
RC
480
481 private:
15648790
TP
482 pthread_null ();
483 static pthread_null _instance;
1fd5e000
CF
484};
485
9a08b2c0 486class pthread_condattr:public verifyable_object
1fd5e000
CF
487{
488public:
15648790 489 static bool is_good_object(pthread_condattr_t const *);
1dc16fc7 490 int shared;
9a08b2c0 491
462f4eff
CF
492 pthread_condattr ();
493 ~pthread_condattr ();
1fd5e000
CF
494};
495
9a08b2c0 496class pthread_cond:public verifyable_object
5ccbf4b6
CF
497{
498public:
15648790
TP
499 static bool is_good_object (pthread_cond_t const *);
500 static bool is_good_initializer (pthread_cond_t const *);
501 static bool is_good_initializer_or_object (pthread_cond_t const *);
502 static bool is_good_initializer_or_bad_object (pthread_cond_t const *);
503 static void init_mutex ();
ed9fe455
TP
504 static int init (pthread_cond_t *, const pthread_condattr_t *);
505
5ccbf4b6 506 int shared;
f592b05d
TP
507
508 unsigned long waiting;
509 unsigned long pending;
15648790 510 HANDLE sem_wait;
f592b05d 511
15648790
TP
512 pthread_mutex mtx_in;
513 pthread_mutex mtx_out;
f592b05d 514
15648790 515 pthread_mutex_t mtx_cond;
f592b05d 516
15648790
TP
517 void unblock (const bool all);
518 int wait (pthread_mutex_t mutex, DWORD dwMilliseconds = INFINITE);
9a08b2c0 519
aea1f301
CF
520 pthread_cond (pthread_condattr *);
521 ~pthread_cond ();
ed9fe455 522
9306ba2e
TP
523 class pthread_cond * next;
524 static void fixup_after_fork ()
525 {
15648790 526 conds.for_each (&pthread_cond::_fixup_after_fork);
9306ba2e
TP
527 }
528
ed9fe455 529private:
15648790
TP
530 void _fixup_after_fork ();
531
9306ba2e 532 static List<pthread_cond> conds;
15648790 533 static native_mutex cond_initialization_lock;
5c83f260
RC
534};
535
00d296a3
TP
536class pthread_rwlockattr:public verifyable_object
537{
538public:
15648790 539 static bool is_good_object(pthread_rwlockattr_t const *);
00d296a3
TP
540 int shared;
541
542 pthread_rwlockattr ();
543 ~pthread_rwlockattr ();
544};
545
546class pthread_rwlock:public verifyable_object
547{
548public:
15648790
TP
549 static bool is_good_object (pthread_rwlock_t const *);
550 static bool is_good_initializer (pthread_rwlock_t const *);
551 static bool is_good_initializer_or_object (pthread_rwlock_t const *);
552 static bool is_good_initializer_or_bad_object (pthread_rwlock_t const *);
553 static void init_mutex ();
00d296a3
TP
554 static int init (pthread_rwlock_t *, const pthread_rwlockattr_t *);
555
556 int shared;
557
15648790
TP
558 unsigned long waiting_readers;
559 unsigned long waiting_writers;
00d296a3
TP
560 pthread_t writer;
561 struct RWLOCK_READER
562 {
563 struct RWLOCK_READER *next;
564 pthread_t thread;
565 } *readers;
566
15648790
TP
567 int rdlock ();
568 int tryrdlock ();
00d296a3 569
15648790
TP
570 int wrlock ();
571 int trywrlock ();
00d296a3 572
15648790 573 int unlock ();
00d296a3
TP
574
575 pthread_mutex mtx;
15648790
TP
576 pthread_cond cond_readers;
577 pthread_cond cond_writers;
00d296a3 578
00d296a3
TP
579 pthread_rwlock (pthread_rwlockattr *);
580 ~pthread_rwlock ();
581
9306ba2e
TP
582 class pthread_rwlock * next;
583 static void fixup_after_fork ()
584 {
15648790 585 rwlocks.for_each (&pthread_rwlock::_fixup_after_fork);
9306ba2e
TP
586 }
587
00d296a3 588private:
9306ba2e
TP
589 static List<pthread_rwlock> rwlocks;
590
15648790
TP
591 void add_reader (struct RWLOCK_READER *rd);
592 void remove_reader (struct RWLOCK_READER *rd);
593 struct RWLOCK_READER *lookup_reader (pthread_t thread);
00d296a3 594
ffb576fb
TP
595 void release ()
596 {
597 if (waiting_writers)
598 {
599 if (!readers)
600 cond_writers.unblock (false);
601 }
602 else if (waiting_readers)
603 cond_readers.unblock (true);
604 }
605
606
15648790
TP
607 static void rdlock_cleanup (void *arg);
608 static void wrlock_cleanup (void *arg);
00d296a3 609
15648790
TP
610 void _fixup_after_fork ();
611
612 static native_mutex rwlock_initialization_lock;
00d296a3
TP
613};
614
5c83f260
RC
615class pthread_once
616{
617public:
618 pthread_mutex_t mutex;
619 int state;
5ccbf4b6 620};
1fd5e000 621
9a08b2c0
CF
622/* shouldn't be here */
623class semaphore:public verifyable_object
1fd5e000 624{
9a08b2c0 625public:
15648790 626 static bool is_good_object(sem_t const *);
01f58e41
RC
627 /* API calls */
628 static int init (sem_t * sem, int pshared, unsigned int value);
629 static int destroy (sem_t * sem);
630 static int wait (sem_t * sem);
631 static int trywait (sem_t * sem);
632 static int post (sem_t * sem);
9d1e72a1 633
9a08b2c0
CF
634 HANDLE win32_obj_id;
635 int shared;
f9229ef7 636 long currentvalue;
9a08b2c0 637
aea1f301
CF
638 semaphore (int, unsigned int);
639 ~semaphore ();
9306ba2e
TP
640
641 class semaphore * next;
642 static void fixup_after_fork ()
643 {
15648790 644 semaphores.for_each (&semaphore::_fixup_after_fork);
9306ba2e
TP
645 }
646
9306ba2e 647private:
15648790
TP
648 void _wait ();
649 void _post ();
650 int _trywait ();
651
652 void _fixup_after_fork ();
653
9306ba2e 654 static List<semaphore> semaphores;
9a08b2c0
CF
655};
656
39b6859a
CF
657class callback
658{
659public:
660 void (*cb)(void);
661 class callback * next;
662};
663
1fd5e000
CF
664class MTinterface
665{
666public:
1dc16fc7 667 // General
5c83f260 668 int concurrency;
e6b98fc8 669 long int threadcount;
1fd5e000 670
1dc16fc7
CF
671 // Used for main thread data, and sigproc thread
672 struct __reent_t reents;
673 struct _winsup_t winsup_reent;
1fd5e000 674
39b6859a
CF
675 callback *pthread_prepare;
676 callback *pthread_child;
677 callback *pthread_parent;
5c83f260 678
f8c8e13b
RC
679 pthread_key reent_key;
680 pthread_key thread_self_key;
681
166b2571 682 void Init (int);
f1f13795 683 void fixup_before_fork (void);
f9229ef7 684 void fixup_after_fork (void);
1fd5e000 685
f8c8e13b
RC
686 MTinterface () :
687 concurrency (0), threadcount (1),
688 pthread_prepare (NULL), pthread_child (NULL), pthread_parent (NULL),
f8c8e13b 689 reent_key (NULL), thread_self_key (NULL)
aea1f301 690 {
aea1f301 691 }
1fd5e000
CF
692};
693
f8c8e13b
RC
694#define MT_INTERFACE user_data->threadinterface
695
b0e82b74 696#endif // MT_SAFE
1fd5e000 697
b0e82b74 698#endif // _CYGNUS_THREADS_
This page took 0.238181 seconds and 5 git commands to generate.