00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00018 #ifndef LIBCWD_PRIVATE_THREADING_H
00019 #define LIBCWD_PRIVATE_THREADING_H
00020
00021 #define LIBCWD_DEBUGDEBUGRWLOCK 0
00022
00023 #if LIBCWD_DEBUGDEBUGRWLOCK
00024 #define LIBCWD_NO_INTERNAL_STRING
00025 #include <raw_write.h>
00026 #undef LIBCWD_NO_INTERNAL_STRING
00027 extern pthread_mutex_t LIBCWD_DEBUGDEBUGLOCK_CERR_mutex;
00028 extern unsigned int LIBCWD_DEBUGDEBUGLOCK_CERR_count;
00029 #define LIBCWD_DEBUGDEBUGRWLOCK_CERR(x) \
00030 do { \
00031 pthread_mutex_lock(&LIBCWD_DEBUGDEBUGLOCK_CERR_mutex); \
00032 FATALDEBUGDEBUG_CERR(x); \
00033 pthread_mutex_unlock(&LIBCWD_DEBUGDEBUGLOCK_CERR_mutex); \
00034 } while(0)
00035 #define LIBCWD_DEBUGDEBUGLOCK_CERR(x) \
00036 do { \
00037 if (instance != static_tsd_instance) \
00038 { \
00039 pthread_mutex_lock(&LIBCWD_DEBUGDEBUGLOCK_CERR_mutex); \
00040 ++LIBCWD_DEBUGDEBUGLOCK_CERR_count; \
00041 FATALDEBUGDEBUG_CERR("[" << LIBCWD_DEBUGDEBUGLOCK_CERR_count << "] " << pthread_self() << ": " << x); \
00042 pthread_mutex_unlock(&LIBCWD_DEBUGDEBUGLOCK_CERR_mutex); \
00043 } \
00044 } while(0)
00045 #else // !LIBCWD_DEBUGDEBUGRWLOCK
00046 #define LIBCWD_DEBUGDEBUGRWLOCK_CERR(x) do { } while(0)
00047 #define LIBCWD_DEBUGDEBUGLOCK_CERR(x) do { } while(0)
00048 #endif // !LIBCWD_DEBUGDEBUGRWLOCK
00049
00050 #ifndef LIBCWD_PRIVATE_SET_ALLOC_CHECKING_H
00051 #include <libcwd/private_set_alloc_checking.h>
00052 #endif
00053 #ifndef LIBCWD_PRIVATE_STRUCT_TSD_H
00054 #include <libcwd/private_struct_TSD.h>
00055 #endif
00056 #ifndef LIBCWD_PRIVATE_MUTEX_INSTANCES_H
00057 #include <libcwd/private_mutex_instances.h>
00058 #endif
00059 #ifndef LIBCWD_CORE_DUMP_H
00060 #include <libcwd/core_dump.h>
00061 #endif
00062 #ifndef LIBCW_CSTRING
00063 #define LIBCW_CSTRING
00064 #include <cstring>
00065 #endif
00066
00067 #ifdef LIBCWD_HAVE_PTHREAD
00068 #ifdef __linux
00069 #ifndef _GNU_SOURCE
00070 #error "You need to use define _GNU_SOURCE in order to make use of the extensions of Linux Threads."
00071 #endif
00072 #endif
00073 #ifndef LIBCW_PTHREAD_H
00074 #define LIBCW_PTHREAD_H
00075 #include <pthread.h>
00076 #endif
00077 #if defined(PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP) && defined(PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP)
00078 #define LIBCWD_USE_LINUXTHREADS 1
00079 #else
00080 #define LIBCWD_USE_POSIX_THREADS 1
00081 #endif
00082 #else
00083 #if LIBCWD_THREAD_SAFE
00084 #error Fatal error: thread support was not detected during configuration of libcwd (did you use --disable-threading?)! \
00085 How come you are trying to compile a threaded program now? \
00086 To fix this problem, either link with libcwd_r (install it), or when you are indeed compiling a \
00087 single threaded application, then get rid of the -D_REENTRANT and/or -D_THREAD_SAFE in your compile flags.
00088 #endif
00089 #endif // LIBCWD_HAVE_PTHREAD
00090
00091 #ifndef LIBCWD_USE_LINUXTHREADS
00092 #define LIBCWD_USE_LINUXTHREADS 0
00093 #endif
00094 #ifndef LIBCWD_USE_POSIX_THREADS
00095 #define LIBCWD_USE_POSIX_THREADS 0
00096 #endif
00097
00098 #if CWDEBUG_DEBUGT
00099 #define LibcwDebugThreads(x) do { x; } while(0)
00100 #else
00101 #define LibcwDebugThreads(x) do { } while(0)
00102 #endif
00103
00104 #if CWDEBUG_DEBUGT || CWDEBUG_DEBUG
00105 #ifndef LIBCWD_PRIVATE_ASSERT_H
00106 #include <libcwd/private_assert.h>
00107 #endif
00108 #endif
00109
00110 #if LIBCWD_THREAD_SAFE
00111
00112 namespace libcwd {
00113
00114 #if LIBCWD_DEBUGDEBUGRWLOCK
00115 inline
00116 _private_::raw_write_nt const&
00117 operator<<(_private_::raw_write_nt const& raw_write, pthread_mutex_t const& mutex)
00118 {
00119 raw_write << "(pthread_mutex_t&)" << (void*)&mutex <<
00120 " = { __m_reserved = " << mutex.__m_reserved <<
00121 ", __m_count = " << mutex.__m_count <<
00122 ", __m_owner = " << (void*)mutex.__m_owner <<
00123 ", __m_kind = " << mutex.__m_kind <<
00124 ", __m_lock = { __status = " << mutex.__m_lock.__status <<
00125 ", __spinlock = " << mutex.__m_lock.__spinlock << " } }";
00126 return raw_write;
00127 }
00128 #endif
00129
00130 namespace _private_ {
00131
00132 extern void initialize_global_mutexes(void);
00133 extern bool WST_multi_threaded;
00134
00135 #if CWDEBUG_DEBUGT
00136 extern void test_for_deadlock(size_t, struct TSD_st&, void const*);
00137 inline void test_for_deadlock(int instance, struct TSD_st& __libcwd_tsd, void const* from)
00138 {
00139 assert(instance < 0x10000);
00140 test_for_deadlock(static_cast<size_t>(instance), __libcwd_tsd, from);
00141 }
00142 inline void test_for_deadlock(void const* ptr, struct TSD_st& __libcwd_tsd, void const* from)
00143 {
00144 assert(reinterpret_cast<size_t>(ptr) >= 0x10000);
00145 test_for_deadlock(reinterpret_cast<size_t>(ptr), __libcwd_tsd, from);
00146 }
00147 #endif
00148
00149
00150
00151
00152
00153
00154
00155
00156
00157
00158
00159
00160
00161
00162
00163
00164
00165
00166
00167
00168
00169
00170 #if LIBCWD_USE_POSIX_THREADS || LIBCWD_USE_LINUXTHREADS
00171
00172
00173 #define LIBCWD_DISABLE_CANCEL \
00174 { \
00175 LIBCWD_DISABLE_CANCEL_NO_BRACE
00176 #define LIBCWD_DISABLE_CANCEL_NO_BRACE \
00177 int __libcwd_oldstate; \
00178 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &__libcwd_oldstate); \
00179 LibcwDebugThreads( ++__libcwd_tsd.cancel_explicitely_disabled )
00180 #if CWDEBUG_ALLOC
00181 #define LIBCWD_ASSERT_USERSPACE_OR_DEFERED_BEFORE_SETCANCELSTATE \
00182 \
00183 \
00184 \
00185 \
00186 LIBCWD_ASSERT( !__libcwd_tsd.internal || __libcwd_tsd.cancel_explicitely_disabled || __libcwd_tsd.cancel_explicitely_deferred )
00187 #else
00188 #define LIBCWD_ASSERT_USERSPACE_OR_DEFERED_BEFORE_SETCANCELSTATE
00189 #endif
00190 #define LIBCWD_ENABLE_CANCEL_NO_BRACE \
00191 LibcwDebugThreads(\
00192 LIBCWD_ASSERT( __libcwd_tsd.cancel_explicitely_disabled > 0 ); \
00193 --__libcwd_tsd.cancel_explicitely_disabled; \
00194 LIBCWD_ASSERT_USERSPACE_OR_DEFERED_BEFORE_SETCANCELSTATE; \
00195 ); \
00196 pthread_setcancelstate(__libcwd_oldstate, NULL)
00197 #define LIBCWD_ENABLE_CANCEL \
00198 LIBCWD_ENABLE_CANCEL_NO_BRACE; \
00199 }
00200
00201 #define LIBCWD_DEFER_CANCEL \
00202 { \
00203 LIBCWD_DEFER_CANCEL_NO_BRACE
00204 #define LIBCWD_DEFER_CANCEL_NO_BRACE \
00205 int __libcwd_oldtype; \
00206 pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, &__libcwd_oldtype); \
00207 LibcwDebugThreads( ++__libcwd_tsd.cancel_explicitely_deferred )
00208 #define LIBCWD_RESTORE_CANCEL_NO_BRACE \
00209 LibcwDebugThreads(\
00210 LIBCWD_ASSERT( __libcwd_tsd.cancel_explicitely_deferred > 0 ); \
00211 --__libcwd_tsd.cancel_explicitely_deferred; \
00212 LIBCWD_ASSERT_USERSPACE_OR_DEFERED_BEFORE_SETCANCELSTATE; \
00213 ); \
00214 pthread_setcanceltype(__libcwd_oldtype, NULL)
00215 #define LIBCWD_RESTORE_CANCEL \
00216 LIBCWD_RESTORE_CANCEL_NO_BRACE; \
00217 }
00218
00219 #if LIBCWD_USE_LINUXTHREADS
00220 #define LIBCWD_DEFER_CLEANUP_PUSH(routine, arg) \
00221 pthread_cleanup_push_defer_np(reinterpret_cast<void(*)(void*)>(routine), reinterpret_cast<void*>(arg)); \
00222 LibcwDebugThreads( ++__libcwd_tsd.cancel_explicitely_deferred; ++__libcwd_tsd.cleanup_handler_installed )
00223 #if CWDEBUG_ALLOC
00224 #define LIBCWD_ASSERT_NONINTERNAL LIBCWD_ASSERT( !__libcwd_tsd.internal )
00225 #else
00226 #define LIBCWD_ASSERT_NONINTERNAL
00227 #endif
00228 #define LIBCWD_CLEANUP_POP_RESTORE(execute) \
00229 LibcwDebugThreads( --__libcwd_tsd.cleanup_handler_installed; \
00230 LIBCWD_ASSERT( __libcwd_tsd.cancel_explicitely_deferred > 0 ); \
00231 LIBCWD_ASSERT_NONINTERNAL; ); \
00232 pthread_cleanup_pop_restore_np(static_cast<int>(execute)); \
00233 LibcwDebugThreads( --__libcwd_tsd.cancel_explicitely_deferred; )
00234 #else // !LIBCWD_USE_LINUXTHREADS
00235 #define LIBCWD_DEFER_CLEANUP_PUSH(routine, arg) \
00236 LIBCWD_DEFER_CANCEL; \
00237 LibcwDebugThreads( ++__libcwd_tsd.cleanup_handler_installed ); \
00238 pthread_cleanup_push(reinterpret_cast<void(*)(void*)>(routine), reinterpret_cast<void*>(arg))
00239 #define LIBCWD_CLEANUP_POP_RESTORE(execute) \
00240 LibcwDebugThreads( --__libcwd_tsd.cleanup_handler_installed ); \
00241 pthread_cleanup_pop(static_cast<int>(execute)); \
00242 LIBCWD_RESTORE_CANCEL
00243 #endif // !LIBCWD_USE_LINUXTHREADS
00244
00245 #define LIBCWD_PUSH_DEFER_TRYLOCK_MUTEX(instance, unlock_routine) \
00246 LIBCWD_DEFER_CLEANUP_PUSH(static_cast<void (*)(void)>(unlock_routine), &::libcwd::_private_::mutex_tct<(instance)>::S_mutex); \
00247 bool __libcwd_lock_successful = ::libcwd::_private_::mutex_tct<(instance)>::trylock()
00248 #define LIBCWD_DEFER_PUSH_LOCKMUTEX(instance, unlock_routine) \
00249 LIBCWD_DEFER_CLEANUP_PUSH(static_cast<void (*)(void)>(unlock_routine), &::libcwd::_private_::mutex_tct<(instance)>::S_mutex); \
00250 ::libcwd::_private_::mutex_tct<(instance)>::lock(); \
00251 bool const __libcwd_lock_successful = true
00252 #define LIBCWD_UNLOCKMUTEX_POP_RESTORE(instance) \
00253 LIBCWD_CLEANUP_POP_RESTORE(__libcwd_lock_successful)
00254
00255 #define LIBCWD_DEBUGDEBUG_ASSERT_CANCEL_DEFERRED \
00256 LibcwDebugThreads( \
00257 if (instance != static_tsd_instance) \
00258 { \
00259 \
00260 \
00261 \
00262 LIBCWD_ASSERT( __libcwd_tsd.cancel_explicitely_deferred || __libcwd_tsd.cancel_explicitely_disabled ); \
00263 } )
00264
00265 template <int instance>
00266 class mutex_tct {
00267 public:
00268 static pthread_mutex_t S_mutex;
00269 #if !LIBCWD_USE_LINUXTHREADS || CWDEBUG_DEBUGT
00270 protected:
00271 static bool volatile S_initialized;
00272 static void S_initialize(void);
00273 #endif
00274 public:
00275 static void initialize(void)
00276 #if LIBCWD_USE_LINUXTHREADS && !CWDEBUG_DEBUGT
00277 { }
00278 #else
00279 {
00280 if (S_initialized)
00281 return;
00282
00283 S_initialize();
00284 }
00285 #endif
00286 public:
00287 static bool trylock(void)
00288 {
00289 LibcwDebugThreads( LIBCWD_ASSERT( S_initialized ) );
00290 #if CWDEBUG_DEBUGT
00291 LIBCWD_TSD_DECLARATION;
00292 #endif
00293 LIBCWD_DEBUGDEBUG_ASSERT_CANCEL_DEFERRED;
00294 LIBCWD_DEBUGDEBUGLOCK_CERR("Trying to lock mutex " << instance << " (" << (void*)&S_mutex << ") from " << __builtin_return_address(0) << " from " << __builtin_return_address(1));
00295 LIBCWD_DEBUGDEBUGLOCK_CERR("pthread_mutex_trylock(" << S_mutex << ").");
00296 bool success = (pthread_mutex_trylock(&S_mutex) == 0);
00297 LIBCWD_DEBUGDEBUGLOCK_CERR("Result = " << success << ". Mutex now " << S_mutex << ".");
00298 #if CWDEBUG_DEBUG || CWDEBUG_DEBUGT
00299 if (success)
00300 {
00301 #if CWDEBUG_DEBUGT
00302 _private_::test_for_deadlock(instance, __libcwd_tsd, __builtin_return_address(0));
00303 #endif
00304 LIBCWD_DEBUGDEBUGLOCK_CERR("mutex_tct::trylock(): instance_locked[" << instance << "] == " << instance_locked[instance] << "; incrementing it.");
00305 instance_locked[instance] += 1;
00306 #if CWDEBUG_DEBUGT
00307 locked_by[instance] = pthread_self();
00308 locked_from[instance] = __builtin_return_address(0);
00309 #endif
00310 }
00311 #endif
00312 LibcwDebugThreads( if (success) { ++__libcwd_tsd.inside_critical_area; } );
00313 return success;
00314 }
00315 static void lock(void)
00316 {
00317 LibcwDebugThreads( LIBCWD_ASSERT( S_initialized ) );
00318 #if CWDEBUG_DEBUGT
00319 TSD_st* tsd_ptr = 0;
00320 if (instance != static_tsd_instance)
00321 {
00322 LIBCWD_TSD_DECLARATION;
00323 tsd_ptr = &__libcwd_tsd;
00324 }
00325 TSD_st& __libcwd_tsd(*tsd_ptr);
00326 #endif
00327 LIBCWD_DEBUGDEBUG_ASSERT_CANCEL_DEFERRED;
00328 LibcwDebugThreads( if (instance != static_tsd_instance) { ++__libcwd_tsd.inside_critical_area; } );
00329 LIBCWD_DEBUGDEBUGLOCK_CERR("locking mutex " << instance << " (" << (void*)&S_mutex << ") from " << __builtin_return_address(0) << " from " << __builtin_return_address(1));
00330 #if CWDEBUG_DEBUGT
00331 if (instance != static_tsd_instance && !(instance >= 2 * reserved_instance_low && instance < 3 * reserved_instance_low))
00332 {
00333 __libcwd_tsd.waiting_for_lock = instance;
00334 LIBCWD_DEBUGDEBUGLOCK_CERR("pthread_mutex_lock(" << S_mutex << ").");
00335 int res = pthread_mutex_lock(&S_mutex);
00336 LIBCWD_DEBUGDEBUGLOCK_CERR("Result = " << res << ". Mutex now " << S_mutex << ".");
00337 LIBCWD_ASSERT( res == 0 );
00338 __libcwd_tsd.waiting_for_lock = 0;
00339 _private_::test_for_deadlock(instance, __libcwd_tsd, __builtin_return_address(0));
00340 }
00341 else
00342 {
00343 LIBCWD_DEBUGDEBUGLOCK_CERR("pthread_mutex_lock(" << S_mutex << ").");
00344 int res = pthread_mutex_lock(&S_mutex);
00345 LIBCWD_DEBUGDEBUGLOCK_CERR("Result = " << res << ". Mutex now " << S_mutex << ".");
00346 LIBCWD_ASSERT( res == 0 );
00347 }
00348 #else // !CWDEBUG_DEBUGT
00349 pthread_mutex_lock(&S_mutex);
00350 #endif // !CWDEBUG_DEBUGT
00351 LIBCWD_DEBUGDEBUGLOCK_CERR("Lock " << instance << " obtained (" << (void*)&S_mutex << ").");
00352 #if CWDEBUG_DEBUG || CWDEBUG_DEBUGT
00353 LIBCWD_DEBUGDEBUGLOCK_CERR("mutex_tct::lock(): instance_locked[" << instance << "] == " << instance_locked[instance] << "; incrementing it.");
00354 instance_locked[instance] += 1;
00355 #if CWDEBUG_DEBUGT
00356 if (locked_by[instance] != 0 && locked_by[instance] != pthread_self())
00357 {
00358 LIBCWD_DEBUGDEBUGLOCK_CERR("mutex " << instance << " (" << (void*)&S_mutex << ") is already set by another thread (" << locked_by[instance] << ")!");
00359 core_dump();
00360 }
00361 locked_by[instance] = pthread_self();
00362 locked_from[instance] = __builtin_return_address(0);
00363 #endif
00364 #endif
00365 }
00366 static void unlock(void)
00367 {
00368 #if CWDEBUG_DEBUGT
00369 TSD_st* tsd_ptr = 0;
00370 if (instance != static_tsd_instance)
00371 {
00372 LIBCWD_TSD_DECLARATION;
00373 tsd_ptr = &__libcwd_tsd;
00374 }
00375 TSD_st& __libcwd_tsd(*tsd_ptr);
00376 #endif
00377 LIBCWD_DEBUGDEBUG_ASSERT_CANCEL_DEFERRED;
00378 #if CWDEBUG_DEBUG || CWDEBUG_DEBUGT
00379 LIBCWD_DEBUGDEBUGLOCK_CERR("mutex_tct::unlock(): instance_locked[" << instance << "] == " << instance_locked[instance] << "; decrementing it.");
00380 LIBCWD_ASSERT( instance_locked[instance] > 0 );
00381 #if CWDEBUG_DEBUGT
00382 if (locked_by[instance] != pthread_self())
00383 {
00384 LIBCWD_DEBUGDEBUGLOCK_CERR("unlocking instance " << instance << " (" << (void*)&S_mutex << ") failed: locked_by[" << instance << "] == " << locked_by[instance] << ".");
00385 core_dump();
00386 }
00387 #endif
00388 instance_locked[instance] -= 1;
00389 #if CWDEBUG_DEBUGT
00390 if (instance_locked[instance] == 0)
00391 {
00392 locked_by[instance] = 0;
00393 LIBCWD_DEBUGDEBUGLOCK_CERR("mutex_tct::unlock(): locked_by[" << instance << "] was reset.");
00394 }
00395 else LIBCWD_DEBUGDEBUGLOCK_CERR("mutex_tct::unlock(): locked_by[" << instance << "] was not reset, it still is " << locked_by[instance] << ".");
00396 #endif
00397 #endif
00398 LIBCWD_DEBUGDEBUGLOCK_CERR("unlocking mutex " << instance << " (" << (void*)&S_mutex << ").");
00399 LIBCWD_DEBUGDEBUGLOCK_CERR("pthread_mutex_unlock(" << S_mutex << ").");
00400 #if CWDEBUG_DEBUGT
00401 int res =
00402 #endif
00403 pthread_mutex_unlock(&S_mutex);
00404 #if CWDEBUG_DEBUGT
00405 LIBCWD_DEBUGDEBUGLOCK_CERR("Result = " << res << ". Mutex now " << S_mutex << ".");
00406 LIBCWD_ASSERT(res == 0);
00407 #endif
00408 LIBCWD_DEBUGDEBUGLOCK_CERR("Lock " << instance << " released (" << (void*)&S_mutex << ").");
00409 LibcwDebugThreads( if (instance != static_tsd_instance) { --__libcwd_tsd.inside_critical_area; } );
00410 }
00411
00412 static void cleanup(void*);
00413 };
00414
00415 #if !LIBCWD_USE_LINUXTHREADS || CWDEBUG_DEBUGT
00416 template <int instance>
00417 bool volatile mutex_tct<instance>::S_initialized = false;
00418
00419 template <int instance>
00420 void mutex_tct<instance>::S_initialize(void)
00421 {
00422 if (instance == mutex_initialization_instance)
00423 {
00424 #if !LIBCWD_USE_LINUXTHREADS
00425 pthread_mutexattr_t mutex_attr;
00426 pthread_mutexattr_init(&mutex_attr);
00427 #if CWDEBUG_DEBUGT
00428 pthread_mutexattr_settype(&mutex_attr, PTHREAD_MUTEX_ERRORCHECK);
00429 #else
00430 pthread_mutexattr_settype(&mutex_attr, PTHREAD_MUTEX_NORMAL);
00431 #endif
00432 pthread_mutex_init(&S_mutex, &mutex_attr);
00433 pthread_mutexattr_destroy(&mutex_attr);
00434 #endif // !LIBCWD_USE_LINUXTHREADS
00435 S_initialized = true;
00436 }
00437 else
00438 {
00439 mutex_tct<mutex_initialization_instance>::initialize();
00440
00441 if (!S_initialized)
00442 {
00443 #if !LIBCWD_USE_LINUXTHREADS
00444 pthread_mutexattr_t mutex_attr;
00445 pthread_mutexattr_init(&mutex_attr);
00446 if (instance < end_recursive_types)
00447 pthread_mutexattr_settype(&mutex_attr, PTHREAD_MUTEX_RECURSIVE);
00448 else
00449 {
00450 #if CWDEBUG_DEBUGT
00451 pthread_mutexattr_settype(&mutex_attr, PTHREAD_MUTEX_ERRORCHECK);
00452 #else
00453 pthread_mutexattr_settype(&mutex_attr, PTHREAD_MUTEX_NORMAL);
00454 #endif
00455 }
00456 pthread_mutex_init(&S_mutex, &mutex_attr);
00457 pthread_mutexattr_destroy(&mutex_attr);
00458 #endif // !LIBCWD_USE_LINUXTHREADS
00459 S_initialized = true;
00460 }
00461
00462 }
00463 }
00464 #endif // !LIBCWD_USE_LINUXTHREADS || CWDEBUG_DEBUGT
00465
00466 template <int instance>
00467 pthread_mutex_t mutex_tct<instance>::S_mutex
00468 #if LIBCWD_USE_LINUXTHREADS
00469 =
00470 #if CWDEBUG_DEBUGT
00471 PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP;
00472 #else
00473 PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP;
00474 #endif
00475 #else // !LIBCWD_USE_LINUXTHREADS
00476 ;
00477 #endif // !LIBCWD_USE_LINUXTHREADS
00478
00479 template <int instance>
00480 void mutex_tct<instance>::cleanup(void*)
00481 {
00482 unlock();
00483 }
00484
00485
00486
00487
00488 template <int instance>
00489 class cond_tct : public mutex_tct<instance> {
00490 private:
00491 static pthread_cond_t S_condition;
00492 #if CWDEBUG_DEBUGT || !LIBCWD_USE_LINUXTHREADS
00493 static bool volatile S_initialized;
00494 private:
00495 static void S_initialize(void);
00496 #endif
00497 public:
00498 static void initialize(void)
00499 #if CWDEBUG_DEBUGT || !LIBCWD_USE_LINUXTHREADS
00500 {
00501 if (S_initialized)
00502 return;
00503 S_initialize();
00504 }
00505 #else
00506 { }
00507 #endif
00508 public:
00509 void wait(void) {
00510 #if CWDEBUG_DEBUG || CWDEBUG_DEBUGT
00511 LIBCWD_DEBUGDEBUGLOCK_CERR("cond_tct::wait(): instance_locked[" << instance << "] == " << instance_locked[instance] << "; decrementing it.");
00512 LIBCWD_ASSERT( instance_locked[instance] > 0 );
00513 #if CWDEBUG_DEBUGT
00514 if (locked_by[instance] != pthread_self())
00515 {
00516 LIBCWD_DEBUGDEBUGLOCK_CERR("unlocking instance " << instance << " (" << (void*)&S_mutex << ") failed: locked_by[" << instance << "] == " << locked_by[instance] << ".");
00517 core_dump();
00518 }
00519 #endif
00520 instance_locked[instance] -= 1;
00521 #if CWDEBUG_DEBUGT
00522 if (instance_locked[instance] == 0)
00523 {
00524 locked_by[instance] = 0;
00525 LIBCWD_DEBUGDEBUGLOCK_CERR("cond_tct::wait(): locked_by[" << instance << "] was reset.");
00526 }
00527 else LIBCWD_DEBUGDEBUGLOCK_CERR("cond_tct::wait(): locked_by[" << instance << "] was not reset, it still is " << locked_by[instance] << ".");
00528 #endif
00529 #endif
00530 LIBCWD_DEBUGDEBUGLOCK_CERR("unlocking mutex " << instance << " (" << (void*)&S_mutex << ").");
00531 LIBCWD_DEBUGDEBUGLOCK_CERR("pthread_cond_wait(" << (void*)&S_condition << ", " << this->S_mutex << ").");
00532 #if CWDEBUG_DEBUGT
00533 int res =
00534 #endif
00535 pthread_cond_wait(&S_condition, &this->S_mutex);
00536 #if CWDEBUG_DEBUGT
00537 LIBCWD_DEBUGDEBUGLOCK_CERR("Result = " << res << ". Mutex now " << S_mutex << ".");
00538 LIBCWD_ASSERT(res == 0);
00539 #endif
00540 LIBCWD_DEBUGDEBUGLOCK_CERR("Lock " << instance << " obtained (" << (void*)&S_mutex << ").");
00541 #if CWDEBUG_DEBUG || CWDEBUG_DEBUGT
00542 LIBCWD_DEBUGDEBUGLOCK_CERR("cond_tct::wait(): instance_locked[" << instance << "] == " << instance_locked[instance] << "; incrementing it.");
00543 instance_locked[instance] += 1;
00544 #if CWDEBUG_DEBUGT
00545 if (locked_by[instance] != 0 && locked_by[instance] != pthread_self())
00546 {
00547 LIBCWD_DEBUGDEBUGLOCK_CERR("mutex " << instance << " (" << (void*)&S_mutex << ") is already set by another thread (" << locked_by[instance] << ")!");
00548 core_dump();
00549 }
00550 locked_by[instance] = pthread_self();
00551 locked_from[instance] = __builtin_return_address(0);
00552 #endif
00553 #endif
00554 }
00555 void signal(void) { pthread_cond_signal(&S_condition); }
00556 void broadcast(void) { pthread_cond_broadcast(&S_condition); }
00557 };
00558
00559 #if CWDEBUG_DEBUGT || !LIBCWD_USE_LINUXTHREADS
00560 template <int instance>
00561 void cond_tct<instance>::S_initialize(void)
00562 {
00563 #if !LIBCWD_USE_LINUXTHREADS
00564 mutex_tct<mutex_initialization_instance>::initialize();
00565 LIBCWD_DEFER_PUSH_LOCKMUTEX(mutex_initialization_instance, mutex_tct<mutex_initialization_instance>::unlock);
00566 if (!S_initialized)
00567 {
00568 pthread_cond_init(&S_condition, NULL);
00569 }
00570 LIBCWD_UNLOCKMUTEX_POP_RESTORE(mutex_initialization_instance);
00571 #endif
00572 mutex_tct<instance>::S_initialize();
00573 }
00574 #endif // !LIBCWD_USE_LINUXTHREADS
00575
00576 #if CWDEBUG_DEBUGT || !LIBCWD_USE_LINUXTHREADS
00577 template <int instance>
00578 bool volatile cond_tct<instance>::S_initialized = false;
00579 #endif
00580
00581 template <int instance>
00582 pthread_cond_t cond_tct<instance>::S_condition
00583 #if LIBCWD_USE_LINUXTHREADS
00584 = PTHREAD_COND_INITIALIZER;
00585 #else // !LIBCWD_USE_LINUXTHREADS
00586 ;
00587 #endif // !LIBCWD_USE_LINUXTHREADS
00588
00589 #endif // LIBCWD_USE_POSIX_THREADS || LIBCWD_USE_LINUXTHREADS
00590
00591
00592
00593
00594
00595
00596
00597
00598
00599
00600
00601
00602
00603
00604
00605
00606
00607
00608
00609
00610
00611
00612
00613
00614 template <int instance>
00615 class rwlock_tct {
00616 private:
00617 static int const readers_instance = instance + reserved_instance_low;
00618 static int const holders_instance = instance + 2 * reserved_instance_low;
00619 typedef cond_tct<holders_instance> cond_t;
00620 static cond_t S_no_holders_condition;
00621 static int S_holders_count;
00622 static bool volatile S_writer_is_waiting;
00623 static pthread_t S_writer_id;
00624 #if CWDEBUG_DEBUGT || !LIBCWD_USE_LINUXTHREADS
00625 static bool S_initialized;
00626 #endif
00627 public:
00628 static void initialize(void)
00629 {
00630 #if CWDEBUG_DEBUGT || !LIBCWD_USE_LINUXTHREADS
00631 if (S_initialized)
00632 return;
00633 LIBCWD_DEBUGDEBUGRWLOCK_CERR(pthread_self() << ": Calling initialize() instance " << instance);
00634 mutex_tct<readers_instance>::initialize();
00635 S_no_holders_condition.initialize();
00636 LIBCWD_DEBUGDEBUGRWLOCK_CERR(pthread_self() << ": Leaving initialize() instance " << instance);
00637 S_initialized = true;
00638 #endif
00639 }
00640 static bool tryrdlock(void)
00641 {
00642 #if CWDEBUG_DEBUGT
00643 LIBCWD_TSD_DECLARATION;
00644 #endif
00645 LibcwDebugThreads( LIBCWD_ASSERT( S_initialized ) );
00646 LIBCWD_DEBUGDEBUG_ASSERT_CANCEL_DEFERRED;
00647 LIBCWD_DEBUGDEBUGRWLOCK_CERR(pthread_self() << ": Calling rwlock_tct<" << instance << ">::tryrdlock()");
00648 if (instance < end_recursive_types && pthread_equal(S_writer_id, pthread_self()))
00649 {
00650 LIBCWD_DEBUGDEBUGRWLOCK_CERR(pthread_self() << ": Leaving rwlock_tct<" << instance << ">::tryrdlock() (skipped: thread has write lock)");
00651 return true;
00652 }
00653
00654 if (S_writer_is_waiting || !S_no_holders_condition.trylock())
00655 return false;
00656 bool success = (S_holders_count != -1);
00657 if (success)
00658 ++S_holders_count;
00659 S_no_holders_condition.unlock();
00660 LibcwDebugThreads(
00661 if (success)
00662 {
00663 ++__libcwd_tsd.inside_critical_area;
00664 _private_::test_for_deadlock(instance, __libcwd_tsd, __builtin_return_address(0));
00665 __libcwd_tsd.instance_rdlocked[instance] += 1;
00666 if (__libcwd_tsd.instance_rdlocked[instance] == 1)
00667 {
00668 __libcwd_tsd.rdlocked_by1[instance] = pthread_self();
00669 __libcwd_tsd.rdlocked_from1[instance] = __builtin_return_address(0);
00670 }
00671 else if (__libcwd_tsd.instance_rdlocked[instance] == 2)
00672 {
00673 __libcwd_tsd.rdlocked_by2[instance] = pthread_self();
00674 __libcwd_tsd.rdlocked_from2[instance] = __builtin_return_address(0);
00675 }
00676 else
00677 core_dump();
00678 }
00679 );
00680 LIBCWD_DEBUGDEBUGRWLOCK_CERR(pthread_self() << ": Leaving rwlock_tct<" << instance << ">::tryrdlock()");
00681 return success;
00682 }
00683 static bool trywrlock(void)
00684 {
00685 LibcwDebugThreads( LIBCWD_ASSERT( S_initialized ) );
00686 #if CWDEBUG_DEBUGT
00687 LIBCWD_TSD_DECLARATION;
00688 #endif
00689 LIBCWD_DEBUGDEBUG_ASSERT_CANCEL_DEFERRED;
00690 LIBCWD_DEBUGDEBUGRWLOCK_CERR(pthread_self() << ": Calling rwlock_tct<" << instance << ">::trywrlock()");
00691 bool success;
00692 if ((success = mutex_tct<readers_instance>::trylock()))
00693 {
00694 S_writer_is_waiting = true;
00695 if ((success = S_no_holders_condition.trylock()))
00696 {
00697 if ((success = (S_holders_count == 0)))
00698 {
00699 S_holders_count = -1;
00700 if (instance < end_recursive_types)
00701 S_writer_id = pthread_self();
00702 #if CWDEBUG_DEBUG || CWDEBUG_DEBUGT
00703 #if CWDEBUG_DEBUGT
00704 _private_::test_for_deadlock(instance, __libcwd_tsd, __builtin_return_address(0));
00705 #endif
00706 LIBCWD_DEBUGDEBUGRWLOCK_CERR(pthread_self() << ": rwlock_tct::trywrlock(): instance_locked[" << instance << "] == " << instance_locked[instance] << "; incrementing it.");
00707 instance_locked[instance] += 1;
00708 #if CWDEBUG_DEBUGT
00709 locked_by[instance] = pthread_self();
00710 locked_from[instance] = __builtin_return_address(0);
00711 #endif
00712 #endif
00713 }
00714 S_no_holders_condition.unlock();
00715 }
00716 S_writer_is_waiting = false;
00717 mutex_tct<readers_instance>::unlock();
00718 }
00719 LibcwDebugThreads( if (success) { ++__libcwd_tsd.inside_critical_area; } );
00720 LIBCWD_DEBUGDEBUGRWLOCK_CERR(pthread_self() << ": Leaving rwlock_tct<" << instance << ">::trywrlock()");
00721 return success;
00722 }
00723 static void rdlock(bool high_priority = false)
00724 {
00725 LibcwDebugThreads( LIBCWD_ASSERT( S_initialized ) );
00726 #if CWDEBUG_DEBUGT
00727 LIBCWD_TSD_DECLARATION;
00728 #endif
00729 LIBCWD_DEBUGDEBUG_ASSERT_CANCEL_DEFERRED;
00730 LIBCWD_DEBUGDEBUGRWLOCK_CERR(pthread_self() << ": Calling rwlock_tct<" << instance << ">::rdlock()");
00731 if (instance < end_recursive_types && pthread_equal(S_writer_id, pthread_self()))
00732 {
00733 LIBCWD_DEBUGDEBUGRWLOCK_CERR(pthread_self() << ": Leaving rwlock_tct<" << instance << ">::rdlock() (skipped: thread has write lock)");
00734 return;
00735 }
00736
00737 if (S_writer_is_waiting)
00738 {
00739 if (!high_priority)
00740 {
00741 mutex_tct<readers_instance>::lock();
00742 mutex_tct<readers_instance>::unlock();
00743 }
00744 }
00745 #if CWDEBUG_DEBUGT
00746 __libcwd_tsd.waiting_for_rdlock = instance;
00747 #endif
00748 S_no_holders_condition.lock();
00749 while (S_holders_count == -1)
00750 S_no_holders_condition.wait();
00751 #if CWDEBUG_DEBUGT
00752 __libcwd_tsd.waiting_for_rdlock = 0;
00753 #endif
00754 ++S_holders_count;
00755 S_no_holders_condition.unlock();
00756 LibcwDebugThreads(
00757 ++__libcwd_tsd.inside_critical_area;
00758
00759
00760
00761
00762
00763
00764
00765
00766
00767
00768
00769
00770 _private_::test_for_deadlock(instance + (high_priority ? high_priority_read_lock_offset : read_lock_offset), __libcwd_tsd, __builtin_return_address(0));
00771 __libcwd_tsd.instance_rdlocked[instance] += 1;
00772 if (__libcwd_tsd.instance_rdlocked[instance] == 1)
00773 {
00774 __libcwd_tsd.rdlocked_by1[instance] = pthread_self();
00775 __libcwd_tsd.rdlocked_from1[instance] = __builtin_return_address(0);
00776 }
00777 else if (__libcwd_tsd.instance_rdlocked[instance] == 2)
00778 {
00779 __libcwd_tsd.rdlocked_by2[instance] = pthread_self();
00780 __libcwd_tsd.rdlocked_from2[instance] = __builtin_return_address(0);
00781 }
00782 else
00783 core_dump();
00784 );
00785 LIBCWD_DEBUGDEBUGRWLOCK_CERR(pthread_self() << ": Leaving rwlock_tct<" << instance << ">::rdlock()");
00786 }
00787 static void rdunlock(void)
00788 {
00789 #if CWDEBUG_DEBUGT
00790 LIBCWD_TSD_DECLARATION;
00791 #endif
00792 LIBCWD_DEBUGDEBUG_ASSERT_CANCEL_DEFERRED;
00793 LIBCWD_DEBUGDEBUGRWLOCK_CERR(pthread_self() << ": Calling rwlock_tct<" << instance << ">::rdunlock()");
00794 if (instance < end_recursive_types && pthread_equal(S_writer_id, pthread_self()))
00795 {
00796 LIBCWD_DEBUGDEBUGRWLOCK_CERR(pthread_self() << ": Leaving rwlock_tct<" << instance << ">::rdunlock() (skipped: thread has write lock)");
00797 return;
00798 }
00799 LibcwDebugThreads( --__libcwd_tsd.inside_critical_area );
00800 S_no_holders_condition.lock();
00801 if (--S_holders_count == 0)
00802 S_no_holders_condition.signal();
00803 S_no_holders_condition.unlock();
00804 LibcwDebugThreads(
00805 if (__libcwd_tsd.instance_rdlocked[instance] == 2)
00806 __libcwd_tsd.rdlocked_by2[instance] = 0;
00807 else
00808 __libcwd_tsd.rdlocked_by1[instance] = 0;
00809 __libcwd_tsd.instance_rdlocked[instance] -= 1;
00810 );
00811 LIBCWD_DEBUGDEBUGRWLOCK_CERR(pthread_self() << ": Leaving rwlock_tct<" << instance << ">::rdunlock()");
00812 }
00813 static void wrlock(void)
00814 {
00815 LibcwDebugThreads( LIBCWD_ASSERT( S_initialized ) );
00816 #if CWDEBUG_DEBUGT
00817 LIBCWD_TSD_DECLARATION;
00818 #endif
00819 LIBCWD_DEBUGDEBUG_ASSERT_CANCEL_DEFERRED;
00820 LIBCWD_DEBUGDEBUGRWLOCK_CERR(pthread_self() << ": Calling rwlock_tct<" << instance << ">::wrlock()");
00821 mutex_tct<readers_instance>::lock();
00822 S_writer_is_waiting = true;
00823 #if CWDEBUG_DEBUGT
00824 __libcwd_tsd.waiting_for_lock = instance;
00825 #endif
00826 S_no_holders_condition.lock();
00827 while (S_holders_count != 0)
00828 S_no_holders_condition.wait();
00829 #if CWDEBUG_DEBUGT
00830 __libcwd_tsd.waiting_for_lock = 0;
00831 #endif
00832 S_writer_is_waiting = false;
00833 mutex_tct<readers_instance>::unlock();
00834 S_holders_count = -1;
00835 S_no_holders_condition.unlock();
00836 if (instance < end_recursive_types)
00837 S_writer_id = pthread_self();
00838 LibcwDebugThreads( ++__libcwd_tsd.inside_critical_area );
00839 #if CWDEBUG_DEBUG || CWDEBUG_DEBUGT
00840 #if CWDEBUG_DEBUGT
00841 _private_::test_for_deadlock(instance, __libcwd_tsd, __builtin_return_address(0));
00842 #endif
00843 LIBCWD_DEBUGDEBUGRWLOCK_CERR(pthread_self() << ": rwlock_tct::wrlock(): instance_locked[" << instance << "] == " << instance_locked[instance] << "; incrementing it.");
00844 instance_locked[instance] += 1;
00845 #if CWDEBUG_DEBUGT
00846 locked_by[instance] = pthread_self();
00847 locked_from[instance] = __builtin_return_address(0);
00848 #endif
00849 #endif
00850 LIBCWD_DEBUGDEBUGRWLOCK_CERR(pthread_self() << ": Leaving rwlock_tct<" << instance << ">::wrlock()");
00851 }
00852 static void wrunlock(void)
00853 {
00854 #if CWDEBUG_DEBUGT
00855 LIBCWD_TSD_DECLARATION;
00856 #endif
00857 LIBCWD_DEBUGDEBUG_ASSERT_CANCEL_DEFERRED;
00858 #if CWDEBUG_DEBUG || CWDEBUG_DEBUGT
00859 LIBCWD_DEBUGDEBUGRWLOCK_CERR(pthread_self() << ": rwlock_tct::wrunlock(): instance_locked[" << instance << "] == " << instance_locked[instance] << "; decrementing it.");
00860 #if CWDEBUG_DEBUGT
00861 LIBCWD_ASSERT( instance_locked[instance] > 0 && locked_by[instance] == pthread_self() );
00862 #endif
00863 instance_locked[instance] -= 1;
00864 #endif
00865 #if CWDEBUG_DEBUGT
00866 if (instance > end_recursive_types || instance_locked[instance] == 0)
00867 {
00868 locked_by[instance] = 0;
00869 LIBCWD_DEBUGDEBUGRWLOCK_CERR(pthread_self() << ": rwlock_tct::unlock(): locked_by[" << instance << "] was reset.");
00870 }
00871 else
00872 {
00873 LIBCWD_DEBUGDEBUGRWLOCK_CERR(pthread_self() << ": rwlock_tct::wrunlock(): locked_by[" << instance << "] was not reset, it still is " << locked_by[instance] << ".");
00874 }
00875 #endif
00876 LIBCWD_DEBUGDEBUGRWLOCK_CERR(pthread_self() << ": Calling rwlock_tct<" << instance << ">::wrunlock()");
00877 LibcwDebugThreads( --__libcwd_tsd.inside_critical_area) ;
00878 if (instance < end_recursive_types)
00879 S_writer_id = 0;
00880 S_no_holders_condition.lock();
00881 S_holders_count = 0;
00882 S_no_holders_condition.signal();
00883 S_no_holders_condition.unlock();
00884 LIBCWD_DEBUGDEBUGRWLOCK_CERR(pthread_self() << ": Leaving rwlock_tct<" << instance << ">::wrunlock()");
00885 }
00886 static void rd2wrlock(void)
00887 {
00888 #if CWDEBUG_DEBUGT
00889 LIBCWD_TSD_DECLARATION;
00890 #endif
00891 LIBCWD_DEBUGDEBUG_ASSERT_CANCEL_DEFERRED;
00892 LIBCWD_DEBUGDEBUGRWLOCK_CERR(pthread_self() << ": Calling rwlock_tct<" << instance << ">::rd2wrlock()");
00893 #if CWDEBUG_DEBUGT
00894 __libcwd_tsd.waiting_for_lock = instance;
00895 #endif
00896 S_no_holders_condition.lock();
00897 if (--S_holders_count > 0)
00898 {
00899 mutex_tct<readers_instance>::lock();
00900 S_writer_is_waiting = true;
00901 while (S_holders_count != 0)
00902 S_no_holders_condition.wait();
00903 S_writer_is_waiting = false;
00904 mutex_tct<readers_instance>::unlock();
00905 }
00906 #if CWDEBUG_DEBUGT
00907 __libcwd_tsd.waiting_for_lock = 0;
00908 #endif
00909 S_holders_count = -1;
00910 S_no_holders_condition.unlock();
00911 if (instance < end_recursive_types)
00912 S_writer_id = pthread_self();
00913 #if CWDEBUG_DEBUG || CWDEBUG_DEBUGT
00914 #if CWDEBUG_DEBUGT
00915 _private_::test_for_deadlock(instance, __libcwd_tsd, __builtin_return_address(0));
00916 #endif
00917 LIBCWD_DEBUGDEBUGRWLOCK_CERR(pthread_self() << ": rwlock_tct::rd2wrlock(): instance_locked[" << instance << "] == " << instance_locked[instance] << "; incrementing it.");
00918 instance_locked[instance] += 1;
00919 #if CWDEBUG_DEBUGT
00920 locked_by[instance] = pthread_self();
00921 locked_from[instance] = __builtin_return_address(0);
00922 #endif
00923 #endif
00924 LibcwDebugThreads(
00925 if (__libcwd_tsd.instance_rdlocked[instance] == 2)
00926 __libcwd_tsd.rdlocked_by2[instance] = 0;
00927 else
00928 __libcwd_tsd.rdlocked_by1[instance] = 0;
00929 __libcwd_tsd.instance_rdlocked[instance] -= 1;
00930 );
00931 LIBCWD_DEBUGDEBUGRWLOCK_CERR(pthread_self() << ": Leaving rwlock_tct<" << instance << ">::rd2wrlock()");
00932 }
00933 static void wr2rdlock(void)
00934 {
00935 #if CWDEBUG_DEBUGT
00936 LIBCWD_TSD_DECLARATION;
00937 #endif
00938 LIBCWD_DEBUGDEBUG_ASSERT_CANCEL_DEFERRED;
00939 #if CWDEBUG_DEBUG || CWDEBUG_DEBUGT
00940 LIBCWD_DEBUGDEBUGRWLOCK_CERR(pthread_self() << ": rwlock_tct::wr2rdlock(): instance_locked[" << instance << "] == " << instance_locked[instance] << "; decrementing it.");
00941 #if CWDEBUG_DEBUGT
00942 LIBCWD_ASSERT( instance_locked[instance] > 0 && locked_by[instance] == pthread_self() );
00943 #endif
00944 instance_locked[instance] -= 1;
00945 #if CWDEBUG_DEBUGT
00946 if (instance > end_recursive_types || instance_locked[instance] == 0)
00947 {
00948 locked_by[instance] = 0;
00949 LIBCWD_DEBUGDEBUGRWLOCK_CERR(pthread_self() << ": rwlock_tct::wr2rdlock(): locked_by[" << instance << "] was reset.");
00950 }
00951 else
00952 {
00953 LIBCWD_DEBUGDEBUGRWLOCK_CERR(pthread_self() << ": rwlock_tct::wr2rdlock(): locked_by[" << instance << "] was not reset, it still is " << locked_by[instance] << ".");
00954 }
00955 #endif
00956 #endif
00957 LIBCWD_DEBUGDEBUGRWLOCK_CERR(pthread_self() << ": Calling rwlock_tct<" << instance << ">::wr2rdlock()");
00958 if (instance < end_recursive_types)
00959 S_writer_id = 0;
00960 S_holders_count = 1;
00961 LibcwDebugThreads(
00962 _private_::test_for_deadlock(instance, __libcwd_tsd, __builtin_return_address(0));
00963 if (instance >= instance_rdlocked_size)
00964 core_dump();
00965 __libcwd_tsd.instance_rdlocked[instance] += 1;
00966 if (__libcwd_tsd.instance_rdlocked[instance] == 1)
00967 {
00968 __libcwd_tsd.rdlocked_by1[instance] = pthread_self();
00969 __libcwd_tsd.rdlocked_from1[instance] = __builtin_return_address(0);
00970 }
00971 else if (__libcwd_tsd.instance_rdlocked[instance] == 2)
00972 {
00973 __libcwd_tsd.rdlocked_by2[instance] = pthread_self();
00974 __libcwd_tsd.rdlocked_from2[instance] = __builtin_return_address(0);
00975 }
00976 else
00977 core_dump();
00978 );
00979 LIBCWD_DEBUGDEBUGRWLOCK_CERR(pthread_self() << ": Leaving rwlock_tct<" << instance << ">::wr2rdlock()");
00980 }
00981
00982 static void cleanup(void*);
00983 };
00984
00985 template <int instance>
00986 int rwlock_tct<instance>::S_holders_count = 0;
00987
00988 template <int instance>
00989 bool volatile rwlock_tct<instance>::S_writer_is_waiting = 0;
00990
00991 template <int instance>
00992 pthread_t rwlock_tct<instance>::S_writer_id = 0;
00993
00994 #if CWDEBUG_DEBUGT || !LIBCWD_USE_LINUXTHREADS
00995 template <int instance>
00996 bool rwlock_tct<instance>::S_initialized = 0;
00997 #endif
00998
00999 template <int instance>
01000 typename rwlock_tct<instance>::cond_t rwlock_tct<instance>::S_no_holders_condition;
01001
01002 template <int instance>
01003 void rwlock_tct<instance>::cleanup(void*)
01004 {
01005 if (S_holders_count == -1)
01006 wrunlock();
01007 else
01008 rdunlock();
01009 }
01010
01011 extern void fatal_cancellation(void*);
01012
01013 }
01014 }
01015
01016 #else // !LIBCWD_THREAD_SAFE
01017 #define LIBCWD_DISABLE_CANCEL
01018 #define LIBCWD_DISABLE_CANCEL_NO_BRACE
01019 #define LIBCWD_ENABLE_CANCEL_NO_BRACE
01020 #define LIBCWD_ENABLE_CANCEL
01021 #define LIBCWD_DEFER_CANCEL
01022 #define LIBCWD_DEFER_CANCEL_NO_BRACE
01023 #define LIBCWD_RESTORE_CANCEL_NO_BRACE
01024 #define LIBCWD_RESTORE_CANCEL
01025 #define LIBCWD_DEFER_CLEANUP_PUSH(routine, arg)
01026 #define LIBCWD_CLEANUP_POP_RESTORE(execute)
01027 #define LIBCWD_PUSH_DEFER_TRYLOCK_MUTEX(instance, unlock_routine)
01028 #define LIBCWD_DEFER_PUSH_LOCKMUTEX(instance, unlock_routine)
01029 #define LIBCWD_UNLOCKMUTEX_POP_RESTORE(instance)
01030 #define LIBCWD_DEBUGDEBUG_ASSERT_CANCEL_DEFERRED
01031 #endif // LIBCWD_THREAD_SAFE
01032 #endif // LIBCWD_PRIVATE_THREADING_H
01033