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