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