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