]> sourceware.org Git - newlib-cygwin.git/blame - winsup/cygwin/thread.h
* cygwin.din (pthread_attr_getstack): Export.
[newlib-cygwin.git] / winsup / cygwin / thread.h
CommitLineData
1fd5e000
CF
1/* thread.h: Locking and threading module definitions
2
a7d2cc16 3 Copyright 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2007,
f00fe1b8 4 2008, 2009, 2010, 2011 Red Hat, Inc.
462f4eff 5
1fd5e000
CF
6This file is part of Cygwin.
7
8This software is a copyrighted work licensed under the terms of the
9Cygwin license. Please consult the file "CYGWIN_LICENSE" for
10details. */
11
893ac8e0
CF
12#ifndef _THREAD_H
13#define _THREAD_H
1fd5e000 14
2d1d1eb1 15#define LOCK_MMAP_LIST 1
1fd5e000
CF
16
17#define WRITE_LOCK 1
18#define READ_LOCK 2
19
5c83f260 20#include <pthread.h>
2ff03dc2 21#include <limits.h>
66a83f3e 22#include "security.h"
29d52c8a 23#include <errno.h>
056b8e60 24#include "cygerrno.h"
1fd5e000 25
ed364fa9
CF
26enum cw_sig_wait
27{
28 cw_sig_nosig,
29 cw_sig_eintr,
30 cw_sig_resume
31};
32
85564567
CF
33enum cw_cancel_action
34{
35 cw_cancel_self,
36 cw_no_cancel_self,
37 cw_no_cancel
38};
39
39fc0d36
CF
40DWORD cancelable_wait (HANDLE, DWORD, const cw_cancel_action = cw_cancel_self,
41 const enum cw_sig_wait = cw_sig_nosig)
ed364fa9
CF
42 __attribute__ ((regparm (3)));
43
28194e81 44class fast_mutex
ed9fe455
TP
45{
46public:
28194e81
TP
47 fast_mutex () :
48 lock_counter (0), win32_obj_id (0)
49 {
50 }
51
52 ~fast_mutex ()
53 {
54 if(win32_obj_id)
55 CloseHandle (win32_obj_id);
56 }
57
58 bool init ()
59 {
7cba834b 60 lock_counter = 0;
3700578e 61 win32_obj_id = ::CreateEvent (&sec_none_nih, false, false, NULL);
28194e81
TP
62 if (!win32_obj_id)
63 {
3700578e 64 debug_printf ("CreateEvent failed. %E");
5c9ccece 65 return false;
28194e81
TP
66 }
67 return true;
68 }
69
70 void lock ()
71 {
ed364fa9 72 if (InterlockedIncrement ((long *) &lock_counter) != 1)
85564567 73 cancelable_wait (win32_obj_id, INFINITE, cw_no_cancel, cw_sig_resume);
28194e81
TP
74 }
75
76 void unlock ()
77 {
ed364fa9 78 if (InterlockedDecrement ((long *) &lock_counter))
3700578e 79 ::SetEvent (win32_obj_id);
28194e81
TP
80 }
81
ed9fe455 82private:
28194e81
TP
83 unsigned long lock_counter;
84 HANDLE win32_obj_id;
ed9fe455
TP
85};
86
1fd5e000
CF
87class per_process;
88class pinfo;
89
9a08b2c0
CF
90#define PTHREAD_MAGIC 0xdf0df045
91#define PTHREAD_MUTEX_MAGIC PTHREAD_MAGIC+1
92#define PTHREAD_KEY_MAGIC PTHREAD_MAGIC+2
93#define PTHREAD_ATTR_MAGIC PTHREAD_MAGIC+3
94#define PTHREAD_MUTEXATTR_MAGIC PTHREAD_MAGIC+4
95#define PTHREAD_COND_MAGIC PTHREAD_MAGIC+5
96#define PTHREAD_CONDATTR_MAGIC PTHREAD_MAGIC+6
97#define SEM_MAGIC PTHREAD_MAGIC+7
2ff03dc2 98#define PTHREAD_ONCE_MAGIC PTHREAD_MAGIC+8
00d296a3
TP
99#define PTHREAD_RWLOCK_MAGIC PTHREAD_MAGIC+9
100#define PTHREAD_RWLOCKATTR_MAGIC PTHREAD_MAGIC+10
f00fe1b8 101#define PTHREAD_SPINLOCK_MAGIC PTHREAD_MAGIC+11
5c83f260 102
b4fa8164 103#define MUTEX_OWNER_ANONYMOUS ((pthread_t) -1)
5d68d1de 104
2b1407d3
CF
105typedef unsigned long thread_magic_t;
106
5c83f260 107/* verifyable_object should not be defined here - it's a general purpose class */
1fd5e000 108
9a08b2c0
CF
109class verifyable_object
110{
111public:
2b1407d3 112 thread_magic_t magic;
1fd5e000 113
2b1407d3
CF
114 verifyable_object (thread_magic_t verifyer): magic (verifyer) {}
115 virtual ~verifyable_object () { magic = 0; }
9a08b2c0
CF
116};
117
9c510edc 118typedef enum
86336f4f
RC
119{
120 VALID_OBJECT,
121 INVALID_OBJECT,
122 VALID_STATIC_OBJECT
123} verifyable_object_state;
124
28194e81 125template <class list_node> inline void
94d24160 126List_insert (list_node *&head, list_node *node)
28194e81
TP
127{
128 if (!node)
129 return;
94d24160
TP
130 do
131 node->next = head;
132 while (InterlockedCompareExchangePointer (&head, node, node->next) != node->next);
28194e81
TP
133}
134
135template <class list_node> inline void
98854988 136List_remove (fast_mutex &mx, list_node *&head, list_node const *node)
28194e81
TP
137{
138 if (!node)
139 return;
140 mx.lock ();
94d24160 141 if (head)
28194e81 142 {
19adafdc 143 if (InterlockedCompareExchangePointer (&head, node->next, node) != node)
5c9ccece
CF
144 {
145 list_node *cur = head;
146
147 while (cur->next && node != cur->next)
148 cur = cur->next;
149 if (node == cur->next)
150 cur->next = cur->next->next;
151 }
28194e81
TP
152 }
153 mx.unlock ();
154}
9a4d574b 155
28194e81
TP
156
157template <class list_node> class List
158{
159 public:
9306ba2e
TP
160 List() : head(NULL)
161 {
28194e81 162 mx_init ();
9306ba2e
TP
163 }
164
28194e81 165 ~List()
9306ba2e 166 {
9306ba2e
TP
167 }
168
28194e81 169 void fixup_after_fork ()
9306ba2e 170 {
28194e81
TP
171 mx_init ();
172 }
15648790 173
28194e81
TP
174 void insert (list_node *node)
175 {
94d24160 176 List_insert (head, node);
9306ba2e
TP
177 }
178
28194e81 179 void remove (list_node *node)
9306ba2e 180 {
28194e81 181 List_remove (mx, head, node);
9306ba2e
TP
182 }
183
15648790 184 void for_each (void (list_node::*callback) ())
9306ba2e 185 {
28194e81
TP
186 mx.lock ();
187 list_node *cur = head;
188 while (cur)
9306ba2e 189 {
5c9ccece
CF
190 (cur->*callback) ();
191 cur = cur->next;
9306ba2e 192 }
28194e81 193 mx.unlock ();
9306ba2e
TP
194 }
195
8fbd574e
CV
196 fast_mutex mx;
197 list_node *head;
198
af428c1e 199protected:
28194e81
TP
200 void mx_init ()
201 {
202 if (!mx.init ())
203 api_fatal ("Could not create mutex for list synchronisation.");
204 }
af428c1e
RC
205};
206
9a4d574b 207class pthread_key: public verifyable_object
5c83f260 208{
65a7ca7b 209 DWORD tls_index;
5c83f260 210public:
15648790 211 static bool is_good_object (pthread_key_t const *);
f1f13795 212
65a7ca7b
CF
213 int set (const void *value) {TlsSetValue (tls_index, (void *) value); return 0;}
214 void *get () const {return TlsGetValue (tls_index);}
5c83f260 215
20b94ee9 216 pthread_key (void (*)(void *));
aea1f301 217 ~pthread_key ();
28194e81 218 static void fixup_before_fork ()
9306ba2e 219 {
28194e81 220 keys.for_each (&pthread_key::_fixup_before_fork);
9306ba2e
TP
221 }
222
28194e81 223 static void fixup_after_fork ()
9306ba2e 224 {
28194e81
TP
225 keys.fixup_after_fork ();
226 keys.for_each (&pthread_key::_fixup_after_fork);
9306ba2e
TP
227 }
228
15648790 229 static void run_all_destructors ()
9306ba2e 230 {
15648790 231 keys.for_each (&pthread_key::run_destructor);
9306ba2e 232 }
af428c1e
RC
233
234 /* List support calls */
235 class pthread_key *next;
f1f13795 236private:
af428c1e 237 static List<pthread_key> keys;
28194e81
TP
238 void _fixup_before_fork ();
239 void _fixup_after_fork ();
20b94ee9 240 void (*destructor) (void *);
15648790 241 void run_destructor ();
af428c1e 242 void *fork_buf;
5c83f260
RC
243};
244
9a4d574b 245class pthread_attr: public verifyable_object
1fd5e000 246{
9a08b2c0 247public:
15648790 248 static bool is_good_object(pthread_attr_t const *);
9a08b2c0 249 int joinable;
5c83f260
RC
250 int contentionscope;
251 int inheritsched;
252 struct sched_param schedparam;
705a187e 253 void *stackaddr;
9a08b2c0
CF
254 size_t stacksize;
255
aea1f301
CF
256 pthread_attr ();
257 ~pthread_attr ();
1fd5e000
CF
258};
259
9a4d574b 260class pthread_mutexattr: public verifyable_object
43c3c4e3
RC
261{
262public:
15648790 263 static bool is_good_object(pthread_mutexattr_t const *);
43c3c4e3
RC
264 int pshared;
265 int mutextype;
aea1f301
CF
266 pthread_mutexattr ();
267 ~pthread_mutexattr ();
43c3c4e3
RC
268};
269
9a4d574b 270class pthread_mutex: public verifyable_object
43c3c4e3
RC
271{
272public:
15648790 273 static void init_mutex ();
2b1407d3
CF
274 static int init (pthread_mutex_t *, const pthread_mutexattr_t *attr,
275 const pthread_mutex_t);
478ea460
CF
276 static bool is_good_object (pthread_mutex_t const *);
277 static bool is_initializer (pthread_mutex_t const *);
278 static bool is_initializer_or_object (pthread_mutex_t const *);
279 static bool is_initializer_or_bad_object (pthread_mutex_t const *);
43c3c4e3 280
3700578e
CF
281 int lock ();
282 int trylock ();
283 int unlock ();
284 int destroy ();
478ea460 285 void set_type (int in_type) {type = in_type;}
2ff03dc2 286
15648790 287 int lock_recursive ()
2ff03dc2 288 {
478ea460 289 if (recursion_counter == UINT_MAX)
2ff03dc2 290 return EAGAIN;
478ea460 291 recursion_counter++;
2ff03dc2
TP
292 return 0;
293 }
294
478ea460
CF
295 bool can_be_unlocked ();
296
43c3c4e3
RC
297 pthread_mutex (pthread_mutexattr * = NULL);
298 pthread_mutex (pthread_mutex_t *, pthread_mutexattr *);
299 ~pthread_mutex ();
ed9fe455 300
478ea460 301 class pthread_mutex *next;
9306ba2e
TP
302 static void fixup_after_fork ()
303 {
28194e81 304 mutexes.fixup_after_fork ();
15648790 305 mutexes.for_each (&pthread_mutex::_fixup_after_fork);
9306ba2e
TP
306 }
307
f00fe1b8 308protected:
478ea460
CF
309 unsigned long lock_counter;
310 HANDLE win32_obj_id;
478ea460
CF
311 pthread_t owner;
312#ifdef DEBUGGING
313 DWORD tid; /* the thread id of the owner */
314#endif
478ea460 315
f00fe1b8 316 void set_shared (int in_shared) { pshared = in_shared; }
478ea460
CF
317 void set_owner (pthread_t self)
318 {
319 recursion_counter = 1;
320 owner = self;
321#ifdef DEBUGGING
322 tid = GetCurrentThreadId ();
323#endif
324 }
f00fe1b8 325
478ea460
CF
326 static const pthread_t _new_mutex;
327 static const pthread_t _unlocked_mutex;
328 static const pthread_t _destroyed_mutex;
329
f00fe1b8
CV
330private:
331 unsigned int recursion_counter;
332 LONG condwaits;
333 int type;
334 int pshared;
335
478ea460 336 bool no_owner ();
15648790 337 void _fixup_after_fork ();
2ff03dc2 338
9306ba2e 339 static List<pthread_mutex> mutexes;
28194e81 340 static fast_mutex mutex_initialization_lock;
478ea460 341 friend class pthread_cond;
43c3c4e3
RC
342};
343
f00fe1b8
CV
344class pthread_spinlock: public pthread_mutex
345{
346public:
347 static bool is_good_object (pthread_spinlock_t const *);
348 static int init (pthread_spinlock_t *, int);
349
350 int lock ();
351 int unlock ();
352
353 pthread_spinlock (int);
354};
355
09cbb9d6 356#define WAIT_CANCELED (WAIT_OBJECT_0 + 1)
c9a76075 357#define WAIT_SIGNALED (WAIT_OBJECT_0 + 2)
09cbb9d6 358
e431827c 359class _cygtls;
9a4d574b 360class pthread: public verifyable_object
1fd5e000
CF
361{
362public:
9a08b2c0
CF
363 HANDLE win32_obj_id;
364 class pthread_attr attr;
365 void *(*function) (void *);
1dc16fc7
CF
366 void *arg;
367 void *return_ptr;
c6e0f665 368 bool valid;
1dc16fc7 369 bool suspended;
42faed41 370 bool canceled;
5c83f260 371 int cancelstate, canceltype;
e431827c 372 _cygtls *cygtls;
d288c1c7 373 HANDLE cancel_event;
e9259cb2 374 pthread_t joiner;
5c83f260 375
7d7e7a21 376 virtual bool create (void *(*)(void *), pthread_attr *, void *);
4e786173 377
aea1f301
CF
378 pthread ();
379 virtual ~pthread ();
9a08b2c0 380
56a188d1 381 static void init_mainthread ();
15648790 382 static bool is_good_object(pthread_t const *);
aea1f301
CF
383 static void atforkprepare();
384 static void atforkparent();
385 static void atforkchild();
9a08b2c0 386
aea1f301
CF
387 /* API calls */
388 static int cancel (pthread_t);
389 static int join (pthread_t * thread, void **return_val);
390 static int detach (pthread_t * thread);
391 static int create (pthread_t * thread, const pthread_attr_t * attr,
01f58e41 392 void *(*start_routine) (void *), void *arg);
aea1f301
CF
393 static int once (pthread_once_t *, void (*)(void));
394 static int atfork(void (*)(void), void (*)(void), void (*)(void));
395 static int suspend (pthread_t * thread);
396 static int resume (pthread_t * thread);
01f58e41 397
9a4d574b 398 virtual void exit (void *value_ptr) __attribute__ ((noreturn));
d288c1c7 399
aea1f301 400 virtual int cancel ();
9d1e72a1 401
aea1f301 402 virtual void testcancel ();
a91ac4dc 403 static HANDLE get_cancel_event ();
aea1f301 404 static void static_cancel_self ();
d288c1c7 405
aea1f301
CF
406 virtual int setcancelstate (int state, int *oldstate);
407 virtual int setcanceltype (int type, int *oldtype);
d288c1c7 408
aea1f301
CF
409 virtual void push_cleanup_handler (__pthread_cleanup_handler *handler);
410 virtual void pop_cleanup_handler (int const execute);
007276b3 411
aea1f301 412 static pthread* self ();
c350feda 413 static DWORD WINAPI thread_init_wrapper (void *);
007276b3 414
aea1f301 415 virtual unsigned long getsequence_np();
4e786173 416
a4cea440
TP
417 static int equal (pthread_t t1, pthread_t t2)
418 {
419 return t1 == t2;
420 }
421
e1e196a2
TP
422 /* List support calls */
423 class pthread *next;
424 static void fixup_after_fork ()
425 {
28194e81 426 threads.fixup_after_fork ();
e1e196a2
TP
427 threads.for_each (&pthread::_fixup_after_fork);
428 }
429
c6e0f665
TP
430 static void suspend_all_except_self ()
431 {
432 threads.for_each (&pthread::suspend_except_self);
433 }
434
435 static void resume_all ()
436 {
437 threads.for_each (&pthread::resume);
438 }
439
9a08b2c0 440private:
e1e196a2 441 static List<pthread> threads;
aea1f301
CF
442 DWORD thread_id;
443 __pthread_cleanup_handler *cleanup_stack;
444 pthread_mutex mutex;
70300fdb 445 _cygtls *parent_tls;
aea1f301 446
c6e0f665
TP
447 void suspend_except_self ();
448 void resume ();
449
e1e196a2
TP
450 void _fixup_after_fork ();
451
2f9ae2ed 452 void pop_all_cleanup_handlers ();
aea1f301
CF
453 void precreate (pthread_attr *);
454 void postcreate ();
c76d70d7 455 bool create_cancel_event ();
56a188d1 456 static void set_tls_self_pointer (pthread *);
aea1f301 457 void cancel_self ();
15648790 458 DWORD get_thread_id ();
4e786173
RC
459};
460
15648790 461class pthread_null : public pthread
4e786173 462{
d04cf16c 463 public:
15648790
TP
464 static pthread *get_null_pthread();
465 ~pthread_null();
aea1f301
CF
466
467 /* From pthread These should never get called
468 * as the ojbect is not verifyable
469 */
7d7e7a21 470 bool create (void *(*)(void *), pthread_attr *, void *);
9a4d574b 471 void exit (void *value_ptr) __attribute__ ((noreturn));
aea1f301
CF
472 int cancel ();
473 void testcancel ();
474 int setcancelstate (int state, int *oldstate);
475 int setcanceltype (int type, int *oldtype);
476 void push_cleanup_handler (__pthread_cleanup_handler *handler);
477 void pop_cleanup_handler (int const execute);
478 unsigned long getsequence_np();
4e786173
RC
479
480 private:
15648790
TP
481 pthread_null ();
482 static pthread_null _instance;
1fd5e000
CF
483};
484
9a4d574b 485class pthread_condattr: public verifyable_object
1fd5e000
CF
486{
487public:
15648790 488 static bool is_good_object(pthread_condattr_t const *);
1dc16fc7 489 int shared;
9a08b2c0 490
462f4eff
CF
491 pthread_condattr ();
492 ~pthread_condattr ();
1fd5e000
CF
493};
494
9a4d574b 495class pthread_cond: public verifyable_object
5ccbf4b6
CF
496{
497public:
15648790 498 static bool is_good_object (pthread_cond_t const *);
478ea460
CF
499 static bool is_initializer (pthread_cond_t const *);
500 static bool is_initializer_or_object (pthread_cond_t const *);
501 static bool is_initializer_or_bad_object (pthread_cond_t const *);
15648790 502 static void init_mutex ();
ed9fe455
TP
503 static int init (pthread_cond_t *, const pthread_condattr_t *);
504
5ccbf4b6 505 int shared;
f592b05d
TP
506
507 unsigned long waiting;
508 unsigned long pending;
15648790 509 HANDLE sem_wait;
f592b05d 510
15648790
TP
511 pthread_mutex mtx_in;
512 pthread_mutex mtx_out;
f592b05d 513
15648790 514 pthread_mutex_t mtx_cond;
f592b05d 515
15648790
TP
516 void unblock (const bool all);
517 int wait (pthread_mutex_t mutex, DWORD dwMilliseconds = INFINITE);
9a08b2c0 518
aea1f301
CF
519 pthread_cond (pthread_condattr *);
520 ~pthread_cond ();
ed9fe455 521
9306ba2e
TP
522 class pthread_cond * next;
523 static void fixup_after_fork ()
524 {
28194e81 525 conds.fixup_after_fork ();
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;
28194e81 533 static fast_mutex cond_initialization_lock;
5c83f260
RC
534};
535
9a4d574b 536class pthread_rwlockattr: public verifyable_object
00d296a3
TP
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
9a4d574b 546class pthread_rwlock: public verifyable_object
00d296a3
TP
547{
548public:
15648790 549 static bool is_good_object (pthread_rwlock_t const *);
478ea460
CF
550 static bool is_initializer (pthread_rwlock_t const *);
551 static bool is_initializer_or_object (pthread_rwlock_t const *);
552 static bool is_initializer_or_bad_object (pthread_rwlock_t const *);
15648790 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;
f8190b57 565 unsigned long n;
00d296a3 566 } *readers;
28194e81 567 fast_mutex readers_mx;
00d296a3 568
15648790
TP
569 int rdlock ();
570 int tryrdlock ();
00d296a3 571
15648790
TP
572 int wrlock ();
573 int trywrlock ();
00d296a3 574
15648790 575 int unlock ();
00d296a3
TP
576
577 pthread_mutex mtx;
15648790
TP
578 pthread_cond cond_readers;
579 pthread_cond cond_writers;
00d296a3 580
00d296a3
TP
581 pthread_rwlock (pthread_rwlockattr *);
582 ~pthread_rwlock ();
583
9306ba2e
TP
584 class pthread_rwlock * next;
585 static void fixup_after_fork ()
586 {
28194e81 587 rwlocks.fixup_after_fork ();
15648790 588 rwlocks.for_each (&pthread_rwlock::_fixup_after_fork);
9306ba2e
TP
589 }
590
00d296a3 591private:
9306ba2e
TP
592 static List<pthread_rwlock> rwlocks;
593
15648790
TP
594 void add_reader (struct RWLOCK_READER *rd);
595 void remove_reader (struct RWLOCK_READER *rd);
596 struct RWLOCK_READER *lookup_reader (pthread_t thread);
00d296a3 597
ffb576fb
TP
598 void release ()
599 {
600 if (waiting_writers)
601 {
5c9ccece
CF
602 if (!readers)
603 cond_writers.unblock (false);
ffb576fb
TP
604 }
605 else if (waiting_readers)
606 cond_readers.unblock (true);
607 }
608
609
15648790
TP
610 static void rdlock_cleanup (void *arg);
611 static void wrlock_cleanup (void *arg);
00d296a3 612
15648790
TP
613 void _fixup_after_fork ();
614
28194e81 615 static fast_mutex rwlock_initialization_lock;
00d296a3
TP
616};
617
5c83f260
RC
618class pthread_once
619{
620public:
621 pthread_mutex_t mutex;
622 int state;
5ccbf4b6 623};
1fd5e000 624
9a08b2c0 625/* shouldn't be here */
9a4d574b 626class semaphore: public verifyable_object
1fd5e000 627{
9a08b2c0 628public:
15648790 629 static bool is_good_object(sem_t const *);
01f58e41 630 /* API calls */
8fbd574e
CV
631 static int init (sem_t *sem, int pshared, unsigned int value);
632 static int destroy (sem_t *sem);
633 static sem_t *open (unsigned long long hash, LUID luid, int fd, int oflag,
634 mode_t mode, unsigned int value, bool &wasopen);
635 static int close (sem_t *sem);
636 static int wait (sem_t *sem);
637 static int post (sem_t *sem);
638 static int getvalue (sem_t *sem, int *sval);
639 static int trywait (sem_t *sem);
640 static int timedwait (sem_t *sem, const struct timespec *abstime);
641
642 static int getinternal (sem_t *sem, int *sfd, unsigned long long *shash,
643 LUID *sluid, unsigned int *sval);
9d1e72a1 644
9a08b2c0
CF
645 HANDLE win32_obj_id;
646 int shared;
f9229ef7 647 long currentvalue;
8fbd574e
CV
648 int fd;
649 unsigned long long hash;
650 LUID luid;
651 sem_t *sem;
9a08b2c0 652
aea1f301 653 semaphore (int, unsigned int);
8fbd574e 654 semaphore (unsigned long long, LUID, int, sem_t *, int, mode_t, unsigned int);
aea1f301 655 ~semaphore ();
9306ba2e
TP
656
657 class semaphore * next;
658 static void fixup_after_fork ()
659 {
28194e81 660 semaphores.fixup_after_fork ();
15648790 661 semaphores.for_each (&semaphore::_fixup_after_fork);
9306ba2e 662 }
8fbd574e
CV
663 static void terminate ()
664 {
056b8e60 665 save_errno save;
8fbd574e
CV
666 semaphores.for_each (&semaphore::_terminate);
667 }
9306ba2e 668
9306ba2e 669private:
c9a76075 670 int _wait ();
15648790 671 void _post ();
07233966 672 int _getvalue (int *sval);
15648790 673 int _trywait ();
07233966 674 int _timedwait (const struct timespec *abstime);
15648790
TP
675
676 void _fixup_after_fork ();
8fbd574e 677 void _terminate ();
15648790 678
9306ba2e 679 static List<semaphore> semaphores;
9a08b2c0
CF
680};
681
39b6859a
CF
682class callback
683{
684public:
685 void (*cb)(void);
686 class callback * next;
687};
688
9a4d574b 689struct MTinterface
1fd5e000 690{
1dc16fc7 691 // General
5c83f260 692 int concurrency;
e6b98fc8 693 long int threadcount;
1fd5e000 694
39b6859a
CF
695 callback *pthread_prepare;
696 callback *pthread_child;
697 callback *pthread_parent;
5c83f260 698
c8fa3426 699 void Init ();
2f9ae2ed
CF
700 void fixup_before_fork ();
701 void fixup_after_fork ();
1fd5e000 702
29d52c8a 703#if 0 // avoid initialization since zero is implied and
f8c8e13b 704 MTinterface () :
9a4d574b 705 concurrency (0), threadcount (0),
29d52c8a 706 pthread_prepare (NULL), pthread_child (NULL), pthread_parent (NULL)
aea1f301 707 {
aea1f301 708 }
9a4d574b 709#endif
1fd5e000
CF
710};
711
f8c8e13b 712#define MT_INTERFACE user_data->threadinterface
893ac8e0 713#endif // _THREAD_H
This page took 0.49967 seconds and 5 git commands to generate.