18 #ifndef LIBCWD_PRIVATE_THREADING_H
19 #define LIBCWD_PRIVATE_THREADING_H
21 #define LIBCWD_DEBUGDEBUGRWLOCK 0
23 #if LIBCWD_DEBUGDEBUGRWLOCK
24 #define LIBCWD_NO_INTERNAL_STRING
25 #include "raw_write.h"
26 #undef LIBCWD_NO_INTERNAL_STRING
27 extern pthread_mutex_t LIBCWD_DEBUGDEBUGLOCK_CERR_mutex;
28 extern unsigned int LIBCWD_DEBUGDEBUGLOCK_CERR_count;
29 #define LIBCWD_DEBUGDEBUGRWLOCK_CERR(x) \
31 pthread_mutex_lock(&LIBCWD_DEBUGDEBUGLOCK_CERR_mutex); \
32 FATALDEBUGDEBUG_CERR(x); \
33 pthread_mutex_unlock(&LIBCWD_DEBUGDEBUGLOCK_CERR_mutex); \
35 #define LIBCWD_DEBUGDEBUGLOCK_CERR(x) \
37 if (instance != static_tsd_instance) \
39 pthread_mutex_lock(&LIBCWD_DEBUGDEBUGLOCK_CERR_mutex); \
40 ++LIBCWD_DEBUGDEBUGLOCK_CERR_count; \
41 FATALDEBUGDEBUG_CERR("[" << LIBCWD_DEBUGDEBUGLOCK_CERR_count << "] " << pthread_self() << ": " << x); \
42 pthread_mutex_unlock(&LIBCWD_DEBUGDEBUGLOCK_CERR_mutex); \
46 #define LIBCWD_DEBUGDEBUGRWLOCK_CERR(x) do { } while(0)
47 #define LIBCWD_DEBUGDEBUGLOCK_CERR(x) do { } while(0)
50 #ifndef LIBCWD_PRIVATE_SET_ALLOC_CHECKING_H
53 #ifndef LIBCWD_PRIVATE_STRUCT_TSD_H
56 #ifndef LIBCWD_PRIVATE_MUTEX_INSTANCES_H
59 #ifndef LIBCWD_CORE_DUMP_H
67 #ifdef LIBCWD_HAVE_PTHREAD
70 #error "You need to use define _GNU_SOURCE in order to make use of the extensions of Linux Threads."
73 #ifndef LIBCW_PTHREAD_H
74 #define LIBCW_PTHREAD_H
77 #if defined(PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP) && defined(PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP)
78 #define LIBCWD_USE_LINUXTHREADS 1
80 #define LIBCWD_USE_POSIX_THREADS 1
83 #if LIBCWD_THREAD_SAFE
84 #error Fatal error: thread support was not detected during configuration of libcwd (did you use --disable-threading?)! \
85 How come you are trying to compile a threaded program now? \
86 To fix this problem, either link with libcwd_r (install it), or when you are indeed compiling a \
87 single threaded application, then get rid of the -pthread (and/or -D_REENTRANT and/or -D_THREAD_SAFE) in your compile flags.
91 #ifndef LIBCWD_USE_LINUXTHREADS
92 #define LIBCWD_USE_LINUXTHREADS 0
94 #ifndef LIBCWD_USE_POSIX_THREADS
95 #define LIBCWD_USE_POSIX_THREADS 0
99 #define LibcwDebugThreads(x) do { x; } while(0)
101 #define LibcwDebugThreads(x) do { } while(0)
104 #if CWDEBUG_DEBUGT || CWDEBUG_DEBUG
105 #ifndef LIBCWD_PRIVATE_ASSERT_H
110 #if LIBCWD_THREAD_SAFE
114 #if LIBCWD_DEBUGDEBUGRWLOCK
116 _private_::raw_write_nt
const&
117 operator<<(_private_::raw_write_nt
const& raw_write, pthread_mutex_t
const& mutex)
119 raw_write <<
"(pthread_mutex_t&)" << (
void*)&mutex <<
121 "{ __lock = " << mutex.__data.__lock <<
", "
122 "__count = " << mutex.__data.__count <<
", "
123 "__owner = " << mutex.__data.__owner <<
", "
124 "__nusers = " << mutex.__data.__nusers <<
", "
125 "__kind = " << mutex.__data.__kind <<
"} }";
130 namespace _private_ {
132 extern void initialize_global_mutexes();
133 extern bool WST_multi_threaded;
136 extern void test_for_deadlock(
size_t,
struct TSD_st&,
void const*);
137 inline void test_for_deadlock(
int instance,
struct TSD_st& __libcwd_tsd,
void const* from)
139 assert(instance < 0x10000);
140 test_for_deadlock(
static_cast<size_t>(instance), __libcwd_tsd, from);
142 inline void test_for_deadlock(
void const* ptr,
struct TSD_st& __libcwd_tsd,
void const* from)
144 assert(
reinterpret_cast<size_t>(ptr) >= 0x10000);
145 test_for_deadlock(
reinterpret_cast<size_t>(ptr), __libcwd_tsd, from);
170 #if LIBCWD_USE_POSIX_THREADS || LIBCWD_USE_LINUXTHREADS
173 #define LIBCWD_DISABLE_CANCEL \
175 LIBCWD_DISABLE_CANCEL_NO_BRACE
176 #define LIBCWD_DISABLE_CANCEL_NO_BRACE \
177 int __libcwd_oldstate; \
178 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &__libcwd_oldstate); \
179 LibcwDebugThreads( ++__libcwd_tsd.cancel_explicitely_disabled )
181 #define LIBCWD_ASSERT_USERSPACE_OR_DEFERED_BEFORE_SETCANCELSTATE \
186 LIBCWD_ASSERT( !__libcwd_tsd.internal || __libcwd_tsd.cancel_explicitely_disabled || __libcwd_tsd.cancel_explicitely_deferred )
188 #define LIBCWD_ASSERT_USERSPACE_OR_DEFERED_BEFORE_SETCANCELSTATE
190 #define LIBCWD_ENABLE_CANCEL_NO_BRACE \
192 LIBCWD_ASSERT( __libcwd_tsd.cancel_explicitely_disabled > 0 ); \
193 --__libcwd_tsd.cancel_explicitely_disabled; \
194 LIBCWD_ASSERT_USERSPACE_OR_DEFERED_BEFORE_SETCANCELSTATE; \
196 pthread_setcancelstate(__libcwd_oldstate, NULL)
197 #define LIBCWD_ENABLE_CANCEL \
198 LIBCWD_ENABLE_CANCEL_NO_BRACE; \
201 #define LIBCWD_DEFER_CANCEL \
203 LIBCWD_DEFER_CANCEL_NO_BRACE
204 #define LIBCWD_DEFER_CANCEL_NO_BRACE \
205 int __libcwd_oldtype; \
206 pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, &__libcwd_oldtype); \
207 LibcwDebugThreads( ++__libcwd_tsd.cancel_explicitely_deferred )
208 #define LIBCWD_RESTORE_CANCEL_NO_BRACE \
210 LIBCWD_ASSERT( __libcwd_tsd.cancel_explicitely_deferred > 0 ); \
211 --__libcwd_tsd.cancel_explicitely_deferred; \
212 LIBCWD_ASSERT_USERSPACE_OR_DEFERED_BEFORE_SETCANCELSTATE; \
214 pthread_setcanceltype(__libcwd_oldtype, NULL)
215 #define LIBCWD_RESTORE_CANCEL \
216 LIBCWD_RESTORE_CANCEL_NO_BRACE; \
219 #if LIBCWD_USE_LINUXTHREADS
220 #define LIBCWD_DEFER_CLEANUP_PUSH(routine, arg) \
221 pthread_cleanup_push_defer_np(reinterpret_cast<void(*)(void*)>(routine), reinterpret_cast<void*>(arg)); \
222 LibcwDebugThreads( ++__libcwd_tsd.cancel_explicitely_deferred; ++__libcwd_tsd.cleanup_handler_installed )
224 #define LIBCWD_ASSERT_NONINTERNAL LIBCWD_ASSERT( !__libcwd_tsd.internal )
226 #define LIBCWD_ASSERT_NONINTERNAL
228 #define LIBCWD_CLEANUP_POP_RESTORE(execute) \
229 LibcwDebugThreads( --__libcwd_tsd.cleanup_handler_installed; \
230 LIBCWD_ASSERT( __libcwd_tsd.cancel_explicitely_deferred > 0 ); \
231 LIBCWD_ASSERT_NONINTERNAL; ); \
232 pthread_cleanup_pop_restore_np(static_cast<int>(execute)); \
233 LibcwDebugThreads( --__libcwd_tsd.cancel_explicitely_deferred; )
235 #define LIBCWD_DEFER_CLEANUP_PUSH(routine, arg) \
236 LIBCWD_DEFER_CANCEL; \
237 LibcwDebugThreads( ++__libcwd_tsd.cleanup_handler_installed ); \
238 pthread_cleanup_push(reinterpret_cast<void(*)(void*)>(routine), reinterpret_cast<void*>(arg))
239 #define LIBCWD_CLEANUP_POP_RESTORE(execute) \
240 LibcwDebugThreads( --__libcwd_tsd.cleanup_handler_installed ); \
241 pthread_cleanup_pop(static_cast<int>(execute)); \
242 LIBCWD_RESTORE_CANCEL
245 #define LIBCWD_PUSH_DEFER_TRYLOCK_MUTEX(instance, unlock_routine) \
246 LIBCWD_DEFER_CLEANUP_PUSH(static_cast<void (*)()>(unlock_routine), &::libcwd::_private_::mutex_tct<(instance)>::S_mutex); \
247 bool __libcwd_lock_successful = ::libcwd::_private_::mutex_tct<(instance)>::try_lock()
248 #define LIBCWD_DEFER_PUSH_LOCKMUTEX(instance, unlock_routine) \
249 LIBCWD_DEFER_CLEANUP_PUSH(static_cast<void (*)()>(unlock_routine), &::libcwd::_private_::mutex_tct<(instance)>::S_mutex); \
250 ::libcwd::_private_::mutex_tct<(instance)>::lock(); \
251 bool const __libcwd_lock_successful = true
252 #define LIBCWD_UNLOCKMUTEX_POP_RESTORE(instance) \
253 LIBCWD_CLEANUP_POP_RESTORE(__libcwd_lock_successful)
255 #define LIBCWD_DEBUGDEBUG_ASSERT_CANCEL_DEFERRED \
257 if (instance != static_tsd_instance) \
262 LIBCWD_ASSERT( __libcwd_tsd.cancel_explicitely_deferred || __libcwd_tsd.cancel_explicitely_disabled ); \
265 template <
int instance>
268 static pthread_mutex_t S_mutex;
269 #if !LIBCWD_USE_LINUXTHREADS || CWDEBUG_DEBUGT
271 static bool volatile S_initialized;
272 static void S_initialize();
275 static void initialize()
276 #if LIBCWD_USE_LINUXTHREADS && !CWDEBUG_DEBUGT
287 static bool try_lock()
289 LibcwDebugThreads( LIBCWD_ASSERT( S_initialized ) );
291 LIBCWD_TSD_DECLARATION;
293 LIBCWD_DEBUGDEBUG_ASSERT_CANCEL_DEFERRED;
294 LIBCWD_DEBUGDEBUGLOCK_CERR(
"Trying to lock mutex " << instance <<
" (" << (
void*)&S_mutex <<
") from " << __builtin_return_address(0) <<
" from " << __builtin_return_address(1));
295 LIBCWD_DEBUGDEBUGLOCK_CERR(
"pthread_mutex_trylock(" << S_mutex <<
").");
296 bool success = (pthread_mutex_trylock(&S_mutex) == 0);
297 LIBCWD_DEBUGDEBUGLOCK_CERR(
"Result = " << success <<
". Mutex now " << S_mutex <<
".");
298 #if CWDEBUG_DEBUG || CWDEBUG_DEBUGT
302 _private_::test_for_deadlock(instance, __libcwd_tsd, __builtin_return_address(0));
304 LIBCWD_DEBUGDEBUGLOCK_CERR(
"mutex_tct::try_lock(): instance_locked[" << instance <<
"] == " << instance_locked[instance] <<
"; incrementing it.");
305 instance_locked[instance] += 1;
307 locked_by[instance] = pthread_self();
308 locked_from[instance] = __builtin_return_address(0);
312 LibcwDebugThreads(
if (success) { ++__libcwd_tsd.inside_critical_area; } );
317 LibcwDebugThreads( LIBCWD_ASSERT( S_initialized ) );
320 if (instance != static_tsd_instance)
322 LIBCWD_TSD_DECLARATION;
323 tsd_ptr = &__libcwd_tsd;
325 TSD_st& __libcwd_tsd(*tsd_ptr);
327 LIBCWD_DEBUGDEBUG_ASSERT_CANCEL_DEFERRED;
328 LibcwDebugThreads(
if (instance != static_tsd_instance) { ++__libcwd_tsd.inside_critical_area; } );
329 LIBCWD_DEBUGDEBUGLOCK_CERR(
"locking mutex " << instance <<
" (" << (
void*)&S_mutex <<
") from " << __builtin_return_address(0) <<
" from " << __builtin_return_address(1));
331 if (instance != static_tsd_instance && !(instance >= 2 * reserved_instance_low && instance < 3 * reserved_instance_low))
333 __libcwd_tsd.waiting_for_lock = instance;
334 LIBCWD_DEBUGDEBUGLOCK_CERR(
"pthread_mutex_lock(" << S_mutex <<
").");
335 int res = pthread_mutex_lock(&S_mutex);
336 LIBCWD_DEBUGDEBUGLOCK_CERR(
"Result = " << res <<
". Mutex now " << S_mutex <<
".");
337 #if LIBCWD_DEBUGDEBUGRWLOCK
338 LIBCWD_ASSERT( res == 0 || res == EDEADLK );
340 __libcwd_tsd.waiting_for_lock = 0;
341 _private_::test_for_deadlock(instance, __libcwd_tsd, __builtin_return_address(0));
342 LIBCWD_ASSERT( res == 0 );
346 LIBCWD_DEBUGDEBUGLOCK_CERR(
"pthread_mutex_lock(" << S_mutex <<
").");
347 int res = pthread_mutex_lock(&S_mutex);
348 LIBCWD_DEBUGDEBUGLOCK_CERR(
"Result = " << res <<
". Mutex now " << S_mutex <<
".");
349 LIBCWD_ASSERT( res == 0 );
352 pthread_mutex_lock(&S_mutex);
354 LIBCWD_DEBUGDEBUGLOCK_CERR(
"Lock " << instance <<
" obtained (" << (
void*)&S_mutex <<
").");
355 #if CWDEBUG_DEBUG || CWDEBUG_DEBUGT
356 LIBCWD_DEBUGDEBUGLOCK_CERR(
"mutex_tct::lock(): instance_locked[" << instance <<
"] == " << instance_locked[instance] <<
"; incrementing it.");
357 instance_locked[instance] += 1;
359 if (locked_by[instance] != 0 && locked_by[instance] != pthread_self())
361 LIBCWD_DEBUGDEBUGLOCK_CERR(
"mutex " << instance <<
" (" << (
void*)&S_mutex <<
") is already set by another thread (" << locked_by[instance] <<
")!");
364 locked_by[instance] = pthread_self();
365 locked_from[instance] = __builtin_return_address(0);
373 if (instance != static_tsd_instance)
375 LIBCWD_TSD_DECLARATION;
376 tsd_ptr = &__libcwd_tsd;
378 TSD_st& __libcwd_tsd(*tsd_ptr);
380 LIBCWD_DEBUGDEBUG_ASSERT_CANCEL_DEFERRED;
381 #if CWDEBUG_DEBUG || CWDEBUG_DEBUGT
382 LIBCWD_DEBUGDEBUGLOCK_CERR(
"mutex_tct::unlock(): instance_locked[" << instance <<
"] == " << instance_locked[instance] <<
"; decrementing it.");
383 LIBCWD_ASSERT( instance_locked[instance] > 0 );
385 if (locked_by[instance] != pthread_self())
387 LIBCWD_DEBUGDEBUGLOCK_CERR(
"unlocking instance " << instance <<
" (" << (
void*)&S_mutex <<
") failed: locked_by[" << instance <<
"] == " << locked_by[instance] <<
".");
391 instance_locked[instance] -= 1;
393 if (instance_locked[instance] == 0)
395 locked_by[instance] = 0;
396 LIBCWD_DEBUGDEBUGLOCK_CERR(
"mutex_tct::unlock(): locked_by[" << instance <<
"] was reset.");
398 else LIBCWD_DEBUGDEBUGLOCK_CERR(
"mutex_tct::unlock(): locked_by[" << instance <<
"] was not reset, it still is " << locked_by[instance] <<
".");
401 LIBCWD_DEBUGDEBUGLOCK_CERR(
"unlocking mutex " << instance <<
" (" << (
void*)&S_mutex <<
").");
402 LIBCWD_DEBUGDEBUGLOCK_CERR(
"pthread_mutex_unlock(" << S_mutex <<
").");
406 pthread_mutex_unlock(&S_mutex);
408 LIBCWD_DEBUGDEBUGLOCK_CERR(
"Result = " << res <<
". Mutex now " << S_mutex <<
".");
409 LIBCWD_ASSERT(res == 0);
411 LIBCWD_DEBUGDEBUGLOCK_CERR(
"Lock " << instance <<
" released (" << (
void*)&S_mutex <<
").");
412 LibcwDebugThreads(
if (instance != static_tsd_instance) { --__libcwd_tsd.inside_critical_area; } );
415 static void cleanup(
void*);
418 #if !LIBCWD_USE_LINUXTHREADS || CWDEBUG_DEBUGT
419 template <
int instance>
420 bool volatile mutex_tct<instance>::S_initialized =
false;
422 template <
int instance>
423 void mutex_tct<instance>::S_initialize()
425 if (instance == mutex_initialization_instance)
427 #if !LIBCWD_USE_LINUXTHREADS
428 pthread_mutexattr_t mutex_attr;
429 pthread_mutexattr_init(&mutex_attr);
431 pthread_mutexattr_settype(&mutex_attr, PTHREAD_MUTEX_ERRORCHECK);
433 pthread_mutexattr_settype(&mutex_attr, PTHREAD_MUTEX_NORMAL);
435 pthread_mutex_init(&S_mutex, &mutex_attr);
436 pthread_mutexattr_destroy(&mutex_attr);
438 S_initialized =
true;
442 mutex_tct<mutex_initialization_instance>::initialize();
446 #if !LIBCWD_USE_LINUXTHREADS
447 pthread_mutexattr_t mutex_attr;
448 pthread_mutexattr_init(&mutex_attr);
449 if (instance < end_recursive_types)
450 pthread_mutexattr_settype(&mutex_attr, PTHREAD_MUTEX_RECURSIVE);
454 pthread_mutexattr_settype(&mutex_attr, PTHREAD_MUTEX_ERRORCHECK);
456 pthread_mutexattr_settype(&mutex_attr, PTHREAD_MUTEX_NORMAL);
459 pthread_mutex_init(&S_mutex, &mutex_attr);
460 pthread_mutexattr_destroy(&mutex_attr);
462 S_initialized =
true;
469 template <
int instance>
470 pthread_mutex_t mutex_tct<instance>::S_mutex
471 #if LIBCWD_USE_LINUXTHREADS
474 PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP;
476 PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP;
482 template <
int instance>
483 void mutex_tct<instance>::cleanup(
void*)
491 template <
int instance>
492 class cond_tct :
public mutex_tct<instance> {
494 static pthread_cond_t S_condition;
495 #if CWDEBUG_DEBUGT || !LIBCWD_USE_LINUXTHREADS
496 static bool volatile S_initialized;
498 static void S_initialize();
501 static void initialize()
502 #if CWDEBUG_DEBUGT || !LIBCWD_USE_LINUXTHREADS
513 #if CWDEBUG_DEBUG || CWDEBUG_DEBUGT
514 LIBCWD_DEBUGDEBUGLOCK_CERR(
"cond_tct::wait(): instance_locked[" << instance <<
"] == " << instance_locked[instance] <<
"; decrementing it.");
515 LIBCWD_ASSERT( instance_locked[instance] > 0 );
517 if (locked_by[instance] != pthread_self())
519 LIBCWD_DEBUGDEBUGLOCK_CERR(
"unlocking instance " << instance <<
" (" << (
void*)&this->S_mutex <<
") failed: locked_by[" << instance <<
"] == " << locked_by[instance] <<
".");
523 instance_locked[instance] -= 1;
525 if (instance_locked[instance] == 0)
527 locked_by[instance] = 0;
528 LIBCWD_DEBUGDEBUGLOCK_CERR(
"cond_tct::wait(): locked_by[" << instance <<
"] was reset.");
530 else LIBCWD_DEBUGDEBUGLOCK_CERR(
"cond_tct::wait(): locked_by[" << instance <<
"] was not reset, it still is " << locked_by[instance] <<
".");
533 LIBCWD_DEBUGDEBUGLOCK_CERR(
"unlocking mutex " << instance <<
" (" << (
void*)&this->S_mutex <<
").");
534 LIBCWD_DEBUGDEBUGLOCK_CERR(
"pthread_cond_wait(" << (
void*)&S_condition <<
", " << this->S_mutex <<
").");
538 pthread_cond_wait(&S_condition, &this->S_mutex);
540 LIBCWD_DEBUGDEBUGLOCK_CERR(
"Result = " << res <<
". Mutex now " << this->S_mutex <<
".");
541 LIBCWD_ASSERT(res == 0);
543 LIBCWD_DEBUGDEBUGLOCK_CERR(
"Lock " << instance <<
" obtained (" << (
void*)&this->S_mutex <<
").");
544 #if CWDEBUG_DEBUG || CWDEBUG_DEBUGT
545 LIBCWD_DEBUGDEBUGLOCK_CERR(
"cond_tct::wait(): instance_locked[" << instance <<
"] == " << instance_locked[instance] <<
"; incrementing it.");
546 instance_locked[instance] += 1;
548 if (locked_by[instance] != 0 && locked_by[instance] != pthread_self())
550 LIBCWD_DEBUGDEBUGLOCK_CERR(
"mutex " << instance <<
" (" << (
void*)&this->S_mutex <<
") is already set by another thread (" << locked_by[instance] <<
")!");
553 locked_by[instance] = pthread_self();
554 locked_from[instance] = __builtin_return_address(0);
558 void signal() { pthread_cond_signal(&S_condition); }
559 void broadcast() { pthread_cond_broadcast(&S_condition); }
562 #if CWDEBUG_DEBUGT || !LIBCWD_USE_LINUXTHREADS
563 template <
int instance>
564 void cond_tct<instance>::S_initialize()
566 #if !LIBCWD_USE_LINUXTHREADS
567 mutex_tct<mutex_initialization_instance>::initialize();
568 LIBCWD_DEFER_PUSH_LOCKMUTEX(mutex_initialization_instance, mutex_tct<mutex_initialization_instance>::unlock);
571 pthread_cond_init(&S_condition, NULL);
573 LIBCWD_UNLOCKMUTEX_POP_RESTORE(mutex_initialization_instance);
575 mutex_tct<instance>::S_initialize();
579 #if CWDEBUG_DEBUGT || !LIBCWD_USE_LINUXTHREADS
580 template <
int instance>
581 bool volatile cond_tct<instance>::S_initialized =
false;
584 template <
int instance>
585 pthread_cond_t cond_tct<instance>::S_condition
586 #if LIBCWD_USE_LINUXTHREADS
587 = PTHREAD_COND_INITIALIZER;
617 template <
int instance>
620 static int const readers_instance = instance + reserved_instance_low;
621 static int const holders_instance = instance + 2 * reserved_instance_low;
622 typedef cond_tct<holders_instance> cond_t;
623 static cond_t S_no_holders_condition;
624 static int S_holders_count;
625 static bool volatile S_writer_is_waiting;
626 static pthread_t S_writer_id;
627 #if CWDEBUG_DEBUGT || !LIBCWD_USE_LINUXTHREADS
628 static bool S_initialized;
631 static void initialize()
633 #if CWDEBUG_DEBUGT || !LIBCWD_USE_LINUXTHREADS
636 LIBCWD_DEBUGDEBUGRWLOCK_CERR(pthread_self() <<
": Calling initialize() instance " << instance);
637 mutex_tct<readers_instance>::initialize();
638 S_no_holders_condition.initialize();
639 LIBCWD_DEBUGDEBUGRWLOCK_CERR(pthread_self() <<
": Leaving initialize() instance " << instance);
640 S_initialized =
true;
643 static bool tryrdlock()
646 LIBCWD_TSD_DECLARATION;
648 LibcwDebugThreads( LIBCWD_ASSERT( S_initialized ) );
649 LIBCWD_DEBUGDEBUG_ASSERT_CANCEL_DEFERRED;
650 LIBCWD_DEBUGDEBUGRWLOCK_CERR(pthread_self() <<
": Calling rwlock_tct<" << instance <<
">::tryrdlock()");
651 if (instance < end_recursive_types && pthread_equal(S_writer_id, pthread_self()))
653 LIBCWD_DEBUGDEBUGRWLOCK_CERR(pthread_self() <<
": Leaving rwlock_tct<" << instance <<
">::tryrdlock() (skipped: thread has write lock)");
657 if (S_writer_is_waiting || !S_no_holders_condition.try_lock())
659 bool success = (S_holders_count != -1);
662 S_no_holders_condition.unlock();
666 ++__libcwd_tsd.inside_critical_area;
667 _private_::test_for_deadlock(instance, __libcwd_tsd, __builtin_return_address(0));
668 __libcwd_tsd.instance_rdlocked[instance] += 1;
669 if (__libcwd_tsd.instance_rdlocked[instance] == 1)
671 __libcwd_tsd.rdlocked_by1[instance] = pthread_self();
672 __libcwd_tsd.rdlocked_from1[instance] = __builtin_return_address(0);
674 else if (__libcwd_tsd.instance_rdlocked[instance] == 2)
676 __libcwd_tsd.rdlocked_by2[instance] = pthread_self();
677 __libcwd_tsd.rdlocked_from2[instance] = __builtin_return_address(0);
683 LIBCWD_DEBUGDEBUGRWLOCK_CERR(pthread_self() <<
": Leaving rwlock_tct<" << instance <<
">::tryrdlock()");
686 static bool trywrlock()
688 LibcwDebugThreads( LIBCWD_ASSERT( S_initialized ) );
690 LIBCWD_TSD_DECLARATION;
692 LIBCWD_DEBUGDEBUG_ASSERT_CANCEL_DEFERRED;
693 LIBCWD_DEBUGDEBUGRWLOCK_CERR(pthread_self() <<
": Calling rwlock_tct<" << instance <<
">::trywrlock()");
695 if ((success = mutex_tct<readers_instance>::try_lock()))
697 S_writer_is_waiting =
true;
698 if ((success = S_no_holders_condition.try_lock()))
700 if ((success = (S_holders_count == 0)))
702 S_holders_count = -1;
703 if (instance < end_recursive_types)
704 S_writer_id = pthread_self();
705 #if CWDEBUG_DEBUG || CWDEBUG_DEBUGT
707 _private_::test_for_deadlock(instance, __libcwd_tsd, __builtin_return_address(0));
709 LIBCWD_DEBUGDEBUGRWLOCK_CERR(pthread_self() <<
": rwlock_tct::trywrlock(): instance_locked[" << instance <<
"] == " << instance_locked[instance] <<
"; incrementing it.");
710 instance_locked[instance] += 1;
712 locked_by[instance] = pthread_self();
713 locked_from[instance] = __builtin_return_address(0);
717 S_no_holders_condition.unlock();
719 S_writer_is_waiting =
false;
720 mutex_tct<readers_instance>::unlock();
722 LibcwDebugThreads(
if (success) { ++__libcwd_tsd.inside_critical_area; } );
723 LIBCWD_DEBUGDEBUGRWLOCK_CERR(pthread_self() <<
": Leaving rwlock_tct<" << instance <<
">::trywrlock()");
726 static void rdlock(
bool high_priority =
false)
728 LibcwDebugThreads( LIBCWD_ASSERT( S_initialized ) );
730 LIBCWD_TSD_DECLARATION;
732 LIBCWD_DEBUGDEBUG_ASSERT_CANCEL_DEFERRED;
733 LIBCWD_DEBUGDEBUGRWLOCK_CERR(pthread_self() <<
": Calling rwlock_tct<" << instance <<
">::rdlock()");
734 if (instance < end_recursive_types && pthread_equal(S_writer_id, pthread_self()))
736 LIBCWD_DEBUGDEBUGRWLOCK_CERR(pthread_self() <<
": Leaving rwlock_tct<" << instance <<
">::rdlock() (skipped: thread has write lock)");
740 if (S_writer_is_waiting)
744 mutex_tct<readers_instance>::lock();
745 mutex_tct<readers_instance>::unlock();
749 __libcwd_tsd.waiting_for_rdlock = instance;
751 S_no_holders_condition.lock();
752 while (S_holders_count == -1)
753 S_no_holders_condition.wait();
755 __libcwd_tsd.waiting_for_rdlock = 0;
758 S_no_holders_condition.unlock();
760 ++__libcwd_tsd.inside_critical_area;
773 _private_::test_for_deadlock(instance + (high_priority ? high_priority_read_lock_offset : read_lock_offset), __libcwd_tsd, __builtin_return_address(0));
774 __libcwd_tsd.instance_rdlocked[instance] += 1;
775 if (__libcwd_tsd.instance_rdlocked[instance] == 1)
777 __libcwd_tsd.rdlocked_by1[instance] = pthread_self();
778 __libcwd_tsd.rdlocked_from1[instance] = __builtin_return_address(0);
780 else if (__libcwd_tsd.instance_rdlocked[instance] == 2)
782 __libcwd_tsd.rdlocked_by2[instance] = pthread_self();
783 __libcwd_tsd.rdlocked_from2[instance] = __builtin_return_address(0);
788 LIBCWD_DEBUGDEBUGRWLOCK_CERR(pthread_self() <<
": Leaving rwlock_tct<" << instance <<
">::rdlock()");
790 static void rdunlock()
793 LIBCWD_TSD_DECLARATION;
795 LIBCWD_DEBUGDEBUG_ASSERT_CANCEL_DEFERRED;
796 LIBCWD_DEBUGDEBUGRWLOCK_CERR(pthread_self() <<
": Calling rwlock_tct<" << instance <<
">::rdunlock()");
797 if (instance < end_recursive_types && pthread_equal(S_writer_id, pthread_self()))
799 LIBCWD_DEBUGDEBUGRWLOCK_CERR(pthread_self() <<
": Leaving rwlock_tct<" << instance <<
">::rdunlock() (skipped: thread has write lock)");
802 LibcwDebugThreads( --__libcwd_tsd.inside_critical_area );
803 S_no_holders_condition.lock();
804 if (--S_holders_count == 0)
805 S_no_holders_condition.signal();
806 S_no_holders_condition.unlock();
808 if (__libcwd_tsd.instance_rdlocked[instance] == 2)
809 __libcwd_tsd.rdlocked_by2[instance] = 0;
811 __libcwd_tsd.rdlocked_by1[instance] = 0;
812 __libcwd_tsd.instance_rdlocked[instance] -= 1;
814 LIBCWD_DEBUGDEBUGRWLOCK_CERR(pthread_self() <<
": Leaving rwlock_tct<" << instance <<
">::rdunlock()");
818 LibcwDebugThreads( LIBCWD_ASSERT( S_initialized ) );
820 LIBCWD_TSD_DECLARATION;
822 LIBCWD_DEBUGDEBUG_ASSERT_CANCEL_DEFERRED;
823 LIBCWD_DEBUGDEBUGRWLOCK_CERR(pthread_self() <<
": Calling rwlock_tct<" << instance <<
">::wrlock()");
824 mutex_tct<readers_instance>::lock();
825 S_writer_is_waiting =
true;
827 __libcwd_tsd.waiting_for_lock = instance;
829 S_no_holders_condition.lock();
830 while (S_holders_count != 0)
831 S_no_holders_condition.wait();
833 __libcwd_tsd.waiting_for_lock = 0;
835 S_writer_is_waiting =
false;
836 mutex_tct<readers_instance>::unlock();
837 S_holders_count = -1;
838 S_no_holders_condition.unlock();
839 if (instance < end_recursive_types)
840 S_writer_id = pthread_self();
841 LibcwDebugThreads( ++__libcwd_tsd.inside_critical_area );
842 #if CWDEBUG_DEBUG || CWDEBUG_DEBUGT
844 _private_::test_for_deadlock(instance, __libcwd_tsd, __builtin_return_address(0));
846 LIBCWD_DEBUGDEBUGRWLOCK_CERR(pthread_self() <<
": rwlock_tct::wrlock(): instance_locked[" << instance <<
"] == " << instance_locked[instance] <<
"; incrementing it.");
847 instance_locked[instance] += 1;
849 locked_by[instance] = pthread_self();
850 locked_from[instance] = __builtin_return_address(0);
853 LIBCWD_DEBUGDEBUGRWLOCK_CERR(pthread_self() <<
": Leaving rwlock_tct<" << instance <<
">::wrlock()");
855 static void wrunlock()
858 LIBCWD_TSD_DECLARATION;
860 LIBCWD_DEBUGDEBUG_ASSERT_CANCEL_DEFERRED;
861 #if CWDEBUG_DEBUG || CWDEBUG_DEBUGT
862 LIBCWD_DEBUGDEBUGRWLOCK_CERR(pthread_self() <<
": rwlock_tct::wrunlock(): instance_locked[" << instance <<
"] == " << instance_locked[instance] <<
"; decrementing it.");
864 LIBCWD_ASSERT( instance_locked[instance] > 0 && locked_by[instance] == pthread_self() );
866 instance_locked[instance] -= 1;
869 if (instance > end_recursive_types || instance_locked[instance] == 0)
871 locked_by[instance] = 0;
872 LIBCWD_DEBUGDEBUGRWLOCK_CERR(pthread_self() <<
": rwlock_tct::unlock(): locked_by[" << instance <<
"] was reset.");
876 LIBCWD_DEBUGDEBUGRWLOCK_CERR(pthread_self() <<
": rwlock_tct::wrunlock(): locked_by[" << instance <<
"] was not reset, it still is " << locked_by[instance] <<
".");
879 LIBCWD_DEBUGDEBUGRWLOCK_CERR(pthread_self() <<
": Calling rwlock_tct<" << instance <<
">::wrunlock()");
880 LibcwDebugThreads( --__libcwd_tsd.inside_critical_area) ;
881 if (instance < end_recursive_types)
883 S_no_holders_condition.lock();
885 S_no_holders_condition.signal();
886 S_no_holders_condition.unlock();
887 LIBCWD_DEBUGDEBUGRWLOCK_CERR(pthread_self() <<
": Leaving rwlock_tct<" << instance <<
">::wrunlock()");
889 static void rd2wrlock()
892 LIBCWD_TSD_DECLARATION;
894 LIBCWD_DEBUGDEBUG_ASSERT_CANCEL_DEFERRED;
895 LIBCWD_DEBUGDEBUGRWLOCK_CERR(pthread_self() <<
": Calling rwlock_tct<" << instance <<
">::rd2wrlock()");
897 __libcwd_tsd.waiting_for_lock = instance;
899 S_no_holders_condition.lock();
900 if (--S_holders_count > 0)
902 mutex_tct<readers_instance>::lock();
903 S_writer_is_waiting =
true;
904 while (S_holders_count != 0)
905 S_no_holders_condition.wait();
906 S_writer_is_waiting =
false;
907 mutex_tct<readers_instance>::unlock();
910 __libcwd_tsd.waiting_for_lock = 0;
912 S_holders_count = -1;
913 S_no_holders_condition.unlock();
914 if (instance < end_recursive_types)
915 S_writer_id = pthread_self();
916 #if CWDEBUG_DEBUG || CWDEBUG_DEBUGT
918 _private_::test_for_deadlock(instance, __libcwd_tsd, __builtin_return_address(0));
920 LIBCWD_DEBUGDEBUGRWLOCK_CERR(pthread_self() <<
": rwlock_tct::rd2wrlock(): instance_locked[" << instance <<
"] == " << instance_locked[instance] <<
"; incrementing it.");
921 instance_locked[instance] += 1;
923 locked_by[instance] = pthread_self();
924 locked_from[instance] = __builtin_return_address(0);
928 if (__libcwd_tsd.instance_rdlocked[instance] == 2)
929 __libcwd_tsd.rdlocked_by2[instance] = 0;
931 __libcwd_tsd.rdlocked_by1[instance] = 0;
932 __libcwd_tsd.instance_rdlocked[instance] -= 1;
934 LIBCWD_DEBUGDEBUGRWLOCK_CERR(pthread_self() <<
": Leaving rwlock_tct<" << instance <<
">::rd2wrlock()");
936 static void wr2rdlock()
939 LIBCWD_TSD_DECLARATION;
941 LIBCWD_DEBUGDEBUG_ASSERT_CANCEL_DEFERRED;
942 #if CWDEBUG_DEBUG || CWDEBUG_DEBUGT
943 LIBCWD_DEBUGDEBUGRWLOCK_CERR(pthread_self() <<
": rwlock_tct::wr2rdlock(): instance_locked[" << instance <<
"] == " << instance_locked[instance] <<
"; decrementing it.");
945 LIBCWD_ASSERT( instance_locked[instance] > 0 && locked_by[instance] == pthread_self() );
947 instance_locked[instance] -= 1;
949 if (instance > end_recursive_types || instance_locked[instance] == 0)
951 locked_by[instance] = 0;
952 LIBCWD_DEBUGDEBUGRWLOCK_CERR(pthread_self() <<
": rwlock_tct::wr2rdlock(): locked_by[" << instance <<
"] was reset.");
956 LIBCWD_DEBUGDEBUGRWLOCK_CERR(pthread_self() <<
": rwlock_tct::wr2rdlock(): locked_by[" << instance <<
"] was not reset, it still is " << locked_by[instance] <<
".");
960 LIBCWD_DEBUGDEBUGRWLOCK_CERR(pthread_self() <<
": Calling rwlock_tct<" << instance <<
">::wr2rdlock()");
961 if (instance < end_recursive_types)
963 S_no_holders_condition.lock();
965 S_no_holders_condition.signal();
966 S_no_holders_condition.unlock();
968 _private_::test_for_deadlock(instance, __libcwd_tsd, __builtin_return_address(0));
969 if (instance >= instance_rdlocked_size)
971 __libcwd_tsd.instance_rdlocked[instance] += 1;
972 if (__libcwd_tsd.instance_rdlocked[instance] == 1)
974 __libcwd_tsd.rdlocked_by1[instance] = pthread_self();
975 __libcwd_tsd.rdlocked_from1[instance] = __builtin_return_address(0);
977 else if (__libcwd_tsd.instance_rdlocked[instance] == 2)
979 __libcwd_tsd.rdlocked_by2[instance] = pthread_self();
980 __libcwd_tsd.rdlocked_from2[instance] = __builtin_return_address(0);
985 LIBCWD_DEBUGDEBUGRWLOCK_CERR(pthread_self() <<
": Leaving rwlock_tct<" << instance <<
">::wr2rdlock()");
988 static void cleanup(
void*);
991 template <
int instance>
992 int rwlock_tct<instance>::S_holders_count = 0;
994 template <
int instance>
995 bool volatile rwlock_tct<instance>::S_writer_is_waiting = 0;
997 template <
int instance>
998 pthread_t rwlock_tct<instance>::S_writer_id = 0;
1000 #if CWDEBUG_DEBUGT || !LIBCWD_USE_LINUXTHREADS
1001 template <
int instance>
1002 bool rwlock_tct<instance>::S_initialized = 0;
1005 template <
int instance>
1006 typename rwlock_tct<instance>::cond_t rwlock_tct<instance>::S_no_holders_condition;
1008 template <
int instance>
1009 void rwlock_tct<instance>::cleanup(
void*)
1011 if (S_holders_count == -1)
1017 extern void fatal_cancellation(
void*);
1023 #define LIBCWD_DISABLE_CANCEL
1024 #define LIBCWD_DISABLE_CANCEL_NO_BRACE
1025 #define LIBCWD_ENABLE_CANCEL_NO_BRACE
1026 #define LIBCWD_ENABLE_CANCEL
1027 #define LIBCWD_DEFER_CANCEL
1028 #define LIBCWD_DEFER_CANCEL_NO_BRACE
1029 #define LIBCWD_RESTORE_CANCEL_NO_BRACE
1030 #define LIBCWD_RESTORE_CANCEL
1031 #define LIBCWD_DEFER_CLEANUP_PUSH(routine, arg)
1032 #define LIBCWD_CLEANUP_POP_RESTORE(execute)
1033 #define LIBCWD_PUSH_DEFER_TRYLOCK_MUTEX(instance, unlock_routine)
1034 #define LIBCWD_DEFER_PUSH_LOCKMUTEX(instance, unlock_routine)
1035 #define LIBCWD_UNLOCKMUTEX_POP_RESTORE(instance)
1036 #define LIBCWD_DEBUGDEBUG_ASSERT_CANCEL_DEFERRED
void core_dump()
Dump core of current thread.
Definition: debug.cc:806
namespace for libcwd.
Definition: debug.cc:87
std::ostream & operator<<(std::ostream &os, memblk_types_nt memblk_type)
Allow writing a memblk_types_nt directly to an ostream.
Definition: debugmalloc.cc:688