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