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