Thread: [libcw-cvs] [CVS] Module src (Page 5)
Abandoned project
Status: Beta
Brought to you by:
libcw
From: Carlo W. <li...@us...> - 2002-01-25 04:46:36
|
CVSROOT : /cvsroot/libcw Module : src Commit time: 2002-00-25 04:46:34 UTC Modified files: libcwd/configure.in libcwd/include/libcw/private_threading.h Log message: Using condition variables instead of semaphores because the latter caused a deadlock as a result of a self-lock in pthread_exit prior to calling pthread_destroy_specifics which calls free() which then called sem_wait() which also tries to obtain that lock. This seems to work. ---------------------- diff included ---------------------- Index: src/libcwd/configure.in diff -u src/libcwd/configure.in:1.96 src/libcwd/configure.in:1.97 --- src/libcwd/configure.in:1.96 Thu Jan 24 13:16:09 2002 +++ src/libcwd/configure.in Thu Jan 24 20:46:24 2002 @@ -1,5 +1,5 @@ dnl Process this file with autoconf to produce a configure script. -AC_REVISION($Revision: 1.96 $)dnl +AC_REVISION($Revision: 1.97 $)dnl dnl General intialization of `autoconf' varaibles. dnl Ensure that the directory specified with --srcdir was correct @@ -368,7 +368,8 @@ if test "$ac_cv_search_pthread_create" = "none required"; then dnl Even if nothing is required, we still need to use -lpthread explicitly dnl while linking a shared library, otherwise the versioning info of - dnl versioned symbols will be missing! This is needed for the sem_* calls. + dnl versioned symbols will be missing! This is needed for pthread_create + dnl itself even!. AC_CHECK_LIB(pthread, pthread_create, [LIB_THREADS_SHARED=-lpthread]) fi fi Index: src/libcwd/include/libcw/private_threading.h diff -u src/libcwd/include/libcw/private_threading.h:1.12 src/libcwd/include/libcw/private_threading.h:1.13 --- src/libcwd/include/libcw/private_threading.h:1.12 Thu Jan 24 13:16:09 2002 +++ src/libcwd/include/libcw/private_threading.h Thu Jan 24 20:46:24 2002 @@ -1,4 +1,4 @@ -// $Header: /cvsroot/l/li/libcw/src/libcwd/include/libcw/private_threading.h,v 1.12 2002/01/24 21:16:09 libcw Exp $ +// $Header: /cvsroot/l/li/libcw/src/libcwd/include/libcw/private_threading.h,v 1.13 2002/01/25 04:46:24 libcw Exp $ // // Copyright (C) 2001, by // @@ -18,7 +18,7 @@ #ifndef LIBCW_PRIVATE_THREADING_H #define LIBCW_PRIVATE_THREADING_H -#define LIBCWD_DEBUGDEBUGRWLOCK 1 +#define LIBCWD_DEBUGDEBUGRWLOCK 0 #if LIBCWD_DEBUGDEBUGRWLOCK #define LIBCWD_NO_INTERNAL_STRING @@ -107,7 +107,7 @@ static pthread_key_t S_key; static TSD* S_temporary_instance; static bool S_initializing; - static bool S_WNS_initialized; + static bool S_initialized; static void S_alloc_key(void) throw(); static TSD* S_initialize(void) throw(); static void S_destroy(void* tsd_ptr) throw(); @@ -119,7 +119,7 @@ instance = S_initialize(); return *instance; } - static bool initialized(void) { return S_WNS_initialized; } + static bool initialized(void) { return S_initialized; } }; #endif // defined(LIBCWD_USE_POSIX_THREADS) || defined(LIBCWD_USE_LINUXTHREADS) @@ -184,11 +184,11 @@ #if defined(LIBCWD_USE_POSIX_THREADS) || defined(LIBCWD_USE_LINUXTHREADS) template <int instance> class mutex_tct { - private: + protected: static pthread_mutex_t S_mutex; #ifndef LIBCWD_USE_LINUXTHREADS - static bool S_initialized; private: + static bool S_initialized; static void S_initialize(void) throw(); #endif public: @@ -259,9 +259,12 @@ template <int instance> void mutex_tct<instance>::S_initialize(void) throw() { - if (instance != mutex_initialization_instance) // The mutex_initialization_instance is - mutex_tct<mutex_initialization_instance>::lock(); // initialized before threads are created - // (from initialize_global_mutexes()). + if (instance != mutex_initialization_instance) + { + mutex_tct<mutex_initialization_instance>::initialize(); + mutex_tct<mutex_initialization_instance>::lock(); + } + if (!S_initialized) // Check again now that we are locked. { pthread_mutexattr_t mutex_attr; @@ -307,6 +310,68 @@ ; #endif // !LIBCWD_USE_LINUXTHREADS +template <int instance> + class cond_tct : public mutex_tct<instance> { + private: + static pthread_cond_t S_condition; +#ifndef LIBCWD_USE_LINUXTHREADS + static bool S_initialized; + private: + static void S_initialize(void) throw(); +#endif + public: + static void initialize(void) throw() +#ifdef LIBCWD_USE_LINUXTHREADS + { } +#else + { + if (S_initialized) // Check if the static `S_mutex' already has been initialized. + return; // No need to lock: `S_initialized' is only set after it is + // really initialized. + S_initialize(); + } +#endif + public: + void wait(void) { +#ifdef DEBUGDEBUG + assert( is_locked(instance) ); +#endif + pthread_cond_wait(&S_condition, &S_mutex); + } + void signal(void) { pthread_cond_signal(&S_condition); } + void broadcast(void) { pthread_cond_broadcast(&S_condition); } + }; + +#ifndef LIBCWD_USE_LINUXTHREADS +template <int instance> + void cond_tct<instance>::S_initialize(void) throw() + { + mutex_tct<mutex_initialization_instance>::initialize(); + mutex_tct<mutex_initialization_instance>::lock(); + + if (!S_initialized) // Check again now that we are locked. + { + pthread_cond_init(&S_condition, NULL); + S_initialized = true; + } + + mutex_tct<mutex_initialization_instance>::unlock(); + } +#endif // !LIBCWD_USE_LINUXTHREADS + +#ifndef LIBCWD_USE_LINUXTHREADS +template <int instance> + bool cond_tct<instance>::S_initialized = false; +#endif + +template <int instance> + pthread_cond_t cond_tct<instance>::S_condition +#ifdef LIBCWD_USE_LINUXTHREADS + = PTHREAD_COND_INITIALIZER; +#else // !LIBCWD_USE_LINUXTHREADS + ; +#endif // !LIBCWD_USE_LINUXTHREADS + #endif // defined(LIBCWD_USE_POSIX_THREADS) || defined(LIBCWD_USE_LINUXTHREADS) // @@ -333,111 +398,101 @@ class rwlock_tct { private: static int const readers_instance = instance + reserved_instance_low; - static int const readers_count_instance = instance + 2 * reserved_instance_low; - static sem_t S_no_readers_left; // 0: locked, 1: unlocked. - static int S_readers_count; + static int const holders_instance = instance + 2 * reserved_instance_low; + typedef cond_tct<holders_instance> cond_t; + static cond_t S_cond_no_holders; + static int S_holders_count; // Number of readers or -1 if a writer locked this object. static bool S_writer_is_waiting; static pthread_t S_writer_id; - static bool S_WNS_initialized; +#if LIBCWD_DEBUGTHREADS || !defined(LIBCWD_USE_LINUXTHREADS) + static bool S_initialized; // Set when initialized. +#endif public: static void initialize(void) throw() { - if (S_WNS_initialized) +#if LIBCWD_DEBUGTHREADS || !defined(LIBCWD_USE_LINUXTHREADS) + if (S_initialized) return; LIBCWD_DEBUGDEBUGRWLOCK_CERR(pthread_self() << ": Calling initialize() instance " << instance); mutex_tct<readers_instance>::initialize(); - mutex_tct<readers_count_instance>::initialize(); -#if LIBCWD_DEBUGTHREADS - int res = -#endif - sem_init(&S_no_readers_left, 0, 1); -#if LIBCWD_DEBUGDEBUGRWLOCK - LIBCWD_DEBUGDEBUGRWLOCK_CERR("res == " << res << "; &S_no_readers_left = " << (void*)&S_no_readers_left); - int val; - sem_getvalue(&S_no_readers_left, &val); - LIBCWD_DEBUGDEBUGRWLOCK_CERR(pthread_self() << ": &S_no_readers_left " << &S_no_readers_left << " contains value " << val); -#endif -#if LIBCWD_DEBUGTHREADS - if (res != 0) - LIBCWD_DEBUGDEBUGRWLOCK_CERR("res == " << strerror(res) ); - assert( res == 0 ); -#endif - S_WNS_initialized = true; + S_cond_no_holders.initialize(); LIBCWD_DEBUGDEBUGRWLOCK_CERR(pthread_self() << ": Leaving initialize() instance " << instance); + S_initialized = true; +#endif } static bool tryrdlock(void) throw() { #if LIBCWD_DEBUGTHREADS - assert(S_WNS_initialized); + assert(S_initialized); #endif LIBCWD_DEBUGDEBUGRWLOCK_CERR(pthread_self() << ": Calling rwlock_tct<" << instance << ">::tryrdlock()"); if (instance < end_recursive_types && pthread_equal(S_writer_id, pthread_self())) { - LIBCWD_DEBUGDEBUGRWLOCK_CERR(pthread_self() << ": Leaving rwlock_tct<" << instance << ">::tryrdlock()"); - return true; // No error checking is done. + LIBCWD_DEBUGDEBUGRWLOCK_CERR(pthread_self() << ": Leaving rwlock_tct<" << instance << ">::tryrdlock() (skipped: thread has write lock)"); + return; // No error checking is done. } - if (S_writer_is_waiting || !mutex_tct<readers_count_instance>::trylock()) - { - LIBCWD_DEBUGDEBUGRWLOCK_CERR(pthread_self() << ": Leaving rwlock_tct<" << instance << ">::tryrdlock()"); + // Give a writer a higher priority (kinda fuzzy). + if (S_writer_is_waiting || !S_cond_no_holders.trylock()) return false; - } - bool success = (++S_readers_count != 1) || (sem_trywait(&S_no_readers_left) == 0); - if (!success) - S_readers_count = 0; - mutex_tct<readers_count_instance>::unlock(); + bool success = (S_holders_count != -1); + if (success) + ++S_holders_count; // Add one reader. + S_cond_no_holders.unlock(); LIBCWD_DEBUGDEBUGRWLOCK_CERR(pthread_self() << ": Leaving rwlock_tct<" << instance << ">::tryrdlock()"); return success; } static bool trywrlock(void) throw() { #if LIBCWD_DEBUGTHREADS - assert(S_WNS_initialized); + assert(S_initialized); #endif LIBCWD_DEBUGDEBUGRWLOCK_CERR(pthread_self() << ": Calling rwlock_tct<" << instance << ">::trywrlock()"); -#ifndef DEBUGDEBUG - LIBCWD_DEBUGDEBUGRWLOCK_CERR(pthread_self() << ": Leaving rwlock_tct<" << instance << ">::trywrlock()"); - return sem_trywait(&S_no_readers_left) == 0; -#else - bool res = (sem_trywait(&S_no_readers_left) == 0); - if (res) - instance_locked[instance] += 1; + bool success; + success = mutex_tct<readers_instance>::trylock(); // Block new readers, + while (success) + { + S_writer_is_waiting = true; // from this moment on. + if (!S_cond_no_holders.trylock()) + { + S_writer_is_waiting = false; + mutex_tct<readers_instance>::unlock(); + success = false; + break; + } + while (S_holders_count != 0) // Other readers or writers have this lock? + S_cond_no_holders.wait(); // Wait until all current holders are done. + S_writer_is_waiting = false; // Stop checking the lock for new readers. + mutex_tct<readers_instance>::unlock(); // Release blocked readers. + S_holders_count = -1; // Mark that we have a writer. + S_cond_no_holders.unlock(); + if (instance < end_recursive_types) + S_writer_id = pthread_self(); + } LIBCWD_DEBUGDEBUGRWLOCK_CERR(pthread_self() << ": Leaving rwlock_tct<" << instance << ">::trywrlock()"); - return res; -#endif + return success; } static void rdlock(void) throw() { #if LIBCWD_DEBUGTHREADS - assert(S_WNS_initialized); + assert(S_initialized); #endif LIBCWD_DEBUGDEBUGRWLOCK_CERR(pthread_self() << ": Calling rwlock_tct<" << instance << ">::rdlock()"); if (instance < end_recursive_types && pthread_equal(S_writer_id, pthread_self())) { - LIBCWD_DEBUGDEBUGRWLOCK_CERR(pthread_self() << ": Leaving rwlock_tct<" << instance << ">::rdlock() ILLEGAL!"); + LIBCWD_DEBUGDEBUGRWLOCK_CERR(pthread_self() << ": Leaving rwlock_tct<" << instance << ">::rdlock() (skipped: thread has write lock)"); return; // No error checking is done. } - if (S_writer_is_waiting) + // Give a writer a higher priority (kinda fuzzy). + if (S_writer_is_waiting) // If there is a writer interested, { - mutex_tct<readers_instance>::lock(); + mutex_tct<readers_instance>::lock(); // then give it precedence and wait here. mutex_tct<readers_instance>::unlock(); } - mutex_tct<readers_count_instance>::lock(); - LIBCWD_DEBUGDEBUGRWLOCK_CERR(pthread_self() << ": Inside readers_count_instance critical area; S_readers_count == " << S_readers_count); - if (++S_readers_count == 1) - { -#if LIBCWD_DEBUGDEBUGRWLOCK - int val; - sem_getvalue(&S_no_readers_left, &val); - LIBCWD_DEBUGDEBUGRWLOCK_CERR(pthread_self() << ": &S_no_readers_left " << &S_no_readers_left << " contains value " << val); - LIBCWD_DEBUGDEBUGRWLOCK_CERR(pthread_self() << ": Calling sem_wait..."); -#endif - sem_wait(&S_no_readers_left); // Warning: must be done while S_readers_count is still locked! -#if LIBCWD_DEBUGDEBUGRWLOCK - sem_getvalue(&S_no_readers_left, &val); - LIBCWD_DEBUGDEBUGRWLOCK_CERR(pthread_self() << ": &S_no_readers_left " << &S_no_readers_left << " now contains value " << val); -#endif - } - mutex_tct<readers_count_instance>::unlock(); + S_cond_no_holders.lock(); + while (S_holders_count == -1) // Writer locked it? + S_cond_no_holders.wait(); // Wait for writer to finish. + ++S_holders_count; // Add one reader. + S_cond_no_holders.unlock(); LIBCWD_DEBUGDEBUGRWLOCK_CERR(pthread_self() << ": Leaving rwlock_tct<" << instance << ">::rdlock()"); } static void rdunlock(void) throw() @@ -445,128 +500,88 @@ LIBCWD_DEBUGDEBUGRWLOCK_CERR(pthread_self() << ": Calling rwlock_tct<" << instance << ">::rdunlock()"); if (instance < end_recursive_types && pthread_equal(S_writer_id, pthread_self())) { - LIBCWD_DEBUGDEBUGRWLOCK_CERR(pthread_self() << ": Leaving rwlock_tct<" << instance << ">::rdunlock() ILLEGAL!"); + LIBCWD_DEBUGDEBUGRWLOCK_CERR(pthread_self() << ": Leaving rwlock_tct<" << instance << ">::rdunlock() (skipped: thread has write lock)"); return; // No error checking is done. - } - mutex_tct<readers_count_instance>::lock(); - LIBCWD_DEBUGDEBUGRWLOCK_CERR(pthread_self() << ": Inside readers_count_instance critical area; S_readers_count == " << S_readers_count); - if (--S_readers_count == 0) - { -#if LIBCWD_DEBUGDEBUGRWLOCK - int val; - sem_getvalue(&S_no_readers_left, &val); - LIBCWD_DEBUGDEBUGRWLOCK_CERR(pthread_self() << ": &S_no_readers_left " << &S_no_readers_left << " contains value " << val); - LIBCWD_DEBUGDEBUGRWLOCK_CERR(pthread_self() << ": Calling sem_post..."); -#endif - sem_post(&S_no_readers_left); -#if LIBCWD_DEBUGDEBUGRWLOCK - sem_getvalue(&S_no_readers_left, &val); - LIBCWD_DEBUGDEBUGRWLOCK_CERR(pthread_self() << ": &S_no_readers_left " << &S_no_readers_left << " now contains value " << val); -#endif } - mutex_tct<readers_count_instance>::unlock(); + S_cond_no_holders.lock(); + if (--S_holders_count == 0) // Was this the last reader? + S_cond_no_holders.signal(); // Tell waiting threads. + S_cond_no_holders.unlock(); LIBCWD_DEBUGDEBUGRWLOCK_CERR(pthread_self() << ": Leaving rwlock_tct<" << instance << ">::rdunlock()"); } static void wrlock(void) throw() { #if LIBCWD_DEBUGTHREADS - assert(S_WNS_initialized); + assert(S_initialized); #endif LIBCWD_DEBUGDEBUGRWLOCK_CERR(pthread_self() << ": Calling rwlock_tct<" << instance << ">::wrlock()"); mutex_tct<readers_instance>::lock(); // Block new readers, - S_writer_is_waiting = true; -#if LIBCWD_DEBUGDEBUGRWLOCK - int val; - sem_getvalue(&S_no_readers_left, &val); - LIBCWD_DEBUGDEBUGRWLOCK_CERR(pthread_self() << ": &S_no_readers_left " << &S_no_readers_left << " contains value " << val); - LIBCWD_DEBUGDEBUGRWLOCK_CERR(pthread_self() << ": Calling sem_wait..."); -#endif - sem_wait(&S_no_readers_left); // Warning: must be done while S_readers_count is still locked! -#if LIBCWD_DEBUGDEBUGRWLOCK - sem_getvalue(&S_no_readers_left, &val); - LIBCWD_DEBUGDEBUGRWLOCK_CERR(pthread_self() << ": &S_no_readers_left " << &S_no_readers_left << " now contains value " << val); -#endif + S_writer_is_waiting = true; // from this moment on. + S_cond_no_holders.lock(); + while (S_holders_count != 0) // Other readers or writers have this lock? + S_cond_no_holders.wait(); // Wait until all current holders are done. + S_writer_is_waiting = false; // Stop checking the lock for new readers. + mutex_tct<readers_instance>::unlock(); // Release blocked readers. + S_holders_count = -1; // Mark that we have a writer. + S_cond_no_holders.unlock(); if (instance < end_recursive_types) S_writer_id = pthread_self(); - S_writer_is_waiting = false; - mutex_tct<readers_instance>::unlock(); + LIBCWD_DEBUGDEBUGRWLOCK_CERR(pthread_self() << ": Leaving rwlock_tct<" << instance << ">::wrlock()"); #ifdef DEBUGDEBUG instance_locked[instance] += 1; #endif - LIBCWD_DEBUGDEBUGRWLOCK_CERR(pthread_self() << ": Leaving rwlock_tct<" << instance << ">::wrlock()"); } static void wrunlock(void) throw() { - LIBCWD_DEBUGDEBUGRWLOCK_CERR(pthread_self() << ": Calling rwlock_tct<" << instance << ">::wrunlock()"); #ifdef DEBUGDEBUG instance_locked[instance] -= 1; #endif + LIBCWD_DEBUGDEBUGRWLOCK_CERR(pthread_self() << ": Calling rwlock_tct<" << instance << ">::wrunlock()"); if (instance < end_recursive_types) S_writer_id = 0; - if(1) - { -#if LIBCWD_DEBUGDEBUGRWLOCK - int val; - sem_getvalue(&S_no_readers_left, &val); - LIBCWD_DEBUGDEBUGRWLOCK_CERR(pthread_self() << ": &S_no_readers_left " << &S_no_readers_left << " contains value " << val); - LIBCWD_DEBUGDEBUGRWLOCK_CERR(pthread_self() << ": Calling sem_post..."); -#endif - sem_post(&S_no_readers_left); -#if LIBCWD_DEBUGDEBUGRWLOCK - sem_getvalue(&S_no_readers_left, &val); - LIBCWD_DEBUGDEBUGRWLOCK_CERR(pthread_self() << ": &S_no_readers_left " << &S_no_readers_left << " now contains value " << val); -#endif - } + S_cond_no_holders.lock(); + S_holders_count = 0; // We have no writer anymore. + S_cond_no_holders.signal(); // No readers and no writers left. + S_cond_no_holders.unlock(); LIBCWD_DEBUGDEBUGRWLOCK_CERR(pthread_self() << ": Leaving rwlock_tct<" << instance << ">::wrunlock()"); } static void rd2wrlock() throw() { LIBCWD_DEBUGDEBUGRWLOCK_CERR(pthread_self() << ": Calling rwlock_tct<" << instance << ">::rd2wrlock()"); - mutex_tct<readers_count_instance>::lock(); - bool inherit_lock = (--S_readers_count == 0); - mutex_tct<readers_count_instance>::unlock(); - if (!inherit_lock) + S_cond_no_holders.lock(); + if (--S_holders_count > 0) { - mutex_tct<readers_instance>::lock(); // Block new readers, + mutex_tct<readers_instance>::lock(); // Block new readers. S_writer_is_waiting = true; -#if LIBCWD_DEBUGDEBUGRWLOCK - int val; - sem_getvalue(&S_no_readers_left, &val); - LIBCWD_DEBUGDEBUGRWLOCK_CERR(pthread_self() << ": &S_no_readers_left " << &S_no_readers_left << " contains value " << val); - LIBCWD_DEBUGDEBUGRWLOCK_CERR(pthread_self() << ": Calling sem_wait..."); -#endif - sem_wait(&S_no_readers_left); // Warning: must be done while S_readers_count is still locked! -#if LIBCWD_DEBUGDEBUGRWLOCK - sem_getvalue(&S_no_readers_left, &val); - LIBCWD_DEBUGDEBUGRWLOCK_CERR(pthread_self() << ": &S_no_readers_left " << &S_no_readers_left << " now contains value " << val); -#endif - if (instance < end_recursive_types) - S_writer_id = pthread_self(); + while (S_holders_count != 0) + S_cond_no_holders.wait(); S_writer_is_waiting = false; - mutex_tct<readers_instance>::unlock(); + mutex_tct<readers_instance>::unlock(); // Release blocked readers. } + S_holders_count = -1; // We are a writer now. + S_cond_no_holders.unlock(); + if (instance < end_recursive_types) + S_writer_id = pthread_self(); + LIBCWD_DEBUGDEBUGRWLOCK_CERR(pthread_self() << ": Leaving rwlock_tct<" << instance << ">::rd2wrlock()"); #ifdef DEBUGDEBUG instance_locked[instance] += 1; #endif - LIBCWD_DEBUGDEBUGRWLOCK_CERR(pthread_self() << ": Leaving rwlock_tct<" << instance << ">::rd2wrlock()"); } static void wr2rdlock() throw() { - LIBCWD_DEBUGDEBUGRWLOCK_CERR(pthread_self() << ": Calling rwlock_tct<" << instance << ">::wr2rdlock()"); #ifdef DEBUGDEBUG instance_locked[instance] -= 1; #endif - mutex_tct<readers_count_instance>::lock(); + LIBCWD_DEBUGDEBUGRWLOCK_CERR(pthread_self() << ": Calling rwlock_tct<" << instance << ">::wr2rdlock()"); if (instance < end_recursive_types) S_writer_id = 0; - ++S_readers_count; - mutex_tct<readers_count_instance>::unlock(); + S_holders_count = 1; // Turn writer into a reader (atomic operation). LIBCWD_DEBUGDEBUGRWLOCK_CERR(pthread_self() << ": Leaving rwlock_tct<" << instance << ">::wr2rdlock()"); } }; template <int instance> - int rwlock_tct<instance>::S_readers_count = 0; + int rwlock_tct<instance>::S_holders_count = 0; template <int instance> bool rwlock_tct<instance>::S_writer_is_waiting = 0; @@ -574,11 +589,13 @@ template <int instance> pthread_t rwlock_tct<instance>::S_writer_id = 0; +#if LIBCWD_DEBUGTHREADS || !defined(LIBCWD_USE_LINUXTHREADS) template <int instance> - bool rwlock_tct<instance>::S_WNS_initialized = 0; + bool rwlock_tct<instance>::S_initialized = 0; +#endif template <int instance> - sem_t rwlock_tct<instance>::S_no_readers_left; + typename rwlock_tct<instance>::cond_t rwlock_tct<instance>::S_cond_no_holders; //=================================================================================================== // Implementation of Thread Specific Data. @@ -597,7 +614,7 @@ bool thread_specific_data_tct<TSD>::S_initializing; template<class TSD> - bool thread_specific_data_tct<TSD>::S_WNS_initialized; + bool thread_specific_data_tct<TSD>::S_initialized; template<class TSD> void thread_specific_data_tct<TSD>::S_destroy(void* tsd_ptr) throw() @@ -645,7 +662,7 @@ // contain relevant information. std::memcpy((void*)instance, new_TSD_space, sizeof(TSD)); // Put the temporary TSD in its final place. S_initializing = false; - S_WNS_initialized = true; + S_initialized = true; mutex_tct<tsd_initialization_instance>::unlock(); if (WST_multi_threaded) // Is this a second (or later) thread? debug_tsd_init(); // Initialize the TSD of existing debug objects. ----------------------- End of diff ----------------------- |
From: Carlo W. <li...@us...> - 2002-01-25 16:40:35
|
CVSROOT : /cvsroot/libcw Module : src Commit time: 2002-00-25 16:40:33 UTC Modified files: libcwd/tests/threads4.cc Log message: Work in progress. ---------------------- diff included ---------------------- Index: src/libcwd/tests/threads4.cc diff -u src/libcwd/tests/threads4.cc:1.6 src/libcwd/tests/threads4.cc:1.7 --- src/libcwd/tests/threads4.cc:1.6 Thu Jan 24 13:16:10 2002 +++ src/libcwd/tests/threads4.cc Fri Jan 25 08:40:23 2002 @@ -12,8 +12,8 @@ #endif int const loopsize = 1000; -int const number_of_threads = 2; -int const number_of_threads2 = 2; +int const number_of_threads = 4; +int const number_of_threads2 = 4; void* thread_function2(void* arguments) { ----------------------- End of diff ----------------------- |
From: Carlo W. <li...@us...> - 2002-01-25 16:45:17
|
CVSROOT : /cvsroot/libcw Module : src Commit time: 2002-00-25 16:45:16 UTC Modified files: libcwd/include/libcw/private_threading.h Log message: Defined macros LIBCWD_CLEANUP_PUSH_DEFER(routine, arg) and LIBCWD_CLEANUP_POP_DEFER(execute). Using 0 or 1 for LIBCWD_USE_POSIX_THREADS and LIBCWD_USE_LINUXTHREADS now. ---------------------- diff included ---------------------- Index: src/libcwd/include/libcw/private_threading.h diff -u src/libcwd/include/libcw/private_threading.h:1.13 src/libcwd/include/libcw/private_threading.h:1.14 --- src/libcwd/include/libcw/private_threading.h:1.13 Thu Jan 24 20:46:24 2002 +++ src/libcwd/include/libcw/private_threading.h Fri Jan 25 08:45:05 2002 @@ -1,6 +1,6 @@ -// $Header: /cvsroot/l/li/libcw/src/libcwd/include/libcw/private_threading.h,v 1.13 2002/01/25 04:46:24 libcw Exp $ +// $Header: /cvsroot/l/li/libcw/src/libcwd/include/libcw/private_threading.h,v 1.14 2002/01/25 16:45:05 libcw Exp $ // -// Copyright (C) 2001, by +// Copyright (C) 2001 - 2002, by // // Carlo Wood, Run on IRC <ca...@al...> // RSA-1024 0x624ACAD5 1997-01-26 Sign & Encrypt @@ -48,12 +48,19 @@ #include <pthread.h> #include <semaphore.h> #if defined(PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP) && defined(PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP) -#define LIBCWD_USE_LINUXTHREADS +#define LIBCWD_USE_LINUXTHREADS 1 #else -#define LIBCWD_USE_POSIX_THREADS +#define LIBCWD_USE_POSIX_THREADS 1 #endif #endif // LIBCWD_HAVE_PTHREAD +#ifndef LIBCWD_USE_LINUXTHREADS +#define LIBCWD_USE_LINUXTHREADS 0 +#endif +#ifndef LIBCWD_USE_POSIX_THREADS +#define LIBCWD_USE_POSIX_THREADS 0 +#endif + #ifndef DEBUGDEBUG #define LIBCWD_DEBUGTHREADS 0 // Toggle this if necessary. #else @@ -91,6 +98,21 @@ #ifdef LIBCWD_THREAD_SAFE +#if LIBCWD_USE_LINUXTHREADS +#define LIBCWD_CLEANUP_PUSH_DEFER(routine, arg) pthread_cleanup_push_defer_np(routine, arg) +#define LIBCWD_CLEANUP_POP_DEFER(execute) pthread_cleanup_pop_defer_np(execute) +#elif LIBCWD_USE_POSIX_THREADS +#define LIBCWD_CLEANUP_PUSH_DEFER(routine, arg) \ + { \ + int __libcwd_oldtype; \ + pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, &__libcwd_oldtype); \ + pthread_cleanup_push(routine, arg); +#define LIBCWD_CLEANUP_POP_DEFER(execute) \ + pthread_cleanup_pop(execute); \ + pthread_setcanceltype(__libcwd_oldtype, NULL); \ + } +#endif + namespace libcw { namespace debug { namespace _private_ { @@ -99,7 +121,7 @@ extern bool WST_multi_threaded; #endif -#if defined(LIBCWD_USE_POSIX_THREADS) || defined(LIBCWD_USE_LINUXTHREADS) +#if LIBCWD_USE_POSIX_THREADS || LIBCWD_USE_LINUXTHREADS template<class TSD> class thread_specific_data_tct { private: @@ -121,7 +143,7 @@ } static bool initialized(void) { return S_initialized; } }; -#endif // defined(LIBCWD_USE_POSIX_THREADS) || defined(LIBCWD_USE_LINUXTHREADS) +#endif // LIBCWD_USE_POSIX_THREADS || LIBCWD_USE_LINUXTHREADS //=================================================================================================== // @@ -181,19 +203,19 @@ __inline__ bool is_locked(int instance) { return instance_locked[instance] > 0; } #endif -#if defined(LIBCWD_USE_POSIX_THREADS) || defined(LIBCWD_USE_LINUXTHREADS) +#if LIBCWD_USE_POSIX_THREADS || LIBCWD_USE_LINUXTHREADS template <int instance> class mutex_tct { protected: static pthread_mutex_t S_mutex; -#ifndef LIBCWD_USE_LINUXTHREADS +#if !LIBCWD_USE_LINUXTHREADS private: static bool S_initialized; static void S_initialize(void) throw(); #endif public: static void initialize(void) throw() -#ifdef LIBCWD_USE_LINUXTHREADS +#if LIBCWD_USE_LINUXTHREADS { } #else { @@ -255,7 +277,7 @@ } }; -#ifndef LIBCWD_USE_LINUXTHREADS +#if !LIBCWD_USE_LINUXTHREADS template <int instance> void mutex_tct<instance>::S_initialize(void) throw() { @@ -284,16 +306,16 @@ if (instance != mutex_initialization_instance) mutex_tct<mutex_initialization_instance>::unlock(); } -#endif // LIBCWD_USE_LINUXTHREADS +#endif // !LIBCWD_USE_LINUXTHREADS -#ifndef LIBCWD_USE_LINUXTHREADS +#if !LIBCWD_USE_LINUXTHREADS template <int instance> bool mutex_tct<instance>::S_initialized = false; #endif template <int instance> pthread_mutex_t mutex_tct<instance>::S_mutex -#ifdef LIBCWD_USE_LINUXTHREADS +#if LIBCWD_USE_LINUXTHREADS = #if LIBCWD_DEBUGTHREADS PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP; @@ -314,14 +336,14 @@ class cond_tct : public mutex_tct<instance> { private: static pthread_cond_t S_condition; -#ifndef LIBCWD_USE_LINUXTHREADS +#if !LIBCWD_USE_LINUXTHREADS static bool S_initialized; private: static void S_initialize(void) throw(); #endif public: static void initialize(void) throw() -#ifdef LIBCWD_USE_LINUXTHREADS +#if LIBCWD_USE_LINUXTHREADS { } #else { @@ -342,7 +364,7 @@ void broadcast(void) { pthread_cond_broadcast(&S_condition); } }; -#ifndef LIBCWD_USE_LINUXTHREADS +#if !LIBCWD_USE_LINUXTHREADS template <int instance> void cond_tct<instance>::S_initialize(void) throw() { @@ -359,20 +381,20 @@ } #endif // !LIBCWD_USE_LINUXTHREADS -#ifndef LIBCWD_USE_LINUXTHREADS +#if !LIBCWD_USE_LINUXTHREADS template <int instance> bool cond_tct<instance>::S_initialized = false; #endif template <int instance> pthread_cond_t cond_tct<instance>::S_condition -#ifdef LIBCWD_USE_LINUXTHREADS +#if LIBCWD_USE_LINUXTHREADS = PTHREAD_COND_INITIALIZER; #else // !LIBCWD_USE_LINUXTHREADS ; #endif // !LIBCWD_USE_LINUXTHREADS -#endif // defined(LIBCWD_USE_POSIX_THREADS) || defined(LIBCWD_USE_LINUXTHREADS) +#endif // LIBCWD_USE_POSIX_THREADS || LIBCWD_USE_LINUXTHREADS // // template <int instance> This class may not use system calls (it may not call malloc(3)). @@ -404,13 +426,13 @@ static int S_holders_count; // Number of readers or -1 if a writer locked this object. static bool S_writer_is_waiting; static pthread_t S_writer_id; -#if LIBCWD_DEBUGTHREADS || !defined(LIBCWD_USE_LINUXTHREADS) +#if LIBCWD_DEBUGTHREADS || !LIBCWD_USE_LINUXTHREADS static bool S_initialized; // Set when initialized. #endif public: static void initialize(void) throw() { -#if LIBCWD_DEBUGTHREADS || !defined(LIBCWD_USE_LINUXTHREADS) +#if LIBCWD_DEBUGTHREADS || !LIBCWD_USE_LINUXTHREADS if (S_initialized) return; LIBCWD_DEBUGDEBUGRWLOCK_CERR(pthread_self() << ": Calling initialize() instance " << instance); @@ -589,7 +611,7 @@ template <int instance> pthread_t rwlock_tct<instance>::S_writer_id = 0; -#if LIBCWD_DEBUGTHREADS || !defined(LIBCWD_USE_LINUXTHREADS) +#if LIBCWD_DEBUGTHREADS || !LIBCWD_USE_LINUXTHREADS template <int instance> bool rwlock_tct<instance>::S_initialized = 0; #endif @@ -600,7 +622,7 @@ //=================================================================================================== // Implementation of Thread Specific Data. -#if defined(LIBCWD_USE_POSIX_THREADS) || defined(LIBCWD_USE_LINUXTHREADS) +#if LIBCWD_USE_POSIX_THREADS || LIBCWD_USE_LINUXTHREADS template<class TSD> pthread_once_t thread_specific_data_tct<TSD>::S_key_once = PTHREAD_ONCE_INIT; @@ -668,7 +690,7 @@ debug_tsd_init(); // Initialize the TSD of existing debug objects. return instance; } -#endif // defined(LIBCWD_USE_POSIX_THREADS) || defined(LIBCWD_USE_LINUXTHREADS) +#endif // LIBCWD_USE_POSIX_THREADS || LIBCWD_USE_LINUXTHREADS // End of Thread Specific Data //=================================================================================================== ----------------------- End of diff ----------------------- |
From: Carlo W. <li...@us...> - 2002-01-25 17:30:05
|
CVSROOT : /cvsroot/libcw Module : src Commit time: 2002-00-25 17:30:03 UTC Modified files: libcwd/acconfig.h libcwd/configure.in Log message: Added new test for struct _pthread_cleanup_buufer. ---------------------- diff included ---------------------- Index: src/libcwd/acconfig.h diff -u src/libcwd/acconfig.h:1.8 src/libcwd/acconfig.h:1.9 --- src/libcwd/acconfig.h:1.8 Wed Aug 22 21:13:12 2001 +++ src/libcwd/acconfig.h Fri Jan 25 09:29:53 2002 @@ -27,6 +27,9 @@ // Defined when --enable-libcwd-threading is used. #undef LIBCWD_THREAD_SAFE + +// Defined when having struct _pthread_cleanup_buffer. +#undef HAVE__PTHREAD_CLEANUP_BUFFER @BOTTOM@ #endif // LIBCW_CONFIG_H Index: src/libcwd/configure.in diff -u src/libcwd/configure.in:1.97 src/libcwd/configure.in:1.98 --- src/libcwd/configure.in:1.97 Thu Jan 24 20:46:24 2002 +++ src/libcwd/configure.in Fri Jan 25 09:29:53 2002 @@ -1,5 +1,5 @@ dnl Process this file with autoconf to produce a configure script. -AC_REVISION($Revision: 1.97 $)dnl +AC_REVISION($Revision: 1.98 $)dnl dnl General intialization of `autoconf' varaibles. dnl Ensure that the directory specified with --srcdir was correct @@ -372,6 +372,8 @@ dnl itself even!. AC_CHECK_LIB(pthread, pthread_create, [LIB_THREADS_SHARED=-lpthread]) fi + + AC_CHECK_TYPE([struct _pthread_cleanup_buffer],[AC_DEFINE(HAVE__PTHREAD_CLEANUP_BUFFER)],,[#include <pthread.h>]) fi dnl This test needs the full set of libraries we just determined. ----------------------- End of diff ----------------------- |
From: Carlo W. <li...@us...> - 2002-01-26 02:06:44
|
CVSROOT : /cvsroot/libcw Module : src Commit time: 2002-00-26 02:06:43 UTC Modified files: libcwd/acconfig.h libcwd/bfd.cc libcwd/configure.in libcwd/debug.cc libcwd/include/libcw/debug_config.ho.in libcwd/include/libcw/macro_AllocTag.h libcwd/include/libcw/private_threading.h libcwd/include/libcw/type_info.h Log message: Added support for asynchrone cancellation of threads. All locks hold by a given thread will now be unlocked when a thread is cancelled. ---------------------- diff included ---------------------- Index: src/libcwd/acconfig.h diff -u src/libcwd/acconfig.h:1.9 src/libcwd/acconfig.h:1.10 --- src/libcwd/acconfig.h:1.9 Fri Jan 25 09:29:53 2002 +++ src/libcwd/acconfig.h Fri Jan 25 18:06:32 2002 @@ -27,9 +27,6 @@ // Defined when --enable-libcwd-threading is used. #undef LIBCWD_THREAD_SAFE - -// Defined when having struct _pthread_cleanup_buffer. -#undef HAVE__PTHREAD_CLEANUP_BUFFER @BOTTOM@ #endif // LIBCW_CONFIG_H Index: src/libcwd/bfd.cc diff -u src/libcwd/bfd.cc:1.94 src/libcwd/bfd.cc:1.95 --- src/libcwd/bfd.cc:1.94 Wed Jan 23 21:48:29 2002 +++ src/libcwd/bfd.cc Fri Jan 25 18:06:33 2002 @@ -1,4 +1,4 @@ -// $Header: /cvsroot/l/li/libcw/src/libcwd/bfd.cc,v 1.94 2002/01/24 05:48:29 libcw Exp $ +// $Header: /cvsroot/l/li/libcw/src/libcwd/bfd.cc,v 1.95 2002/01/26 02:06:33 libcw Exp $ // // Copyright (C) 2000 - 2001, by // @@ -66,6 +66,7 @@ #ifdef LIBCWD_THREAD_SAFE using libcw::debug::_private_::rwlock_tct; using libcw::debug::_private_::mutex_tct; +using libcw::debug::_private_::cancel_buffer_t; using libcw::debug::_private_::object_files_instance; using libcw::debug::_private_::dlopen_map_instance; #define BFD_INITIALIZE_LOCK rwlock_tct<object_files_instance>::initialize(); @@ -75,8 +76,8 @@ #define BFD_RELEASE_READ_LOCK rwlock_tct<object_files_instance>::rdunlock(); #define BFD_ACQUIRE_READ2WRITE_LOCK rwlock_tct<object_files_instance>::rd2wrlock(); #define BFD_ACQUIRE_WRITE2READ_LOCK rwlock_tct<object_files_instance>::wr2rdlock(); -#define DLOPEN_MAP_ACQUIRE_LOCK mutex_tct<dlopen_map_instance>::lock(); -#define DLOPEN_MAP_RELEASE_LOCK mutex_tct<dlopen_map_instance>::unlock(); +#define DLOPEN_MAP_ACQUIRE_LOCK cancel_buffer_t buffer; mutex_tct<dlopen_map_instance>::lock(buffer); +#define DLOPEN_MAP_RELEASE_LOCK mutex_tct<dlopen_map_instance>::unlock(buffer); #else // !LIBCWD_THREAD_SAFE #define BFD_INITIALIZE_LOCK #define BFD_ACQUIRE_WRITE_LOCK Index: src/libcwd/configure.in diff -u src/libcwd/configure.in:1.98 src/libcwd/configure.in:1.99 --- src/libcwd/configure.in:1.98 Fri Jan 25 09:29:53 2002 +++ src/libcwd/configure.in Fri Jan 25 18:06:33 2002 @@ -1,5 +1,5 @@ dnl Process this file with autoconf to produce a configure script. -AC_REVISION($Revision: 1.98 $)dnl +AC_REVISION($Revision: 1.99 $)dnl dnl General intialization of `autoconf' varaibles. dnl Ensure that the directory specified with --srcdir was correct @@ -336,6 +336,8 @@ CW_CONFIG_HAVE_PTHREADS=undef AC_SUBST(LIB_THREADS) AC_SUBST(LIB_THREADS_SHARED) +CW_CONFIG_HAVE__PTHREAD_CLEANUP_BUFFER=undef +AC_SUBST(CW_CONFIG_HAVE__PTHREAD_CLEANUP_BUFFER) if test "$libcwd_config_threading" = yes; then dnl Check if we have POSIX threads @@ -373,7 +375,7 @@ AC_CHECK_LIB(pthread, pthread_create, [LIB_THREADS_SHARED=-lpthread]) fi - AC_CHECK_TYPE([struct _pthread_cleanup_buffer],[AC_DEFINE(HAVE__PTHREAD_CLEANUP_BUFFER)],,[#include <pthread.h>]) + AC_CHECK_TYPE([struct _pthread_cleanup_buffer],[CW_CONFIG_HAVE__PTHREAD_CLEANUP_BUFFER=define],,[#include <pthread.h>]) fi dnl This test needs the full set of libraries we just determined. Index: src/libcwd/debug.cc diff -u src/libcwd/debug.cc:1.58 src/libcwd/debug.cc:1.59 --- src/libcwd/debug.cc:1.58 Sun Jan 20 19:20:24 2002 +++ src/libcwd/debug.cc Fri Jan 25 18:06:33 2002 @@ -1,4 +1,4 @@ -// $Header: /cvsroot/l/li/libcw/src/libcwd/debug.cc,v 1.58 2002/01/21 03:20:24 libcw Exp $ +// $Header: /cvsroot/l/li/libcw/src/libcwd/debug.cc,v 1.59 2002/01/26 02:06:33 libcw Exp $ // // Copyright (C) 2000 - 2001, by // @@ -1110,7 +1110,8 @@ #ifdef LIBCWD_THREAD_SAFE _private_::mutex_tct<_private_::write_max_len_instance>::initialize(); - _private_::mutex_tct<_private_::write_max_len_instance>::lock(); + _private_::cancel_buffer_t buffer; + _private_::mutex_tct<_private_::write_max_len_instance>::lock(buffer); #endif // MT: This is not strict thread safe because it is possible that after threads are already // running, a new shared library is dlopen-ed with a new global channel_ct with a larger @@ -1128,7 +1129,7 @@ static int next_index; WNS_index = ++next_index; // Don't use index 0, it is used to make sure that uninitialized channels appear to be off. - _private_::mutex_tct<_private_::write_max_len_instance>::unlock(); + _private_::mutex_tct<_private_::write_max_len_instance>::unlock(buffer); __libcwd_tsd.off_cnt_array[WNS_index] = 0; #else @@ -1187,13 +1188,14 @@ #ifdef LIBCWD_THREAD_SAFE _private_::mutex_tct<_private_::write_max_len_instance>::initialize(); - _private_::mutex_tct<_private_::write_max_len_instance>::lock(); + _private_::cancel_buffer_t buffer; + _private_::mutex_tct<_private_::write_max_len_instance>::lock(buffer); #endif // MT: See comment in channel_ct::NS_initialize above. if (label_len > WST_max_len) WST_max_len = label_len; #ifdef LIBCWD_THREAD_SAFE - _private_::mutex_tct<_private_::write_max_len_instance>::unlock(); + _private_::mutex_tct<_private_::write_max_len_instance>::unlock(buffer); #endif strncpy(WNS_label, label, label_len); Index: src/libcwd/include/libcw/debug_config.ho.in diff -u src/libcwd/include/libcw/debug_config.ho.in:1.15 src/libcwd/include/libcw/debug_config.ho.in:1.16 --- src/libcwd/include/libcw/debug_config.ho.in:1.15 Tue Jan 8 15:04:59 2002 +++ src/libcwd/include/libcw/debug_config.ho.in Fri Jan 25 18:06:33 2002 @@ -1,5 +1,5 @@ // @configure_input@ -// $Header: /cvsroot/l/li/libcw/src/libcwd/include/libcw/debug_config.ho.in,v 1.15 2002/01/08 23:04:59 libcw Exp $ +// $Header: /cvsroot/l/li/libcw/src/libcwd/include/libcw/debug_config.ho.in,v 1.16 2002/01/26 02:06:33 libcw Exp $ // // Copyright (C) 2000 - 2001, by // @@ -340,5 +340,6 @@ #@CW_CONFIG_THREAD_SAFE@ LIBCWD_THREAD_SAFE #@CW_CONFIG_HAVE_PTHREADS@ LIBCWD_HAVE_PTHREAD +#@CW_CONFIG_HAVE__PTHREAD_CLEANUP_BUFFER@ HAVE__PTHREAD_CLEANUP_BUFFER #endif // LIBCW_DEBUG_CONFIG_H Index: src/libcwd/include/libcw/macro_AllocTag.h diff -u src/libcwd/include/libcw/macro_AllocTag.h:1.4 src/libcwd/include/libcw/macro_AllocTag.h:1.5 --- src/libcwd/include/libcw/macro_AllocTag.h:1.4 Tue Jan 8 15:04:59 2002 +++ src/libcwd/include/libcw/macro_AllocTag.h Fri Jan 25 18:06:33 2002 @@ -1,4 +1,4 @@ -// $Header: /cvsroot/l/li/libcw/src/libcwd/include/libcw/macro_AllocTag.h,v 1.4 2002/01/08 23:04:59 libcw Exp $ +// $Header: /cvsroot/l/li/libcw/src/libcwd/include/libcw/macro_AllocTag.h,v 1.5 2002/01/26 02:06:33 libcw Exp $ // // Copyright (C) 2000 - 2001, by // @@ -148,11 +148,12 @@ set_alloc_label(p, ::libcw::debug::type_info_of(p), const_cast<char const*>(desc)) #ifdef LIBCWD_THREAD_SAFE -#define LIBCWD_LOCK_desc__if_still_NULL_then ::libcw::debug::_private_::\ - mutex_tct< ::libcw::debug::_private_::alloc_tag_desc_instance>::lock(); \ +#define LIBCWD_LOCK_desc__if_still_NULL_then \ + ::libcw::debug::_private_::cancel_buffer_t __libcwd_buffer; \ + ::libcw::debug::_private_::mutex_tct< ::libcw::debug::_private_::alloc_tag_desc_instance>::lock(__libcwd_buffer); \ if (!desc) -#define LIBCWD_UNLOCK_desc ::libcw::debug::_private_::\ - mutex_tct< ::libcw::debug::_private_::alloc_tag_desc_instance>::unlock(); +#define LIBCWD_UNLOCK_desc \ + ::libcw::debug::_private_::mutex_tct< ::libcw::debug::_private_::alloc_tag_desc_instance>::unlock(__libcwd_buffer); #else // !LIBCWD_THREAD_SAFE #define LIBCWD_LOCK_desc__if_still_NULL_then #define LIBCWD_UNLOCK_desc Index: src/libcwd/include/libcw/private_threading.h diff -u src/libcwd/include/libcw/private_threading.h:1.14 src/libcwd/include/libcw/private_threading.h:1.15 --- src/libcwd/include/libcw/private_threading.h:1.14 Fri Jan 25 08:45:05 2002 +++ src/libcwd/include/libcw/private_threading.h Fri Jan 25 18:06:33 2002 @@ -1,4 +1,4 @@ -// $Header: /cvsroot/l/li/libcw/src/libcwd/include/libcw/private_threading.h,v 1.14 2002/01/25 16:45:05 libcw Exp $ +// $Header: /cvsroot/l/li/libcw/src/libcwd/include/libcw/private_threading.h,v 1.15 2002/01/26 02:06:33 libcw Exp $ // // Copyright (C) 2001 - 2002, by // @@ -56,6 +56,7 @@ #ifndef LIBCWD_USE_LINUXTHREADS #define LIBCWD_USE_LINUXTHREADS 0 +#undef HAVE__PTHREAD_CLEANUP_BUFFER #endif #ifndef LIBCWD_USE_POSIX_THREADS #define LIBCWD_USE_POSIX_THREADS 0 @@ -98,19 +99,10 @@ #ifdef LIBCWD_THREAD_SAFE -#if LIBCWD_USE_LINUXTHREADS -#define LIBCWD_CLEANUP_PUSH_DEFER(routine, arg) pthread_cleanup_push_defer_np(routine, arg) -#define LIBCWD_CLEANUP_POP_DEFER(execute) pthread_cleanup_pop_defer_np(execute) -#elif LIBCWD_USE_POSIX_THREADS -#define LIBCWD_CLEANUP_PUSH_DEFER(routine, arg) \ - { \ - int __libcwd_oldtype; \ - pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, &__libcwd_oldtype); \ - pthread_cleanup_push(routine, arg); -#define LIBCWD_CLEANUP_POP_DEFER(execute) \ - pthread_cleanup_pop(execute); \ - pthread_setcanceltype(__libcwd_oldtype, NULL); \ - } +#if LIBCWD_USE_LINUXTHREADS && defined(HAVE__PTHREAD_CLEANUP_BUFFER) +#define LIBCWD_USE_PTHREAD_CLEANUP_BUFFER 1 +#else +#define LIBCWD_USE_PTHREAD_CLEANUP_BUFFER 0 #endif namespace libcw { @@ -162,13 +154,6 @@ // (using -O2 this is at most a single test and nothing at all when // Linuxthreads are being used. // -// Examples. -// -// mutex_tct<instance_id_const>::initialize(); -// if (mutex_tct<instance_id_const>::trylock()) ... -// mutex_tct<instance_id_const>::lock(); -// mutex_tct<instance_id_const>::unlock(); -// // The different instance-ids used in libcwd. enum mutex_instance_nt { @@ -203,6 +188,47 @@ __inline__ bool is_locked(int instance) { return instance_locked[instance] > 0; } #endif +#if LIBCWD_USE_PTHREAD_CLEANUP_BUFFER +typedef struct _pthread_cleanup_buffer cancel_buffer_t; + +__inline__ +void +cleanup_push_defer(int (*routine)(pthread_mutex_t*) throw(), pthread_mutex_t& mutex, cancel_buffer_t& buffer) +{ + _pthread_cleanup_push_defer (&(buffer), reinterpret_cast<void(*)(void*)>(routine), reinterpret_cast<void*>(&mutex)); +} + +__inline__ +void +cleanup_pop_restore(bool execute, cancel_buffer_t& buffer) +{ + _pthread_cleanup_pop_restore (&buffer, execute ? 1 : 0); +} + +#else // !LIBCWD_USE_PTHREAD_CLEANUP_BUFFER +typedef int cancel_buffer_t; + +__inline__ +void +cleanup_push_defer(int (*routine)(pthread_mutex_t*) throw(), pthread_mutex_t& mutex, cancel_buffer_t& buffer) +{ + pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, &buffer); + pthread_cleanup_push(reinterpret_cast<void(*)(void*)>(routine), reinterpret_cast<void*>(&mutex)); +} + +#if defined(pthread_cleanup_pop) && defined(pthread_cleanup_push) +#warning "If next you get a 'parse error before `{' token' error, then contact the author of libcwd to get your threads library supported." +#endif + +__inline__ +void +cleanup_pop_restore(bool execute, cancel_buffer_t& buffer) +{ + pthread_cleanup_pop(execute ? 1 : 0); + pthread_setcanceltype(buffer, NULL); +} +#endif // !LIBCWD_USE_PTHREAD_CLEANUP_BUFFER + #if LIBCWD_USE_POSIX_THREADS || LIBCWD_USE_LINUXTHREADS template <int instance> class mutex_tct { @@ -226,22 +252,24 @@ } #endif public: - static bool trylock(void) throw() + static bool trylock(cancel_buffer_t& buffer) throw() { -#ifndef DEBUGDEBUG - return (pthread_mutex_trylock(&S_mutex) == 0); -#else - bool res = (pthread_mutex_trylock(&S_mutex) == 0); - if (res) + cleanup_push_defer(pthread_mutex_unlock, S_mutex, buffer); + bool success = (pthread_mutex_trylock(&S_mutex) == 0); + if (!success) + cleanup_pop_restore(false, buffer); +#ifdef DEBUGDEBUG + else instance_locked[instance] += 1; - return res; #endif + return success; } - static void lock(void) throw() + static void lock(cancel_buffer_t& buffer) throw() { #if LIBCWD_DEBUGDEBUGRWLOCK if (instance != tsd_initialization_instance) LIBCWD_DEBUGDEBUGRWLOCK_CERR(pthread_self() << ": locking mutex " << instance); #endif + cleanup_push_defer(pthread_mutex_unlock, S_mutex, buffer); #if LIBCWD_DEBUGTHREADS int res = #endif @@ -256,21 +284,15 @@ instance_locked[instance] += 1; #endif } - static void unlock(void) throw() + static void unlock(cancel_buffer_t& buffer) throw() { #ifdef DEBUGDEBUG instance_locked[instance] -= 1; #endif #if LIBCWD_DEBUGDEBUGRWLOCK if (instance != tsd_initialization_instance) LIBCWD_DEBUGDEBUGRWLOCK_CERR(pthread_self() << ": unlocking mutex " << instance); -#endif -#if LIBCWD_DEBUGTHREADS - int res = #endif - pthread_mutex_unlock(&S_mutex); -#if LIBCWD_DEBUGTHREADS - assert( res == 0 ); -#endif + cleanup_pop_restore(true, buffer); #if LIBCWD_DEBUGDEBUGRWLOCK if (instance != tsd_initialization_instance) LIBCWD_DEBUGDEBUGRWLOCK_CERR(pthread_self() << ": mutex " << instance << " unlocked"); #endif @@ -281,12 +303,9 @@ template <int instance> void mutex_tct<instance>::S_initialize(void) throw() { - if (instance != mutex_initialization_instance) - { - mutex_tct<mutex_initialization_instance>::initialize(); - mutex_tct<mutex_initialization_instance>::lock(); - } - + mutex_tct<mutex_initialization_instance>::initialize(); + cancel_buffer_ct buffer; + mutex_tct<mutex_initialization_instance>::lock(buffer); if (!S_initialized) // Check again now that we are locked. { pthread_mutexattr_t mutex_attr; @@ -303,9 +322,21 @@ pthread_mutex_init(&S_mutex, &mutex_attr); S_initialized = true; } - if (instance != mutex_initialization_instance) - mutex_tct<mutex_initialization_instance>::unlock(); + mutex_tct<mutex_initialization_instance>::unlock(buffer); } + +template <> + void mutex_tct<mutex_initialization_instance>::S_initialize(void) throw() + { + pthread_mutexattr_t mutex_attr; +#if LIBCWD_DEBUGTHREADS + pthread_mutexattr_settype(&mutex_attr, PTHREAD_MUTEX_ERRORCHECK); +#else + pthread_mutexattr_settype(&mutex_attr, PTHREAD_MUTEX_NORMAL); +#endif + pthread_mutex_init(&S_mutex, &mutex_attr); + S_initialized = true; + } #endif // !LIBCWD_USE_LINUXTHREADS #if !LIBCWD_USE_LINUXTHREADS @@ -369,15 +400,14 @@ void cond_tct<instance>::S_initialize(void) throw() { mutex_tct<mutex_initialization_instance>::initialize(); - mutex_tct<mutex_initialization_instance>::lock(); - + cancel_buffer_t buffer; + mutex_tct<mutex_initialization_instance>::lock(buffer); if (!S_initialized) // Check again now that we are locked. { pthread_cond_init(&S_condition, NULL); S_initialized = true; } - - mutex_tct<mutex_initialization_instance>::unlock(); + mutex_tct<mutex_initialization_instance>::unlock(buffer); } #endif // !LIBCWD_USE_LINUXTHREADS @@ -454,12 +484,13 @@ return; // No error checking is done. } // Give a writer a higher priority (kinda fuzzy). - if (S_writer_is_waiting || !S_cond_no_holders.trylock()) + cancel_buffer_t buffer; + if (S_writer_is_waiting || !S_cond_no_holders.trylock(buffer)) return false; bool success = (S_holders_count != -1); if (success) ++S_holders_count; // Add one reader. - S_cond_no_holders.unlock(); + S_cond_no_holders.unlock(buffer); LIBCWD_DEBUGDEBUGRWLOCK_CERR(pthread_self() << ": Leaving rwlock_tct<" << instance << ">::tryrdlock()"); return success; } @@ -469,24 +500,25 @@ assert(S_initialized); #endif LIBCWD_DEBUGDEBUGRWLOCK_CERR(pthread_self() << ": Calling rwlock_tct<" << instance << ">::trywrlock()"); - bool success; - success = mutex_tct<readers_instance>::trylock(); // Block new readers, + cancel_buffer_t buffer; + bool success = mutex_tct<readers_instance>::trylock(buffer); // Block new readers, while (success) { - S_writer_is_waiting = true; // from this moment on. - if (!S_cond_no_holders.trylock()) + S_writer_is_waiting = true; // from this moment on. + cancel_buffer_t buffer2; + if (!S_cond_no_holders.trylock(buffer2)) { S_writer_is_waiting = false; - mutex_tct<readers_instance>::unlock(); + mutex_tct<readers_instance>::unlock(buffer); success = false; break; } while (S_holders_count != 0) // Other readers or writers have this lock? S_cond_no_holders.wait(); // Wait until all current holders are done. S_writer_is_waiting = false; // Stop checking the lock for new readers. - mutex_tct<readers_instance>::unlock(); // Release blocked readers. + mutex_tct<readers_instance>::unlock(buffer); // Release blocked readers. S_holders_count = -1; // Mark that we have a writer. - S_cond_no_holders.unlock(); + S_cond_no_holders.unlock(buffer2); if (instance < end_recursive_types) S_writer_id = pthread_self(); } @@ -507,14 +539,16 @@ // Give a writer a higher priority (kinda fuzzy). if (S_writer_is_waiting) // If there is a writer interested, { - mutex_tct<readers_instance>::lock(); // then give it precedence and wait here. - mutex_tct<readers_instance>::unlock(); + cancel_buffer_t buffer; + mutex_tct<readers_instance>::lock(buffer); // then give it precedence and wait here. + mutex_tct<readers_instance>::unlock(buffer); } - S_cond_no_holders.lock(); + cancel_buffer_t buffer2; + S_cond_no_holders.lock(buffer2); while (S_holders_count == -1) // Writer locked it? S_cond_no_holders.wait(); // Wait for writer to finish. ++S_holders_count; // Add one reader. - S_cond_no_holders.unlock(); + S_cond_no_holders.unlock(buffer2); LIBCWD_DEBUGDEBUGRWLOCK_CERR(pthread_self() << ": Leaving rwlock_tct<" << instance << ">::rdlock()"); } static void rdunlock(void) throw() @@ -525,10 +559,11 @@ LIBCWD_DEBUGDEBUGRWLOCK_CERR(pthread_self() << ": Leaving rwlock_tct<" << instance << ">::rdunlock() (skipped: thread has write lock)"); return; // No error checking is done. } - S_cond_no_holders.lock(); + cancel_buffer_t buffer; + S_cond_no_holders.lock(buffer); if (--S_holders_count == 0) // Was this the last reader? S_cond_no_holders.signal(); // Tell waiting threads. - S_cond_no_holders.unlock(); + S_cond_no_holders.unlock(buffer); LIBCWD_DEBUGDEBUGRWLOCK_CERR(pthread_self() << ": Leaving rwlock_tct<" << instance << ">::rdunlock()"); } static void wrlock(void) throw() @@ -537,15 +572,17 @@ assert(S_initialized); #endif LIBCWD_DEBUGDEBUGRWLOCK_CERR(pthread_self() << ": Calling rwlock_tct<" << instance << ">::wrlock()"); - mutex_tct<readers_instance>::lock(); // Block new readers, + cancel_buffer_t buffer; + mutex_tct<readers_instance>::lock(buffer); // Block new readers, S_writer_is_waiting = true; // from this moment on. - S_cond_no_holders.lock(); + cancel_buffer_t buffer2; + S_cond_no_holders.lock(buffer2); while (S_holders_count != 0) // Other readers or writers have this lock? S_cond_no_holders.wait(); // Wait until all current holders are done. S_writer_is_waiting = false; // Stop checking the lock for new readers. - mutex_tct<readers_instance>::unlock(); // Release blocked readers. + mutex_tct<readers_instance>::unlock(buffer); // Release blocked readers. S_holders_count = -1; // Mark that we have a writer. - S_cond_no_holders.unlock(); + S_cond_no_holders.unlock(buffer2); if (instance < end_recursive_types) S_writer_id = pthread_self(); LIBCWD_DEBUGDEBUGRWLOCK_CERR(pthread_self() << ": Leaving rwlock_tct<" << instance << ">::wrlock()"); @@ -561,27 +598,30 @@ LIBCWD_DEBUGDEBUGRWLOCK_CERR(pthread_self() << ": Calling rwlock_tct<" << instance << ">::wrunlock()"); if (instance < end_recursive_types) S_writer_id = 0; - S_cond_no_holders.lock(); + cancel_buffer_t buffer; + S_cond_no_holders.lock(buffer); S_holders_count = 0; // We have no writer anymore. S_cond_no_holders.signal(); // No readers and no writers left. - S_cond_no_holders.unlock(); + S_cond_no_holders.unlock(buffer); LIBCWD_DEBUGDEBUGRWLOCK_CERR(pthread_self() << ": Leaving rwlock_tct<" << instance << ">::wrunlock()"); } static void rd2wrlock() throw() { LIBCWD_DEBUGDEBUGRWLOCK_CERR(pthread_self() << ": Calling rwlock_tct<" << instance << ">::rd2wrlock()"); - S_cond_no_holders.lock(); + cancel_buffer_t buffer2; + S_cond_no_holders.lock(buffer2); if (--S_holders_count > 0) { - mutex_tct<readers_instance>::lock(); // Block new readers. + cancel_buffer_t buffer; + mutex_tct<readers_instance>::lock(buffer); // Block new readers. S_writer_is_waiting = true; while (S_holders_count != 0) S_cond_no_holders.wait(); S_writer_is_waiting = false; - mutex_tct<readers_instance>::unlock(); // Release blocked readers. + mutex_tct<readers_instance>::unlock(buffer); // Release blocked readers. } S_holders_count = -1; // We are a writer now. - S_cond_no_holders.unlock(); + S_cond_no_holders.unlock(buffer2); if (instance < end_recursive_types) S_writer_id = pthread_self(); LIBCWD_DEBUGDEBUGRWLOCK_CERR(pthread_self() << ": Leaving rwlock_tct<" << instance << ">::rd2wrlock()"); @@ -664,10 +704,11 @@ TSD* thread_specific_data_tct<TSD>::S_initialize(void) throw() { pthread_once(&S_key_once, S_alloc_key); - mutex_tct<tsd_initialization_instance>::lock(); + cancel_buffer_t cancel_buffer; + mutex_tct<tsd_initialization_instance>::lock(cancel_buffer); if (S_initializing) { - mutex_tct<tsd_initialization_instance>::unlock(); + mutex_tct<tsd_initialization_instance>::unlock(cancel_buffer); return S_temporary_instance; } char new_TSD_space[sizeof(TSD)]; // Allocate space on the stack. @@ -685,7 +726,7 @@ std::memcpy((void*)instance, new_TSD_space, sizeof(TSD)); // Put the temporary TSD in its final place. S_initializing = false; S_initialized = true; - mutex_tct<tsd_initialization_instance>::unlock(); + mutex_tct<tsd_initialization_instance>::unlock(cancel_buffer); if (WST_multi_threaded) // Is this a second (or later) thread? debug_tsd_init(); // Initialize the TSD of existing debug objects. return instance; Index: src/libcwd/include/libcw/type_info.h diff -u src/libcwd/include/libcw/type_info.h:1.16 src/libcwd/include/libcw/type_info.h:1.17 --- src/libcwd/include/libcw/type_info.h:1.16 Tue Jan 8 15:04:59 2002 +++ src/libcwd/include/libcw/type_info.h Fri Jan 25 18:06:33 2002 @@ -1,4 +1,4 @@ -// $Header: /cvsroot/l/li/libcw/src/libcwd/include/libcw/type_info.h,v 1.16 2002/01/08 23:04:59 libcw Exp $ +// $Header: /cvsroot/l/li/libcw/src/libcwd/include/libcw/type_info.h,v 1.17 2002/01/26 02:06:33 libcw Exp $ // // Copyright (C) 2000 - 2001, by // @@ -220,10 +220,11 @@ { #ifdef LIBCWD_THREAD_SAFE volatile static bool spin_lock = false; - _private_::mutex_tct<_private_::type_info_of_instance>::lock(); + _private_::cancel_buffer_t buffer; + _private_::mutex_tct<_private_::type_info_of_instance>::lock(buffer); while(spin_lock); spin_lock = true; - _private_::mutex_tct<_private_::type_info_of_instance>::unlock(); + _private_::mutex_tct<_private_::type_info_of_instance>::unlock(buffer); if (::libcwd_type_info_exact<T>::value_c.size() == 0) // Recheck now that we acquired the lock. #endif { ----------------------- End of diff ----------------------- |
From: Carlo W. <li...@us...> - 2002-01-31 04:42:21
|
CVSROOT : /cvsroot/libcw Module : src Commit time: 2002-00-31 04:42:19 UTC Modified files: libcwd/Makefile.am libcwd/bfd.cc libcwd/debug.cc libcwd/debugmalloc.cc libcwd/elf32.cc libcwd/threading.cc libcwd/include/raw_write.h libcwd/include/libcw/macro_AllocTag.h libcwd/include/libcw/macro_ForAllDebugChannels.h libcwd/include/libcw/macro_ForAllDebugObjects.h libcwd/include/libcw/private_struct_TSD.h libcwd/include/libcw/private_threading.h libcwd/include/libcw/type_info.h libcwd/tests/threads4.cc Log message: Set the cancel type to deferred at the start of any lock, and restore it when unlocking. Make sure that pthread_setcanceltype isn't called with `internal' set. Moved the location lookup inside realloc outside the critical area. ---------------------- diff included ---------------------- Index: src/libcwd/Makefile.am diff -u src/libcwd/Makefile.am:1.43 src/libcwd/Makefile.am:1.44 --- src/libcwd/Makefile.am:1.43 Thu Jan 24 13:16:09 2002 +++ src/libcwd/Makefile.am Wed Jan 30 20:42:08 2002 @@ -27,7 +27,8 @@ demangle.cc \ demangle3.cc \ strerrno.cc \ - type_info.cc + type_info.cc \ + wrapcnclpnts.c libcwd_la_LDFLAGS = -version-info $(VERSIONINFO) $(LIB_THREADS_SHARED) Index: src/libcwd/bfd.cc diff -u src/libcwd/bfd.cc:1.95 src/libcwd/bfd.cc:1.96 --- src/libcwd/bfd.cc:1.95 Fri Jan 25 18:06:33 2002 +++ src/libcwd/bfd.cc Wed Jan 30 20:42:08 2002 @@ -1,4 +1,4 @@ -// $Header: /cvsroot/l/li/libcw/src/libcwd/bfd.cc,v 1.95 2002/01/26 02:06:33 libcw Exp $ +// $Header: /cvsroot/l/li/libcw/src/libcwd/bfd.cc,v 1.96 2002/01/31 04:42:08 libcw Exp $ // // Copyright (C) 2000 - 2001, by // @@ -66,7 +66,6 @@ #ifdef LIBCWD_THREAD_SAFE using libcw::debug::_private_::rwlock_tct; using libcw::debug::_private_::mutex_tct; -using libcw::debug::_private_::cancel_buffer_t; using libcw::debug::_private_::object_files_instance; using libcw::debug::_private_::dlopen_map_instance; #define BFD_INITIALIZE_LOCK rwlock_tct<object_files_instance>::initialize(); @@ -76,8 +75,8 @@ #define BFD_RELEASE_READ_LOCK rwlock_tct<object_files_instance>::rdunlock(); #define BFD_ACQUIRE_READ2WRITE_LOCK rwlock_tct<object_files_instance>::rd2wrlock(); #define BFD_ACQUIRE_WRITE2READ_LOCK rwlock_tct<object_files_instance>::wr2rdlock(); -#define DLOPEN_MAP_ACQUIRE_LOCK cancel_buffer_t buffer; mutex_tct<dlopen_map_instance>::lock(buffer); -#define DLOPEN_MAP_RELEASE_LOCK mutex_tct<dlopen_map_instance>::unlock(buffer); +#define DLOPEN_MAP_ACQUIRE_LOCK LIBCWD_DEFER_PUSH_LOCKMUTEX(dlopen_map_instance, &mutex_tct<dlopen_map_instance>::unlock); +#define DLOPEN_MAP_RELEASE_LOCK LIBCWD_UNLOCKMUTEX_POP_RESTORE(dlopen_map_instance) #else // !LIBCWD_THREAD_SAFE #define BFD_INITIALIZE_LOCK #define BFD_ACQUIRE_WRITE_LOCK @@ -1013,8 +1012,17 @@ // but the sanity checks inside the allocators used in load_object_file() // require the lock to be set. Fortunately is therefore also doesn't hurt // that we keep the lock a long time (during the execution of ldd_prog). + // Same thing for the LIBCWD_DEFER_CANCEL, needed for the sanity checks. + // However - here we have another sanity check that controls if we aren't + // setting the cancel state too often (recursively), and in *this* case + // that is unavoidable. Therefore we decrement these sanity check counters + // in order to fool the check, right after we set the lock. BFD_INITIALIZE_LOCK + LIBCWD_DEFER_CANCEL BFD_ACQUIRE_WRITE_LOCK +#if LIBCWD_DEBUGTHREADS + --__libcwd_tsd.cancel_explicitely_deferred; +#endif load_object_file(fullpath.value->data(), 0); // Load all shared objects @@ -1041,8 +1049,18 @@ load_object_file(l->l_name, reinterpret_cast<void*>(l->l_addr)); } NEEDS_WRITE_LOCK_object_files().sort(object_file_greater()); +#if LIBCWD_DEBUGTHREADS + ++__libcwd_tsd.cancel_explicitely_deferred; +#endif BFD_RELEASE_WRITE_LOCK + set_alloc_checking_on(LIBCWD_TSD); + // End INTERNAL! + // **************************************************************************** + + // We put this outside the 'internal' region because it might call __pthread_do_exit. + LIBCWD_RESTORE_CANCEL + #ifdef ALWAYS_PRINT_LOADING Debug( dc::bfd.restore(state2) ); Debug( libcw_do.restore(state) ); @@ -1050,10 +1068,6 @@ WST_initialized = true; // MT: Safe, this function is Single Threaded. - set_alloc_checking_on(LIBCWD_TSD); - // End INTERNAL! - // **************************************************************************** - #ifdef DEBUGDEBUGBFD // Dump all symbols for (object_files_ct::reverse_iterator i(object_files().rbegin()); i != object_files().rend(); ++i) @@ -1112,9 +1126,12 @@ && !ST_init()) return unknown_function_c; + symbol_ct const* symbol; + LIBCWD_DEFER_CANCEL BFD_ACQUIRE_READ_LOCK; - symbol_ct const* symbol = pc_symbol((bfd_vma)(size_t)addr, NEEDS_READ_LOCK_find_object_file(addr)); + symbol = pc_symbol((bfd_vma)(size_t)addr, NEEDS_READ_LOCK_find_object_file(addr)); BFD_RELEASE_READ_LOCK; + LIBCWD_RESTORE_CANCEL if (!symbol) return unknown_function_c; @@ -1177,8 +1194,10 @@ } } + object_file_ct* object_file; + LIBCWD_DEFER_CANCEL BFD_ACQUIRE_READ_LOCK; - object_file_ct* object_file = NEEDS_READ_LOCK_find_object_file(addr); + object_file = NEEDS_READ_LOCK_find_object_file(addr); #ifdef HAVE__DL_LOADED if (!object_file) { @@ -1211,6 +1230,7 @@ #else BFD_RELEASE_READ_LOCK; #endif + LIBCWD_RESTORE_CANCEL if (!object_file) { LIBCWD_Dout(dc::bfd, "No object file for address " << addr); @@ -1227,6 +1247,7 @@ asection const* sect = bfd_get_section(p); char const* file; LIBCWD_ASSERT( object_file->get_bfd() == abfd ); + LIBCWD_DEFER_CANCEL set_alloc_checking_off(LIBCWD_TSD); #ifdef DEBUGUSEGNULIBBFD bfd_find_nearest_line(abfd, const_cast<asection*>(sect), const_cast<asymbol**>(object_file->get_symbol_table()), @@ -1235,6 +1256,7 @@ abfd->find_nearest_line(p, (char*)addr - (char*)object_file->get_lbase(), &file, &M_func, &M_line); #endif set_alloc_checking_on(LIBCWD_TSD); + LIBCWD_RESTORE_CANCEL LIBCWD_ASSERT( !(M_func && !p->name) ); // Please inform the author of libcwd if this assertion fails. M_func = p->name; @@ -1436,6 +1458,7 @@ return handle; #endif set_alloc_checking_off(LIBCWD_TSD); + LIBCWD_DEFER_CANCEL_NO_BRACE BFD_ACQUIRE_WRITE_LOCK; cwbfd::object_file_ct* object_file = cwbfd::load_object_file(name, cwbfd::unknown_l_addr); set_alloc_checking_on(LIBCWD_TSD); @@ -1443,15 +1466,26 @@ { set_alloc_checking_off(LIBCWD_TSD); cwbfd::NEEDS_WRITE_LOCK_object_files().sort(cwbfd::object_file_greater()); - BFD_RELEASE_WRITE_LOCK; set_alloc_checking_on(LIBCWD_TSD); + BFD_RELEASE_WRITE_LOCK; + LIBCWD_RESTORE_CANCEL_NO_BRACE + // MT: dlopen_map uses a userspace_allocator and might therefore write to dc::malloc. + // This means that the thread can be cancelled inside the insert() call, leaving + // dlopen_map in an undefined state. Therefore we disable cancellation. + LIBCWD_DISABLE_CANCEL DLOPEN_MAP_ACQUIRE_LOCK; libcw::debug::_private_::dlopen_map.insert(std::pair<void* const, dlloaded_st>(handle, dlloaded_st(object_file, flags))); +#ifdef LIBCWD_THREAD_SAFE DLOPEN_MAP_RELEASE_LOCK; + // If the thread is cancelled next, then we don't need to take action regarding dlopen_map: + // The shared library will state loaded. + LIBCWD_ENABLE_CANCEL +#endif } else { BFD_RELEASE_WRITE_LOCK; + LIBCWD_RESTORE_CANCEL_NO_BRACE } return handle; } @@ -1462,6 +1496,7 @@ LIBCWD_ASSERT( !__libcwd_tsd.internal ); int ret = ::dlclose(handle); DLOPEN_MAP_ACQUIRE_LOCK; + // MT: Cancellation is defered at this point. The first cancellation point is in DLOPEN_MAP_RELEASE_LOCK. libcw::debug::_private_::dlopen_map_ct::iterator iter(libcw::debug::_private_::dlopen_map.find(handle)); if (iter != libcw::debug::_private_::dlopen_map.end()) { @@ -1473,9 +1508,19 @@ set_alloc_checking_on(LIBCWD_TSD); } #endif +#ifdef LIBCWD_THREAD_SAFE + // MT: dlopen_map uses a userspace_allocator and might therefore write to dc::malloc. + // This means that the thread can be cancelled inside the erase() call, leaving + // dlopen_map in an undefined state. Therefore we disable cancellation. + int oldstate; + pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &oldstate); +#endif libcw::debug::_private_::dlopen_map.erase(iter); - DLOPEN_MAP_RELEASE_LOCK; +#ifdef LIBCWD_THREAD_SAFE + pthread_setcancelstate(oldstate, NULL); +#endif } + DLOPEN_MAP_RELEASE_LOCK; return ret; } } // extern "C" Index: src/libcwd/debug.cc diff -u src/libcwd/debug.cc:1.59 src/libcwd/debug.cc:1.60 --- src/libcwd/debug.cc:1.59 Fri Jan 25 18:06:33 2002 +++ src/libcwd/debug.cc Wed Jan 30 20:42:08 2002 @@ -1,4 +1,4 @@ -// $Header: /cvsroot/l/li/libcw/src/libcwd/debug.cc,v 1.59 2002/01/26 02:06:33 libcw Exp $ +// $Header: /cvsroot/l/li/libcw/src/libcwd/debug.cc,v 1.60 2002/01/31 04:42:08 libcw Exp $ // // Copyright (C) 2000 - 2001, by // @@ -300,20 +300,20 @@ debug_objects_ct debug_objects; // List with all debug devices. // _private_:: - void debug_channels_ct::init(void) + void debug_channels_ct::internal_init(LIBCWD_TSD_PARAM) { +#ifdef DEBUGDEBUGMALLOC + LIBCWD_ASSERT( __libcwd_tsd.internal ); +#endif #ifdef LIBCWD_THREAD_SAFE _private_::rwlock_tct<_private_::debug_channels_instance>::initialize(); #endif DEBUG_CHANNELS_ACQUIRE_READ_LOCK if (!WNS_debug_channels) // MT: `WNS_debug_channels' is only false when this object is still Non_Shared. { - LIBCWD_TSD_DECLARATION - set_alloc_checking_off(LIBCWD_TSD); DEBUG_CHANNELS_ACQUIRE_READ2WRITE_LOCK WNS_debug_channels = new debug_channels_ct::container_type; DEBUG_CHANNELS_RELEASE_WRITE_LOCK - set_alloc_checking_on(LIBCWD_TSD); } #ifdef LIBCWD_THREAD_SAFE else @@ -340,7 +340,7 @@ #endif // _private_:: - void debug_objects_ct::init(void) + void debug_objects_ct::internal_init(LIBCWD_TSD_PARAM) { #ifdef LIBCWD_THREAD_SAFE _private_::rwlock_tct<_private_::debug_objects_instance>::initialize(); @@ -353,12 +353,9 @@ // It is possible that malloc is not initialized yet. init_debugmalloc(); #endif - LIBCWD_TSD_DECLARATION - set_alloc_checking_off(LIBCWD_TSD); DEBUG_OBJECTS_ACQUIRE_READ2WRITE_LOCK WNS_debug_objects = new debug_objects_ct::container_type; DEBUG_OBJECTS_RELEASE_WRITE_LOCK - set_alloc_checking_on(LIBCWD_TSD); } #ifdef LIBCWD_THREAD_SAFE else @@ -880,14 +877,20 @@ #endif LIBCWD_TSD_DECLARATION + LIBCWD_DEFER_CANCEL set_alloc_checking_off(LIBCWD_TSD); // debug_objects is internal. - _private_::debug_objects.init(); + _private_::debug_objects.internal_init(LIBCWD_TSD); DEBUG_OBJECTS_ACQUIRE_WRITE_LOCK if (find(_private_::debug_objects.write_locked().begin(), _private_::debug_objects.write_locked().end(), this) == _private_::debug_objects.write_locked().end()) // Not added before? _private_::debug_objects.write_locked().push_back(this); DEBUG_OBJECTS_RELEASE_WRITE_LOCK +#ifdef LIBCWD_THREAD_SAFE + set_alloc_checking_on(LIBCWD_TSD); + LIBCWD_RESTORE_CANCEL + set_alloc_checking_off(LIBCWD_TSD); // debug_objects is internal. +#endif new (_private_::WST_dummy_laf) laf_ct(0, channels::dc::debug.get_label(), 0); // Leaks 24 bytes of memory #ifndef LIBCWD_THREAD_SAFE tsd.init(); @@ -964,9 +967,8 @@ } namespace _private_ { - void debug_tsd_init(void) + void debug_tsd_init(LIBCWD_TSD_PARAM) { - LIBCWD_TSD_DECLARATION ForAllDebugObjects( set_alloc_checking_off(LIBCWD_TSD); LIBCWD_DO_TSD(debugObject).init(); @@ -1006,6 +1008,7 @@ init_magic = 0; #endif LIBCWD_TSD_DECLARATION + LIBCWD_DEFER_CANCEL set_alloc_checking_off(LIBCWD_TSD); DEBUG_OBJECTS_ACQUIRE_WRITE_LOCK { @@ -1016,6 +1019,7 @@ } DEBUG_OBJECTS_RELEASE_WRITE_LOCK set_alloc_checking_on(LIBCWD_TSD); + LIBCWD_RESTORE_CANCEL } /** @@ -1031,7 +1035,11 @@ channel_ct* find_channel(char const* label) { channel_ct* tmp = NULL; - _private_::debug_channels.init(); + LIBCWD_TSD_DECLARATION + LIBCWD_DEFER_CANCEL + set_alloc_checking_off(LIBCWD_TSD); + _private_::debug_channels.internal_init(LIBCWD_TSD); + set_alloc_checking_on(LIBCWD_TSD); DEBUG_CHANNELS_ACQUIRE_READ_LOCK for(_private_::debug_channels_ct::container_type::const_iterator i(_private_::debug_channels.read_locked().begin()); i != _private_::debug_channels.read_locked().end(); ++i) @@ -1040,6 +1048,7 @@ tmp = (*i); } DEBUG_CHANNELS_RELEASE_READ_LOCK + LIBCWD_RESTORE_CANCEL return tmp; } @@ -1077,7 +1086,10 @@ LIBCWD_TSD_DECLARATION if (LIBCWD_DO_TSD_MEMBER(debug_object, _off) < 0) { - _private_::debug_channels.init(); + LIBCWD_DEFER_CANCEL + set_alloc_checking_off(LIBCWD_TSD); + _private_::debug_channels.internal_init(LIBCWD_TSD); + set_alloc_checking_on(LIBCWD_TSD); DEBUG_CHANNELS_ACQUIRE_READ_LOCK for(_private_::debug_channels_ct::container_type::const_iterator i(_private_::debug_channels.read_locked().begin()); i != _private_::debug_channels.read_locked().end(); ++i) @@ -1091,6 +1103,7 @@ LibcwDoutScopeEnd; } DEBUG_CHANNELS_RELEASE_READ_LOCK + LIBCWD_RESTORE_CANCEL } } @@ -1108,10 +1121,20 @@ if (label_len > max_label_len_c) // Only happens for customized channels DoutFatal( dc::core, "strlen(\"" << label << "\") > " << max_label_len_c ); + LIBCWD_TSD_DECLARATION + #ifdef LIBCWD_THREAD_SAFE _private_::mutex_tct<_private_::write_max_len_instance>::initialize(); - _private_::cancel_buffer_t buffer; - _private_::mutex_tct<_private_::write_max_len_instance>::lock(buffer); + LIBCWD_DEFER_CANCEL + _private_::mutex_tct<_private_::write_max_len_instance>::lock(); + // MT: This critical area does not contain cancellation points. + // When this thread is cancelled later, there is no need to take action: + // the debug channel is global and can be used by any thread. We want + // to keep the maximum label length as set by this channel. Even when + // this debug channel is part of shared library that is being loaded + // by dlopen() then it won't get removed when this thread is cancelled. + // (Actually, a downwards update of WST_max_len should be done by + // dlclose if at all). #endif // MT: This is not strict thread safe because it is possible that after threads are already // running, a new shared library is dlopen-ed with a new global channel_ct with a larger @@ -1122,14 +1145,14 @@ if (label_len > WST_max_len) WST_max_len = label_len; - LIBCWD_TSD_DECLARATION #ifdef LIBCWD_THREAD_SAFE // MT: Take advantage of the `write_max_len_instance' lock to prefend simultaneous access // to `next_index' in the case of simultaneously dlopen-loaded libraries. static int next_index; WNS_index = ++next_index; // Don't use index 0, it is used to make sure that uninitialized channels appear to be off. - _private_::mutex_tct<_private_::write_max_len_instance>::unlock(buffer); + _private_::mutex_tct<_private_::write_max_len_instance>::unlock(); + LIBCWD_RESTORE_CANCEL __libcwd_tsd.off_cnt_array[WNS_index] = 0; #else @@ -1143,8 +1166,9 @@ // order in which they appear in the ForAllDebugChannels is not // dependent on the order in which these global objects are // initialized. + LIBCWD_DEFER_CANCEL set_alloc_checking_off(LIBCWD_TSD); // debug_channels is internal. - _private_::debug_channels.init(); + _private_::debug_channels.internal_init(LIBCWD_TSD); DEBUG_CHANNELS_ACQUIRE_WRITE_LOCK { _private_::debug_channels_ct::container_type& channels(_private_::debug_channels.write_locked()); @@ -1156,6 +1180,7 @@ } DEBUG_CHANNELS_RELEASE_WRITE_LOCK set_alloc_checking_on(LIBCWD_TSD); + LIBCWD_RESTORE_CANCEL // Turn debug channel "WARNING" on by default. if (strncmp(WNS_label, "WARNING", label_len) == 0) @@ -1188,14 +1213,15 @@ #ifdef LIBCWD_THREAD_SAFE _private_::mutex_tct<_private_::write_max_len_instance>::initialize(); - _private_::cancel_buffer_t buffer; - _private_::mutex_tct<_private_::write_max_len_instance>::lock(buffer); + LIBCWD_DEFER_CANCEL + _private_::mutex_tct<_private_::write_max_len_instance>::lock(); #endif - // MT: See comment in channel_ct::NS_initialize above. + // MT: See comments in channel_ct::NS_initialize above. if (label_len > WST_max_len) WST_max_len = label_len; #ifdef LIBCWD_THREAD_SAFE - _private_::mutex_tct<_private_::write_max_len_instance>::unlock(buffer); + _private_::mutex_tct<_private_::write_max_len_instance>::unlock(); + LIBCWD_RESTORE_CANCEL #endif strncpy(WNS_label, label, label_len); Index: src/libcwd/debugmalloc.cc diff -u src/libcwd/debugmalloc.cc:1.76 src/libcwd/debugmalloc.cc:1.77 --- src/libcwd/debugmalloc.cc:1.76 Tue Jan 22 20:03:44 2002 +++ src/libcwd/debugmalloc.cc Wed Jan 30 20:42:08 2002 @@ -1,4 +1,4 @@ -// $Header: /cvsroot/l/li/libcw/src/libcwd/debugmalloc.cc,v 1.76 2002/01/23 04:03:44 libcw Exp $ +// $Header: /cvsroot/l/li/libcw/src/libcwd/debugmalloc.cc,v 1.77 2002/01/31 04:42:08 libcw Exp $ // // Copyright (C) 2000 - 2001, by // @@ -173,7 +173,6 @@ #ifdef LIBCWD_THREAD_SAFE using libcw::debug::_private_::rwlock_tct; using libcw::debug::_private_::memblk_map_instance; -#define INITIALIZE_RWLOCK rwlock_tct<memblk_map_instance>::initialize(); #define ACQUIRE_WRITE_LOCK rwlock_tct<memblk_map_instance>::wrlock(); #define RELEASE_WRITE_LOCK rwlock_tct<memblk_map_instance>::wrunlock(); #define ACQUIRE_READ_LOCK rwlock_tct<memblk_map_instance>::rdlock(); @@ -181,7 +180,6 @@ #define ACQUIRE_READ2WRITE_LOCK rwlock_tct<memblk_map_instance>::rd2wrlock(); #define ACQUIRE_WRITE2READ_LOCK rwlock_tct<memblk_map_instance>::wr2rdlock(); #else // !LIBCWD_THREAD_SAFE -#define INITIALIZE_RWLOCK #define ACQUIRE_WRITE_LOCK #define RELEASE_WRITE_LOCK #define ACQUIRE_READ_LOCK @@ -1241,26 +1239,40 @@ --LIBCWD_DO_TSD_MEMBER(libcw_do, _off); #endif +#ifdef DEBUGDEBUGMALLOC + bool error; +#endif + memblk_info_ct* memblk_info; + + LIBCWD_DEFER_CANCEL + DEBUGDEBUG_CERR( "internal_malloc: internal == " << __libcwd_tsd.internal << "; setting it to 1." ); __libcwd_tsd.internal = 1; // Update our administration: ACQUIRE_WRITE_LOCK - memblk_ct memblk(memblk_key_ct(mptr, size), memblk_info_ct(mptr, size, flag)); // MT: memblk_info_ct() needs wrlock. - std::pair<memblk_map_ct::iterator, bool> const& iter(memblk_map_write->insert(memblk)); + std::pair<memblk_map_ct::iterator, bool> const& + iter(memblk_map_write->insert(memblk_ct(memblk_key_ct(mptr, size), memblk_info_ct(mptr, size, flag)))); + memblk_info = &(*iter.first).second; +#ifdef DEBUGDEBUGMALLOC + error = !iter.second; +#endif RELEASE_WRITE_LOCK DEBUGDEBUG_CERR( "internal_malloc: internal == " << __libcwd_tsd.internal << "; setting it to 0." ); __libcwd_tsd.internal = 0; + LIBCWD_RESTORE_CANCEL + +#ifdef DEBUGDEBUGMALLOC // MT-safe: iter points to an element that is garanteed unique to this thread (we just allocated it). - if (!iter.second) + if (error) DoutFatalInternal( dc::core, "memblk_map corrupt: Newly allocated block collides with existing memblk!" ); +#endif - memblk_info_ct& memblk_info((*iter.first).second); - memblk_info.lock(); // Lock ownership (doesn't call malloc). + memblk_info->lock(); // Lock ownership (doesn't call malloc). #ifdef DEBUGUSEBFD - memblk_info.get_alloc_node()->location_reference().move(loc); + memblk_info->get_alloc_node()->location_reference().move(loc); #endif #if defined(DEBUGDEBUGMALLOC) && defined(DEBUGDEBUGOUTPUT) @@ -1354,11 +1366,13 @@ return; } + LIBCWD_DEFER_CANCEL_NO_BRACE ACQUIRE_READ_LOCK memblk_map_ct::const_iterator const& iter(memblk_map_read->find(memblk_key_ct(ptr, 0))); if (iter == memblk_map_read->end() || (*iter).first.start() != ptr) { RELEASE_READ_LOCK + LIBCWD_RESTORE_CANCEL_NO_BRACE #ifdef DEBUGMAGICMALLOC if (((size_t*)ptr)[-2] == INTERNAL_MAGIC_NEW_BEGIN || ((size_t*)ptr)[-2] == INTERNAL_MAGIC_NEW_ARRAY_BEGIN || @@ -1442,6 +1456,8 @@ DEBUGDEBUG_CERR( "__libcwd_free: internal == " << __libcwd_tsd.internal << "; setting it to 0." ); __libcwd_tsd.internal = 0; + LIBCWD_RESTORE_CANCEL_NO_BRACE + #ifdef DEBUGMAGICMALLOC if (f == memblk_type_external) __libc_free(ptr); @@ -1489,7 +1505,6 @@ // This block is Single Threaded. if (WST_initialization_state == 0) // Only true once. { - INITIALIZE_RWLOCK _private_::set_alloc_checking_off(LIBCWD_TSD); memblk_map.MT_unsafe = new memblk_map_ct; // MT-safe: There are no threads created yet when we get here. WST_initialization_state = -1; @@ -1533,6 +1548,8 @@ */ bool test_delete(void const* ptr) { + bool res; + LIBCWD_DEFER_CANCEL ACQUIRE_READ_LOCK memblk_map_ct::const_iterator const& iter(memblk_map_read->find(memblk_key_ct(ptr, 0))); // MT: Because the expression `(*iter).first.start()' is included inside the locked @@ -1540,8 +1557,9 @@ // this allocation at the same time. The behaviour of the application would // still be undefined however because it makes it possible that this function // returns false (not deleted) for a deleted memory block. - bool res = (iter == memblk_map_read->end() || (*iter).first.start() != ptr); + res = (iter == memblk_map_read->end() || (*iter).first.start() != ptr); RELEASE_READ_LOCK + LIBCWD_RESTORE_CANCEL return res; } @@ -1551,9 +1569,12 @@ */ size_t mem_size(void) { + size_t memsize; + LIBCWD_DEFER_CANCEL ACQUIRE_READ_LOCK - size_t memsize = const_dm_alloc_ct::get_memsize(); + memsize = const_dm_alloc_ct::get_memsize(); RELEASE_READ_LOCK + LIBCWD_RESTORE_CANCEL return memsize; } @@ -1563,9 +1584,12 @@ */ unsigned long mem_blocks(void) { + unsigned long memblks; + LIBCWD_DEFER_CANCEL ACQUIRE_READ_LOCK - unsigned long memblks = const_dm_alloc_ct::get_memblks(); + memblks = const_dm_alloc_ct::get_memblks(); RELEASE_READ_LOCK + LIBCWD_RESTORE_CANCEL return memblks; } @@ -1577,10 +1601,14 @@ */ std::ostream& operator<<(std::ostream& o, malloc_report_nt) { + size_t memsize; + unsigned long memblks; + LIBCWD_DEFER_CANCEL ACQUIRE_READ_LOCK - size_t memsize = const_dm_alloc_ct::get_memsize(); - unsigned long memblks = const_dm_alloc_ct::get_memblks(); + memsize = const_dm_alloc_ct::get_memsize(); + memblks = const_dm_alloc_ct::get_memblks(); RELEASE_READ_LOCK + LIBCWD_RESTORE_CANCEL o << "Allocated memory: " << memsize << " bytes in " << memblks << " blocks"; return o; } @@ -1615,25 +1643,30 @@ { LIBCWD_TSD_DECLARATION // Print out the entire `map': + memblk_map_ct const* memblk_map_copy; + LIBCWD_DEFER_CANCEL __libcwd_tsd.internal = 1; ACQUIRE_READ_LOCK - memblk_map_ct const* memblk_map_copy = new memblk_map_ct(*memblk_map_read); + memblk_map_copy = new memblk_map_ct(*memblk_map_read); __libcwd_tsd.internal = 0; LibcwDout( channels, debug_object, dc_malloc, "map:" ); int cnt = 0; for(memblk_map_ct::const_iterator iter(memblk_map_copy->begin()); iter != memblk_map_copy->end(); ++iter) LibcwDout( channels, debug_object, dc_malloc|nolabel_cf, ++cnt << ":\t(*iter).first = " << (*iter).first << '\n' << "\t(*iter).second = " << (*iter).second ); - __libcwd_tsd.internal = 1; RELEASE_READ_LOCK + LIBCWD_RESTORE_CANCEL + __libcwd_tsd.internal = 1; delete memblk_map_copy; __libcwd_tsd.internal = 0; } + LIBCWD_DEFER_CANCEL ACQUIRE_READ_LOCK LibcwDout( channels, debug_object, dc_malloc, "Allocated memory: " << const_dm_alloc_ct::get_memsize() << " bytes in " << const_dm_alloc_ct::get_memblks() << " blocks." ); if (base_alloc_list) const_cast<dm_alloc_ct const*>(base_alloc_list)->show_alloc_list(1, channels::dc_malloc); RELEASE_READ_LOCK + LIBCWD_RESTORE_CANCEL } //============================================================================= @@ -1663,11 +1696,13 @@ #ifdef DEBUGDEBUGMALLOC LIBCWD_ASSERT( !__libcwd_tsd.internal ); #endif + LIBCWD_DEFER_CANCEL ACQUIRE_READ_LOCK memblk_map_ct::const_iterator const& iter(memblk_map_read->find(memblk_key_ct(ptr, 0))); if (iter == memblk_map_read->end() || (*iter).first.start() != ptr) { RELEASE_READ_LOCK + LIBCWD_RESTORE_CANCEL_NO_BRACE DoutFatalInternal( dc::core, "Trying to turn non-existing memory block (" << ptr << ") into an 'internal' block" ); } DEBUGDEBUG_CERR( "make_invisible: internal == " << __libcwd_tsd.internal << "; setting it to 1." ); @@ -1677,6 +1712,7 @@ RELEASE_WRITE_LOCK DEBUGDEBUG_CERR( "make_invisible: internal == " << __libcwd_tsd.internal << "; setting it to 0." ); __libcwd_tsd.internal = 0; + LIBCWD_RESTORE_CANCEL } /** @@ -1703,6 +1739,8 @@ #ifdef DEBUGDEBUGMALLOC LIBCWD_ASSERT( !__libcwd_tsd.internal ); #endif + //LIBCWD_DEFER_CLEANUP_PUSH(&rwlock_tct<memblk_map_instance>::cleanup, NULL); + LIBCWD_DEFER_CANCEL ACQUIRE_WRITE_LOCK for (memblk_map_ct::iterator iter(memblk_map_write->begin()); iter != memblk_map_write->end(); ++iter) if ((*iter).second.has_alloc_node() && (*iter).first.start() != ptr) @@ -1714,25 +1752,31 @@ __libcwd_tsd.internal = 0; } RELEASE_WRITE_LOCK + LIBCWD_RESTORE_CANCEL + //LIBCWD_CLEANUP_POP_RESTORE(false); } // Undocumented (used in macro AllocTag) void set_alloc_label(void const* ptr, type_info_ct const& ti, char const* description) { + LIBCWD_DEFER_CANCEL ACQUIRE_WRITE_LOCK memblk_map_ct::iterator const& iter(memblk_map_write->find(memblk_key_ct(ptr, 0))); if (iter != memblk_map_write->end() && (*iter).first.start() == ptr) (*iter).second.change_label(ti, description); RELEASE_WRITE_LOCK + LIBCWD_RESTORE_CANCEL } void set_alloc_label(void const* ptr, type_info_ct const& ti, lockable_auto_ptr<char, true> description) { + LIBCWD_DEFER_CANCEL ACQUIRE_WRITE_LOCK memblk_map_ct::iterator const& iter(memblk_map_write->find(memblk_key_ct(ptr, 0))); if (iter != memblk_map_write->end() && (*iter).first.start() == ptr) (*iter).second.change_label(ti, description); RELEASE_WRITE_LOCK + LIBCWD_RESTORE_CANCEL } #undef CALL_ADDRESS @@ -1756,18 +1800,23 @@ LIBCWD_ASSERT( !__libcwd_tsd.recursive && !__libcwd_tsd.internal ); #endif Dout( dc_malloc, "New libcw::debug::marker_ct at " << this ); + bool error = false; + LIBCWD_DEFER_CANCEL ACQUIRE_WRITE_LOCK memblk_map_ct::iterator const& iter(memblk_map_write->find(memblk_key_ct(this, 0))); memblk_info_ct& info((*iter).second); if (iter == memblk_map_write->end() || (*iter).first.start() != this || info.flags() != memblk_type_new) + error = true; + else { - RELEASE_WRITE_LOCK - DoutFatal( dc::core, "Use 'new' for libcw::debug::marker_ct" ); + info.change_label(type_info_of(this), label); + info.change_flags(memblk_type_marker); + info.new_list(); // MT: needs write lock set. } - info.change_label(type_info_of(this), label); - info.change_flags(memblk_type_marker); - info.new_list(); // MT: needs write lock set. RELEASE_WRITE_LOCK + LIBCWD_RESTORE_CANCEL + if (error) + DoutFatal( dc::core, "Use 'new' for libcw::debug::marker_ct" ); #if defined(DEBUGDEBUGMALLOC) && defined(DEBUGDEBUGOUTPUT) Debug( list_allocations_on(libcw_do) ); #endif @@ -1783,11 +1832,13 @@ LIBCWD_ASSERT( !__libcwd_tsd.recursive && !__libcwd_tsd.internal ); #endif + LIBCWD_DEFER_CANCEL_NO_BRACE ACQUIRE_READ_LOCK memblk_map_ct::const_iterator const& iter(memblk_map_read->find(memblk_key_ct(this, 0))); if (iter == memblk_map_read->end() || (*iter).first.start() != this) { RELEASE_READ_LOCK + LIBCWD_RESTORE_CANCEL_NO_BRACE DoutFatal( dc::core, "Trying to delete an invalid marker" ); } @@ -1806,11 +1857,13 @@ if (*const_dm_alloc_ct::current_alloc_list != (*iter).second.a_alloc_node.get()->next_list()) { RELEASE_READ_LOCK + LIBCWD_RESTORE_CANCEL_NO_BRACE DoutFatal( dc::core, "Deleting a marker must be done in the same \"scope\" as where it was allocated" ); } ACQUIRE_READ2WRITE_LOCK dm_alloc_ct::descend_current_alloc_list(); // MT: needs write lock. RELEASE_WRITE_LOCK + LIBCWD_RESTORE_CANCEL_NO_BRACE } /** @@ -1824,29 +1877,34 @@ LIBCWD_ASSERT( !__libcwd_tsd.recursive && !__libcwd_tsd.internal ); #endif + LIBCWD_DEFER_CANCEL_NO_BRACE ACQUIRE_READ_LOCK memblk_map_ct::const_iterator const& iter(memblk_map_read->find(memblk_key_ct(ptr, 0))); if (iter == memblk_map_read->end() || (*iter).first.start() != ptr) { RELEASE_READ_LOCK + LIBCWD_RESTORE_CANCEL_NO_BRACE DoutFatal( dc::core, "Trying to move non-existing memory block (" << ptr << ") outside memory leak test marker" ); } memblk_map_ct::const_iterator const& iter2(memblk_map_read->find(memblk_key_ct(marker, 0))); if (iter2 == memblk_map_read->end() || (*iter2).first.start() != marker) { RELEASE_READ_LOCK + LIBCWD_RESTORE_CANCEL_NO_BRACE DoutFatal( dc::core, "No such marker: " << (void*)marker ); } dm_alloc_ct* alloc_node = (*iter).second.a_alloc_node.get(); if (!alloc_node) { RELEASE_READ_LOCK + LIBCWD_RESTORE_CANCEL_NO_BRACE DoutFatal( dc::core, "Trying to move an invisible memory block outside memory leak test marker" ); } dm_alloc_ct* marker_alloc_node = (*iter2).second.a_alloc_node.get(); if (!marker_alloc_node || marker_alloc_node->a_memblk_type != memblk_type_marker) { RELEASE_READ_LOCK + LIBCWD_RESTORE_CANCEL_NO_BRACE DoutFatal( dc::core, "That is not a marker: " << (void*)marker ); } @@ -1873,11 +1931,13 @@ alloc_node->my_list = marker_alloc_node->my_list; alloc_node->my_owner_node = marker_alloc_node->my_owner_node; RELEASE_WRITE_LOCK + LIBCWD_RESTORE_CANCEL_NO_BRACE return; } } Dout( dc::warning, "Memory block at " << ptr << " is already outside the marker at " << (void*)marker << " (" << marker_alloc_node->type_info_ptr->demangled_name() << ") area!" ); RELEASE_READ_LOCK + LIBCWD_RESTORE_CANCEL_NO_BRACE } #endif // DEBUGMARKER @@ -1915,10 +1975,13 @@ LIBCWD_ASSERT( !__libcwd_tsd.recursive && !__libcwd_tsd.internal ); #endif + alloc_ct const* res; + LIBCWD_DEFER_CANCEL ACQUIRE_READ_LOCK memblk_map_ct::const_iterator const& iter(memblk_map_read->find(memblk_key_ct(ptr, 0))); - alloc_ct const* res = (iter == memblk_map_read->end()) ? NULL : (*iter).second.get_alloc_node(); + res = (iter == memblk_map_read->end()) ? NULL : (*iter).second.get_alloc_node(); RELEASE_READ_LOCK + LIBCWD_RESTORE_CANCEL return res; } @@ -2060,10 +2123,12 @@ __libcwd_tsd.internal = 1; // Update our administration: + LIBCWD_DEFER_CANCEL ACQUIRE_WRITE_LOCK memblk_ct memblk(memblk_key_ct(mptr, size), memblk_info_ct(mptr, size, memblk_type_external)); // MT: memblk_info_ct() needs wrlock. std::pair<memblk_map_ct::iterator, bool> const& iter(memblk_map_write->insert(memblk)); RELEASE_WRITE_LOCK + LIBCWD_RESTORE_CANCEL DEBUGDEBUG_CERR( "register_external_allocation: internal == " << __libcwd_tsd.internal << "; setting it to 0." ); __libcwd_tsd.internal = 0; @@ -2128,7 +2193,7 @@ // We can't use `assert' here, because that can call malloc. if (__libcwd_tsd.recursive > __libcwd_tsd.library_call && !__libcwd_tsd.internal) { - DEBUGDEBUGMALLOC_CERR("DEBUGDEBUGMALLOC: debugmalloc.cc:" << __LINE__ - 2 << ": " << __PRETTY_FUNCTION__ << ": Assertion `__libcwd_tsd.recursive <= __libcwd_tsd.library_call || __libcwd_tsd.internal' failed."); + FATALDEBUGDEBUG_CERR("DEBUGDEBUGMALLOC: debugmalloc.cc:" << __LINE__ - 2 << ": " << __PRETTY_FUNCTION__ << ": Assertion `__libcwd_tsd.recursive <= __libcwd_tsd.library_call || __libcwd_tsd.internal' failed."); core_dump(); } ++__libcwd_tsd.recursive; @@ -2383,13 +2448,24 @@ return mptr; } +#ifdef DEBUGUSEBFD + if (__libcwd_tsd.library_call++) + ++LIBCWD_DO_TSD_MEMBER(libcw_do, _off); // Otherwise debug output will be generated from bfd.cc (location_ct) + location_ct loc(reinterpret_cast<char*>(__builtin_return_address(0)) + builtin_return_address_offset LIBCWD_COMMA_TSD); + if (--__libcwd_tsd.library_call) + --LIBCWD_DO_TSD_MEMBER(libcw_do, _off); +#endif + DEBUGDEBUG_CERR( "__libcwd_realloc: internal == " << __libcwd_tsd.internal << "; setting it to 1." ); __libcwd_tsd.internal = 1; + + LIBCWD_DEFER_CANCEL_NO_BRACE ACQUIRE_READ_LOCK memblk_map_ct::const_iterator const& iter(memblk_map_read->find(memblk_key_ct(ptr, 0))); if (iter == memblk_map_read->end() || (*iter).first.start() != ptr) { RELEASE_READ_LOCK + LIBCWD_RESTORE_CANCEL_NO_BRACE DEBUGDEBUG_CERR( "__libcwd_realloc: internal == " << __libcwd_tsd.internal << "; setting it to 0." ); __libcwd_tsd.internal = 0; DoutInternal( dc::finish, "" ); @@ -2403,6 +2479,7 @@ if (size == 0) { RELEASE_READ_LOCK + LIBCWD_RESTORE_CANCEL_NO_BRACE // MT: At this point, the memory block that `ptr' points at could be freed by // another thread. This is not a problem because `internal_free' will // again set a lock and again try to find the ptr in the memblk_map. @@ -2432,6 +2509,7 @@ ((size_t*)(static_cast<char*>(ptr) + SIZE_PLUS_FOUR(((size_t*)ptr)[-1])))[-1] != MAGIC_MALLOC_END) { RELEASE_READ_LOCK + LIBCWD_RESTORE_CANCEL_NO_BRACE if (((size_t*)ptr)[-2] == MAGIC_NEW_BEGIN && ((size_t*)(static_cast<char*>(ptr) + SIZE_PLUS_FOUR(((size_t*)ptr)[-1])))[-1] == MAGIC_NEW_END) DoutFatalInternal( dc::core, "You can't realloc() a block that was allocated with `new'!" ); @@ -2444,6 +2522,7 @@ #endif { RELEASE_READ_LOCK + LIBCWD_RESTORE_CANCEL_NO_BRACE #if defined(DEBUGDEBUGMALLOC) && defined(DEBUGDEBUGOUTPUT) DoutInternal( dc::finish, "NULL [" << saved_marker << ']' ); #else @@ -2460,14 +2539,6 @@ ((size_t*)(static_cast<char*>(mptr) + SIZE_PLUS_FOUR(size)))[-1] = MAGIC_MALLOC_END; #endif -#ifdef DEBUGUSEBFD - if (__libcwd_tsd.library_call++) - ++LIBCWD_DO_TSD_MEMBER(libcw_do, _off); // Otherwise debug output will be generated from bfd.cc (location_ct) - location_ct loc(reinterpret_cast<char*>(__builtin_return_address(0)) + builtin_return_address_offset LIBCWD_COMMA_TSD); - if (--__libcwd_tsd.library_call) - --LIBCWD_DO_TSD_MEMBER(libcw_do, _off); -#endif - // Update administration DEBUGDEBUG_CERR( "__libcwd_realloc: internal == " << __libcwd_tsd.internal << "; setting it to 1." ); __libcwd_tsd.internal = 1; @@ -2480,6 +2551,7 @@ if (!iter2.second) { RELEASE_WRITE_LOCK + LIBCWD_RESTORE_CANCEL_NO_BRACE DEBUGDEBUG_CERR( "__libcwd_realloc: internal == " << __libcwd_tsd.internal << "; setting it to 0." ); __libcwd_tsd.internal = 0; DoutFatalInternal( dc::core, "memblk_map corrupt: Newly allocated block collides with existing memblk!" ); @@ -2492,6 +2564,7 @@ memblk_info.get_alloc_node()->location_reference().move(loc); #endif RELEASE_WRITE_LOCK + LIBCWD_RESTORE_CANCEL_NO_BRACE #if defined(DEBUGDEBUGMALLOC) && defined(DEBUGDEBUGOUTPUT) DoutInternal( dc::finish, (void*)(mptr) << " [" << saved_marker << ']' ); Index: src/libcwd/elf32.cc diff -u src/libcwd/elf32.cc:1.33 src/libcwd/elf32.cc:1.34 --- src/libcwd/elf32.cc:1.33 Fri Jan 11 18:54:42 2002 +++ src/libcwd/elf32.cc Wed Jan 30 20:42:08 2002 @@ -1,4 +1,4 @@ -// $Header: /cvsroot/l/li/libcw/src/libcwd/elf32.cc,v 1.33 2002/01/12 02:54:42 libcw Exp $ +// $Header: /cvsroot/l/li/libcw/src/libcwd/elf32.cc,v 1.34 2002/01/31 04:42:08 libcw Exp $ // // Copyright (C) 2001, by // @@ -1903,6 +1903,7 @@ #ifdef LIBCWD_THREAD_SAFE _private_::rwlock_tct<_private_::object_files_instance>::wrunlock(); #endif + M_input_stream.close(); } range_st range; range.start = offset; Index: src/libcwd/include/libcw/macro_AllocTag.h diff -u src/libcwd/include/libcw/macro_AllocTag.h:1.5 src/libcwd/include/libcw/macro_AllocTag.h:1.6 --- src/libcwd/include/libcw/macro_AllocTag.h:1.5 Fri Jan 25 18:06:33 2002 +++ src/libcwd/include/libcw/macro_AllocTag.h Wed Jan 30 20:42:08 2002 @@ -1,4 +1,4 @@ -// $Header: /cvsroot/l/li/libcw/src/libcwd/include/libcw/macro_AllocTag.h,v 1.5 2002/01/26 02:06:33 libcw Exp $ +// $Header: /cvsroot/l/li/libcw/src/libcwd/include/libcw/macro_AllocTag.h,v 1.6 2002/01/31 04:42:08 libcw Exp $ // // Copyright (C) 2000 - 2001, by // @@ -147,40 +147,26 @@ #define AllocTag2(p, desc) ::libcw::debug::\ set_alloc_label(p, ::libcw::debug::type_info_of(p), const_cast<char const*>(desc)) -#ifdef LIBCWD_THREAD_SAFE -#define LIBCWD_LOCK_desc__if_still_NULL_then \ - ::libcw::debug::_private_::cancel_buffer_t __libcwd_buffer; \ - ::libcw::debug::_private_::mutex_tct< ::libcw::debug::_private_::alloc_tag_desc_instance>::lock(__libcwd_buffer); \ - if (!desc) -#define LIBCWD_UNLOCK_desc \ - ::libcw::debug::_private_::mutex_tct< ::libcw::debug::_private_::alloc_tag_desc_instance>::unlock(__libcwd_buffer); -#else // !LIBCWD_THREAD_SAFE -#define LIBCWD_LOCK_desc__if_still_NULL_then -#define LIBCWD_UNLOCK_desc -#endif // !LIBCWD_THREAD_SAFE - /** * \brief Annotate <I>type</I> of \a p with a static description. */ #define AllocTag(p, x) \ do { \ - static char* desc; /* MT-safe */ \ - if (!desc) { \ + static char* WNS_desc; /* MT-safe because 'p' is unshared at this moment (it was *just* allocated by the current thread) */ \ + if (!WNS_desc) { \ LIBCWD_TSD_DECLARATION \ ::libcw::debug::_private_::set_alloc_checking_off(LIBCWD_TSD); \ - LIBCWD_LOCK_desc__if_still_NULL_then \ if (1) \ { \ ::libcw::debug::_private_::internal_stringstream buf; \ buf << x << ::std::ends; \ size_t size = LIBCWD_GETBUFSIZE(buf); \ - desc = new char [size]; /* This is never deleted anymore */ \ - buf.rdbuf()->sgetn(desc, size); \ + WNS_desc = new char [size]; /* This is never deleted anymore */ \ + buf.rdbuf()->sgetn(WNS_desc, size); \ } \ - LIBCWD_UNLOCK_desc \ ::libcw::debug::_private_::set_alloc_checking_on(LIBCWD_TSD); \ } \ - ::libcw::debug::set_alloc_label(p, ::libcw::debug::type_info_of(p), desc); \ + ::libcw::debug::set_alloc_label(p, ::libcw::debug::type_info_of(p), WNS_desc); \ } while(0) /** Index: src/libcwd/include/libcw/macro_ForAllDebugChannels.h diff -u src/libcwd/include/libcw/macro_ForAllDebugChannels.h:1.3 src/libcwd/include/libcw/macro_ForAllDebugChannels.h:1.4 --- src/libcwd/include/libcw/macro_ForAllDebugChannels.h:1.3 Tue Jan 8 15:04:59 2002 +++ src/libcwd/include/libcw/macro_ForAllDebugChannels.h Wed Jan 30 20:42:08 2002 @@ -1,4 +1,4 @@ -// $Header: /cvsroot/l/li/libcw/src/libcwd/include/libcw/macro_ForAllDebugChannels.h,v 1.3 2002/01/08 23:04:59 libcw Exp $ +// $Header: /cvsroot/l/li/libcw/src/libcwd/include/libcw/macro_ForAllDebugChannels.h,v 1.4 2002/01/31 04:42:08 libcw Exp $ // // Copyright (C) 2000 - 2001, by // @@ -44,7 +44,7 @@ typedef internal_vector<channel_ct*> container_type; container_type* WNS_debug_channels; public: - void init(void); + void internal_init(LIBCWD_TSD_PARAM); #ifdef LIBCWD_THREAD_SAFE void init_and_rdlock(void); #endif @@ -79,12 +79,14 @@ } // namespace libcw #ifdef LIBCWD_THREAD_SAFE -#define LIBCWD_ForAllDebugChannels_LOCK ::libcw::debug::_private_::\ - debug_channels.init_and_rdlock(); -#define LIBCWD_ForAllDebugChannels_UNLOCK ::libcw::debug::_private_::\ - rwlock_tct< ::libcw::debug::_private_::debug_channels_instance>::rdunlock(); +#define LIBCWD_ForAllDebugChannels_LOCK \ + LIBCWD_DEFER_CLEANUP_PUSH(&::libcw::debug::_private_::rwlock_tct< ::libcw::debug::_private_::debug_channels_instance>::cleanup, NULL); \ + ::libcw::debug::_private_::debug_channels.init_and_rdlock(); +#define LIBCWD_ForAllDebugChannels_UNLOCK \ + ::libcw::debug::_private_::rwlock_tct< ::libcw::debug::_private_::debug_channels_instance>::rdunlock(); \ + LIBCWD_CLEANUP_POP_RESTORE(false); #else // !LIBCWD_THREAD_SAFE -#define LIBCWD_ForAllDebugChannels_LOCK ::libcw::debug::_private_::debug_channels.init(); +#define LIBCWD_ForAllDebugChannels_LOCK ::libcw::debug::_private_::debug_channels.init(LIBCWD_TSD); #define LIBCWD_ForAllDebugChannels_UNLOCK #endif // !LIBCWD_THREAD_SAFE Index: src/libcwd/include/libcw/macro_ForAllDebugObjects.h diff -u src/libcwd/include/libcw/macro_ForAllDebugObjects.h:1.3 src/libcwd/include/libcw/macro_ForAllDebugObjects.h:1.4 --- src/libcwd/include/libcw/macro_ForAllDebugObjects.h:1.3 Tue Jan 8 15:04:59 2002 +++ src/libcwd/include/libcw/macro_ForAllDebugObjects.h Wed Jan 30 20:42:08 2002 @@ -1,4 +1,4 @@ -// $Header: /cvsroot/l/li/libcw/src/libcwd/include/libcw/macro_ForAllDebugObjects.h,v 1.3 2002/01/08 23:04:59 libcw Exp $ +// $Header: /cvsroot/l/li/libcw/src/libcwd/include/libcw/macro_ForAllDebugObjects.h,v 1.4 2002/01/31 04:42:08 libcw Exp $ // // Copyright (C) 2000 - 2001, by // @@ -46,7 +46,7 @@ private: container_type* WNS_debug_objects; public: - void init(void); + void internal_init(LIBCWD_TSD_PARAM); #ifdef LIBCWD_THREAD_SAFE void init_and_rdlock(void); #endif @@ -82,12 +82,14 @@ } // namespace libcw #ifdef LIBCWD_THREAD_SAFE -#define LIBCWD_ForAllDebugObjects_LOCK ::libcw::debug::_private_::\ - debug_objects.init_and_rdlock(); -#define LIBCWD_ForAllDebugObjects_UNLOCK ::libcw::debug::_private_::\ - rwlock_tct< ::libcw::debug::_private_::debug_objects_instance>::rdunlock(); +#define LIBCWD_ForAllDebugObjects_LOCK \ + LIBCWD_DEFER_CLEANUP_PUSH(&::libcw::debug::_private_::rwlock_tct< ::libcw::debug::_private_::debug_objects_instance>::cleanup, NULL); \ + ::libcw::debug::_private_::debug_objects.init_and_rdlock(); +#define LIBCWD_ForAllDebugObjects_UNLOCK \ + ::libcw::debug::_private_::rwlock_tct< ::libcw::debug::_private_::debug_objects_instance>::rdunlock(); \ + LIBCWD_CLEANUP_POP_RESTORE(false); #else // !LIBCWD_THREAD_SAFE -#define LIBCWD_ForAllDebugObjects_LOCK ::libcw::debug::_private_::debug_objects.init(); +#define LIBCWD_ForAllDebugObjects_LOCK ::libcw::debug::_private_::debug_objects.init(LIBCWD_TSD); #define LIBCWD_ForAllDebugObjects_UNLOCK #endif // !LIBCWD_THREAD_SAFE @@ -116,7 +118,7 @@ { \ using namespace ::libcw::debug; \ using namespace DEBUGCHANNELS; \ - debug_ct& debugObject(*(*__libcw_i)); \ + ::libcw::debug::debug_ct& debugObject(*(*__libcw_i)); \ { STATEMENT; } \ } \ LIBCWD_ForAllDebugObjects_UNLOCK \ Index: src/libcwd/include/libcw/private_struct_TSD.h diff -u src/libcwd/include/libcw/private_struct_TSD.h:1.1 src/libcwd/include/libcw/private_struct_TSD.h:1.2 --- src/libcwd/include/libcw/private_struct_TSD.h:1.1 Tue Jan 22 20:03:45 2002 +++ src/libcwd/include/libcw/private_struct_TSD.h Wed Jan 30 20:42:08 2002 @@ -1,4 +1,4 @@ -// $Header: /cvsroot/l/li/libcw/src/libcwd/include/libcw/private_struct_TSD.h,v 1.1 2002/01/23 04:03:45 libcw Exp $ +// $Header: /cvsroot/l/li/libcw/src/libcwd/include/libcw/private_struct_TSD.h,v 1.2 2002/01/31 04:42:08 libcw Exp $ // // Copyright (C) 2001, by // @@ -26,6 +26,12 @@ #include <cstring> // Needed for std::memset. #endif +#ifndef DEBUGDEBUG +#define LIBCWD_DEBUGTHREADS 0 // Toggle this if necessary. +#else +#define LIBCWD_DEBUGTHREADS 1 +#endif + namespace libcw { namespace debug { namespace _private_ { @@ -81,6 +87,10 @@ #endif #ifdef LIBCWD_THREAD_SAFE // Directly contained in debug_ct when not threaded. debug_tsd_st do_array[16]; // Thread Specific Data of Debug Objects. +#if LIBCWD_DEBUGTHREADS + int cancel_explicitely_deferred; + int cancel_explicitely_disabled; +#endif #endif int off_cnt_array[256]; TSD_st(void) { std::memset(this, 0, sizeof(struct TSD_st)); } Index: src/libcwd/include/libcw/private_threading.h diff -u src/libcwd/include/libcw/private_threading.h:1.15 src/libcwd/include/libcw/private_threading.h:1.16 --- src/libcwd/include/libcw/private_threading.h:1.15 Fri Jan 25 18:06:33 2002 +++ src/libcwd/include/libcw/private_threading.h Wed Jan 30 20:42:08 2002 @@ -1,4 +1,4 @@ -// $Header: /cvsroot/l/li/libcw/src/libcwd/include/libcw/private_threading.h,v 1.15 2002/01/26 02:06:33 libcw Exp $ +// $Header: /cvsroot/l/li/libcw/src/libcwd/include/libcw/private_threading.h,v 1.16 2002/01/31 04:42:08 libcw Exp $ // // Copyright (C) 2001 - 2002, by // @@ -29,12 +29,12 @@ #define LIBCWD_DEBUGDEBUGRWLOCK_CERR(x) #endif // LIBCWD_DEBUGDEBUGRWLOCK -#ifndef LIBCW_PRIVATE_STRUCT_TSD_H -#include <libcw/private_struct_TSD.h> -#endif #ifndef LIBCW_PRIVATE_SET_ALLOC_CHECKING_H #include <libcw/private_set_alloc_checking.h> #endif +#ifndef LIBCW_PRIVATE_STRUCT_TSD_H +#include <libcw/private_struct_TSD.h> +#endif #ifndef LIBCW_CASSERT #define LIBCW_CASSERT #include <cassert> @@ -62,10 +62,10 @@ #define LIBCWD_USE_POSIX_THREADS 0 #endif -#ifndef DEBUGDEBUG -#define LIBCWD_DEBUGTHREADS 0 // Toggle this if necessary. +#if LIBCWD_DEBUGTHREADS +#define LibcwDebugThreads(x) x #else -#define LIBCWD_DEBUGTHREADS 1 +#define LibcwDebugThreads(x) #endif #if LIBCWD_DEBUGTHREADS @@ -99,12 +99,6 @@ #ifdef LIBCWD_THREAD_SAFE -#if LIBCWD_USE_LINUXTHREADS && defined(HAVE__PTHREAD_CLEANUP_BUFFER) -#define LIBCWD_USE_PTHREAD_CLEANUP_BUFFER 1 -#else -#define LIBCWD_USE_PTHREAD_CLEANUP_BUFFER 0 -#endif - namespace libcw { namespace debug { namespace _private_ { @@ -187,61 +181,130 @@ // corresponding instance. __inline__ bool is_locked(int instance) { return instance_locked[instance] > 0; } #endif - -#if LIBCWD_USE_PTHREAD_CLEANUP_BUFFER -typedef struct _pthread_cleanup_buffer cancel_buffer_t; -__inline__ -void -cleanup_push_defer(int (*routine)(pthread_mutex_t*) throw(), pthread_mutex_t& mutex, cancel_buffer_t& buffer) -{ - _pthread_cleanup_push_defer (&(buffer), reinterpret_cast<void(*)(void*)>(routine), reinterpret_cast<void*>(&mutex)); -} - -__inline__ -void -cleanup_pop_restore(bool execute, cancel_buffer_t& buffer) -{ - _pthread_cleanup_pop_restore (&buffer, execute ? 1 : 0); -} - -#else // !LIBCWD_USE_PTHREAD_CLEANUP_BUFFER -typedef int cancel_buffer_t; - -__inline__ -void -cleanup_push_defer(int (*routine)(pthread_mutex_t*) throw(), pthread_mutex_t& mutex, cancel_buffer_t& buffer) -{ - pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, &buffer); - pthread_cleanup_push(reinterpret_cast<void(*)(void*)>(routine), reinterpret_cast<void*>(&mutex)); -} - -#if defined(pthread_cleanup_pop) && defined(pthread_cleanup_push) -#warning "If next you get a 'parse error before `{' token' error, then contact the author of libcwd to get your threads library supported." -#endif - -__inline__ -void -cleanup_pop_restore(bool execute, cancel_buffer_t& buffer) -{ - pthread_cleanup_pop(execute ? 1 : 0); - pthread_setcanceltype(buffer, NULL); -} -#endif // !LIBCWD_USE_PTHREAD_CLEANUP_BUFFER +//========================================================================================================================================17" +// class mutex_tct #if LIBCWD_USE_POSIX_THREADS || LIBCWD_USE_LINUXTHREADS +// We have to use macros because pthread_cleanup_push and pthread_cleanup_pop +// are macros with an unmatched '{' and '}' respectively. +#define LIBCWD_DISABLE_CANCEL \ + { \ + LIBCWD_DISABLE_CANCEL_NO_BRACE +#define LIBCWD_DISABLE_CANCEL_NO_BRACE \ + int __libcwd_oldstate; \ + pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &__libcwd_oldstate); \ + LibcwDebugThreads( \ + { \ + LIBCWD_TSD_DECLARATION; \ + ++__libcwd_tsd.cancel_explicitely_disabled; \ + } ) +#define LIBCWD_ENABLE_CANCEL_NO_BRACE \ + LibcwDebugThreads(\ + { \ + LIBCWD_TSD_DECLARATION; \ + if (--__libcwd_tsd.cancel_explicitely_disabled < 0) \ + ::libcw::debug::core_dump(); \ + /* pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL) can call */ \ + /* __pthread_do_exit() when the thread is cancelled in the meantime. */ \ + /* This might free allocations that are allocated in userspace. */ \ + if (__libcwd_tsd.internal) \ + ::libcw::debug::core_dump(); \ + } ) \ + pthread_setcancelstate(__libcwd_oldstate, NULL); +#define LIBCWD_ENABLE_CANCEL \ + LIBCWD_ENABLE_CANCEL_NO_BRACE \ + } + +#define LIBCWD_DEFER_CANCEL \ + { \ + LIBCWD_DEFER_CANCEL_NO_BRACE +#define LIBCWD_DEFER_CANCEL_NO_BRACE \ + int __libcwd_oldtype; \ + pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, &__libcwd_oldtype); \ + LibcwDebugThreads( \ + { \ + LIBCWD_TSD_DECLARATION; \ + ++__libcwd_tsd.cancel_explicitely_deferred; \ + } ) +#define LIBCWD_RESTORE_CANCEL_NO_BRACE \ + LibcwDebugThreads(\ + { \ + LIBCWD_TSD_DECLARATION; \ + if (--__libcwd_tsd.cancel_explicitely_deferred < 0) \ + ::libcw::debug::core_dump(); \ + /* pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL) will calls */ \ + /* __pthread_do_exit() when the thread is cancelled in the meantime. */ \ + /* This might free allocations that are allocated in userspace. */ \ + if (__libcwd_tsd.internal) \ + ::libcw::debug::core_dump(); \ + } ) \ + pthread_setcanceltype(__libcwd_oldtype, NULL); +#define LIBCWD_RESTORE_CANCEL \ + LIBCWD_RESTORE_CANCEL_NO_BRACE \ + } + +#if LIBCWD_USE_LINUXTHREADS +#define LIBCWD_DEFER_CLEANUP_PUSH(routine, arg) \ + pthread_cleanup_push_defer_np(reinterpret_cast<void(*)(void*)>(routine), reinterpret_cast<void*>(arg)); \ + LibcwDebugThreads( \ + { \ + LIBCWD_TSD_DECLARATION; \ + ++__libcwd_tsd.cancel_explicitely_deferred; \ + } ) +#define LIBCWD_CLEANUP_POP_RESTORE(execute) \ + LibcwDebugThreads(\ + { \ + LIBCWD_TSD_DECLARATION; \ + if (--__libcwd_tsd.cancel_explicitely_deferred < 0) \ + ::libcw::debug::core_dump(); \ + if (__libcwd_tsd.internal) \ + ::libcw::debug::core_dump(); \ + } ) \ + pthread_cleanup_pop_restore_np(static_cast<int>(execute)) +#else // !LIBCWD_USE_LINUXTHREADS +#define LIBCWD_DEFER_CLEANUP_PUSH(routine, arg) \ + LIBCWD_DEFER_CANCEL \ + pthread_cleanup_push(reinterpret_cast<void(*)(void*)>(routine), reinterpret_cast<void*>(arg)) +#define LIBCWD_CLEANUP_POP_RESTORE(execute) \ + pthread_cleanup_pop(static_cast<int>(execute)); \ + LIBCWD_RESTORE_CANCEL +#endif // !LIBCWD_USE_LINUXTHREADS + +#define LIBCWD_PUSH_DEFER_TRYLOCK_MUTEX(instance, unlock_routine) \ + LIBCWD_DEFER_CLEANUP_PUSH(static_cast<void (*)(void)>(unlock_routine), &::libcw::debug::_private_::mutex_tct<(instance)>::S_mutex); \ + bool __libcwd_lock_successful = ::libcw::debug::_private_::mutex_tct<(instance)>::trylock() +#define LIBCWD_DEFER_PUSH_LOCKMUTEX(instance, unlock_routine) \ + LIBCWD_DEFER_CLEANUP_PUSH(static_cast<void (*)(void)>(unlock_routine), &::libcw::debug::_private_::mutex_tct<(instance)>::S_mutex); \ + ::libcw::debug::_private_::mutex_tct<(instance)>::lock(); \ + bool const __libcwd_lock_successful = true +#define LIBCWD_UNLOCKMUTEX_POP_RESTORE(instance) \ + LIBCWD_CLEANUP_POP_RESTORE(__libcwd_lock_successful) + +#define LIBCWD_DEBUGDEBUG_ASSERT_CANCEL_DEFERRED \ + LibcwDebugThreads( \ + if (instance != tsd_initialization_instance) \ + { \ + LIBCWD_TSD_DECLARATION; \ + /* When entering a critical area, make sure that we have explictely deferred cancellation of this */ \ + /* thread (or disabled that) because when cancellation would happen in the middle of the critical */ \ + /* area then the lock would stay locked. */ \ + if (!__libcwd_tsd.cancel_explicitely_deferred && !__libcwd_tsd.cancel_explicitely_disabled) \ + ::libcw::debug::core_dump(); \ + } ) + template <int instance> class mutex_tct { - protected: + public: static pthread_mutex_t S_mutex; -#if !LIBCWD_USE_LINUXTHREADS - private: +#if !LIBCWD_USE_LINUXTHREADS || LIBCWD_DEBUGTHREADS + protected: static bool S_initialized; static void S_initialize(void) throw(); #endif public: static void initialize(void) throw() -#if LIBCWD_USE_LINUXTHREADS +#if LIBCWD_USE_LINUXTHREADS && !LIBCWD_DEBUGTHREADS { } #else { @@ -252,24 +315,24 @@ } #endif public: - static bool trylock(cancel_buffer_t& buffer) throw() + static bool trylock(void) throw() { - cleanup_push_defer(pthread_mutex_unlock, S_mutex, buffer); + LibcwDebugThreads( assert( S_initialized ) ); + LIBCWD_DEBUGDEBUG_ASSERT_CANCEL_DEFERRED bool success = (pthread_mutex_trylock(&S_mutex) == 0); - if (!success) - cleanup_pop_restore(false, buffer); #ifdef DEBUGDEBUG - else + if (success) instance_locked[instance] += 1; #endif return success; } - static void lock(cancel_buffer_t& buffer) throw() + static void lock(void) throw() { + LibcwDebugThreads( assert( S_initialized ) ); + LIBCWD_DEBUGDEBUG_ASSERT_CANCEL_DEFERRED #if LIBCWD_DEBUGDEBUGRWLOCK if (instance != tsd_initialization_instance) LIBCWD_DEBUGDEBUGRWLOCK_CERR(pthread_self() << ": locking mutex " << instance); #endif - cleanup_push_defer(pthread_mutex_unlock, S_mutex, buffer); #if LIBCWD_DEBUGTHREADS int res = #endif @@ -284,65 +347,68 @@ instance_locked[instance] += 1; #endif } - static void unlock(cancel_buffer_t& buffer) throw() + static void unlock(void) throw() { + LIBCWD_DEBUGDEBUG_ASSERT_CANCEL_DEFERRED #ifdef DEBUGDEBUG instance_locked[instance] -= 1; #endif #if LIBCWD_DEBUGDEBUGRWLOCK if (instance != tsd_initialization_instance) LIBCWD_DEBUGDEBUGRWLOCK_CERR(pthread_self() << ": unlocking mutex " << instance); #endif - cleanup_pop_restore(true, buffer); + pthread_mutex_unlock(&S_mutex); #if LIBCWD_DEBUGDEBUGRWLOCK if (instance != tsd_initialization_instance) LIBCWD_DEBUGDEBUGRWLOCK_CERR(pthread_self() << ": mutex " << instance << " unlocked"); #endif } }; -#if !LIBCWD_USE_LINUXTHREADS +#if !LIBCWD_USE_LINUXTHREADS || LIBCWD_DEBUGTHREADS +template <int instance> + bool mutex_tct<instance>::S_initialized = false; + template <int instance> void mutex_tct<instance>::S_initialize(void) throw() { - mutex_tct<mutex_initialization_instance>::initialize(); - cancel_buffer_ct buffer; - mutex_tct<mutex_initialization_instance>::lock(buffer); - if (!S_initialized) // Check again now that we are locked. + if (instance == mutex_initialization_instance) // Specialization. { +#if !LIBCWD_USE_LINUXTHREADS pthread_mutexattr_t mutex_attr; - if (instance < end_recursive_types) - pthread_mutexattr_settype(&mutex_attr, PTHREAD_MUTEX_RECURSIVE); - else - { #if LIBCWD_DEBUGTHREADS - pthread_mutexattr_settype(&mutex_attr, PTHREAD_MUTEX_ERRORCHECK); + pthread_mutexattr_settype(&mutex_attr, PTHREAD_MUTEX_ERRORCHECK); #else - pthread_mutexattr_settype(&mutex_attr, PTHREAD_MUTEX_NORMAL); + pthread_mutexattr_settype(&mutex_attr, PTHREAD_MUTEX_NORMAL); #endif - } pthread_mutex_init(&S_mutex, &mutex_attr); +#endif // !LIBCWD_USE_LINUXTHREADS S_initialized = true; } - mutex_tct<mutex_initialization_instance>::unlock(buffer); - } - -template <> - void mutex_tct<mutex_initialization_instance>::S_initialize(void) throw() - { - pthread_mutexattr_t mutex_attr; + else // General case. + { + mutex_tct<mutex_initialization_instance>::initialize(); + /* LIBCWD_DEFER_PUSH_LOCKMUTEX(mutex_initialization_instance, mutex_tct<mutex_initialization_instance>::unlock); */ + if (!S_initialized) // Check again now that we are locked. + { +#if !LIBCWD_USE_LINUXTHREADS + pthread_mutexattr_t mutex_attr; + if (instance < end_recursive_types) + pthread_mutexattr_settype(&mutex_attr, PTHREAD_MUTEX_RECURSIVE); + else + { #if LIBCWD_DEBUGTHREADS - pthread_mutexattr_settype(&mutex_attr, PTHREAD_MUTEX_ERRORCHECK); + pthread_mutexattr_settype(&mutex_attr, PTHREAD_MUTEX_ERRORCHECK); #else - pthread_mutexattr_settype(&mutex_attr, PTHREAD_MUTEX_NORMAL); + pthread_mutexattr_settype(&mutex_attr, PTHREAD_MUTEX_NORMAL); #endif - pthread_mutex_init(&S_mutex, &mutex_attr); - S_initialized = true; - } + } + pthread_mutex_init(&S_mutex, &mutex_attr); #endif // !LIBCWD_USE_LINUXTHREADS - -#if !LIBCWD_USE_LINUXTHREADS -template <int instance> - bool mutex_tct<instance>::S_initialized = false; -#endif + S_initialized = true; + } + /* LIBCWD_UNLOCKMUTEX_POP_RESTORE(mutex_initialization_instance); */ + } + } +#endif // !LIBCWD_USE_LINUXTHREADS || LIBCWD_DEBUGTHREADS template <int instance> pthread_mutex_t mutex_tct<instance>::S_mutex @@ -363,26 +429,27 @@ ; #endif // !LIBCWD_USE_LINUXTHREADS +//========================================================================================================================================17" +// class cond_tct + template <int instance> class cond_tct : public mutex_tct<instance> { private: static pthread_cond_t S_condition; -#if !LIBCWD_USE_LINUXTHREADS - static bool S_initialized; +#if LIBCWD_DEBUGTHREADS || !LIBCWD_USE_LINUXTHREADS private: static void S_initialize(void) throw(); #endif public: static void initialize(void) throw() -#if LIBCWD_USE_LINUXTHREADS - { } -#else +#if LIBCWD_DEBUGTHREADS || !LIBCWD_USE_LINUXTHREADS { - if (S_initialized) // Check if the static `S_mutex' already has been initialized. - return; // No need to lock: `S_initialized' is only set after it is - // really initialized. + if (S_initialized) + return; S_initialize(); } +#else + { } #endif public: void wait(void) { @@ -395,19 +462,20 @@ void broadcast(void) { pthread_cond_broadcast(&S_condition); } }; -#if !LIBCWD_USE_LINUXTHREADS +#if LIBCWD_DEBUGTHREADS || !LIBCWD_USE_LINUXTHREADS template <int instance> void cond_tct<instance>::S_initialize(void) throw() { +#if !LIBCWD_USE_LINUXTHREADS mutex_tct<mutex_initialization_instance>::initialize(); - cancel_buffer_t buffer; - mutex_tct<mutex_initialization_instance>::lock(buffer); + LIBCWD_DEFER_PUSH_LOCKMUTEX(mutex_initialization_instance, mutex_tct<mutex_initialization_instance>::unlock); if (!S_initialized) // Check again now that we are locked. { pthread_cond_init(&S_condition, NULL); - S_initialized = true; } - mutex_tct<mutex_initialization_instance>::unlock(buffer); + LIBCWD_UNLOCKMUTEX_POP_RESTORE(mutex_initialization_instance); +#endif + mutex_tct<instance>::S_initialize(); } #endif // !LIBCWD_USE_LINUXTHREADS @@ -426,6 +494,9 @@ #endif // LIBCWD_USE_POSIX_THREADS || LIBCWD_USE_LINUXTHREADS +//========================================================================================================================================17" +// class rwlock_tct + // // template <int instance> This class may not use system calls (it may not call malloc(3)). // class rwlock_tct; @@ -452,12 +523,12 @@ static int const readers_instance = instance + reserved_instance_low; static int const holders_instance = instance + 2 * reserved_instance_low; typedef cond_tct<holders_instance> cond_t; - static cond_t S_cond_no_holders; + static cond_t S_no_holders_condition; static int S_holders_count; // Number of readers or -1 if a writer locked this object. static bool S_writer_is_waiting; static pthread_t S_writer_id; #if LIBCWD_DEBUGTHREADS || !LIBCWD_USE_LINUXTHREADS - static bool S_initialized; // Set when initialized. + static bool S_initialized; // Set when initialized. #endif public: static void initialize(void) throw() @@ -467,16 +538,15 @@ return; LIBCWD_DEBUGDEBUGRWLOCK_CERR(pthread_self() << ": Calling initialize() instance " << insta... [truncated message content] |
From: Carlo W. <li...@us...> - 2002-01-31 04:45:05
|
CVSROOT : /cvsroot/libcw Module : src Commit time: 2002-00-31 04:45:04 UTC Added files: libcwd/README.threads libcwd/wrapcnclpnts.c Log message: Work in progress. Going to detect calls to cancellation points while in deferred cancel mode inside a critical area without an installed cleanup routine. ---------------------- diff included ---------------------- Index: src/libcwd/README.threads diff -u /dev/null src/libcwd/README.threads:1.1 --- /dev/null Wed Jan 30 20:45:04 2002 +++ src/libcwd/README.threads Wed Jan 30 20:44:54 2002 @@ -0,0 +1,6 @@ +glibc-2.2.4 defines the following cancellable syscalls: + +accept close connect fcntl fsync lseek lseek64 msync nanosleep +open open64 pause pread pread64 pwrite pwrite64 read recv recvfrom +recvmsg send sendmsg sendto system tcdrain wait waitpid write + Index: src/libcwd/wrapcnclpnts.c diff -u /dev/null src/libcwd/wrapcnclpnts.c:1.1 --- /dev/null Wed Jan 30 20:45:04 2002 +++ src/libcwd/wrapcnclpnts.c Wed Jan 30 20:44:54 2002 @@ -0,0 +1,113 @@ +#define __USE_LARGEFILE64 +#include <unistd.h> +#include <fcntl.h> +#include <sys/mman.h> +#include <pthread.h> +#include <stdarg.h> +#include <stddef.h> +#include <stdlib.h> +#include <termios.h> +#include <sys/resource.h> +#include <sys/wait.h> +#include <sys/socket.h> + +#define CANCELABLE_SYSCALL(res_type, name, param_list, params) \ +res_type __libc_##name param_list; \ +res_type \ +__attribute__ ((weak)) \ +name param_list \ +{ \ + res_type result; \ + int oldtype; \ + pthread_setcanceltype (PTHREAD_CANCEL_ASYNCHRONOUS, &oldtype); \ + result = __libc_##name params; \ + pthread_setcanceltype (oldtype, NULL); \ + return result; \ +} + +#define CANCELABLE_SYSCALL_VA(res_type, name, param_list, params, last_arg) \ +res_type __libc_##name param_list; \ +res_type \ +__attribute__ ((weak)) \ +name param_list \ +{ \ + res_type result; \ + int oldtype; \ + va_list ap; \ + pthread_setcanceltype (PTHREAD_CANCEL_ASYNCHRONOUS, &oldtype); \ + va_start (ap, last_arg); \ + result = __libc_##name params; \ + va_end (ap); \ + pthread_setcanceltype (oldtype, NULL); \ + return result; \ +} + +#define strong_alias(name, aliasname) extern __typeof (name) aliasname __attribute__ ((alias (#name))); + +CANCELABLE_SYSCALL (int, close, (int fd), (fd)) +strong_alias (close, __close) + +CANCELABLE_SYSCALL_VA (int, fcntl, (int fd, int cmd, ...), (fd, cmd, va_arg (ap, long int)), cmd) +strong_alias (fcntl, __fcntl) + +CANCELABLE_SYSCALL (int, fsync, (int fd), (fd)) + +CANCELABLE_SYSCALL (off_t, lseek, (int fd, off_t offset, int whence), (fd, offset, whence)) +strong_alias (lseek, __lseek) + +//CANCELABLE_SYSCALL (off64_t, lseek64, (int fd, off64_t offset, int whence), (fd, offset, whence)) + +CANCELABLE_SYSCALL (int, msync, (__ptr_t addr, size_t length, int flags), (addr, length, flags)) + +CANCELABLE_SYSCALL (int, nanosleep, (const struct timespec *requested_time, struct timespec *remaining), (requested_time, remaining)) + +CANCELABLE_SYSCALL_VA (int, open, (const char *pathname, int flags, ...), (pathname, flags, va_arg (ap, mode_t)), flags) +strong_alias (open, __open) + +CANCELABLE_SYSCALL_VA (int, open64, (const char *pathname, int flags, ...), (pathname, flags, va_arg (ap, mode_t)), flags) +strong_alias (open64, __open64) + +CANCELABLE_SYSCALL (int, pause, (void), ()) + +CANCELABLE_SYSCALL (ssize_t, pread, (int fd, void *buf, size_t count, off_t offset), (fd, buf, count, offset)) + +//CANCELABLE_SYSCALL (ssize_t, pread64, (int fd, void *buf, size_t count, off64_t offset), (fd, buf, count, offset)) +//strong_alias (pread64, __pread64) + +CANCELABLE_SYSCALL (ssize_t, pwrite, (int fd, const void *buf, size_t n, off_t offset), (fd, buf, n, offset)) + +//CANCELABLE_SYSCALL (ssize_t, pwrite64, (int fd, const void *buf, size_t n, off64_t offset), (fd, buf, n, offset)) +//strong_alias (pwrite64, __pwrite64) + +CANCELABLE_SYSCALL (ssize_t, read, (int fd, void *buf, size_t count), (fd, buf, count)) +strong_alias (read, __read) + +CANCELABLE_SYSCALL (int, system, (const char *line), (line)) + +CANCELABLE_SYSCALL (int, tcdrain, (int fd), (fd)) + +CANCELABLE_SYSCALL (__pid_t, wait, (__WAIT_STATUS_DEFN stat_loc), (stat_loc)) +strong_alias (wait, __wait) + +CANCELABLE_SYSCALL (__pid_t, waitpid, (__pid_t pid, int *stat_loc, int options), (pid, stat_loc, options)) + +CANCELABLE_SYSCALL (ssize_t, write, (int fd, const void *buf, size_t n), (fd, buf, n)) +strong_alias (write, __write) + +CANCELABLE_SYSCALL (int, accept, (int fd, __SOCKADDR_ARG addr, socklen_t *addr_len), (fd, addr, addr_len)) + +CANCELABLE_SYSCALL (int, connect, (int fd, __CONST_SOCKADDR_ARG addr, socklen_t len), (fd, addr, len)) +strong_alias (connect, __connect) + +CANCELABLE_SYSCALL (ssize_t, recv, (int fd, __ptr_t buf, size_t n, int flags), (fd, buf, n, flags)) + +CANCELABLE_SYSCALL (ssize_t, recvfrom, (int fd, __ptr_t buf, size_t n, int flags, __SOCKADDR_ARG addr, socklen_t *addr_len), (fd, buf, n, flags, addr, addr_len)) + +CANCELABLE_SYSCALL (ssize_t, recvmsg, (int fd, struct msghdr *message, int flags), (fd, message, flags)) + +CANCELABLE_SYSCALL (ssize_t, send, (int fd, const __ptr_t buf, size_t n, int flags), (fd, buf, n, flags)) +strong_alias (send, __send) + +CANCELABLE_SYSCALL (ssize_t, sendmsg, (int fd, const struct msghdr *message, int flags), (fd, message, flags)) + +CANCELABLE_SYSCALL (ssize_t, sendto, (int fd, const __ptr_t buf, size_t n, int flags, __CONST_SOCKADDR_ARG addr, socklen_t addr_len), (fd, buf, n, flags, addr, addr_len)) ----------------------- End of diff ----------------------- |
From: Carlo W. <li...@us...> - 2002-02-01 05:11:30
|
CVSROOT : /cvsroot/libcw Module : src Commit time: 2002-01-01 05:11:29 UTC Modified files: libcwd/bfd.cc Log message: Compile error fixes for #define DEBUGDEBUGBFD ---------------------- diff included ---------------------- Index: src/libcwd/bfd.cc diff -u src/libcwd/bfd.cc:1.96 src/libcwd/bfd.cc:1.97 --- src/libcwd/bfd.cc:1.96 Wed Jan 30 20:42:08 2002 +++ src/libcwd/bfd.cc Thu Jan 31 21:11:19 2002 @@ -1,4 +1,4 @@ -// $Header: /cvsroot/l/li/libcw/src/libcwd/bfd.cc,v 1.96 2002/01/31 04:42:08 libcw Exp $ +// $Header: /cvsroot/l/li/libcw/src/libcwd/bfd.cc,v 1.97 2002/02/01 05:11:19 libcw Exp $ // // Copyright (C) 2000 - 2001, by // @@ -45,6 +45,9 @@ #endif #include <cstdio> // Needed for vsnprintf. #include <algorithm> +#ifdef DEBUGDEBUGBFD +#include <iomanip> +#endif #include "cwd_debug.h" #include "ios_base_Init.h" #ifdef CWDEBUG_DLOPEN_DEFINED @@ -878,21 +881,21 @@ // cwbfd:: void dump_object_file_symbols(object_file_ct const* object_file) { - cout << setiosflags(ios_base::left) << setw(15) << "Start address" << setw(50) << "File name" << setw(20) << "Number of symbols" << endl; - cout << "0x" << setfill('0') << setiosflags(ios_base::right) << setw(8) << hex << (unsigned long)object_file->get_lbase() << " "; - cout << setfill(' ') << setiosflags(ios_base::left) << setw(50) << object_file->get_bfd()->filename; - cout << dec << setiosflags(ios_base::left); - cout << object_file->get_number_of_symbols() << endl; - - cout << setiosflags(ios_base::left) << setw(12) << "Start"; - cout << ' ' << setiosflags(ios_base::right) << setw(6) << "Size" << ' '; - cout << "Name value flags\n"; + std::cout << std::setiosflags(std::ios_base::left) << std::setw(15) << "Start address" << std::setw(50) << "File name" << std::setw(20) << "Number of symbols\n"; + std::cout << "0x" << std::setfill('0') << std::setiosflags(std::ios_base::right) << std::setw(8) << std::hex << (unsigned long)object_file->get_lbase() << " "; + std::cout << std::setfill(' ') << std::setiosflags(std::ios_base::left) << std::setw(50) << object_file->get_bfd()->filename; + std::cout << std::dec << std::setiosflags(std::ios_base::left); + std::cout << object_file->get_number_of_symbols() << std::endl; + + std::cout << std::setiosflags(std::ios_base::left) << std::setw(12) << "Start"; + std::cout << ' ' << std::setiosflags(std::ios_base::right) << std::setw(6) << "Size" << ' '; + std::cout << "Name value flags\n"; asymbol** symbol_table = object_file->get_symbol_table(); for (long n = object_file->get_number_of_symbols() - 1; n >= 0; --n) { - cout << setiosflags(ios_base::left) << setw(12) << (void*)symbol_start_addr(symbol_table[n]); - cout << ' ' << setiosflags(ios_base::right) << setw(6) << symbol_size(symbol_table[n]) << ' '; - cout << symbol_table[n]->name << ' ' << (void*)symbol_table[n]->value << ' ' << oct << symbol_table[n]->flags << endl; + std::cout << std::setiosflags(std::ios_base::left) << std::setw(12) << (void*)symbol_start_addr(symbol_table[n]); + std::cout << ' ' << std::setiosflags(std::ios_base::right) << std::setw(6) << symbol_size(symbol_table[n]) << ' '; + std::cout << symbol_table[n]->name << ' ' << (void*)symbol_table[n]->value << ' ' << std::oct << symbol_table[n]->flags << std::endl; } } #endif @@ -1069,9 +1072,13 @@ WST_initialized = true; // MT: Safe, this function is Single Threaded. #ifdef DEBUGDEBUGBFD + LIBCWD_DEFER_CANCEL + BFD_ACQUIRE_READ_LOCK // Dump all symbols - for (object_files_ct::reverse_iterator i(object_files().rbegin()); i != object_files().rend(); ++i) + for (object_files_ct::const_reverse_iterator i(NEEDS_READ_LOCK_object_files().rbegin()); i != NEEDS_READ_LOCK_object_files().rend(); ++i) dump_object_file_symbols(*i); + BFD_RELEASE_READ_LOCK + LIBCWD_RESTORE_CANCEL #endif return true; ----------------------- End of diff ----------------------- |
From: Carlo W. <li...@us...> - 2002-02-01 05:12:26
|
CVSROOT : /cvsroot/libcw Module : src Commit time: 2002-01-01 05:12:26 UTC Modified files: libcwd/tests/Makefile.am Added files: libcwd/tests/lines.cc Log message: New test that only works as of g++-3.0.4. ---------------------- diff included ---------------------- Index: src/libcwd/tests/Makefile.am diff -u src/libcwd/tests/Makefile.am:1.19 src/libcwd/tests/Makefile.am:1.20 --- src/libcwd/tests/Makefile.am:1.19 Sun Jan 6 09:59:31 2002 +++ src/libcwd/tests/Makefile.am Thu Jan 31 21:12:16 2002 @@ -13,7 +13,8 @@ dout_alloc \ mangling \ allocator \ -stabs +stabs \ +lines CLEANFILES=$(EXTRA_PROGRAMS) @@ -28,6 +29,7 @@ threads4_SOURCES = threads4.cc allocator_SOURCES = allocator.cc stabs_SOURCES = stabs.cc +lines_SOURCES = lines.cc include_HEADERS = sys.h debug.h sys.h syslog_debug.h threads_debug.h initbug_GlobalObject.h Index: src/libcwd/tests/lines.cc diff -u /dev/null src/libcwd/tests/lines.cc:1.1 --- /dev/null Thu Jan 31 21:12:26 2002 +++ src/libcwd/tests/lines.cc Thu Jan 31 21:12:16 2002 @@ -0,0 +1,22 @@ +#include <libcw/sysd.h> +#include <libcw/debug.h> + +void print_line(void) +{ + libcw::debug::location_ct loc((char*)__builtin_return_address(0) + libcw::debug::builtin_return_address_offset); + Dout(dc::notice, loc); +} + +int main(void) +{ + Debug( libcw_do.on() ); + Debug( dc::bfd.on() ); + Debug( dc::notice.on() ); + + int i = 0; print_line(); +#line __LINE__ "foo.c" + i++; print_line(); +#line __LINE__ "bar.c" + print_line(); return i; +} + ----------------------- End of diff ----------------------- |
From: Carlo W. <li...@us...> - 2002-02-01 05:14:22
|
CVSROOT : /cvsroot/libcw Module : src Commit time: 2002-01-01 05:14:22 UTC Modified files: libcwd/wrapcnclpnts.c Log message: Compile error fixes for the cancelable system calls using off64_t. ---------------------- diff included ---------------------- Index: src/libcwd/wrapcnclpnts.c diff -u src/libcwd/wrapcnclpnts.c:1.1 src/libcwd/wrapcnclpnts.c:1.2 --- src/libcwd/wrapcnclpnts.c:1.1 Wed Jan 30 20:44:54 2002 +++ src/libcwd/wrapcnclpnts.c Thu Jan 31 21:14:12 2002 @@ -1,4 +1,8 @@ -#define __USE_LARGEFILE64 +#include <libcw/debug_config.h> // Needed for LIBCWD_DEBUG_THREADS + +#if LIBCWD_DEBUG_THREADS + +#define _LARGEFILE64_SOURCE #include <unistd.h> #include <fcntl.h> #include <sys/mman.h> @@ -55,7 +59,7 @@ CANCELABLE_SYSCALL (off_t, lseek, (int fd, off_t offset, int whence), (fd, offset, whence)) strong_alias (lseek, __lseek) -//CANCELABLE_SYSCALL (off64_t, lseek64, (int fd, off64_t offset, int whence), (fd, offset, whence)) +CANCELABLE_SYSCALL (off64_t, lseek64, (int fd, off64_t offset, int whence), (fd, offset, whence)) CANCELABLE_SYSCALL (int, msync, (__ptr_t addr, size_t length, int flags), (addr, length, flags)) @@ -71,13 +75,13 @@ CANCELABLE_SYSCALL (ssize_t, pread, (int fd, void *buf, size_t count, off_t offset), (fd, buf, count, offset)) -//CANCELABLE_SYSCALL (ssize_t, pread64, (int fd, void *buf, size_t count, off64_t offset), (fd, buf, count, offset)) -//strong_alias (pread64, __pread64) +CANCELABLE_SYSCALL (ssize_t, pread64, (int fd, void *buf, size_t count, off64_t offset), (fd, buf, count, offset)) +strong_alias (pread64, __pread64) CANCELABLE_SYSCALL (ssize_t, pwrite, (int fd, const void *buf, size_t n, off_t offset), (fd, buf, n, offset)) -//CANCELABLE_SYSCALL (ssize_t, pwrite64, (int fd, const void *buf, size_t n, off64_t offset), (fd, buf, n, offset)) -//strong_alias (pwrite64, __pwrite64) +CANCELABLE_SYSCALL (ssize_t, pwrite64, (int fd, const void *buf, size_t n, off64_t offset), (fd, buf, n, offset)) +strong_alias (pwrite64, __pwrite64) CANCELABLE_SYSCALL (ssize_t, read, (int fd, void *buf, size_t count), (fd, buf, count)) strong_alias (read, __read) @@ -111,3 +115,5 @@ CANCELABLE_SYSCALL (ssize_t, sendmsg, (int fd, const struct msghdr *message, int flags), (fd, message, flags)) CANCELABLE_SYSCALL (ssize_t, sendto, (int fd, const __ptr_t buf, size_t n, int flags, __CONST_SOCKADDR_ARG addr, socklen_t addr_len), (fd, buf, n, flags, addr, addr_len)) + +#endif // LIBCWD_DEBUG_THREADS ----------------------- End of diff ----------------------- |
From: Carlo W. <li...@us...> - 2002-02-01 05:21:16
|
CVSROOT : /cvsroot/libcw Module : src Commit time: 2002-01-01 05:21:16 UTC Modified files: libcwd/bfd.cc libcwd/configure.in libcwd/threading.cc libcwd/wrapcnclpnts.c libcwd/include/libcw/debug_config.ho.in libcwd/include/libcw/private_struct_TSD.h libcwd/include/libcw/private_threading.h Log message: New configure options --enable-libcwd-debugt. Use DEBUGDEBUGTHREADS instead of LIBCWD_DEBUGTHREADS. ---------------------- diff included ---------------------- Index: src/libcwd/bfd.cc diff -u src/libcwd/bfd.cc:1.97 src/libcwd/bfd.cc:1.98 --- src/libcwd/bfd.cc:1.97 Thu Jan 31 21:11:19 2002 +++ src/libcwd/bfd.cc Thu Jan 31 21:21:05 2002 @@ -1,4 +1,4 @@ -// $Header: /cvsroot/l/li/libcw/src/libcwd/bfd.cc,v 1.97 2002/02/01 05:11:19 libcw Exp $ +// $Header: /cvsroot/l/li/libcw/src/libcwd/bfd.cc,v 1.98 2002/02/01 05:21:05 libcw Exp $ // // Copyright (C) 2000 - 2001, by // @@ -1023,7 +1023,7 @@ BFD_INITIALIZE_LOCK LIBCWD_DEFER_CANCEL BFD_ACQUIRE_WRITE_LOCK -#if LIBCWD_DEBUGTHREADS +#ifdef DEBUGDEBUGTHREADS --__libcwd_tsd.cancel_explicitely_deferred; #endif load_object_file(fullpath.value->data(), 0); @@ -1052,7 +1052,7 @@ load_object_file(l->l_name, reinterpret_cast<void*>(l->l_addr)); } NEEDS_WRITE_LOCK_object_files().sort(object_file_greater()); -#if LIBCWD_DEBUGTHREADS +#ifdef DEBUGDEBUGTHREADS ++__libcwd_tsd.cancel_explicitely_deferred; #endif BFD_RELEASE_WRITE_LOCK Index: src/libcwd/configure.in diff -u src/libcwd/configure.in:1.99 src/libcwd/configure.in:1.100 --- src/libcwd/configure.in:1.99 Fri Jan 25 18:06:33 2002 +++ src/libcwd/configure.in Thu Jan 31 21:21:05 2002 @@ -1,5 +1,5 @@ dnl Process this file with autoconf to produce a configure script. -AC_REVISION($Revision: 1.99 $)dnl +AC_REVISION($Revision: 1.100 $)dnl dnl General intialization of `autoconf' varaibles. dnl Ensure that the directory specified with --srcdir was correct @@ -101,6 +101,12 @@ threading where needed.], libcwd_config_threading=$enableval) +libcwd_config_debugt=no +AC_ARG_ENABLE(libcwd-debugt, + [ --enable-libcwd-debugt enable debugging of threading debugging code + in libcwd itself.], + libcwd_config_debugt=$enableval) + dnl Restore the environment variables used when running `configure' when dnl `config.status --recheck' was invoked. dnl Always let CXX and CXXCPP override cached values @@ -208,6 +214,8 @@ CW_CONFIG_DEBUGDEBUGOUTPUT=undef AC_SUBST(CW_CONFIG_DEBUGDEBUGMALLOC) CW_CONFIG_DEBUGDEBUGMALLOC=undef +AC_SUBST(CW_CONFIG_DEBUGDEBUGTHREADS) +CW_CONFIG_DEBUGDEBUGTHREADS=undef AC_SUBST(CW_CONFIG_DEBUGMARKER) CW_CONFIG_DEBUGMARKER=undef AC_SUBST(CW_CONFIG_HAVE___LIBC_MALLOC) @@ -391,6 +399,10 @@ if test "$libcwd_config_debugm" = yes; then CW_CONFIG_DEBUGDEBUGMALLOC=define +fi + +if test "$libcwd_config_debugt" = yes; then + CW_CONFIG_DEBUGDEBUGTHREADS=define fi if test "$libcwd_config_marker" = yes; then Index: src/libcwd/include/libcw/debug_config.ho.in diff -u src/libcwd/include/libcw/debug_config.ho.in:1.16 src/libcwd/include/libcw/debug_config.ho.in:1.17 --- src/libcwd/include/libcw/debug_config.ho.in:1.16 Fri Jan 25 18:06:33 2002 +++ src/libcwd/include/libcw/debug_config.ho.in Thu Jan 31 21:21:05 2002 @@ -1,5 +1,5 @@ // @configure_input@ -// $Header: /cvsroot/l/li/libcw/src/libcwd/include/libcw/debug_config.ho.in,v 1.16 2002/01/26 02:06:33 libcw Exp $ +// $Header: /cvsroot/l/li/libcw/src/libcwd/include/libcw/debug_config.ho.in,v 1.17 2002/02/01 05:21:05 libcw Exp $ // // Copyright (C) 2000 - 2001, by // @@ -263,9 +263,50 @@ #endif // +// autoconf defines that are needed. +// + +#ifdef DEBUGMALLOC +#@CW_CONFIG_HAVE___LIBC_MALLOC@ DEBUGMALLOCEXTERNALCLINKAGE +#endif + +#ifdef DEBUGUSEBFD +#@CW_CONFIG_HAVE_DLOPEN@ CWDEBUG_DLOPEN_DEFINED +#endif + +#@CW_CONFIG_THREAD_SAFE@ LIBCWD_THREAD_SAFE +#@CW_CONFIG_HAVE_PTHREADS@ LIBCWD_HAVE_PTHREAD + +#ifdef LIBCWD_THREAD_SAFE +/** \defgroup enable_libcwd_debugt --enable-libcwd-debugt (DEBUGDEBUGTHREADS) + * \ingroup group_configuration + * + * \par Description + * + * Turns on sanity checks related to libcwds critical areas and cancellation points. + * The checks test if cancellation has been explicitely deferred or disabled at the entrance + * of a critical area and that no cancellation point is called from within critical areas + * without cleanup handler. + * + * \par When to use it + * + * Never, unless you are a developer of libcwd. + * If someone requests it then I might extend this to a user interface however. + * + * \par Configure option + * + * This is disabled by default. + * Use \shellcommand configure --enable-libcwd-debugt \endshellcommand to enable it. + */ + +#@CW_CONFIG_DEBUGDEBUGTHREADS@ DEBUGDEBUGTHREADS +#endif // LIBCWD_THREAD_SAFE + +// // Configuration signature // +#ifdef __cplusplus namespace libcw { namespace debug { @@ -325,21 +366,6 @@ } // namespace debug } // namespace libcw - -// -// autoconf defines that are needed. -// - -#ifdef DEBUGMALLOC -#@CW_CONFIG_HAVE___LIBC_MALLOC@ DEBUGMALLOCEXTERNALCLINKAGE -#endif - -#ifdef DEBUGUSEBFD -#@CW_CONFIG_HAVE_DLOPEN@ CWDEBUG_DLOPEN_DEFINED -#endif - -#@CW_CONFIG_THREAD_SAFE@ LIBCWD_THREAD_SAFE -#@CW_CONFIG_HAVE_PTHREADS@ LIBCWD_HAVE_PTHREAD -#@CW_CONFIG_HAVE__PTHREAD_CLEANUP_BUFFER@ HAVE__PTHREAD_CLEANUP_BUFFER +#endif // __cplusplus #endif // LIBCW_DEBUG_CONFIG_H Index: src/libcwd/include/libcw/private_struct_TSD.h diff -u src/libcwd/include/libcw/private_struct_TSD.h:1.2 src/libcwd/include/libcw/private_struct_TSD.h:1.3 --- src/libcwd/include/libcw/private_struct_TSD.h:1.2 Wed Jan 30 20:42:08 2002 +++ src/libcwd/include/libcw/private_struct_TSD.h Thu Jan 31 21:21:05 2002 @@ -1,4 +1,4 @@ -// $Header: /cvsroot/l/li/libcw/src/libcwd/include/libcw/private_struct_TSD.h,v 1.2 2002/01/31 04:42:08 libcw Exp $ +// $Header: /cvsroot/l/li/libcw/src/libcwd/include/libcw/private_struct_TSD.h,v 1.3 2002/02/01 05:21:05 libcw Exp $ // // Copyright (C) 2001, by // @@ -26,12 +26,6 @@ #include <cstring> // Needed for std::memset. #endif -#ifndef DEBUGDEBUG -#define LIBCWD_DEBUGTHREADS 0 // Toggle this if necessary. -#else -#define LIBCWD_DEBUGTHREADS 1 -#endif - namespace libcw { namespace debug { namespace _private_ { @@ -87,7 +81,7 @@ #endif #ifdef LIBCWD_THREAD_SAFE // Directly contained in debug_ct when not threaded. debug_tsd_st do_array[16]; // Thread Specific Data of Debug Objects. -#if LIBCWD_DEBUGTHREADS +#ifdef DEBUGDEBUGTHREADS int cancel_explicitely_deferred; int cancel_explicitely_disabled; #endif Index: src/libcwd/include/libcw/private_threading.h diff -u src/libcwd/include/libcw/private_threading.h:1.16 src/libcwd/include/libcw/private_threading.h:1.17 --- src/libcwd/include/libcw/private_threading.h:1.16 Wed Jan 30 20:42:08 2002 +++ src/libcwd/include/libcw/private_threading.h Thu Jan 31 21:21:05 2002 @@ -1,4 +1,4 @@ -// $Header: /cvsroot/l/li/libcw/src/libcwd/include/libcw/private_threading.h,v 1.16 2002/01/31 04:42:08 libcw Exp $ +// $Header: /cvsroot/l/li/libcw/src/libcwd/include/libcw/private_threading.h,v 1.17 2002/02/01 05:21:05 libcw Exp $ // // Copyright (C) 2001 - 2002, by // @@ -62,13 +62,13 @@ #define LIBCWD_USE_POSIX_THREADS 0 #endif -#if LIBCWD_DEBUGTHREADS +#ifdef DEBUGDEBUGTHREADS #define LibcwDebugThreads(x) x #else #define LibcwDebugThreads(x) #endif -#if LIBCWD_DEBUGTHREADS +#ifdef DEBUGDEBUGTHREADS #ifndef LIBCW_CASSERT #define LIBCW_CASSERT #include <cassert> @@ -297,14 +297,14 @@ class mutex_tct { public: static pthread_mutex_t S_mutex; -#if !LIBCWD_USE_LINUXTHREADS || LIBCWD_DEBUGTHREADS +#if !LIBCWD_USE_LINUXTHREADS || defined(DEBUGDEBUGTHREADS) protected: static bool S_initialized; static void S_initialize(void) throw(); #endif public: static void initialize(void) throw() -#if LIBCWD_USE_LINUXTHREADS && !LIBCWD_DEBUGTHREADS +#if LIBCWD_USE_LINUXTHREADS && !defined(DEBUGDEBUGTHREADS) { } #else { @@ -333,11 +333,11 @@ #if LIBCWD_DEBUGDEBUGRWLOCK if (instance != tsd_initialization_instance) LIBCWD_DEBUGDEBUGRWLOCK_CERR(pthread_self() << ": locking mutex " << instance); #endif -#if LIBCWD_DEBUGTHREADS +#ifdef DEBUGDEBUGTHREADS int res = #endif pthread_mutex_lock(&S_mutex); -#if LIBCWD_DEBUGTHREADS +#ifdef DEBUGDEBUGTHREADS assert( res == 0 ); #endif #if LIBCWD_DEBUGDEBUGRWLOCK @@ -363,7 +363,7 @@ } }; -#if !LIBCWD_USE_LINUXTHREADS || LIBCWD_DEBUGTHREADS +#if !LIBCWD_USE_LINUXTHREADS || defined(DEBUGDEBUGTHREADS) template <int instance> bool mutex_tct<instance>::S_initialized = false; @@ -374,7 +374,7 @@ { #if !LIBCWD_USE_LINUXTHREADS pthread_mutexattr_t mutex_attr; -#if LIBCWD_DEBUGTHREADS +#ifdef DEBUGDEBUGTHREADS pthread_mutexattr_settype(&mutex_attr, PTHREAD_MUTEX_ERRORCHECK); #else pthread_mutexattr_settype(&mutex_attr, PTHREAD_MUTEX_NORMAL); @@ -395,7 +395,7 @@ pthread_mutexattr_settype(&mutex_attr, PTHREAD_MUTEX_RECURSIVE); else { -#if LIBCWD_DEBUGTHREADS +#ifdef DEBUGDEBUGTHREADS pthread_mutexattr_settype(&mutex_attr, PTHREAD_MUTEX_ERRORCHECK); #else pthread_mutexattr_settype(&mutex_attr, PTHREAD_MUTEX_NORMAL); @@ -408,13 +408,13 @@ /* LIBCWD_UNLOCKMUTEX_POP_RESTORE(mutex_initialization_instance); */ } } -#endif // !LIBCWD_USE_LINUXTHREADS || LIBCWD_DEBUGTHREADS +#endif // !LIBCWD_USE_LINUXTHREADS || defined(DEBUGDEBUGTHREADS) template <int instance> pthread_mutex_t mutex_tct<instance>::S_mutex #if LIBCWD_USE_LINUXTHREADS = -#if LIBCWD_DEBUGTHREADS +#ifdef DEBUGDEBUGTHREADS PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP; #else PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP; @@ -436,13 +436,13 @@ class cond_tct : public mutex_tct<instance> { private: static pthread_cond_t S_condition; -#if LIBCWD_DEBUGTHREADS || !LIBCWD_USE_LINUXTHREADS +#if defined(DEBUGDEBUGTHREADS) || !LIBCWD_USE_LINUXTHREADS private: static void S_initialize(void) throw(); #endif public: static void initialize(void) throw() -#if LIBCWD_DEBUGTHREADS || !LIBCWD_USE_LINUXTHREADS +#if defined(DEBUGDEBUGTHREADS) || !LIBCWD_USE_LINUXTHREADS { if (S_initialized) return; @@ -462,7 +462,7 @@ void broadcast(void) { pthread_cond_broadcast(&S_condition); } }; -#if LIBCWD_DEBUGTHREADS || !LIBCWD_USE_LINUXTHREADS +#if defined(DEBUGDEBUGTHREADS) || !LIBCWD_USE_LINUXTHREADS template <int instance> void cond_tct<instance>::S_initialize(void) throw() { @@ -527,13 +527,13 @@ static int S_holders_count; // Number of readers or -1 if a writer locked this object. static bool S_writer_is_waiting; static pthread_t S_writer_id; -#if LIBCWD_DEBUGTHREADS || !LIBCWD_USE_LINUXTHREADS +#if defined(DEBUGDEBUGTHREADS) || !LIBCWD_USE_LINUXTHREADS static bool S_initialized; // Set when initialized. #endif public: static void initialize(void) throw() { -#if LIBCWD_DEBUGTHREADS || !LIBCWD_USE_LINUXTHREADS +#if defined(DEBUGDEBUGTHREADS) || !LIBCWD_USE_LINUXTHREADS if (S_initialized) return; LIBCWD_DEBUGDEBUGRWLOCK_CERR(pthread_self() << ": Calling initialize() instance " << instance); @@ -713,7 +713,7 @@ template <int instance> pthread_t rwlock_tct<instance>::S_writer_id = 0; -#if LIBCWD_DEBUGTHREADS || !LIBCWD_USE_LINUXTHREADS +#if defined(DEBUGDEBUGTHREADS) || !LIBCWD_USE_LINUXTHREADS template <int instance> bool rwlock_tct<instance>::S_initialized = 0; #endif @@ -756,7 +756,7 @@ LIBCWD_TSD_DECLARATION set_alloc_checking_off(LIBCWD_TSD); delete instance; -#if LIBCWD_DEBUGTHREADS +#ifdef DEBUGDEBUGTHREADS // Hopefully S_destroy doesn't get called in the thread itself! assert( instance != &thread_specific_data_tct<TSD>::instance() ); #endif Index: src/libcwd/threading.cc diff -u src/libcwd/threading.cc:1.3 src/libcwd/threading.cc:1.4 --- src/libcwd/threading.cc:1.3 Wed Jan 30 20:42:08 2002 +++ src/libcwd/threading.cc Thu Jan 31 21:21:05 2002 @@ -1,4 +1,4 @@ -// $Header: /cvsroot/l/li/libcw/src/libcwd/threading.cc,v 1.3 2002/01/31 04:42:08 libcw Exp $ +// $Header: /cvsroot/l/li/libcw/src/libcwd/threading.cc,v 1.4 2002/02/01 05:21:05 libcw Exp $ // // Copyright (C) 2001, by // @@ -30,7 +30,7 @@ void initialize_global_mutexes(void) throw() { -#if !LIBCWD_USE_LINUXTHREADS || LIBCWD_DEBUGTHREADS +#if !LIBCWD_USE_LINUXTHREADS || defined(DEBUGDEBUGTHREADS) mutex_tct<mutex_initialization_instance>::initialize(); rwlock_tct<object_files_instance>::initialize(); mutex_tct<dlopen_map_instance>::initialize(); @@ -41,7 +41,7 @@ #if __GNUC__ == 2 && __GNUC_MINOR__ < 96 mutex_tct<type_info_of_instance>::initialize(); #endif -#endif // !LIBCWD_USE_LINUXTHREADS || LIBCWD_DEBUGTHREADS +#endif // !LIBCWD_USE_LINUXTHREADS || defined(DEBUGDEBUGTHREADS) } #ifdef LIBCWD_USE_LINUXTHREADS Index: src/libcwd/wrapcnclpnts.c diff -u src/libcwd/wrapcnclpnts.c:1.2 src/libcwd/wrapcnclpnts.c:1.3 --- src/libcwd/wrapcnclpnts.c:1.2 Thu Jan 31 21:14:12 2002 +++ src/libcwd/wrapcnclpnts.c Thu Jan 31 21:21:05 2002 @@ -1,6 +1,6 @@ -#include <libcw/debug_config.h> // Needed for LIBCWD_DEBUG_THREADS +#include <libcw/debug_config.h> // Needed for DEBUGDEBUGTHREADS -#if LIBCWD_DEBUG_THREADS +#ifdef DEBUGDEBUGTHREADS #define _LARGEFILE64_SOURCE #include <unistd.h> @@ -116,4 +116,4 @@ CANCELABLE_SYSCALL (ssize_t, sendto, (int fd, const __ptr_t buf, size_t n, int flags, __CONST_SOCKADDR_ARG addr, socklen_t addr_len), (fd, buf, n, flags, addr, addr_len)) -#endif // LIBCWD_DEBUG_THREADS +#endif // DEBUGDEBUGTHREADS ----------------------- End of diff ----------------------- |
From: Carlo W. <li...@us...> - 2002-02-01 15:48:33
|
CVSROOT : /cvsroot/libcw Module : src Commit time: 2002-01-01 15:48:32 UTC Modified files: libcwd/elf32.cc Log message: Bug fix: the .debug_line section can be completely empty. ---------------------- diff included ---------------------- Index: src/libcwd/elf32.cc diff -u src/libcwd/elf32.cc:1.34 src/libcwd/elf32.cc:1.35 --- src/libcwd/elf32.cc:1.34 Wed Jan 30 20:42:08 2002 +++ src/libcwd/elf32.cc Fri Feb 1 07:48:21 2002 @@ -1,4 +1,4 @@ -// $Header: /cvsroot/l/li/libcw/src/libcwd/elf32.cc,v 1.34 2002/01/31 04:42:08 libcw Exp $ +// $Header: /cvsroot/l/li/libcw/src/libcwd/elf32.cc,v 1.35 2002/02/01 15:48:21 libcw Exp $ // // Copyright (C) 2001, by // @@ -1490,7 +1490,7 @@ // doing DWARF in find_nearest_line(). location.set_func_iter(M_function_names.insert(cur_func).first); - do + while( debug_line_ptr < debug_line_ptr_end ) { file = 0; // One less than the `file' mentioned in the documentation. column = 0; @@ -1655,7 +1655,6 @@ } } } - while( debug_line_ptr < debug_line_ptr_end ); LIBCWD_ASSERT( debug_line_ptr == debug_line_ptr_end ); // End state machine code. @@ -1885,7 +1884,6 @@ } M_inside_find_nearest_line = true; #if DEBUGSTABS || DEBUGDWARF - int off = libcw::debug::libcw_do._off; libcw::debug::debug_ct::OnOffState state; Debug( libcw_do.force_on(state) ); libcw::debug::channel_ct::OnOffState state2; ----------------------- End of diff ----------------------- |
From: Carlo W. <li...@us...> - 2002-02-03 04:15:23
|
CVSROOT : /cvsroot/libcw Module : src Commit time: 2002-01-03 04:15:22 UTC Modified files: libcwd/Makefile.am libcwd/bfd.cc libcwd/configure.in libcwd/debug.cc libcwd/debugmalloc.cc libcwd/elf32.cc libcwd/threading.cc libcwd/include/raw_write.h libcwd/include/libcw/macro_ForAllDebugChannels.h libcwd/include/libcw/macro_ForAllDebugObjects.h libcwd/include/libcw/private_struct_TSD.h libcwd/include/libcw/private_threading.h Log message: Now compiles again without --enable-libcwd-threading. Now is cancel-safe: No cancellation point syscalls are done inside libcwd critical areas or cancellation is disabled first or a cleanup handler is installed (it is not certain that these cleanup handlers do the right thing though, but they should at least unlock all locks). ---------------------- diff included ---------------------- Index: src/libcwd/Makefile.am diff -u src/libcwd/Makefile.am:1.44 src/libcwd/Makefile.am:1.45 --- src/libcwd/Makefile.am:1.44 Wed Jan 30 20:42:08 2002 +++ src/libcwd/Makefile.am Sat Feb 2 20:15:11 2002 @@ -28,7 +28,7 @@ demangle3.cc \ strerrno.cc \ type_info.cc \ - wrapcnclpnts.c + wrapcnclpnts.cc libcwd_la_LDFLAGS = -version-info $(VERSIONINFO) $(LIB_THREADS_SHARED) Index: src/libcwd/bfd.cc diff -u src/libcwd/bfd.cc:1.98 src/libcwd/bfd.cc:1.99 --- src/libcwd/bfd.cc:1.98 Thu Jan 31 21:21:05 2002 +++ src/libcwd/bfd.cc Sat Feb 2 20:15:11 2002 @@ -1,4 +1,4 @@ -// $Header: /cvsroot/l/li/libcw/src/libcwd/bfd.cc,v 1.98 2002/02/01 05:21:05 libcw Exp $ +// $Header: /cvsroot/l/li/libcw/src/libcwd/bfd.cc,v 1.99 2002/02/03 04:15:11 libcw Exp $ // // Copyright (C) 2000 - 2001, by // @@ -78,8 +78,8 @@ #define BFD_RELEASE_READ_LOCK rwlock_tct<object_files_instance>::rdunlock(); #define BFD_ACQUIRE_READ2WRITE_LOCK rwlock_tct<object_files_instance>::rd2wrlock(); #define BFD_ACQUIRE_WRITE2READ_LOCK rwlock_tct<object_files_instance>::wr2rdlock(); -#define DLOPEN_MAP_ACQUIRE_LOCK LIBCWD_DEFER_PUSH_LOCKMUTEX(dlopen_map_instance, &mutex_tct<dlopen_map_instance>::unlock); -#define DLOPEN_MAP_RELEASE_LOCK LIBCWD_UNLOCKMUTEX_POP_RESTORE(dlopen_map_instance) +#define DLOPEN_MAP_ACQUIRE_LOCK mutex_tct<dlopen_map_instance>::lock(); +#define DLOPEN_MAP_RELEASE_LOCK mutex_tct<dlopen_map_instance>::unlock(); #else // !LIBCWD_THREAD_SAFE #define BFD_INITIALIZE_LOCK #define BFD_ACQUIRE_WRITE_LOCK @@ -1013,19 +1013,12 @@ // Load executable // No write lock is really needed because this is a Single Threaded function, // but the sanity checks inside the allocators used in load_object_file() - // require the lock to be set. Fortunately is therefore also doesn't hurt + // require the lock to be set. Fortunately it therefore also doesn't hurt // that we keep the lock a long time (during the execution of ldd_prog). // Same thing for the LIBCWD_DEFER_CANCEL, needed for the sanity checks. - // However - here we have another sanity check that controls if we aren't - // setting the cancel state too often (recursively), and in *this* case - // that is unavoidable. Therefore we decrement these sanity check counters - // in order to fool the check, right after we set the lock. BFD_INITIALIZE_LOCK - LIBCWD_DEFER_CANCEL + LIBCWD_DEFER_CLEANUP_PUSH(_private_::fatal_cancellation, const_cast<char*>("while reading debug information from a shared library")) BFD_ACQUIRE_WRITE_LOCK -#ifdef DEBUGDEBUGTHREADS - --__libcwd_tsd.cancel_explicitely_deferred; -#endif load_object_file(fullpath.value->data(), 0); // Load all shared objects @@ -1052,9 +1045,6 @@ load_object_file(l->l_name, reinterpret_cast<void*>(l->l_addr)); } NEEDS_WRITE_LOCK_object_files().sort(object_file_greater()); -#ifdef DEBUGDEBUGTHREADS - ++__libcwd_tsd.cancel_explicitely_deferred; -#endif BFD_RELEASE_WRITE_LOCK set_alloc_checking_on(LIBCWD_TSD); @@ -1062,7 +1052,7 @@ // **************************************************************************** // We put this outside the 'internal' region because it might call __pthread_do_exit. - LIBCWD_RESTORE_CANCEL + LIBCWD_CLEANUP_POP_RESTORE(false) #ifdef ALWAYS_PRINT_LOADING Debug( dc::bfd.restore(state2) ); @@ -1450,6 +1440,16 @@ namespace _private_ { typedef std::map<void*, dlloaded_st, std::less<void*>, userspace_allocator::rebind<void*>::other> dlopen_map_ct; static dlopen_map_ct dlopen_map; + +#ifdef LIBCWD_THREAD_SAFE +void dlopen_cleanup1(void* arg) +{ + TSD_st& __libcwd_tsd = (*static_cast<TSD_st*>(arg)); + set_alloc_checking_on(LIBCWD_TSD); + BFD_RELEASE_WRITE_LOCK +} +#endif + } } } @@ -1464,35 +1464,26 @@ if ((flags & RTLD_NOLOAD)) return handle; #endif - set_alloc_checking_off(LIBCWD_TSD); - LIBCWD_DEFER_CANCEL_NO_BRACE + cwbfd::object_file_ct* object_file; + LIBCWD_DEFER_CLEANUP_PUSH(libcw::debug::_private_::dlopen_cleanup1, &__libcwd_tsd) // In case we are cancelled inside cwbfd::load_object_file(). BFD_ACQUIRE_WRITE_LOCK; - cwbfd::object_file_ct* object_file = cwbfd::load_object_file(name, cwbfd::unknown_l_addr); + set_alloc_checking_off(LIBCWD_TSD); + object_file = cwbfd::load_object_file(name, cwbfd::unknown_l_addr); + if (object_file) + cwbfd::NEEDS_WRITE_LOCK_object_files().sort(cwbfd::object_file_greater()); set_alloc_checking_on(LIBCWD_TSD); + BFD_RELEASE_WRITE_LOCK; + LIBCWD_CLEANUP_POP_RESTORE(false) if (object_file) { - set_alloc_checking_off(LIBCWD_TSD); - cwbfd::NEEDS_WRITE_LOCK_object_files().sort(cwbfd::object_file_greater()); - set_alloc_checking_on(LIBCWD_TSD); - BFD_RELEASE_WRITE_LOCK; - LIBCWD_RESTORE_CANCEL_NO_BRACE // MT: dlopen_map uses a userspace_allocator and might therefore write to dc::malloc. // This means that the thread can be cancelled inside the insert() call, leaving // dlopen_map in an undefined state. Therefore we disable cancellation. LIBCWD_DISABLE_CANCEL - DLOPEN_MAP_ACQUIRE_LOCK; + DLOPEN_MAP_ACQUIRE_LOCK libcw::debug::_private_::dlopen_map.insert(std::pair<void* const, dlloaded_st>(handle, dlloaded_st(object_file, flags))); -#ifdef LIBCWD_THREAD_SAFE - DLOPEN_MAP_RELEASE_LOCK; - // If the thread is cancelled next, then we don't need to take action regarding dlopen_map: - // The shared library will state loaded. + DLOPEN_MAP_RELEASE_LOCK LIBCWD_ENABLE_CANCEL -#endif - } - else - { - BFD_RELEASE_WRITE_LOCK; - LIBCWD_RESTORE_CANCEL_NO_BRACE } return handle; } @@ -1502,8 +1493,8 @@ LIBCWD_TSD_DECLARATION LIBCWD_ASSERT( !__libcwd_tsd.internal ); int ret = ::dlclose(handle); - DLOPEN_MAP_ACQUIRE_LOCK; - // MT: Cancellation is defered at this point. The first cancellation point is in DLOPEN_MAP_RELEASE_LOCK. + LIBCWD_DEFER_CANCEL + DLOPEN_MAP_ACQUIRE_LOCK libcw::debug::_private_::dlopen_map_ct::iterator iter(libcw::debug::_private_::dlopen_map.find(handle)); if (iter != libcw::debug::_private_::dlopen_map.end()) { @@ -1527,7 +1518,8 @@ pthread_setcancelstate(oldstate, NULL); #endif } - DLOPEN_MAP_RELEASE_LOCK; + DLOPEN_MAP_RELEASE_LOCK + LIBCWD_RESTORE_CANCEL return ret; } } // extern "C" Index: src/libcwd/configure.in diff -u src/libcwd/configure.in:1.100 src/libcwd/configure.in:1.101 --- src/libcwd/configure.in:1.100 Thu Jan 31 21:21:05 2002 +++ src/libcwd/configure.in Sat Feb 2 20:15:11 2002 @@ -1,5 +1,5 @@ dnl Process this file with autoconf to produce a configure script. -AC_REVISION($Revision: 1.100 $)dnl +AC_REVISION($Revision: 1.101 $)dnl dnl General intialization of `autoconf' varaibles. dnl Ensure that the directory specified with --srcdir was correct @@ -344,8 +344,6 @@ CW_CONFIG_HAVE_PTHREADS=undef AC_SUBST(LIB_THREADS) AC_SUBST(LIB_THREADS_SHARED) -CW_CONFIG_HAVE__PTHREAD_CLEANUP_BUFFER=undef -AC_SUBST(CW_CONFIG_HAVE__PTHREAD_CLEANUP_BUFFER) if test "$libcwd_config_threading" = yes; then dnl Check if we have POSIX threads @@ -382,8 +380,6 @@ dnl itself even!. AC_CHECK_LIB(pthread, pthread_create, [LIB_THREADS_SHARED=-lpthread]) fi - - AC_CHECK_TYPE([struct _pthread_cleanup_buffer],[CW_CONFIG_HAVE__PTHREAD_CLEANUP_BUFFER=define],,[#include <pthread.h>]) fi dnl This test needs the full set of libraries we just determined. Index: src/libcwd/debug.cc diff -u src/libcwd/debug.cc:1.60 src/libcwd/debug.cc:1.61 --- src/libcwd/debug.cc:1.60 Wed Jan 30 20:42:08 2002 +++ src/libcwd/debug.cc Sat Feb 2 20:15:11 2002 @@ -1,4 +1,4 @@ -// $Header: /cvsroot/l/li/libcw/src/libcwd/debug.cc,v 1.60 2002/01/31 04:42:08 libcw Exp $ +// $Header: /cvsroot/l/li/libcw/src/libcwd/debug.cc,v 1.61 2002/02/03 04:15:11 libcw Exp $ // // Copyright (C) 2000 - 2001, by // @@ -75,7 +75,7 @@ char* buf; bool used_malloc = false; int curlen = rdbuf()->pubseekoff(0, ios_base::cur, ios_base::out) - rdbuf()->pubseekoff(0, ios_base::cur, ios_base::in); - if (curlen > 512 || !(buf = (char*)alloca(curlen))) + if (curlen > 512 || !(buf = (char*)__builtin_alloca(curlen))) { set_alloc_checking_off(LIBCWD_TSD); buf = (char*)malloc(curlen); @@ -90,7 +90,9 @@ ++__libcwd_tsd.library_call; ++LIBCWD_DO_TSD_MEMBER(libcw_do, _off); #endif + LIBCWD_DISABLE_CANCEL // We don't want Dout() to be a cancellation point. os->write(buf, curlen); + LIBCWD_ENABLE_CANCEL #ifdef DEBUGMALLOC --LIBCWD_DO_TSD_MEMBER(libcw_do, _off); --__libcwd_tsd.library_call; @@ -300,11 +302,8 @@ debug_objects_ct debug_objects; // List with all debug devices. // _private_:: - void debug_channels_ct::internal_init(LIBCWD_TSD_PARAM) + void debug_channels_ct::init(LIBCWD_TSD_PARAM) { -#ifdef DEBUGDEBUGMALLOC - LIBCWD_ASSERT( __libcwd_tsd.internal ); -#endif #ifdef LIBCWD_THREAD_SAFE _private_::rwlock_tct<_private_::debug_channels_instance>::initialize(); #endif @@ -312,7 +311,9 @@ if (!WNS_debug_channels) // MT: `WNS_debug_channels' is only false when this object is still Non_Shared. { DEBUG_CHANNELS_ACQUIRE_READ2WRITE_LOCK + set_alloc_checking_off(LIBCWD_TSD); WNS_debug_channels = new debug_channels_ct::container_type; + set_alloc_checking_on(LIBCWD_TSD); DEBUG_CHANNELS_RELEASE_WRITE_LOCK } #ifdef LIBCWD_THREAD_SAFE @@ -340,7 +341,7 @@ #endif // _private_:: - void debug_objects_ct::internal_init(LIBCWD_TSD_PARAM) + void debug_objects_ct::init(LIBCWD_TSD_PARAM) { #ifdef LIBCWD_THREAD_SAFE _private_::rwlock_tct<_private_::debug_objects_instance>::initialize(); @@ -354,7 +355,9 @@ init_debugmalloc(); #endif DEBUG_OBJECTS_ACQUIRE_READ2WRITE_LOCK + set_alloc_checking_off(LIBCWD_TSD); WNS_debug_objects = new debug_objects_ct::container_type; + set_alloc_checking_on(LIBCWD_TSD); DEBUG_OBJECTS_RELEASE_WRITE_LOCK } #ifdef LIBCWD_THREAD_SAFE @@ -762,53 +765,53 @@ ++_off; DEBUGDEBUG_CERR( "Entering debug_ct::finish(), _off became " << _off ); + // Handle control flags, if any: + if ((current->mask & error_cf)) + *current_oss << ": " << strerrno(current->err) << " (" << strerror(current->err) << ')'; + if (!(current->mask & nonewline_cf)) + current_oss->put('\n'); + // Write buffer to ostream. static_cast<buffer_ct*>(current_oss)->writeto(target_os LIBCWD_COMMA_TSD); - channel_set.mask = current->mask; - channel_set.label = current->label; // Handle control flags, if any: - if (channel_set.mask == 0) - target_os->put('\n'); - else + if (current->mask != 0) { - if ((channel_set.mask & error_cf)) - *target_os << ": " << strerrno(current->err) << " (" << strerror(current->err) << ')'; - if ((channel_set.mask & coredump_maskbit)) - { - if (!__libcwd_tsd.recursive_fatal) - { - __libcwd_tsd.recursive_fatal = true; - *target_os << std::endl; // First time, try to write a new-line and flush. - } - core_dump(); - } - if ((channel_set.mask & fatal_maskbit)) + if ((current->mask & (coredump_maskbit|fatal_maskbit))) { + set_alloc_checking_on(LIBCWD_TSD); if (!__libcwd_tsd.recursive_fatal) { __libcwd_tsd.recursive_fatal = true; - *target_os << std::endl; + LIBCWD_DISABLE_CANCEL + *target_os << std::flush; // First time, try to flush. + LIBCWD_ENABLE_CANCEL } + if ((current->mask & coredump_maskbit)) + core_dump(); DEBUGDEBUG_CERR( "Deleting `current' " << (void*)current ); delete current; DEBUGDEBUG_CERR( "Done deleting `current'" ); set_alloc_checking_on(LIBCWD_TSD); exit(254); } - if ((channel_set.mask & wait_cf)) + if ((current->mask & wait_cf)) { - *target_os << "\n(type return)"; + *target_os << "(type return)"; if (debug_object.interactive) { *target_os << std::flush; while(std::cin.get() != '\n'); } } - if (!(channel_set.mask & nonewline_cf)) - *target_os << '\n'; - if ((channel_set.mask & flush_cf)) + if ((current->mask & flush_cf)) + { + set_alloc_checking_on(LIBCWD_TSD); + LIBCWD_DISABLE_CANCEL *target_os << std::flush; + LIBCWD_ENABLE_CANCEL + set_alloc_checking_off(LIBCWD_TSD); + } } DEBUGDEBUG_CERR( "Deleting `current' " << (void*)current ); @@ -825,11 +828,12 @@ // Restore previous buffer as being the current one, if any. if (laf_stack.size()) { + control_flag_t mask = current->mask; current = laf_stack.top(); DEBUGDEBUG_CERR( "current = " << (void*)current ); current_oss = ¤t->oss; DEBUGDEBUG_CERR( "current_oss = " << (void*)current_oss ); - if ((channel_set.mask & flush_cf)) + if ((mask & flush_cf)) current->mask |= flush_cf; // Propagate flush to real ostream. } else @@ -857,7 +861,9 @@ DoutFatal( dc::core, "Don't use `DoutFatal' together with `continued_cf', use `Dout' instead. (This message can also occur when using DoutFatal correctly but from the constructor of a global object)." ); } +#ifdef LIBCWD_THREAD_SAFE int debug_ct::S_index_count = 0; +#endif void debug_ct::NS_init(void) { @@ -878,8 +884,8 @@ LIBCWD_TSD_DECLARATION LIBCWD_DEFER_CANCEL + _private_::debug_objects.init(LIBCWD_TSD); set_alloc_checking_off(LIBCWD_TSD); // debug_objects is internal. - _private_::debug_objects.internal_init(LIBCWD_TSD); DEBUG_OBJECTS_ACQUIRE_WRITE_LOCK if (find(_private_::debug_objects.write_locked().begin(), _private_::debug_objects.write_locked().end(), this) @@ -1037,9 +1043,7 @@ channel_ct* tmp = NULL; LIBCWD_TSD_DECLARATION LIBCWD_DEFER_CANCEL - set_alloc_checking_off(LIBCWD_TSD); - _private_::debug_channels.internal_init(LIBCWD_TSD); - set_alloc_checking_on(LIBCWD_TSD); + _private_::debug_channels.init(LIBCWD_TSD); DEBUG_CHANNELS_ACQUIRE_READ_LOCK for(_private_::debug_channels_ct::container_type::const_iterator i(_private_::debug_channels.read_locked().begin()); i != _private_::debug_channels.read_locked().end(); ++i) @@ -1087,9 +1091,9 @@ if (LIBCWD_DO_TSD_MEMBER(debug_object, _off) < 0) { LIBCWD_DEFER_CANCEL - set_alloc_checking_off(LIBCWD_TSD); - _private_::debug_channels.internal_init(LIBCWD_TSD); - set_alloc_checking_on(LIBCWD_TSD); + _private_::debug_channels.init(LIBCWD_TSD); + LIBCWD_RESTORE_CANCEL + LIBCWD_DEFER_CLEANUP_PUSH(&rwlock_tct<debug_channels_instance>::cleanup, NULL) DEBUG_CHANNELS_ACQUIRE_READ_LOCK for(_private_::debug_channels_ct::container_type::const_iterator i(_private_::debug_channels.read_locked().begin()); i != _private_::debug_channels.read_locked().end(); ++i) @@ -1102,8 +1106,8 @@ LibcwDoutStream.write(": Disabled", 10); LibcwDoutScopeEnd; } - DEBUG_CHANNELS_RELEASE_READ_LOCK - LIBCWD_RESTORE_CANCEL + DEBUG_CHANNELS_RELEASE_READ_LOCK + LIBCWD_CLEANUP_POP_RESTORE(false) } } @@ -1167,19 +1171,19 @@ // dependent on the order in which these global objects are // initialized. LIBCWD_DEFER_CANCEL - set_alloc_checking_off(LIBCWD_TSD); // debug_channels is internal. - _private_::debug_channels.internal_init(LIBCWD_TSD); + _private_::debug_channels.init(LIBCWD_TSD); DEBUG_CHANNELS_ACQUIRE_WRITE_LOCK { + set_alloc_checking_off(LIBCWD_TSD); // debug_channels is internal. _private_::debug_channels_ct::container_type& channels(_private_::debug_channels.write_locked()); _private_::debug_channels_ct::container_type::iterator i(channels.begin()); for(; i != channels.end(); ++i) if (strncmp((*i)->get_label(), WNS_label, max_label_len_c) > 0) break; channels.insert(i, this); + set_alloc_checking_on(LIBCWD_TSD); } DEBUG_CHANNELS_RELEASE_WRITE_LOCK - set_alloc_checking_on(LIBCWD_TSD); LIBCWD_RESTORE_CANCEL // Turn debug channel "WARNING" on by default. @@ -1378,6 +1382,9 @@ core_dump(); } __libcwd_tsd.recursive_assert = true; +#ifdef DEBUGDEBUGTHREADS + __libcwd_tsd.internal_debugging_code = true; +#endif #endif DoutFatal(dc::core, file << ':' << line << ": " << function << ": Assertion `" << expr << "' failed.\n"); } Index: src/libcwd/debugmalloc.cc diff -u src/libcwd/debugmalloc.cc:1.77 src/libcwd/debugmalloc.cc:1.78 --- src/libcwd/debugmalloc.cc:1.77 Wed Jan 30 20:42:08 2002 +++ src/libcwd/debugmalloc.cc Sat Feb 2 20:15:11 2002 @@ -1,4 +1,4 @@ -// $Header: /cvsroot/l/li/libcw/src/libcwd/debugmalloc.cc,v 1.77 2002/01/31 04:42:08 libcw Exp $ +// $Header: /cvsroot/l/li/libcw/src/libcwd/debugmalloc.cc,v 1.78 2002/02/03 04:15:11 libcw Exp $ // // Copyright (C) 2000 - 2001, by // @@ -1660,13 +1660,13 @@ __libcwd_tsd.internal = 0; } - LIBCWD_DEFER_CANCEL + LIBCWD_DEFER_CLEANUP_PUSH(&rwlock_tct<memblk_map_instance>::cleanup, NULL); ACQUIRE_READ_LOCK LibcwDout( channels, debug_object, dc_malloc, "Allocated memory: " << const_dm_alloc_ct::get_memsize() << " bytes in " << const_dm_alloc_ct::get_memblks() << " blocks." ); if (base_alloc_list) const_cast<dm_alloc_ct const*>(base_alloc_list)->show_alloc_list(1, channels::dc_malloc); RELEASE_READ_LOCK - LIBCWD_RESTORE_CANCEL + LIBCWD_CLEANUP_POP_RESTORE(false); } //============================================================================= Index: src/libcwd/elf32.cc diff -u src/libcwd/elf32.cc:1.35 src/libcwd/elf32.cc:1.36 --- src/libcwd/elf32.cc:1.35 Fri Feb 1 07:48:21 2002 +++ src/libcwd/elf32.cc Sat Feb 2 20:15:11 2002 @@ -1,4 +1,4 @@ -// $Header: /cvsroot/l/li/libcw/src/libcwd/elf32.cc,v 1.35 2002/02/01 15:48:21 libcw Exp $ +// $Header: /cvsroot/l/li/libcw/src/libcwd/elf32.cc,v 1.36 2002/02/03 04:15:11 libcw Exp $ // // Copyright (C) 2001, by // @@ -1928,8 +1928,10 @@ char* object_file_ct::allocate_and_read_section(int i) { char* p = new char[M_sections[i].section_header().sh_size]; + LIBCWD_DISABLE_CANCEL M_input_stream.rdbuf()->pubseekpos(M_sections[i].section_header().sh_offset); M_input_stream.read(p, M_sections[i].section_header().sh_size); + LIBCWD_ENABLE_CANCEL return p; } Index: src/libcwd/include/libcw/macro_ForAllDebugChannels.h diff -u src/libcwd/include/libcw/macro_ForAllDebugChannels.h:1.4 src/libcwd/include/libcw/macro_ForAllDebugChannels.h:1.5 --- src/libcwd/include/libcw/macro_ForAllDebugChannels.h:1.4 Wed Jan 30 20:42:08 2002 +++ src/libcwd/include/libcw/macro_ForAllDebugChannels.h Sat Feb 2 20:15:11 2002 @@ -1,4 +1,4 @@ -// $Header: /cvsroot/l/li/libcw/src/libcwd/include/libcw/macro_ForAllDebugChannels.h,v 1.4 2002/01/31 04:42:08 libcw Exp $ +// $Header: /cvsroot/l/li/libcw/src/libcwd/include/libcw/macro_ForAllDebugChannels.h,v 1.5 2002/02/03 04:15:11 libcw Exp $ // // Copyright (C) 2000 - 2001, by // @@ -44,7 +44,7 @@ typedef internal_vector<channel_ct*> container_type; container_type* WNS_debug_channels; public: - void internal_init(LIBCWD_TSD_PARAM); + void init(LIBCWD_TSD_PARAM); #ifdef LIBCWD_THREAD_SAFE void init_and_rdlock(void); #endif Index: src/libcwd/include/libcw/macro_ForAllDebugObjects.h diff -u src/libcwd/include/libcw/macro_ForAllDebugObjects.h:1.4 src/libcwd/include/libcw/macro_ForAllDebugObjects.h:1.5 --- src/libcwd/include/libcw/macro_ForAllDebugObjects.h:1.4 Wed Jan 30 20:42:08 2002 +++ src/libcwd/include/libcw/macro_ForAllDebugObjects.h Sat Feb 2 20:15:11 2002 @@ -1,4 +1,4 @@ -// $Header: /cvsroot/l/li/libcw/src/libcwd/include/libcw/macro_ForAllDebugObjects.h,v 1.4 2002/01/31 04:42:08 libcw Exp $ +// $Header: /cvsroot/l/li/libcw/src/libcwd/include/libcw/macro_ForAllDebugObjects.h,v 1.5 2002/02/03 04:15:11 libcw Exp $ // // Copyright (C) 2000 - 2001, by // @@ -46,7 +46,7 @@ private: container_type* WNS_debug_objects; public: - void internal_init(LIBCWD_TSD_PARAM); + void init(LIBCWD_TSD_PARAM); #ifdef LIBCWD_THREAD_SAFE void init_and_rdlock(void); #endif Index: src/libcwd/include/libcw/private_struct_TSD.h diff -u src/libcwd/include/libcw/private_struct_TSD.h:1.3 src/libcwd/include/libcw/private_struct_TSD.h:1.4 --- src/libcwd/include/libcw/private_struct_TSD.h:1.3 Thu Jan 31 21:21:05 2002 +++ src/libcwd/include/libcw/private_struct_TSD.h Sat Feb 2 20:15:11 2002 @@ -1,4 +1,4 @@ -// $Header: /cvsroot/l/li/libcw/src/libcwd/include/libcw/private_struct_TSD.h,v 1.3 2002/02/01 05:21:05 libcw Exp $ +// $Header: /cvsroot/l/li/libcw/src/libcwd/include/libcw/private_struct_TSD.h,v 1.4 2002/02/03 04:15:11 libcw Exp $ // // Copyright (C) 2001, by // @@ -84,6 +84,9 @@ #ifdef DEBUGDEBUGTHREADS int cancel_explicitely_deferred; int cancel_explicitely_disabled; + int inside_critical_area; + int cleanup_handler_installed; + int internal_debugging_code; #endif #endif int off_cnt_array[256]; Index: src/libcwd/include/libcw/private_threading.h diff -u src/libcwd/include/libcw/private_threading.h:1.17 src/libcwd/include/libcw/private_threading.h:1.18 --- src/libcwd/include/libcw/private_threading.h:1.17 Thu Jan 31 21:21:05 2002 +++ src/libcwd/include/libcw/private_threading.h Sat Feb 2 20:15:12 2002 @@ -1,4 +1,4 @@ -// $Header: /cvsroot/l/li/libcw/src/libcwd/include/libcw/private_threading.h,v 1.17 2002/02/01 05:21:05 libcw Exp $ +// $Header: /cvsroot/l/li/libcw/src/libcwd/include/libcw/private_threading.h,v 1.18 2002/02/03 04:15:12 libcw Exp $ // // Copyright (C) 2001 - 2002, by // @@ -35,10 +35,6 @@ #ifndef LIBCW_PRIVATE_STRUCT_TSD_H #include <libcw/private_struct_TSD.h> #endif -#ifndef LIBCW_CASSERT -#define LIBCW_CASSERT -#include <cassert> -#endif #ifndef LIBCW_CSTRING #define LIBCW_CSTRING #include <cstring> // Needed for std::memset and std::memcpy. @@ -56,7 +52,6 @@ #ifndef LIBCWD_USE_LINUXTHREADS #define LIBCWD_USE_LINUXTHREADS 0 -#undef HAVE__PTHREAD_CLEANUP_BUFFER #endif #ifndef LIBCWD_USE_POSIX_THREADS #define LIBCWD_USE_POSIX_THREADS 0 @@ -68,10 +63,9 @@ #define LibcwDebugThreads(x) #endif -#ifdef DEBUGDEBUGTHREADS -#ifndef LIBCW_CASSERT -#define LIBCW_CASSERT -#include <cassert> +#if defined(DEBUGDEBUGTHREADS) || defined(DEBUGDEBUG) +#ifndef LIBCW_PRIVATE_ASSERT_H +#include <libcw/private_assert.h> #endif #endif @@ -203,13 +197,12 @@ LibcwDebugThreads(\ { \ LIBCWD_TSD_DECLARATION; \ - if (--__libcwd_tsd.cancel_explicitely_disabled < 0) \ - ::libcw::debug::core_dump(); \ + LIBCWD_ASSERT( __libcwd_tsd.cancel_explicitely_disabled > 0 ); \ + --__libcwd_tsd.cancel_explicitely_disabled; \ /* pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL) can call */ \ /* __pthread_do_exit() when the thread is cancelled in the meantime. */ \ /* This might free allocations that are allocated in userspace. */ \ - if (__libcwd_tsd.internal) \ - ::libcw::debug::core_dump(); \ + LIBCWD_ASSERT( !__libcwd_tsd.internal || __libcwd_tsd.cancel_explicitely_disabled || __libcwd_tsd.cancel_explicitely_deferred ); \ } ) \ pthread_setcancelstate(__libcwd_oldstate, NULL); #define LIBCWD_ENABLE_CANCEL \ @@ -231,13 +224,12 @@ LibcwDebugThreads(\ { \ LIBCWD_TSD_DECLARATION; \ - if (--__libcwd_tsd.cancel_explicitely_deferred < 0) \ - ::libcw::debug::core_dump(); \ + LIBCWD_ASSERT( __libcwd_tsd.cancel_explicitely_deferred > 0 ); \ + --__libcwd_tsd.cancel_explicitely_deferred; \ /* pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL) will calls */ \ /* __pthread_do_exit() when the thread is cancelled in the meantime. */ \ /* This might free allocations that are allocated in userspace. */ \ - if (__libcwd_tsd.internal) \ - ::libcw::debug::core_dump(); \ + LIBCWD_ASSERT( !__libcwd_tsd.internal || __libcwd_tsd.cancel_explicitely_disabled || __libcwd_tsd.cancel_explicitely_deferred ); \ } ) \ pthread_setcanceltype(__libcwd_oldtype, NULL); #define LIBCWD_RESTORE_CANCEL \ @@ -251,22 +243,33 @@ { \ LIBCWD_TSD_DECLARATION; \ ++__libcwd_tsd.cancel_explicitely_deferred; \ + ++__libcwd_tsd.cleanup_handler_installed; \ } ) #define LIBCWD_CLEANUP_POP_RESTORE(execute) \ LibcwDebugThreads(\ { \ LIBCWD_TSD_DECLARATION; \ - if (--__libcwd_tsd.cancel_explicitely_deferred < 0) \ - ::libcw::debug::core_dump(); \ - if (__libcwd_tsd.internal) \ - ::libcw::debug::core_dump(); \ + --__libcwd_tsd.cleanup_handler_installed; \ + LIBCWD_ASSERT( __libcwd_tsd.cancel_explicitely_deferred > 0 ); \ + --__libcwd_tsd.cancel_explicitely_deferred; \ + LIBCWD_ASSERT( !__libcwd_tsd.internal ); \ } ) \ pthread_cleanup_pop_restore_np(static_cast<int>(execute)) #else // !LIBCWD_USE_LINUXTHREADS #define LIBCWD_DEFER_CLEANUP_PUSH(routine, arg) \ LIBCWD_DEFER_CANCEL \ + LibcwDebugThreads( \ + { \ + LIBCWD_TSD_DECLARATION; \ + ++__libcwd_tsd.cleanup_handler_installed; \ + } ) \ pthread_cleanup_push(reinterpret_cast<void(*)(void*)>(routine), reinterpret_cast<void*>(arg)) #define LIBCWD_CLEANUP_POP_RESTORE(execute) \ + LibcwDebugThreads( \ + { \ + LIBCWD_TSD_DECLARATION; \ + --__libcwd_tsd.cleanup_handler_installed; \ + } ) \ pthread_cleanup_pop(static_cast<int>(execute)); \ LIBCWD_RESTORE_CANCEL #endif // !LIBCWD_USE_LINUXTHREADS @@ -289,8 +292,7 @@ /* When entering a critical area, make sure that we have explictely deferred cancellation of this */ \ /* thread (or disabled that) because when cancellation would happen in the middle of the critical */ \ /* area then the lock would stay locked. */ \ - if (!__libcwd_tsd.cancel_explicitely_deferred && !__libcwd_tsd.cancel_explicitely_disabled) \ - ::libcw::debug::core_dump(); \ + LIBCWD_ASSERT( __libcwd_tsd.cancel_explicitely_deferred || __libcwd_tsd.cancel_explicitely_disabled ); \ } ) template <int instance> @@ -317,19 +319,21 @@ public: static bool trylock(void) throw() { - LibcwDebugThreads( assert( S_initialized ) ); + LibcwDebugThreads( LIBCWD_ASSERT( S_initialized ) ); LIBCWD_DEBUGDEBUG_ASSERT_CANCEL_DEFERRED bool success = (pthread_mutex_trylock(&S_mutex) == 0); #ifdef DEBUGDEBUG if (success) instance_locked[instance] += 1; #endif + LibcwDebugThreads( if (success) { LIBCWD_TSD_DECLARATION; ++__libcwd_tsd.inside_critical_area; } ); return success; } static void lock(void) throw() { - LibcwDebugThreads( assert( S_initialized ) ); + LibcwDebugThreads( LIBCWD_ASSERT( S_initialized ) ); LIBCWD_DEBUGDEBUG_ASSERT_CANCEL_DEFERRED + LibcwDebugThreads( if (instance != tsd_initialization_instance) { LIBCWD_TSD_DECLARATION ++__libcwd_tsd.inside_critical_area; } ); #if LIBCWD_DEBUGDEBUGRWLOCK if (instance != tsd_initialization_instance) LIBCWD_DEBUGDEBUGRWLOCK_CERR(pthread_self() << ": locking mutex " << instance); #endif @@ -337,9 +341,7 @@ int res = #endif pthread_mutex_lock(&S_mutex); -#ifdef DEBUGDEBUGTHREADS - assert( res == 0 ); -#endif + LibcwDebugThreads( LIBCWD_ASSERT( res == 0 ) ); #if LIBCWD_DEBUGDEBUGRWLOCK if (instance != tsd_initialization_instance) LIBCWD_DEBUGDEBUGRWLOCK_CERR(pthread_self() << ": mutex " << instance << " locked"); #endif @@ -360,6 +362,7 @@ #if LIBCWD_DEBUGDEBUGRWLOCK if (instance != tsd_initialization_instance) LIBCWD_DEBUGDEBUGRWLOCK_CERR(pthread_self() << ": mutex " << instance << " unlocked"); #endif + LibcwDebugThreads( if (instance != tsd_initialization_instance) { LIBCWD_TSD_DECLARATION --__libcwd_tsd.inside_critical_area; } ); } }; @@ -454,7 +457,7 @@ public: void wait(void) { #ifdef DEBUGDEBUG - assert( is_locked(instance) ); + LIBCWD_ASSERT( is_locked(instance) ); #endif pthread_cond_wait(&S_condition, &S_mutex); } @@ -545,7 +548,7 @@ } static bool tryrdlock(void) throw() { - LibcwDebugThreads( assert( S_initialized ) ); + LibcwDebugThreads( LIBCWD_ASSERT( S_initialized ) ); LIBCWD_DEBUGDEBUG_ASSERT_CANCEL_DEFERRED LIBCWD_DEBUGDEBUGRWLOCK_CERR(pthread_self() << ": Calling rwlock_tct<" << instance << ">::tryrdlock()"); if (instance < end_recursive_types && pthread_equal(S_writer_id, pthread_self())) @@ -560,12 +563,13 @@ if (success) ++S_holders_count; // Add one reader. S_no_holders_condition.unlock(); + LibcwDebugThreads( if (success) { LIBCWD_TSD_DECLARATION; ++__libcwd_tsd.inside_critical_area; } ); LIBCWD_DEBUGDEBUGRWLOCK_CERR(pthread_self() << ": Leaving rwlock_tct<" << instance << ">::tryrdlock()"); return success; } static bool trywrlock(void) throw() { - LibcwDebugThreads( assert( S_initialized ) ); + LibcwDebugThreads( LIBCWD_ASSERT( S_initialized ) ); LIBCWD_DEBUGDEBUG_ASSERT_CANCEL_DEFERRED LIBCWD_DEBUGDEBUGRWLOCK_CERR(pthread_self() << ": Calling rwlock_tct<" << instance << ">::trywrlock()"); bool success = mutex_tct<readers_instance>::trylock(); // Block new readers, @@ -588,12 +592,13 @@ if (instance < end_recursive_types) S_writer_id = pthread_self(); } + LibcwDebugThreads( if (success) { LIBCWD_TSD_DECLARATION; ++__libcwd_tsd.inside_critical_area; } ); LIBCWD_DEBUGDEBUGRWLOCK_CERR(pthread_self() << ": Leaving rwlock_tct<" << instance << ">::trywrlock()"); return success; } static void rdlock(void) throw() { - LibcwDebugThreads( assert( S_initialized ) ); + LibcwDebugThreads( LIBCWD_ASSERT( S_initialized ) ); LIBCWD_DEBUGDEBUG_ASSERT_CANCEL_DEFERRED LIBCWD_DEBUGDEBUGRWLOCK_CERR(pthread_self() << ": Calling rwlock_tct<" << instance << ">::rdlock()"); if (instance < end_recursive_types && pthread_equal(S_writer_id, pthread_self())) @@ -612,6 +617,7 @@ S_no_holders_condition.wait(); // Wait for writer to finish. ++S_holders_count; // Add one reader. S_no_holders_condition.unlock(); + LibcwDebugThreads( LIBCWD_TSD_DECLARATION; ++__libcwd_tsd.inside_critical_area ); LIBCWD_DEBUGDEBUGRWLOCK_CERR(pthread_self() << ": Leaving rwlock_tct<" << instance << ">::rdlock()"); } static void rdunlock(void) throw() @@ -623,6 +629,7 @@ LIBCWD_DEBUGDEBUGRWLOCK_CERR(pthread_self() << ": Leaving rwlock_tct<" << instance << ">::rdunlock() (skipped: thread has write lock)"); return; // No error checking is done. } + LibcwDebugThreads( LIBCWD_TSD_DECLARATION; --__libcwd_tsd.inside_critical_area ); S_no_holders_condition.lock(); if (--S_holders_count == 0) // Was this the last reader? S_no_holders_condition.signal(); // Tell waiting threads. @@ -631,7 +638,7 @@ } static void wrlock(void) throw() { - LibcwDebugThreads( assert( S_initialized ) ); + LibcwDebugThreads( LIBCWD_ASSERT( S_initialized ) ); LIBCWD_DEBUGDEBUG_ASSERT_CANCEL_DEFERRED LIBCWD_DEBUGDEBUGRWLOCK_CERR(pthread_self() << ": Calling rwlock_tct<" << instance << ">::wrlock()"); mutex_tct<readers_instance>::lock(); // Block new readers, @@ -645,6 +652,7 @@ S_no_holders_condition.unlock(); if (instance < end_recursive_types) S_writer_id = pthread_self(); + LibcwDebugThreads( LIBCWD_TSD_DECLARATION; ++__libcwd_tsd.inside_critical_area ); LIBCWD_DEBUGDEBUGRWLOCK_CERR(pthread_self() << ": Leaving rwlock_tct<" << instance << ">::wrlock()"); #ifdef DEBUGDEBUG instance_locked[instance] += 1; @@ -657,6 +665,7 @@ instance_locked[instance] -= 1; #endif LIBCWD_DEBUGDEBUGRWLOCK_CERR(pthread_self() << ": Calling rwlock_tct<" << instance << ">::wrunlock()"); + LibcwDebugThreads( LIBCWD_TSD_DECLARATION; --__libcwd_tsd.inside_critical_area) ; if (instance < end_recursive_types) S_writer_id = 0; S_no_holders_condition.lock(); @@ -756,10 +765,8 @@ LIBCWD_TSD_DECLARATION set_alloc_checking_off(LIBCWD_TSD); delete instance; -#ifdef DEBUGDEBUGTHREADS // Hopefully S_destroy doesn't get called in the thread itself! - assert( instance != &thread_specific_data_tct<TSD>::instance() ); -#endif + LibcwDebugThreads( LIBCWD_ASSERT( instance != &thread_specific_data_tct<TSD>::instance() ) ); set_alloc_checking_on(LIBCWD_TSD); } @@ -815,10 +822,27 @@ // End of Thread Specific Data //=================================================================================================== +extern void fatal_cancellation(void*) throw(); + } // namespace _private_ } // namespace debug } // namespace libcw +#else // !LIBCWD_THREAD_SAFE +#define LIBCWD_DISABLE_CANCEL +#define LIBCWD_DISABLE_CANCEL_NO_BRACE +#define LIBCWD_ENABLE_CANCEL_NO_BRACE +#define LIBCWD_ENABLE_CANCEL +#define LIBCWD_DEFER_CANCEL +#define LIBCWD_DEFER_CANCEL_NO_BRACE +#define LIBCWD_RESTORE_CANCEL_NO_BRACE +#define LIBCWD_RESTORE_CANCEL +#define LIBCWD_DEFER_CLEANUP_PUSH(routine, arg) +#define LIBCWD_CLEANUP_POP_RESTORE(execute) +#define LIBCWD_PUSH_DEFER_TRYLOCK_MUTEX(instance, unlock_routine) +#define LIBCWD_DEFER_PUSH_LOCKMUTEX(instance, unlock_routine) +#define LIBCWD_UNLOCKMUTEX_POP_RESTORE(instance) +#define LIBCWD_DEBUGDEBUG_ASSERT_CANCEL_DEFERRED #endif // LIBCWD_THREAD_SAFE #endif // LIBCW_PRIVATE_THREADING_H Index: src/libcwd/include/raw_write.h diff -u src/libcwd/include/raw_write.h:1.2 src/libcwd/include/raw_write.h:1.3 --- src/libcwd/include/raw_write.h:1.2 Wed Jan 30 20:42:08 2002 +++ src/libcwd/include/raw_write.h Sat Feb 2 20:15:11 2002 @@ -1,5 +1,5 @@ // Generated automatically from sys.ho.in by configure. -// $Header: /cvsroot/l/li/libcw/src/libcwd/include/raw_write.h,v 1.2 2002/01/31 04:42:08 libcw Exp $ +// $Header: /cvsroot/l/li/libcw/src/libcwd/include/raw_write.h,v 1.3 2002/02/03 04:15:11 libcw Exp $ // // Copyright (C) 2001, by // @@ -22,6 +22,11 @@ #include <libcw/debug_config.h> #ifdef DEBUGDEBUG +#ifdef DEBUGDEBUGTHREADS +#define WRITE __libc_write +#else +#define WRITE write +#endif extern "C" ssize_t write(int fd, const void *buf, size_t count) throw(); #ifdef LIBCWD_THREAD_SAFE @@ -39,12 +44,14 @@ do { \ if (1/*::libcw::debug::_private_::WST_ios_base_initialized FIXME: uncomment again*/) { \ LIBCWD_CANCELSTATE_DISABLE \ - ::write(2, "DEBUGDEBUG: ", 12); \ LIBCWD_TSD_DECLARATION \ + LibcwDebugThreads( ++__libcwd_tsd.internal_debugging_code ); \ + ::write(2, "DEBUGDEBUG: ", 12); \ /* __libcwd_lcwc means library_call write counter. Used to avoid the 'scope of for changed' warning. */ \ for (int __libcwd_lcwc = 0; __libcwd_lcwc < __libcwd_tsd.library_call; ++__libcwd_lcwc) \ ::write(2, " ", 4); \ ::libcw::debug::_private_::raw_write << x << '\n'; \ + LibcwDebugThreads( --__libcwd_tsd.internal_debugging_code ); \ LIBCWD_CANCELSTATE_RESTORE \ } \ } while(0) Index: src/libcwd/threading.cc diff -u src/libcwd/threading.cc:1.4 src/libcwd/threading.cc:1.5 --- src/libcwd/threading.cc:1.4 Thu Jan 31 21:21:05 2002 +++ src/libcwd/threading.cc Sat Feb 2 20:15:11 2002 @@ -1,4 +1,4 @@ -// $Header: /cvsroot/l/li/libcw/src/libcwd/threading.cc,v 1.4 2002/02/01 05:21:05 libcw Exp $ +// $Header: /cvsroot/l/li/libcw/src/libcwd/threading.cc,v 1.5 2002/02/03 04:15:11 libcw Exp $ // // Copyright (C) 2001, by // @@ -14,6 +14,7 @@ // #include "sys.h" +#include "cwd_debug.h" #include <libcw/private_threading.h> namespace libcw { @@ -53,6 +54,12 @@ #else // !LIBCWD_THREAD_SAFE TSD_st __libcwd_tsd; #endif // !LIBCWD_THREAD_SAFE + +void fatal_cancellation(void* arg) throw() +{ + char* text = static_cast<char*>(arg); + Dout(dc::core, "Cancelling a thread " << text << ". This is not supported by libcwd, sorry."); +} } // namespace _private_ } // namespace debug ----------------------- End of diff ----------------------- |
From: Carlo W. <li...@us...> - 2002-02-04 03:50:48
|
CVSROOT : /cvsroot/libcw Module : src Commit time: 2002-01-04 03:50:46 UTC Modified files: libcwd/debugmalloc.cc Added files: libcwd/wrapcnclpnts.cc Log message: Forgot to add wrapcnclpnts.cc is last commit. ---------------------- diff included ---------------------- Index: src/libcwd/debugmalloc.cc diff -u src/libcwd/debugmalloc.cc:1.78 src/libcwd/debugmalloc.cc:1.79 --- src/libcwd/debugmalloc.cc:1.78 Sat Feb 2 20:15:11 2002 +++ src/libcwd/debugmalloc.cc Sun Feb 3 19:50:36 2002 @@ -1,4 +1,4 @@ -// $Header: /cvsroot/l/li/libcw/src/libcwd/debugmalloc.cc,v 1.78 2002/02/03 04:15:11 libcw Exp $ +// $Header: /cvsroot/l/li/libcw/src/libcwd/debugmalloc.cc,v 1.79 2002/02/04 03:50:36 libcw Exp $ // // Copyright (C) 2000 - 2001, by // @@ -1739,7 +1739,6 @@ #ifdef DEBUGDEBUGMALLOC LIBCWD_ASSERT( !__libcwd_tsd.internal ); #endif - //LIBCWD_DEFER_CLEANUP_PUSH(&rwlock_tct<memblk_map_instance>::cleanup, NULL); LIBCWD_DEFER_CANCEL ACQUIRE_WRITE_LOCK for (memblk_map_ct::iterator iter(memblk_map_write->begin()); iter != memblk_map_write->end(); ++iter) @@ -1753,7 +1752,6 @@ } RELEASE_WRITE_LOCK LIBCWD_RESTORE_CANCEL - //LIBCWD_CLEANUP_POP_RESTORE(false); } // Undocumented (used in macro AllocTag) Index: src/libcwd/wrapcnclpnts.cc diff -u /dev/null src/libcwd/wrapcnclpnts.cc:1.1 --- /dev/null Sun Feb 3 19:50:46 2002 +++ src/libcwd/wrapcnclpnts.cc Sun Feb 3 19:50:36 2002 @@ -0,0 +1,145 @@ +// $Header: /cvsroot/l/li/libcw/src/libcwd/wrapcnclpnts.cc,v 1.1 2002/02/04 03:50:36 libcw Exp $ +// +// Copyright (C) 2002, by +// +// Carlo Wood, Run on IRC <ca...@al...> +// RSA-1024 0x624ACAD5 1997-01-26 Sign & Encrypt +// Fingerprint16 = 32 EC A7 B6 AC DB 65 A6 F6 F6 55 DD 1C DC FF 61 +// +// This file may be distributed under the terms of the Q Public License +// version 1.0 as appearing in the file LICENSE.QPL included in the +// packaging of this file. +// + +#define _LARGEFILE64_SOURCE + +#include <libcw/sysd.h> +#include <libcw/debug_config.h> // Needed for DEBUGDEBUGTHREADS + +#ifdef DEBUGDEBUGTHREADS + +#ifndef LIBCW_PRIVATE_THREADING_H +#include <libcw/private_threading.h> +#endif +#ifndef LIBCW_PRIVATE_ASSERT_H +#include <libcw/private_assert.h> +#endif + +extern "C" { +#include <unistd.h> +#include <fcntl.h> +#include <sys/mman.h> +#include <pthread.h> +#include <stdarg.h> +#include <stddef.h> +#include <stdlib.h> +#include <termios.h> +#include <sys/resource.h> +#include <sys/wait.h> +#include <sys/socket.h> +} + +#define CANCELLATION_POINT_SYSCALL(return_t, name, arg_list, args) \ +return_t __libc_##name arg_list; \ +return_t __attribute__ ((weak)) name arg_list \ +{ \ + LIBCWD_TSD_DECLARATION \ + LIBCWD_ASSERT( __libcwd_tsd.inside_critical_area == __libcwd_tsd.cleanup_handler_installed || __libcwd_tsd.cancel_explicitely_disabled || __libcwd_tsd.internal_debugging_code ); \ + int oldtype; \ + pthread_setcanceltype (PTHREAD_CANCEL_ASYNCHRONOUS, &oldtype); \ + return_t res = __libc_##name args; \ + pthread_setcanceltype(oldtype, NULL); \ + return res; \ +} + +#define CANCELLATION_POINT_SYSCALL_VA(return_t, name, arg_list, args, last_arg) \ +return_t __libc_##name arg_list; \ +return_t __attribute__ ((weak)) name arg_list \ +{ \ + LIBCWD_TSD_DECLARATION \ + LIBCWD_ASSERT( __libcwd_tsd.inside_critical_area == __libcwd_tsd.cleanup_handler_installed || __libcwd_tsd.cancel_explicitely_disabled || __libcwd_tsd.internal_debugging_code ); \ + int oldtype; \ + pthread_setcanceltype (PTHREAD_CANCEL_ASYNCHRONOUS, &oldtype); \ + va_list ap; \ + va_start(ap, last_arg); \ + return_t res = __libc_##name args; \ + va_end(ap); \ + pthread_setcanceltype(oldtype, NULL); \ + return res; \ +} + +#define strong_alias(name, aliasname) extern __typeof (name) aliasname __attribute__ ((alias (#name))); + +extern "C" { + +CANCELLATION_POINT_SYSCALL (int, close, (int fd), (fd)) +strong_alias(close, __close) + +CANCELLATION_POINT_SYSCALL_VA (int, fcntl, (int fd, int cmd, ...), (fd, cmd, va_arg (ap, long int)), cmd) +strong_alias(fcntl, __fcntl) + +CANCELLATION_POINT_SYSCALL (int, fsync, (int fd), (fd)) + +CANCELLATION_POINT_SYSCALL (off_t, lseek, (int fd, off_t offset, int whence), (fd, offset, whence)) +strong_alias(lseek, __lseek) + +CANCELLATION_POINT_SYSCALL (off64_t, lseek64, (int fd, off64_t offset, int whence), (fd, offset, whence)) + +CANCELLATION_POINT_SYSCALL (int, msync, (__ptr_t addr, size_t length, int flags), (addr, length, flags)) + +CANCELLATION_POINT_SYSCALL (int, nanosleep, (const struct timespec *requested_time, struct timespec *remaining), (requested_time, remaining)) + +CANCELLATION_POINT_SYSCALL_VA (int, open, (const char *pathname, int flags, ...), (pathname, flags, va_arg (ap, mode_t)), flags) +strong_alias(open, __open) + +CANCELLATION_POINT_SYSCALL_VA (int, open64, (const char *pathname, int flags, ...), (pathname, flags, va_arg (ap, mode_t)), flags) +strong_alias(open64, __open64) + +CANCELLATION_POINT_SYSCALL (int, pause, (void), ()) + +CANCELLATION_POINT_SYSCALL (ssize_t, pread, (int fd, void *buf, size_t count, off_t offset), (fd, buf, count, offset)) + +CANCELLATION_POINT_SYSCALL (ssize_t, pread64, (int fd, void *buf, size_t count, off64_t offset), (fd, buf, count, offset)) +strong_alias(pread64, __pread64) + +CANCELLATION_POINT_SYSCALL (ssize_t, pwrite, (int fd, const void *buf, size_t n, off_t offset), (fd, buf, n, offset)) + +CANCELLATION_POINT_SYSCALL (ssize_t, pwrite64, (int fd, const void *buf, size_t n, off64_t offset), (fd, buf, n, offset)) +strong_alias(pwrite64, __pwrite64) + +CANCELLATION_POINT_SYSCALL (ssize_t, read, (int fd, void *buf, size_t count), (fd, buf, count)) +strong_alias(read, __read) + +CANCELLATION_POINT_SYSCALL (int, system, (const char *line), (line)) + +CANCELLATION_POINT_SYSCALL (int, tcdrain, (int fd), (fd)) + +CANCELLATION_POINT_SYSCALL (__pid_t, wait, (__WAIT_STATUS_DEFN stat_loc), (stat_loc)) +strong_alias(wait, __wait) + +CANCELLATION_POINT_SYSCALL (__pid_t, waitpid, (__pid_t pid, int *stat_loc, int options), (pid, stat_loc, options)) + +CANCELLATION_POINT_SYSCALL (ssize_t, write, (int fd, const void *buf, size_t n), (fd, buf, n)) +strong_alias(write, __write) + +CANCELLATION_POINT_SYSCALL (int, accept, (int fd, __SOCKADDR_ARG addr, socklen_t *addr_len), (fd, addr, addr_len)) + +CANCELLATION_POINT_SYSCALL (int, connect, (int fd, __CONST_SOCKADDR_ARG addr, socklen_t len), (fd, addr, len)) +strong_alias(connect, __connect) + +CANCELLATION_POINT_SYSCALL (ssize_t, recv, (int fd, __ptr_t buf, size_t n, int flags), (fd, buf, n, flags)) + +CANCELLATION_POINT_SYSCALL (ssize_t, recvfrom, (int fd, __ptr_t buf, size_t n, int flags, __SOCKADDR_ARG addr, socklen_t *addr_len), (fd, buf, n, flags, addr, addr_len)) + +CANCELLATION_POINT_SYSCALL (ssize_t, recvmsg, (int fd, struct msghdr *message, int flags), (fd, message, flags)) + +CANCELLATION_POINT_SYSCALL (ssize_t, send, (int fd, const __ptr_t buf, size_t n, int flags), (fd, buf, n, flags)) +strong_alias(send, __send) + +CANCELLATION_POINT_SYSCALL (ssize_t, sendmsg, (int fd, const struct msghdr *message, int flags), (fd, message, flags)) + +CANCELLATION_POINT_SYSCALL (ssize_t, sendto, (int fd, const __ptr_t buf, size_t n, int flags, __CONST_SOCKADDR_ARG addr, socklen_t addr_len), (fd, buf, n, flags, addr, addr_len)) + +} // extern "C" + +#endif // DEBUGDEBUGTHREADS ----------------------- End of diff ----------------------- |
From: Carlo W. <li...@us...> - 2002-02-04 03:51:29
|
CVSROOT : /cvsroot/libcw Module : src Commit time: 2002-01-04 03:51:28 UTC Modified files: libcwd/tests/.cvsignore Log message: Ignore threads4 binary. ---------------------- diff included ---------------------- Index: src/libcwd/tests/.cvsignore diff -u src/libcwd/tests/.cvsignore:1.13 src/libcwd/tests/.cvsignore:1.14 --- src/libcwd/tests/.cvsignore:1.13 Sat Dec 29 20:17:50 2001 +++ src/libcwd/tests/.cvsignore Sun Feb 3 19:51:18 2002 @@ -7,6 +7,7 @@ threads threads2 threads3 +threads4 stabs dout_alloc .deps ----------------------- End of diff ----------------------- |
From: Carlo W. <li...@us...> - 2002-02-06 00:46:20
|
CVSROOT : /cvsroot/libcw Module : src Commit time: 2002-01-06 00:46:18 UTC Modified files: libcwd/debug.cc libcwd/debugmalloc.cc libcwd/threading.cc libcwd/include/cwd_debug.h libcwd/include/libcw/class_debug.inl libcwd/include/libcw/debug_config.ho.in libcwd/include/libcw/macro_Libcwd_macros.h libcwd/include/libcw/private_struct_TSD.h libcwd/include/libcw/private_threading.h libcwd/include/libcw/struct_debug_tsd.h libcwd/tests/threads4.cc Log message: Don't use pthread_setspecific and pthread_getspecific anymore: it would destroy our Thread Specific Data at the start of __pthread_do_exit() and we still need that for the following calls to free() (and perhaps other things, like global destructors, at_exit functions etc etc). ---------------------- diff included ---------------------- Index: src/libcwd/debug.cc diff -u src/libcwd/debug.cc:1.61 src/libcwd/debug.cc:1.62 --- src/libcwd/debug.cc:1.61 Sat Feb 2 20:15:11 2002 +++ src/libcwd/debug.cc Tue Feb 5 16:46:07 2002 @@ -1,4 +1,4 @@ -// $Header: /cvsroot/l/li/libcw/src/libcwd/debug.cc,v 1.61 2002/02/03 04:15:11 libcw Exp $ +// $Header: /cvsroot/l/li/libcw/src/libcwd/debug.cc,v 1.62 2002/02/06 00:46:07 libcw Exp $ // // Copyright (C) 2000 - 2001, by // @@ -88,13 +88,13 @@ int saved_internal = __libcwd_tsd.internal; __libcwd_tsd.internal = 0; ++__libcwd_tsd.library_call; - ++LIBCWD_DO_TSD_MEMBER(libcw_do, _off); + ++LIBCWD_DO_TSD_MEMBER_OFF(libcw_do); #endif LIBCWD_DISABLE_CANCEL // We don't want Dout() to be a cancellation point. os->write(buf, curlen); LIBCWD_ENABLE_CANCEL #ifdef DEBUGMALLOC - --LIBCWD_DO_TSD_MEMBER(libcw_do, _off); + --LIBCWD_DO_TSD_MEMBER_OFF(libcw_do); --__libcwd_tsd.library_call; __libcwd_tsd.internal = saved_internal; #endif @@ -284,6 +284,31 @@ channels::dc::system.NS_initialize("SYSTEM"); libcw_do.NS_init(); // Initialize debug code. + + // Unlimit core size. +#ifdef RLIMIT_CORE + struct rlimit corelim; + if (getrlimit(RLIMIT_CORE, &corelim)) + DoutFatal(dc::fatal|error_cf, "getrlimit(RLIMIT_CORE, &corelim)"); + corelim.rlim_cur = corelim.rlim_max; + if (corelim.rlim_max != RLIM_INFINITY) + { + debug_ct::OnOffState state; + libcw_do.force_on(state); + // The cast is necessary on platforms where corelim.rlim_max is long long + // and libstdc++ was not compiled with support for long long. + Dout(dc::warning, "core size is limited (hard limit: " << (unsigned long)(corelim.rlim_max / 1024) << " kb). Core dumps might be truncated!"); + libcw_do.restore(state); + } + if (setrlimit(RLIMIT_CORE, &corelim)) + DoutFatal(dc::fatal|error_cf, "unlimit core size failed"); +#else + debug_ct::OnOffState state; + libcw_do.force_on(state); + Dout(dc::warning, "Please unlimit core size manually"); + libcw_do.restore(state); +#endif + #ifdef DEBUGUSEBFD cwbfd::ST_init(); // Initialize BFD code. #endif @@ -641,8 +666,8 @@ return; } - ++_off; - DEBUGDEBUG_CERR( "Entering debug_ct::start(), _off became " << _off ); + ++LIBCWD_DO_TSD_MEMBER_OFF(debug_object); + DEBUGDEBUG_CERR( "Entering debug_ct::start(), _off became " << LIBCWD_DO_TSD_MEMBER_OFF(debug_object) ); // Is this an interrupting debug output (in the middle of a continued debug output)? if ((current->mask & continued_cf_maskbit) && unfinished_expected) @@ -730,8 +755,8 @@ static_cast<buffer_ct*>(current_oss)->store_position(); } - --_off; - DEBUGDEBUG_CERR( "Leaving debug_ct::start(), _off became " << _off ); + --LIBCWD_DO_TSD_MEMBER_OFF(debug_object); + DEBUGDEBUG_CERR( "Leaving debug_ct::start(), _off became " << LIBCWD_DO_TSD_MEMBER_OFF(debug_object) ); } void debug_tsd_st::finish(debug_ct& debug_object, channel_set_data_st& channel_set LIBCWD_COMMA_TSD_PARAM) @@ -762,8 +787,8 @@ return; } - ++_off; - DEBUGDEBUG_CERR( "Entering debug_ct::finish(), _off became " << _off ); + ++LIBCWD_DO_TSD_MEMBER_OFF(debug_object); + DEBUGDEBUG_CERR( "Entering debug_ct::finish(), _off became " << LIBCWD_DO_TSD_MEMBER_OFF(debug_object) ); // Handle control flags, if any: if ((current->mask & error_cf)) @@ -849,8 +874,8 @@ start_expected = true; unfinished_expected = false; - --_off; - DEBUGDEBUG_CERR( "Leaving debug_ct::finish(), _off became " << _off ); + --LIBCWD_DO_TSD_MEMBER_OFF(debug_object); + DEBUGDEBUG_CERR( "Leaving debug_ct::finish(), _off became " << LIBCWD_DO_TSD_MEMBER_OFF(debug_object) ); set_alloc_checking_on(LIBCWD_TSD); } @@ -898,56 +923,42 @@ set_alloc_checking_off(LIBCWD_TSD); // debug_objects is internal. #endif new (_private_::WST_dummy_laf) laf_ct(0, channels::dc::debug.get_label(), 0); // Leaks 24 bytes of memory -#ifndef LIBCWD_THREAD_SAFE +#ifdef LIBCWD_THREAD_SAFE + WNS_index = S_index_count++; +#ifdef DEBUGDEBUGTHREADS + LIBCWD_ASSERT( pthread_self() == PTHREAD_THREADS_MAX ); // Only the initial thread should be initializing debug_ct objects. +#endif + LIBCWD_ASSERT( __libcwd_tsd.do_array[WNS_index] == NULL ); + debug_tsd_st& tsd(*(__libcwd_tsd.do_array[WNS_index] = new debug_tsd_st)); +#endif tsd.init(); + set_alloc_checking_on(LIBCWD_TSD); + +#ifdef DEBUGDEBUGOUTPUT + LIBCWD_TSD_MEMBER_OFF = -1; // Print as much debug output as possible right away. #else - WNS_index = ++S_index_count; - __libcwd_tsd.do_array[WNS_index].init(); + LIBCWD_TSD_MEMBER_OFF = 0; // Don't print debug output till the REAL initialization of the debug system + // has been performed (ie, the _application_ start (don't confuse that with + // the constructor - which does nothing)). #endif - set_alloc_checking_on(LIBCWD_TSD); + DEBUGDEBUG_CERR( "debug_ct::NS_init(void), _off set to " << LIBCWD_TSD_MEMBER_OFF ); - // This set current_oss and must be called after tsd.init(). + // This sets current_oss and must be called after tsd.init(). set_ostream(&std::cerr); // Write to std::cerr by default. interactive = true; // and thus we're interactive. WNS_initialized = true; - - // Unlimit core size. -#ifdef RLIMIT_CORE - struct rlimit corelim; - if (getrlimit(RLIMIT_CORE, &corelim)) - DoutFatal(dc::fatal|error_cf, "getrlimit(RLIMIT_CORE, &corelim)"); - corelim.rlim_cur = corelim.rlim_max; - if (corelim.rlim_max != RLIM_INFINITY) - { - OnOffState state; - force_on(state); - // The cast is necessary on platforms where corelim.rlim_max is long long - // and libstdc++ was not compiled with support for long long. - Dout(dc::warning, "core size is limited (hard limit: " << (unsigned long)(corelim.rlim_max / 1024) << " kb). Core dumps might be truncated!"); - restore(state); - } - if (setrlimit(RLIMIT_CORE, &corelim)) - DoutFatal(dc::fatal|error_cf, "unlimit core size failed"); -#else - OnOffState state; - force_on(state); - Dout(dc::warning, "Please unlimit core size manually"); - restore(state); -#endif } - debug_tsd_st::debug_tsd_st(void) : _off(0), tsd_initialized(false) { } // Turn off all debugging until initialization is completed. - void debug_tsd_st::init(void) { #ifdef DEBUGDEBUGMALLOC LIBCWD_TSD_DECLARATION LIBCWD_ASSERT( __libcwd_tsd.internal ); #endif - DEBUGDEBUG_CERR( "In debug_tsd_st::init(void), _off set to 0" ); - start_expected = true; // Of course, we start with expecting the beginning of a debug output. + unfinished_expected = false; + // `current' needs to be non-zero (saving us a check in start()) and // current.mask needs to be 0 to avoid a crash in start(): current = reinterpret_cast<laf_ct*>(_private_::WST_dummy_laf); @@ -962,13 +973,14 @@ marker.NS_internal_init(": ", 2); #ifdef DEBUGDEBUGOUTPUT - _off = -1; // Print as much debug output as possible right away. - first_time = true; // Needed to ignore the first time we call on(). -#else - _off = 0; // Don't print debug output till the REAL initialization of the debug system has been performed - // (ie, the _application_ start (don't confuse that with the constructor - which does nothing)). + first_time = true; #endif - DEBUGDEBUG_CERR( "After debug_tsd_st::init(void), _off set to " << _off ); + off_count = 0; + M_margin_stack = NULL; + M_marker_stack = NULL; + indent = 0; + + tsd_initialized = true; } @@ -977,8 +989,11 @@ { ForAllDebugObjects( set_alloc_checking_off(LIBCWD_TSD); - LIBCWD_DO_TSD(debugObject).init(); + LIBCWD_ASSERT( __libcwd_tsd.do_array[(debugObject).WNS_index] == NULL ); + debug_tsd_st& tsd(*(__libcwd_tsd.do_array[(debugObject).WNS_index] = new debug_tsd_st)); + tsd.init(); set_alloc_checking_on(LIBCWD_TSD); + LIBCWD_DO_TSD_MEMBER_OFF(debugObject) = 0; ); } } @@ -993,9 +1008,6 @@ if (laf_stack.size()) DoutFatal( dc::core|cerr_cf, "Destructing debug_tsd_st with a non-empty laf_stack" ); - ++_off; // Turn all debug output premanently off, otherwise we might re-initialize - // this object again when we try to write debug output to it! - DEBUGDEBUG_CERR( "debug_tsd_st destructed: _off became " << _off ); LIBCWD_TSD_DECLARATION set_alloc_checking_off(LIBCWD_TSD); marker.ST_internal_deinit(); @@ -1088,7 +1100,7 @@ void list_channels_on(debug_ct& debug_object) { LIBCWD_TSD_DECLARATION - if (LIBCWD_DO_TSD_MEMBER(debug_object, _off) < 0) + if (LIBCWD_DO_TSD_MEMBER_OFF(debug_object) < 0) { LIBCWD_DEFER_CANCEL _private_::debug_channels.init(LIBCWD_TSD); @@ -1395,11 +1407,11 @@ { NS_init(); LIBCWD_TSD_DECLARATION - state._off = LIBCWD_TSD_MEMBER(_off); + state._off = LIBCWD_TSD_MEMBER_OFF; #ifdef DEBUGDEBUGOUTPUT state.first_time = LIBCWD_TSD_MEMBER(first_time); #endif - LIBCWD_TSD_MEMBER(_off) = -1; // Turn object on. + LIBCWD_TSD_MEMBER_OFF = -1; // Turn object on. } void debug_ct::restore(debug_ct::OnOffState const& state) @@ -1409,9 +1421,9 @@ if (state.first_time != LIBCWD_TSD_MEMBER(first_time)) // state.first_time && !first_time. core_dump(); // on() was called without first a call to off(). #endif - if (LIBCWD_TSD_MEMBER(_off) != -1) + if (LIBCWD_TSD_MEMBER_OFF != -1) core_dump(); // off() and on() where called and not in equal pairs. - LIBCWD_TSD_MEMBER(_off) = state._off; // Restore. + LIBCWD_TSD_MEMBER_OFF = state._off; // Restore. } void channel_ct::force_on(channel_ct::OnOffState& state, char const* label) Index: src/libcwd/debugmalloc.cc diff -u src/libcwd/debugmalloc.cc:1.79 src/libcwd/debugmalloc.cc:1.80 --- src/libcwd/debugmalloc.cc:1.79 Sun Feb 3 19:50:36 2002 +++ src/libcwd/debugmalloc.cc Tue Feb 5 16:46:07 2002 @@ -1,4 +1,4 @@ -// $Header: /cvsroot/l/li/libcw/src/libcwd/debugmalloc.cc,v 1.79 2002/02/04 03:50:36 libcw Exp $ +// $Header: /cvsroot/l/li/libcw/src/libcwd/debugmalloc.cc,v 1.80 2002/02/06 00:46:07 libcw Exp $ // // Copyright (C) 2000 - 2001, by // @@ -289,7 +289,7 @@ do \ { \ DEBUGDEBUG_DoutInternal_MARKER; \ - if (__libcwd_tsd.library_call == 0 && LIBCWD_DO_TSD_MEMBER(libcw_do, _off) < 0) \ + if (__libcwd_tsd.library_call == 0 && LIBCWD_DO_TSD_MEMBER_OFF(libcw_do) < 0) \ { \ DEBUGDEBUG_CERR( "Entering 'DoutInternal(cntrl, \"" << data << "\")'. internal == " << __libcwd_tsd.internal << '.' ); \ channel_set_bootstrap_st channel_set(LIBCWD_DO_TSD(libcw_do) LIBCWD_COMMA_TSD); \ @@ -301,10 +301,10 @@ if (on) \ { \ LIBCWD_DO_TSD(libcw_do).start(libcw_do, channel_set LIBCWD_COMMA_TSD); \ - ++ LIBCWD_DO_TSD_MEMBER(libcw_do, _off); \ + ++ LIBCWD_DO_TSD_MEMBER_OFF(libcw_do); \ _private_::no_alloc_ostream_ct no_alloc_ostream(*LIBCWD_DO_TSD_MEMBER(libcw_do, current_oss)); \ no_alloc_ostream << data; \ - -- LIBCWD_DO_TSD_MEMBER(libcw_do, _off); \ + -- LIBCWD_DO_TSD_MEMBER_OFF(libcw_do); \ LIBCWD_DO_TSD(libcw_do).finish(libcw_do, channel_set LIBCWD_COMMA_TSD); \ } \ DEBUGDEBUG_CERR( "Leaving 'DoutInternal(cntrl, \"" << data << "\")'. internal = " << __libcwd_tsd.internal << '.' ); \ @@ -327,10 +327,10 @@ channel_set&cntrl; \ } \ LIBCWD_DO_TSD(libcw_do).start(libcw_do, channel_set LIBCWD_COMMA_TSD); \ - ++ LIBCWD_DO_TSD_MEMBER(libcw_do, _off); \ + ++ LIBCWD_DO_TSD_MEMBER_OFF(libcw_do); \ _private_::no_alloc_ostream_ct no_alloc_ostream(*LIBCWD_DO_TSD_MEMBER(libcw_do, current_oss)); \ no_alloc_ostream << data; \ - -- LIBCWD_DO_TSD_MEMBER(libcw_do, _off); \ + -- LIBCWD_DO_TSD_MEMBER_OFF(libcw_do); \ LIBCWD_DO_TSD(libcw_do).fatal_finish(libcw_do, channel_set LIBCWD_COMMA_TSD); /* Never returns */ \ LIBCWD_ASSERT( !"Bug in libcwd!" ); \ } \ @@ -413,9 +413,9 @@ #endif return true; WST_ios_base_initialized = true; - ++LIBCWD_DO_TSD_MEMBER(libcw_do, _off); + ++LIBCWD_DO_TSD_MEMBER_OFF(libcw_do); make_all_allocations_invisible_except(NULL); // Get rid of the <pre ios initialization> allocation list. - --LIBCWD_DO_TSD_MEMBER(libcw_do, _off); + --LIBCWD_DO_TSD_MEMBER_OFF(libcw_do); DEBUGDEBUG_CERR( "Standard streams initialized." ); return false; } @@ -1202,15 +1202,15 @@ if (WST_initialization_state <= 0) // Only true prior to initialization of std::ios_base::Init. { #ifdef DEBUGDEBUG - bool continued_debug_output = (__libcwd_tsd.library_call == 0 && LIBCWD_DO_TSD_MEMBER(libcw_do, _off) < 0); + bool continued_debug_output = (__libcwd_tsd.library_call == 0 && LIBCWD_DO_TSD_MEMBER_OFF(libcw_do) < 0); #endif init_debugmalloc(); #ifdef DEBUGDEBUG - // It is possible that libcwd is not initialized at this point, libcw_do._off == 0 (turned off) + // It is possible that libcwd is not initialized at this point, LIBCWD_DO_TSD_MEMBER_OFF(libcw_do) == 0 (turned off) // and thus no unfinished debug output was printed before entering this function. // Initialization of libcwd with DEBUGDEBUG defined turns on libcwd_do. In order to balance the // continued stack, we print an unfinished debug message here. - if (continued_debug_output != (__libcwd_tsd.library_call == 0 && LIBCWD_DO_TSD_MEMBER(libcw_do, _off) < 0)) + if (continued_debug_output != (__libcwd_tsd.library_call == 0 && LIBCWD_DO_TSD_MEMBER_OFF(libcw_do) < 0)) DoutInternal( dc_malloc|continued_cf, "internal_malloc(" << size << ", " << flag << ") = " ); #endif } @@ -1233,10 +1233,10 @@ #ifdef DEBUGUSEBFD if (__libcwd_tsd.library_call++) - ++LIBCWD_DO_TSD_MEMBER(libcw_do, _off); // Otherwise debug output will be generated from bfd.cc (location_ct) + ++LIBCWD_DO_TSD_MEMBER_OFF(libcw_do); // Otherwise debug output will be generated from bfd.cc (location_ct) location_ct loc(call_addr LIBCWD_COMMA_TSD); if (--__libcwd_tsd.library_call) - --LIBCWD_DO_TSD_MEMBER(libcw_do, _off); + --LIBCWD_DO_TSD_MEMBER_OFF(libcw_do); #endif #ifdef DEBUGDEBUGMALLOC @@ -2111,10 +2111,10 @@ #ifdef DEBUGUSEBFD if (__libcwd_tsd.library_call++) - libcw_do._off++; // Otherwise debug output will be generated from bfd.cc (location_ct) + ++LIBCWD_DO_TSD_MEMBER_OFF(libcw_do); // Otherwise debug output will be generated from bfd.cc (location_ct) location_ct loc(reinterpret_cast<char*>(__builtin_return_address(0)) + builtin_return_address_offset LIBCWD_COMMA_TSD); if (--__libcwd_tsd.library_call) - libcw_do._off--; + --LIBCWD_DO_TSD_MEMBER_OFF(libcw_do); #endif DEBUGDEBUG_CERR( "register_external_allocation: internal == " << __libcwd_tsd.internal << "; setting it to 1." ); @@ -2448,10 +2448,10 @@ #ifdef DEBUGUSEBFD if (__libcwd_tsd.library_call++) - ++LIBCWD_DO_TSD_MEMBER(libcw_do, _off); // Otherwise debug output will be generated from bfd.cc (location_ct) + ++LIBCWD_DO_TSD_MEMBER_OFF(libcw_do); // Otherwise debug output will be generated from bfd.cc (location_ct) location_ct loc(reinterpret_cast<char*>(__builtin_return_address(0)) + builtin_return_address_offset LIBCWD_COMMA_TSD); if (--__libcwd_tsd.library_call) - --LIBCWD_DO_TSD_MEMBER(libcw_do, _off); + --LIBCWD_DO_TSD_MEMBER_OFF(libcw_do); #endif DEBUGDEBUG_CERR( "__libcwd_realloc: internal == " << __libcwd_tsd.internal << "; setting it to 1." ); Index: src/libcwd/include/cwd_debug.h diff -u src/libcwd/include/cwd_debug.h:1.7 src/libcwd/include/cwd_debug.h:1.8 --- src/libcwd/include/cwd_debug.h:1.7 Tue Jan 22 20:03:44 2002 +++ src/libcwd/include/cwd_debug.h Tue Feb 5 16:46:08 2002 @@ -1,5 +1,5 @@ // Generated automatically from sys.ho.in by configure. -// $Header: /cvsroot/l/li/libcw/src/libcwd/include/cwd_debug.h,v 1.7 2002/01/23 04:03:44 libcw Exp $ +// $Header: /cvsroot/l/li/libcw/src/libcwd/include/cwd_debug.h,v 1.8 2002/02/06 00:46:08 libcw Exp $ // // Copyright (C) 2001, by // @@ -101,7 +101,7 @@ #define LIBCWD_Dout( cntrl, data ) \ do \ { \ - if (LIBCWD_DO_TSD_MEMBER(libcw_do, _off) < 0) \ + if (LIBCWD_DO_TSD_MEMBER_OFF(libcw_do) < 0) \ { \ bool on; \ channel_set_bootstrap_st channel_set(LIBCWD_DO_TSD(libcw_do) LIBCWD_COMMA_TSD); \ Index: src/libcwd/include/libcw/class_debug.inl diff -u src/libcwd/include/libcw/class_debug.inl:1.5 src/libcwd/include/libcw/class_debug.inl:1.6 --- src/libcwd/include/libcw/class_debug.inl:1.5 Sun Jan 20 08:25:11 2002 +++ src/libcwd/include/libcw/class_debug.inl Tue Feb 5 16:46:08 2002 @@ -1,4 +1,4 @@ -// $Header: /cvsroot/l/li/libcw/src/libcwd/include/libcw/class_debug.inl,v 1.5 2002/01/20 16:25:11 libcw Exp $ +// $Header: /cvsroot/l/li/libcw/src/libcwd/include/libcw/class_debug.inl,v 1.6 2002/02/06 00:46:08 libcw Exp $ // // Copyright (C) 2000 - 2001, by // @@ -210,7 +210,7 @@ debug_ct::off(void) { LIBCWD_TSD_DECLARATION - ++LIBCWD_TSD_MEMBER(_off); + ++LIBCWD_TSD_MEMBER_OFF; } /** @@ -243,12 +243,12 @@ { LIBCWD_TSD_DECLARATION #ifdef DEBUGDEBUGOUTPUT - if (LIBCWD_TSD_MEMBER(first_time) && LIBCWD_TSD_MEMBER(_off) == -1) + if (LIBCWD_TSD_MEMBER(first_time) && LIBCWD_TSD_MEMBER_OFF == -1) LIBCWD_TSD_MEMBER(first_time) = false; else - --LIBCWD_TSD_MEMBER(_off); + --LIBCWD_TSD_MEMBER_OFF; #else - --LIBCWD_TSD_MEMBER(_off); + --LIBCWD_TSD_MEMBER_OFF; #endif } Index: src/libcwd/include/libcw/debug_config.ho.in diff -u src/libcwd/include/libcw/debug_config.ho.in:1.17 src/libcwd/include/libcw/debug_config.ho.in:1.18 --- src/libcwd/include/libcw/debug_config.ho.in:1.17 Thu Jan 31 21:21:05 2002 +++ src/libcwd/include/libcw/debug_config.ho.in Tue Feb 5 16:46:08 2002 @@ -1,5 +1,5 @@ // @configure_input@ -// $Header: /cvsroot/l/li/libcw/src/libcwd/include/libcw/debug_config.ho.in,v 1.17 2002/02/01 05:21:05 libcw Exp $ +// $Header: /cvsroot/l/li/libcw/src/libcwd/include/libcw/debug_config.ho.in,v 1.18 2002/02/06 00:46:08 libcw Exp $ // // Copyright (C) 2000 - 2001, by // @@ -278,6 +278,11 @@ #@CW_CONFIG_HAVE_PTHREADS@ LIBCWD_HAVE_PTHREAD #ifdef LIBCWD_THREAD_SAFE +#define LIBCWD_DO_MAX 8 // Maximal total number of debug objects in a single application. + // This costs about 640 kb of memory per object! (640 bytes * PTHREAD_THREADS_MAX). +#define LIBCWD_DC_MAX 256 // Maximal total number of debug channels in a single application. + // Costs 4 kb of memory per channel (exclusive the actual channels). + /** \defgroup enable_libcwd_debugt --enable-libcwd-debugt (DEBUGDEBUGTHREADS) * \ingroup group_configuration * Index: src/libcwd/include/libcw/macro_Libcwd_macros.h diff -u src/libcwd/include/libcw/macro_Libcwd_macros.h:1.4 src/libcwd/include/libcw/macro_Libcwd_macros.h:1.5 --- src/libcwd/include/libcw/macro_Libcwd_macros.h:1.4 Fri Jan 18 21:08:54 2002 +++ src/libcwd/include/libcw/macro_Libcwd_macros.h Tue Feb 5 16:46:08 2002 @@ -1,4 +1,4 @@ -// $Header: /cvsroot/l/li/libcw/src/libcwd/include/libcw/macro_Libcwd_macros.h,v 1.4 2002/01/19 05:08:54 libcw Exp $ +// $Header: /cvsroot/l/li/libcw/src/libcwd/include/libcw/macro_Libcwd_macros.h,v 1.5 2002/02/06 00:46:08 libcw Exp $ // // Copyright (C) 2000 - 2002, by // @@ -82,7 +82,7 @@ { \ DEBUGDEBUGLIBCWDOUTMARKER \ LIBCWD_TSD_DECLARATION \ - if (LIBCWD_DO_TSD_MEMBER(debug_obj, _off) < 0) \ + if (LIBCWD_DO_TSD_MEMBER_OFF(debug_obj) < 0) \ { \ using namespace ::libcw::debug; \ ::libcw::debug::channel_set_bootstrap_st __libcwd_channel_set(LIBCWD_DO_TSD(debug_obj) LIBCWD_COMMA_TSD); \ Index: src/libcwd/include/libcw/private_struct_TSD.h diff -u src/libcwd/include/libcw/private_struct_TSD.h:1.4 src/libcwd/include/libcw/private_struct_TSD.h:1.5 --- src/libcwd/include/libcw/private_struct_TSD.h:1.4 Sat Feb 2 20:15:11 2002 +++ src/libcwd/include/libcw/private_struct_TSD.h Tue Feb 5 16:46:08 2002 @@ -1,4 +1,4 @@ -// $Header: /cvsroot/l/li/libcw/src/libcwd/include/libcw/private_struct_TSD.h,v 1.4 2002/02/03 04:15:11 libcw Exp $ +// $Header: /cvsroot/l/li/libcw/src/libcwd/include/libcw/private_struct_TSD.h,v 1.5 2002/02/06 00:46:08 libcw Exp $ // // Copyright (C) 2001, by // @@ -21,10 +21,17 @@ #ifndef LIBCW_DEBUG_CONFIG_H #include <libcw/debug_config.h> #endif +#ifndef LIBCW_PRIVATE_ASSERT_H +#include <libcw/private_assert.h> +#endif #ifndef LIBCW_CSTRING #define LIBCW_CSTRING #include <cstring> // Needed for std::memset. #endif +#ifndef LIBCW_LIMITS_H +#define LIBCW_LIMITS_H +#include <limits.h> // For PTHREAD_THREADS_MAX +#endif namespace libcw { namespace debug { @@ -40,23 +47,41 @@ // `__libcwd_tsd' reference needs to be passed. We use several helper macros for this: #ifdef LIBCWD_THREAD_SAFE -#define LIBCWD_TSD __libcwd_tsd // Optional `__libcwd_tsd' parameter - // (foo() or foo(__libcwd_tsd)). -#define LIBCWD_COMMA_TSD , LIBCWD_TSD // Idem, but as second or higher parameter. +#define LIBCWD_TSD __libcwd_tsd // Optional `__libcwd_tsd' parameter (foo() or foo(__libcwd_tsd)). +#define LIBCWD_COMMA_TSD , LIBCWD_TSD // Idem, but as second or higher parameter. #define LIBCWD_TSD_PARAM ::libcw::debug::_private_::TSD_st& __libcwd_tsd - // Optional function parameter - // (foo(void) or foo(TSD_st& __libcwd_tsd)). -#define LIBCWD_COMMA_TSD_PARAM , LIBCWD_TSD_PARAM - // Idem, but as second or higher parameter. + // Optional function parameter (foo(void) or foo(TSD_st& __libcwd_tsd)). +#define LIBCWD_COMMA_TSD_PARAM , LIBCWD_TSD_PARAM // Idem, but as second or higher parameter. +#define LIBCWD_TSD_INSTANCE ::libcw::debug::_private_::TSD_st::instance() + // For directly passing the `__libcwd_tsd' instance to a function (foo(TSD::instance())). +#define LIBCWD_COMMA_TSD_INSTANCE , LIBCWD_TSD_INSTANCE // Idem, but as second or higher parameter. +#define LIBCWD_TSD_DECLARATION ::libcw::debug::_private_::TSD_st& __libcwd_tsd(::libcw::debug::_private_::TSD_st::instance()); + // Declaration of local `__libcwd_tsd' structure reference. +#define LIBCWD_DO_TSD(debug_object) (*__libcwd_tsd.do_array[(debug_object).WNS_index]) + // For use inside class debug_ct to access member `m'. +#define LIBCWD_TSD_MEMBER_OFF (__libcwd_tsd.do_off_array[WNS_index]) + // For use inside class debug_ct to access member `_off'. +#define LIBCWD_DO_TSD_MEMBER_OFF(debug_object) (__libcwd_tsd.do_off_array[(debug_object).WNS_index]) + // To access member _off of debug object. + #else // !LIBCWD_THREAD_SAFE #define LIBCWD_TSD #define LIBCWD_COMMA_TSD #define LIBCWD_TSD_PARAM void #define LIBCWD_COMMA_TSD_PARAM +#define LIBCWD_TSD_INSTANCE +#define LIBCWD_COMMA_TSD_INSTANCE +#define LIBCWD_TSD_DECLARATION +#define LIBCWD_DO_TSD(debug_object) ((debug_object).tsd) +#define LIBCWD_TSD_MEMBER_OFF (tsd._off) +#define LIBCWD_DO_TSD_MEMBER_OFF(debug_object) ((debug_object).tsd._off) #endif // !LIBCWD_THREAD_SAFE +#define LIBCWD_DO_TSD_MEMBER(debug_object, m) (LIBCWD_DO_TSD(debug_object).m) +#define LIBCWD_TSD_MEMBER(m) LIBCWD_DO_TSD_MEMBER(*this, m) + // This include uses the above macros. #ifndef LIBCW_STRUCT_DEBUG_TSD #include <libcw/struct_debug_tsd.h> @@ -64,9 +89,50 @@ namespace libcw { namespace debug { + +#ifdef LIBCWD_THREAD_SAFE +// This function must return 0 for the initial thread and an integer smaller than PTHREAD_THREADS_MAX that +// is unique per _running_ thread. It can be used as index into an array of size PTHREAD_THREADS_MAX. +__inline__ +unsigned long +thread_index(pthread_t tid) +{ + return tid % PTHREAD_THREADS_MAX; +} +#endif + namespace _private_ { +struct TSD_st; + +extern int WST_initializing_TSD; +// Thread Specific Data (TSD) is stored in a structure TSD_st +// and is accessed through a reference to `__libcwd_tsd'. +#ifndef LIBCWD_THREAD_SAFE +// When LIBCWD_THREAD_SAFE is not defined then `__libcwd_tsd' is simply a global object in namespace _private_: +extern TSD_st __libcwd_tsd; +#else +// Otherwise, the Thread Specific Data is stored in this global area: +extern TSD_st __libcwd_tsd_array[PTHREAD_THREADS_MAX]; +#endif + +#ifdef LIBCWD_THREAD_SAFE +// Internal structure of a thread description structure. +struct pthread_descr_struct { + union { + struct { + struct pthread_descr_struct* self; // Pointer to this structure. + void* __padding[12]; // Reserved for future use by pthreads. + unsigned short libcwd_tsd_index; // Abuse this space for libcwd. + } data; + void* __padding[16]; + } p_header; + // ... +}; +#endif + struct TSD_st { +public: #ifdef DEBUGMALLOC int internal; int library_call; @@ -79,8 +145,6 @@ #ifdef DEBUGDEBUG bool recursive_assert; // Detect loop involving LIBCWD_ASSERT. #endif -#ifdef LIBCWD_THREAD_SAFE // Directly contained in debug_ct when not threaded. - debug_tsd_st do_array[16]; // Thread Specific Data of Debug Objects. #ifdef DEBUGDEBUGTHREADS int cancel_explicitely_deferred; int cancel_explicitely_disabled; @@ -88,18 +152,30 @@ int cleanup_handler_installed; int internal_debugging_code; #endif +#ifdef LIBCWD_THREAD_SAFE + pthread_t tid; + int do_off_array[LIBCWD_DO_MAX]; // Thread Specific on/off counter for Debug Objects. + debug_tsd_st* do_array[LIBCWD_DO_MAX];// Thread Specific Data of Debug Objects or NULL when no debug object. #endif - int off_cnt_array[256]; - TSD_st(void) { std::memset(this, 0, sizeof(struct TSD_st)); } -}; + int off_cnt_array[LIBCWD_DC_MAX]; // Thread Specific Data of Debug Channels. -// Thread Specific Data (TSD) is stored in a structure TSD_st -// and is accessed through a reference to `__libcwd_tsd'. -#ifndef LIBCWD_THREAD_SAFE -// When LIBCWD_THREAD_SAFE is not defined then `__libcwd_tsd' is simply a global object in namespace _private_: -extern TSD_st __libcwd_tsd; -#endif -extern int WST_initializing_TSD; + void S_initialize(void) throw(); + +#ifdef LIBCWD_THREAD_SAFE +//------------------------------------------------------- +// Static data and methods. + +public: + static TSD_st& instance(void) throw() + { + pthread_t tid = pthread_self(); + TSD_st* instance = &__libcwd_tsd_array[thread_index(tid)]; + if (!pthread_equal(tid, instance->tid)) + instance->S_initialize(); + return *instance; + } +#endif // LIBCWD_THREAD_SAFE +}; } // namespace _private_ } // namespace debug Index: src/libcwd/include/libcw/private_threading.h diff -u src/libcwd/include/libcw/private_threading.h:1.18 src/libcwd/include/libcw/private_threading.h:1.19 --- src/libcwd/include/libcw/private_threading.h:1.18 Sat Feb 2 20:15:12 2002 +++ src/libcwd/include/libcw/private_threading.h Tue Feb 5 16:46:08 2002 @@ -1,4 +1,4 @@ -// $Header: /cvsroot/l/li/libcw/src/libcwd/include/libcw/private_threading.h,v 1.18 2002/02/03 04:15:12 libcw Exp $ +// $Header: /cvsroot/l/li/libcw/src/libcwd/include/libcw/private_threading.h,v 1.19 2002/02/06 00:46:08 libcw Exp $ // // Copyright (C) 2001 - 2002, by // @@ -70,61 +70,16 @@ #endif #ifdef LIBCWD_THREAD_SAFE -#define LIBCWD_TSD_INSTANCE ::libcw::debug::_private_::\ - thread_specific_data_tct< ::libcw::debug::_private_::TSD_st>::instance() - // For directly passing the `__libcwd_tsd' instance to a function (foo(TSD::instance())). -#define LIBCWD_COMMA_TSD_INSTANCE , LIBCWD_TSD_INSTANCE - // Idem, but as second or higher parameter. -#define LIBCWD_TSD_DECLARATION ::libcw::debug::_private_::\ - TSD_st& __libcwd_tsd(::libcw::debug::_private_::\ - thread_specific_data_tct< ::libcw::debug::_private_::TSD_st>::instance()); - // Declaration of local `__libcwd_tsd' structure reference. -#define LIBCWD_DO_TSD(debug_object) (__libcwd_tsd.do_array[(debug_object).WNS_index]) - // For use inside class debug_ct to access member `m'. -#else // !LIBCWD_THREAD_SAFE -#define LIBCWD_TSD_INSTANCE -#define LIBCWD_COMMA_TSD_INSTANCE -#define LIBCWD_TSD_DECLARATION -#define LIBCWD_DO_TSD(debug_object) ((debug_object).tsd) -#endif // !LIBCWD_THREAD_SAFE -#define LIBCWD_DO_TSD_MEMBER(debug_object, m) (LIBCWD_DO_TSD(debug_object).m) -#define LIBCWD_TSD_MEMBER(m) LIBCWD_DO_TSD_MEMBER(*this, m) - -#ifdef LIBCWD_THREAD_SAFE - namespace libcw { namespace debug { namespace _private_ { +extern void initialize_global_mutexes(void) throw(); #ifdef DEBUGDEBUG extern bool WST_multi_threaded; #endif -#if LIBCWD_USE_POSIX_THREADS || LIBCWD_USE_LINUXTHREADS -template<class TSD> - class thread_specific_data_tct { - private: - static pthread_once_t S_key_once; - static pthread_key_t S_key; - static TSD* S_temporary_instance; - static bool S_initializing; - static bool S_initialized; - static void S_alloc_key(void) throw(); - static TSD* S_initialize(void) throw(); - static void S_destroy(void* tsd_ptr) throw(); - public: - static TSD& instance(void) throw() - { - TSD* instance = reinterpret_cast<TSD*>(pthread_getspecific(S_key)); - if (!instance) - instance = S_initialize(); - return *instance; - } - static bool initialized(void) { return S_initialized; } - }; -#endif // LIBCWD_USE_POSIX_THREADS || LIBCWD_USE_LINUXTHREADS - //=================================================================================================== // // Mutex locking. @@ -738,89 +693,6 @@ else rdunlock(); } - -//=================================================================================================== -// Implementation of Thread Specific Data. - -#if LIBCWD_USE_POSIX_THREADS || LIBCWD_USE_LINUXTHREADS -template<class TSD> - pthread_once_t thread_specific_data_tct<TSD>::S_key_once = PTHREAD_ONCE_INIT; - -template<class TSD> - pthread_key_t thread_specific_data_tct<TSD>::S_key; - -template<class TSD> - TSD* thread_specific_data_tct<TSD>::S_temporary_instance; - -template<class TSD> - bool thread_specific_data_tct<TSD>::S_initializing; - -template<class TSD> - bool thread_specific_data_tct<TSD>::S_initialized; - -template<class TSD> - void thread_specific_data_tct<TSD>::S_destroy(void* tsd_ptr) throw() - { - TSD* instance = reinterpret_cast<TSD*>(tsd_ptr); - LIBCWD_TSD_DECLARATION - set_alloc_checking_off(LIBCWD_TSD); - delete instance; - // Hopefully S_destroy doesn't get called in the thread itself! - LibcwDebugThreads( LIBCWD_ASSERT( instance != &thread_specific_data_tct<TSD>::instance() ) ); - set_alloc_checking_on(LIBCWD_TSD); - } - -template<class TSD> - void thread_specific_data_tct<TSD>::S_alloc_key(void) throw() - { - pthread_key_create(&S_key, S_destroy); - } - -extern void debug_tsd_init(LIBCWD_TSD_PARAM); -extern void initialize_global_mutexes(void) throw(); - -template<class TSD> - TSD* thread_specific_data_tct<TSD>::S_initialize(void) throw() - { - TSD* instance; - bool initialization_of_second_or_later_thread; - pthread_once(&S_key_once, S_alloc_key); - int oldtype; - pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, &oldtype); // Defer cancellation. - mutex_tct<tsd_initialization_instance>::initialize(); - mutex_tct<tsd_initialization_instance>::lock(); - initialization_of_second_or_later_thread = WST_multi_threaded && !S_initializing; - if (S_initializing) - instance = S_temporary_instance; - else - { - char new_TSD_space[sizeof(TSD)]; // Allocate space on the stack. - S_temporary_instance = new (new_TSD_space) TSD; // Create a temporary TSD. - S_initializing = true; - LIBCWD_TSD_DECLARATION // This will 'return' the temporary TSD if TSD == TSD_st. - initialize_global_mutexes(); // This is a good moment to initialize all pthread mutexes. - set_alloc_checking_off(LIBCWD_TSD); - instance = new TSD; - set_alloc_checking_on(LIBCWD_TSD); - pthread_setspecific(S_key, instance); - // Because pthread_setspecific calls calloc, it is possible that in - // the mean time all of libcwd was initialized. Therefore we need - // to copy the temporary TSD to the real TSD because it might - // contain relevant information. - std::memcpy((void*)instance, new_TSD_space, sizeof(TSD)); // Put the temporary TSD in its final place. - S_initializing = false; - S_initialized = true; - } - mutex_tct<tsd_initialization_instance>::unlock(); - if (initialization_of_second_or_later_thread) // Is this a second (or later) thread? - debug_tsd_init(*instance); // Initialize the TSD of existing debug objects. - pthread_setcanceltype(oldtype, NULL); // Restore cancellation. - return instance; - } -#endif // LIBCWD_USE_POSIX_THREADS || LIBCWD_USE_LINUXTHREADS - -// End of Thread Specific Data -//=================================================================================================== extern void fatal_cancellation(void*) throw(); Index: src/libcwd/include/libcw/struct_debug_tsd.h diff -u src/libcwd/include/libcw/struct_debug_tsd.h:1.5 src/libcwd/include/libcw/struct_debug_tsd.h:1.6 --- src/libcwd/include/libcw/struct_debug_tsd.h:1.5 Tue Jan 22 20:03:45 2002 +++ src/libcwd/include/libcw/struct_debug_tsd.h Tue Feb 5 16:46:08 2002 @@ -1,4 +1,4 @@ -// $Header: /cvsroot/l/li/libcw/src/libcwd/include/libcw/struct_debug_tsd.h,v 1.5 2002/01/23 04:03:45 libcw Exp $ +// $Header: /cvsroot/l/li/libcw/src/libcwd/include/libcw/struct_debug_tsd.h,v 1.6 2002/02/06 00:46:08 libcw Exp $ // // Copyright (C) 2002, by // @@ -55,8 +55,10 @@ struct debug_tsd_st { friend class debug_ct; +#ifndef LIBCWD_THREAD_SAFE int _off; // Debug output is turned on when this variable is -1, otherwise it is off. +#endif bool tsd_initialized; // Set after initialization is completed. @@ -112,7 +114,11 @@ // Initialization and de-initialization. void init(void); - debug_tsd_st(void); + debug_tsd_st(void) : +#ifndef LIBCWD_THREAD_SAFE + _off(0), +#endif + tsd_initialized(false) { } ~debug_tsd_st(); }; Index: src/libcwd/tests/threads4.cc diff -u src/libcwd/tests/threads4.cc:1.8 src/libcwd/tests/threads4.cc:1.9 --- src/libcwd/tests/threads4.cc:1.8 Wed Jan 30 20:42:08 2002 +++ src/libcwd/tests/threads4.cc Tue Feb 5 16:46:08 2002 @@ -9,6 +9,8 @@ libcw::debug::channel_ct hello("HELLO"); } } + +using libcw::debug::thread_index; #endif int const loopsize = 1000; @@ -34,16 +36,16 @@ // And for the debug object. Debug( libcw_do.on() ); char margin[32]; - sprintf(margin, "%-10lu", pthread_self()); - Debug( libcw_do.margin().assign(margin, 10) ); + sprintf(margin, "%-10lu (%04lu) ", pthread_self(), thread_index(pthread_self())); + Debug( libcw_do.margin().assign(margin, 18) ); - Dout(dc::notice, "Entering thread " << pthread_self()); + Dout(dc::notice, "Entering thread " << pthread_self() << " (" << thread_index(pthread_self()) << ')'); int cnt = 0; //strstream ss; for (int i = 0; i < loopsize; ++i) { - Dout(dc::notice, "Thread " << pthread_self() << " now starting loop " << i); - Dout(dc::hello, pthread_self() << ':' << cnt++ << "; This should be printed"); + Dout(dc::notice, "Thread " << pthread_self() << " (" << thread_index(pthread_self()) << ") now starting loop " << i); + Dout(dc::hello, pthread_self() << " (" << thread_index(pthread_self()) << "):" << cnt++ << "; This should be printed"); Debug(dc::hello.off()); Debug(dc::hello.off()); @@ -52,7 +54,7 @@ { Dout(dc::notice|continued_cf, "thread_function: creating thread " << j << ", "); pthread_create(&thread_id[j], NULL, thread_function2, NULL); - Dout(dc::finish, "id " << thread_id[j] << '.'); + Dout(dc::finish, "id " << thread_id[j] << " (" << thread_index(thread_id[j]) << ")."); } Dout(dc::hello, "THIS SHOULD NOT BE PRINTED!!!" << (cnt += loopsize + 1)); Debug(dc::hello.on()); @@ -60,10 +62,10 @@ { void* status; pthread_join(thread_id[j], &status); - Dout(dc::notice, "thread_function: thread " << j << ", id " << thread_id[j] << ", returned with status " << ((bool)status ? "OK" : "ERROR") << '.'); + Dout(dc::notice, "thread_function: thread " << j << ", id " << thread_id[j] << " (" << thread_index(thread_id[j]) << "), returned with status " << ((bool)status ? "OK" : "ERROR") << '.'); } } - Dout(dc::notice, "Leaving thread " << pthread_self()); + Dout(dc::notice, "Leaving thread " << pthread_self() << " (" << thread_index(pthread_self()) << ')'); return (void *)(cnt == loopsize); } @@ -76,7 +78,9 @@ #endif Debug( libcw_do.set_ostream(&std::cout) ); Debug( libcw_do.on() ); - Debug( libcw_do.margin().assign("main ", 10) ); + char margin[32]; + sprintf(margin, "%-10lu (%04lu) ", pthread_self(), thread_index(pthread_self())); + Debug( libcw_do.margin().assign(margin, 18) ); ForAllDebugChannels( if (!debugChannel.is_on()) debugChannel.on(); ); Debug( list_channels_on(libcw_do) ); @@ -86,14 +90,14 @@ { Dout(dc::notice|continued_cf, "main: creating thread " << i << ", "); pthread_create(&thread_id[i], NULL, thread_function, NULL); - Dout(dc::finish, "id " << thread_id[i] << '.'); + Dout(dc::finish, "id " << thread_id[i] << " (" << thread_index(thread_id[i]) << ")."); } for (int i = 0; i < number_of_threads; ++i) { void* status; pthread_join(thread_id[i], &status); - Dout(dc::notice, "main loop: thread " << i << ", id " << thread_id[i] << ", returned with status " << ((bool)status ? "OK" : "ERROR") << '.'); + Dout(dc::notice, "main loop: thread " << i << ", id " << thread_id[i] << " (" << thread_index(thread_id[i]) << "), returned with status " << ((bool)status ? "OK" : "ERROR") << '.'); } Dout(dc::notice, "Exiting from main()"); Index: src/libcwd/threading.cc diff -u src/libcwd/threading.cc:1.5 src/libcwd/threading.cc:1.6 --- src/libcwd/threading.cc:1.5 Sat Feb 2 20:15:11 2002 +++ src/libcwd/threading.cc Tue Feb 5 16:46:07 2002 @@ -1,4 +1,4 @@ -// $Header: /cvsroot/l/li/libcw/src/libcwd/threading.cc,v 1.5 2002/02/03 04:15:11 libcw Exp $ +// $Header: /cvsroot/l/li/libcw/src/libcwd/threading.cc,v 1.6 2002/02/06 00:46:07 libcw Exp $ // // Copyright (C) 2001, by // @@ -60,6 +60,43 @@ char* text = static_cast<char*>(arg); Dout(dc::core, "Cancelling a thread " << text << ". This is not supported by libcwd, sorry."); } + +//=================================================================================================== +// Implementation of Thread Specific Data. + +TSD_st __libcwd_tsd_array[PTHREAD_THREADS_MAX]; + +#if LIBCWD_USE_POSIX_THREADS || LIBCWD_USE_LINUXTHREADS +extern void debug_tsd_init(LIBCWD_TSD_PARAM); + +void TSD_st::S_initialize(void) throw() +{ + int oldtype; + pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, &oldtype); + mutex_tct<tsd_initialization_instance>::initialize(); + mutex_tct<tsd_initialization_instance>::lock(); + debug_tsd_st* old_array[LIBCWD_DO_MAX]; + std::memcpy(old_array, do_array, sizeof(old_array)); + std::memset(this, 0, sizeof(struct TSD_st)); // This structure might be reused and therefore already contain data. + tid = pthread_self(); + initialize_global_mutexes(); // This is a good moment to initialize all pthread mutexes. + mutex_tct<tsd_initialization_instance>::unlock(); + if (WST_multi_threaded) // Is this a second (or later) thread? + { + set_alloc_checking_off(*this); + for (int i = 0; i < LIBCWD_DO_MAX; ++i) + if (old_array[i]) + delete old_array[i]; // Free old objects when this structure is being reused. + set_alloc_checking_on(*this); + debug_tsd_init(*this); // Initialize the TSD of existing debug objects. + } + pthread_setcanceltype(oldtype, NULL); +} + +#endif // LIBCWD_USE_POSIX_THREADS || LIBCWD_USE_LINUXTHREADS + +// End of Thread Specific Data +//=================================================================================================== } // namespace _private_ } // namespace debug ----------------------- End of diff ----------------------- |
From: Carlo W. <li...@us...> - 2002-02-07 00:38:50
|
CVSROOT : /cvsroot/libcw Module : src Commit time: 2002-01-07 00:38:48 UTC Modified files: libcwd/debugmalloc.cc libcwd/threading.cc libcwd/include/libcw/private_struct_TSD.h libcwd/include/libcw/private_threading.h libcwd/tests/threads.cc Log message: Bug fix of rwlock_tct<>::trywrlock(). Don't use rwlock in debugmalloc anymore in order to avoid dead-lock. Fix of tests/threads.cc Detect end of thread by means of a 'clean up' key trick. ---------------------- diff included ---------------------- Index: src/libcwd/debugmalloc.cc diff -u src/libcwd/debugmalloc.cc:1.80 src/libcwd/debugmalloc.cc:1.81 --- src/libcwd/debugmalloc.cc:1.80 Tue Feb 5 16:46:07 2002 +++ src/libcwd/debugmalloc.cc Wed Feb 6 16:38:38 2002 @@ -1,4 +1,4 @@ -// $Header: /cvsroot/l/li/libcw/src/libcwd/debugmalloc.cc,v 1.80 2002/02/06 00:46:07 libcw Exp $ +// $Header: /cvsroot/l/li/libcw/src/libcwd/debugmalloc.cc,v 1.81 2002/02/07 00:38:38 libcw Exp $ // // Copyright (C) 2000 - 2001, by // @@ -171,14 +171,18 @@ // D libcw::debug::dm_alloc_ct::memsize // #ifdef LIBCWD_THREAD_SAFE -using libcw::debug::_private_::rwlock_tct; +using libcw::debug::_private_::mutex_tct; using libcw::debug::_private_::memblk_map_instance; -#define ACQUIRE_WRITE_LOCK rwlock_tct<memblk_map_instance>::wrlock(); -#define RELEASE_WRITE_LOCK rwlock_tct<memblk_map_instance>::wrunlock(); -#define ACQUIRE_READ_LOCK rwlock_tct<memblk_map_instance>::rdlock(); -#define RELEASE_READ_LOCK rwlock_tct<memblk_map_instance>::rdunlock(); -#define ACQUIRE_READ2WRITE_LOCK rwlock_tct<memblk_map_instance>::rd2wrlock(); -#define ACQUIRE_WRITE2READ_LOCK rwlock_tct<memblk_map_instance>::wr2rdlock(); +// We can't use rwlock_tct here because that leads to a dead lock. +// rwlocks have to use condition variables or semaphores and both try to get a +// (libpthread internal) self-lock that is already set by libthread when it calls +// free() in order to destroy thread specific data 1st level arrays. +#define ACQUIRE_WRITE_LOCK mutex_tct<memblk_map_instance>::lock(); // rwlock_tct<memblk_map_instance>::wrlock(); +#define RELEASE_WRITE_LOCK mutex_tct<memblk_map_instance>::unlock(); // rwlock_tct<memblk_map_instance>::wrunlock(); +#define ACQUIRE_READ_LOCK mutex_tct<memblk_map_instance>::lock(); // rwlock_tct<memblk_map_instance>::rdlock(); +#define RELEASE_READ_LOCK mutex_tct<memblk_map_instance>::unlock(); // rwlock_tct<memblk_map_instance>::rdunlock(); +#define ACQUIRE_READ2WRITE_LOCK // rwlock_tct<memblk_map_instance>::rd2wrlock(); +#define ACQUIRE_WRITE2READ_LOCK // rwlock_tct<memblk_map_instance>::wr2rdlock(); #else // !LIBCWD_THREAD_SAFE #define ACQUIRE_WRITE_LOCK #define RELEASE_WRITE_LOCK @@ -1660,7 +1664,7 @@ __libcwd_tsd.internal = 0; } - LIBCWD_DEFER_CLEANUP_PUSH(&rwlock_tct<memblk_map_instance>::cleanup, NULL); + LIBCWD_DEFER_CLEANUP_PUSH(&mutex_tct<memblk_map_instance>::cleanup /* &rwlock_tct<memblk_map_instance>::cleanup */, NULL); ACQUIRE_READ_LOCK LibcwDout( channels, debug_object, dc_malloc, "Allocated memory: " << const_dm_alloc_ct::get_memsize() << " bytes in " << const_dm_alloc_ct::get_memblks() << " blocks." ); if (base_alloc_list) Index: src/libcwd/include/libcw/private_struct_TSD.h diff -u src/libcwd/include/libcw/private_struct_TSD.h:1.5 src/libcwd/include/libcw/private_struct_TSD.h:1.6 --- src/libcwd/include/libcw/private_struct_TSD.h:1.5 Tue Feb 5 16:46:08 2002 +++ src/libcwd/include/libcw/private_struct_TSD.h Wed Feb 6 16:38:38 2002 @@ -1,4 +1,4 @@ -// $Header: /cvsroot/l/li/libcw/src/libcwd/include/libcw/private_struct_TSD.h,v 1.5 2002/02/06 00:46:08 libcw Exp $ +// $Header: /cvsroot/l/li/libcw/src/libcwd/include/libcw/private_struct_TSD.h,v 1.6 2002/02/07 00:38:38 libcw Exp $ // // Copyright (C) 2001, by // @@ -156,6 +156,7 @@ pthread_t tid; int do_off_array[LIBCWD_DO_MAX]; // Thread Specific on/off counter for Debug Objects. debug_tsd_st* do_array[LIBCWD_DO_MAX];// Thread Specific Data of Debug Objects or NULL when no debug object. + void cleanup_routine(void) throw(); #endif int off_cnt_array[LIBCWD_DC_MAX]; // Thread Specific Data of Debug Channels. @@ -164,6 +165,11 @@ #ifdef LIBCWD_THREAD_SAFE //------------------------------------------------------- // Static data and methods. +private: + static pthread_key_t S_exit_key; + static pthread_once_t S_exit_key_once; + static void S_exit_key_alloc(void) throw(); + static void S_cleanup_routine(void* arg) throw(); public: static TSD_st& instance(void) throw() Index: src/libcwd/include/libcw/private_threading.h diff -u src/libcwd/include/libcw/private_threading.h:1.19 src/libcwd/include/libcw/private_threading.h:1.20 --- src/libcwd/include/libcw/private_threading.h:1.19 Tue Feb 5 16:46:08 2002 +++ src/libcwd/include/libcw/private_threading.h Wed Feb 6 16:38:38 2002 @@ -1,4 +1,4 @@ -// $Header: /cvsroot/l/li/libcw/src/libcwd/include/libcw/private_threading.h,v 1.19 2002/02/06 00:46:08 libcw Exp $ +// $Header: /cvsroot/l/li/libcw/src/libcwd/include/libcw/private_threading.h,v 1.20 2002/02/07 00:38:38 libcw Exp $ // // Copyright (C) 2001 - 2002, by // @@ -105,7 +105,7 @@ object_files_instance, // rwlock end_recursive_types, // Fast mutexes. - memblk_map_instance, // rwlock + memblk_map_instance, mutex_initialization_instance, ids_singleton_tct_S_ids_instance, alloc_tag_desc_instance, @@ -319,6 +319,8 @@ #endif LibcwDebugThreads( if (instance != tsd_initialization_instance) { LIBCWD_TSD_DECLARATION --__libcwd_tsd.inside_critical_area; } ); } + // This is used as cleanup handler with LIBCWD_DEFER_CLEANUP_PUSH. + static void cleanup(void*); }; #if !LIBCWD_USE_LINUXTHREADS || defined(DEBUGDEBUGTHREADS) @@ -387,6 +389,12 @@ ; #endif // !LIBCWD_USE_LINUXTHREADS +template <int instance> + void mutex_tct<instance>::cleanup(void*) + { + unlock(); + } + //========================================================================================================================================17" // class cond_tct @@ -509,7 +517,7 @@ if (instance < end_recursive_types && pthread_equal(S_writer_id, pthread_self())) { LIBCWD_DEBUGDEBUGRWLOCK_CERR(pthread_self() << ": Leaving rwlock_tct<" << instance << ">::tryrdlock() (skipped: thread has write lock)"); - return; // No error checking is done. + return true; // No error checking is done. } // Give a writer a higher priority (kinda fuzzy). if (S_writer_is_waiting || !S_no_holders_condition.trylock()) @@ -527,25 +535,22 @@ LibcwDebugThreads( LIBCWD_ASSERT( S_initialized ) ); LIBCWD_DEBUGDEBUG_ASSERT_CANCEL_DEFERRED LIBCWD_DEBUGDEBUGRWLOCK_CERR(pthread_self() << ": Calling rwlock_tct<" << instance << ">::trywrlock()"); - bool success = mutex_tct<readers_instance>::trylock(); // Block new readers, - while (success) + bool success; + if ((success = mutex_tct<readers_instance>::trylock())) { - S_writer_is_waiting = true; // from this moment on. - if (!S_no_holders_condition.trylock()) + S_writer_is_waiting = true; + if ((success = S_no_holders_condition.trylock())) { - S_writer_is_waiting = false; - mutex_tct<readers_instance>::unlock(); - success = false; - break; + if ((success = (S_holders_count == 0))) + { + S_holders_count = -1; // Mark that we have a writer. + if (instance < end_recursive_types) + S_writer_id = pthread_self(); + } + S_no_holders_condition.unlock(); } - while (S_holders_count != 0) // Other readers or writers have this lock? - S_no_holders_condition.wait(); // Wait until all current holders are done. - S_writer_is_waiting = false; // Stop checking the lock for new readers. - mutex_tct<readers_instance>::unlock(); // Release blocked readers. - S_holders_count = -1; // Mark that we have a writer. - S_no_holders_condition.unlock(); - if (instance < end_recursive_types) - S_writer_id = pthread_self(); + S_writer_is_waiting = false; + mutex_tct<readers_instance>::unlock(); } LibcwDebugThreads( if (success) { LIBCWD_TSD_DECLARATION; ++__libcwd_tsd.inside_critical_area; } ); LIBCWD_DEBUGDEBUGRWLOCK_CERR(pthread_self() << ": Leaving rwlock_tct<" << instance << ">::trywrlock()"); Index: src/libcwd/tests/threads.cc diff -u src/libcwd/tests/threads.cc:1.8 src/libcwd/tests/threads.cc:1.9 --- src/libcwd/tests/threads.cc:1.8 Sun Jan 20 19:20:24 2002 +++ src/libcwd/tests/threads.cc Wed Feb 6 16:38:38 2002 @@ -87,25 +87,36 @@ << location_ct((char*)__builtin_return_address(0) + builtin_return_address_offset)); } +static pthread_key_t key; +static pthread_once_t key_once = PTHREAD_ONCE_INIT; +static void destroy(void* arg) { TSD* tsd = reinterpret_cast<TSD*>(arg); delete tsd; } +static void key_alloc() { pthread_key_create(&key, destroy); } + void* thread_function(void* arguments) { static int thread_counter = -1; + pthread_once(&key_once, key_alloc); + pthread_setspecific(key, new TSD); + // Set Thread Specific on/off flags of the debug channels. ForAllDebugChannels( if (!debugChannel.is_on()) debugChannel.on(); ); // And for the debug object. Debug( libcw_do.on() ); // Serialize incrementation. + int my_id; + LIBCWD_DEFER_CANCEL mutex_tct<test_instance0>::lock(); - int my_id = ++thread_counter; + my_id = ++thread_counter; mutex_tct<test_instance0>::unlock(); + LIBCWD_RESTORE_CANCEL state_thread[my_id] = 0; Dout(dc::notice, my_id << ": Entering thread " << pthread_self()); // Get TSD. - TSD& tsd(libcw::debug::_private_::thread_specific_data_tct<TSD>::instance()); + TSD& tsd(*reinterpret_cast<TSD*>(pthread_getspecific(key))); Dout(dc::notice, my_id << ": tsd is " << (void*)&tsd << '.'); Dout(dc::notice, my_id << ": Here we are " << in_the_middle(my_id)); @@ -129,10 +140,14 @@ rwlock_tct<test_instance0>::initialize(); // Test if rwlocks allows multiple read locks but only one write lock. + LIBCWD_DEFER_CANCEL rwlock_tct<test_instance0>::wrlock(); LIBCWD_ASSERT( !rwlock_tct<test_instance0>::trywrlock() ); LIBCWD_ASSERT( !rwlock_tct<test_instance0>::tryrdlock() ); rwlock_tct<test_instance0>::wrunlock(); + LIBCWD_RESTORE_CANCEL + + LIBCWD_DEFER_CANCEL rwlock_tct<test_instance0>::rdlock(); LIBCWD_ASSERT( !rwlock_tct<test_instance0>::trywrlock() ); LIBCWD_ASSERT( rwlock_tct<test_instance0>::tryrdlock() && (rwlock_tct<test_instance0>::rdunlock(), true) ); @@ -145,12 +160,14 @@ rwlock_tct<test_instance0>::rdunlock(); LIBCWD_ASSERT( rwlock_tct<test_instance0>::tryrdlock() && (rwlock_tct<test_instance0>::rdunlock(), true) ); LIBCWD_ASSERT( rwlock_tct<test_instance0>::trywrlock() && (rwlock_tct<test_instance0>::wrunlock(), true) ); + LIBCWD_RESTORE_CANCEL // Now test that a mutex allows only one lock. + LIBCWD_DEFER_CANCEL mutex_tct<test_instance0>::lock(); LIBCWD_ASSERT( !mutex_tct<test_instance0>::trylock() ); mutex_tct<test_instance0>::unlock(); - + LIBCWD_RESTORE_CANCEL pthread_t thread_id[number_of_threads]; for (int i = 0; i < number_of_threads; ++i) Index: src/libcwd/threading.cc diff -u src/libcwd/threading.cc:1.6 src/libcwd/threading.cc:1.7 --- src/libcwd/threading.cc:1.6 Tue Feb 5 16:46:07 2002 +++ src/libcwd/threading.cc Wed Feb 6 16:38:38 2002 @@ -1,4 +1,4 @@ -// $Header: /cvsroot/l/li/libcw/src/libcwd/threading.cc,v 1.6 2002/02/06 00:46:07 libcw Exp $ +// $Header: /cvsroot/l/li/libcw/src/libcwd/threading.cc,v 1.7 2002/02/07 00:38:38 libcw Exp $ // // Copyright (C) 2001, by // @@ -37,7 +37,7 @@ mutex_tct<dlopen_map_instance>::initialize(); #ifdef DEBUGMALLOC mutex_tct<alloc_tag_desc_instance>::initialize(); - rwlock_tct<memblk_map_instance>::initialize(); + mutex_tct<memblk_map_instance>::initialize(); #endif #if __GNUC__ == 2 && __GNUC_MINOR__ < 96 mutex_tct<type_info_of_instance>::initialize(); @@ -67,6 +67,9 @@ TSD_st __libcwd_tsd_array[PTHREAD_THREADS_MAX]; #if LIBCWD_USE_POSIX_THREADS || LIBCWD_USE_LINUXTHREADS +pthread_key_t TSD_st::S_exit_key; +pthread_once_t TSD_st::S_exit_key_once = PTHREAD_ONCE_INIT; + extern void debug_tsd_init(LIBCWD_TSD_PARAM); void TSD_st::S_initialize(void) throw() @@ -90,7 +93,35 @@ set_alloc_checking_on(*this); debug_tsd_init(*this); // Initialize the TSD of existing debug objects. } + pthread_once(&S_exit_key_once, &TSD_st::S_exit_key_alloc); + pthread_setspecific(S_exit_key, (void*)this); pthread_setcanceltype(oldtype, NULL); +} + +void TSD_st::S_exit_key_alloc(void) throw() +{ + pthread_key_create(&S_exit_key, &TSD_st::S_cleanup_routine); +} + +void TSD_st::cleanup_routine(void) throw() +{ + Dout(dc::always, "Thread " << tid << " is exiting."); + set_alloc_checking_off(*this); + for (int i = 0; i < LIBCWD_DO_MAX; ++i) + if (do_array[i]) + { + do_off_array[i] = 0; // Turn all debugging off! Now, hopefully, we won't use do_array[i] anymore. + debug_tsd_st* ptr = do_array[i]; + do_array[i] = NULL; // Be paranoid. + delete ptr; // Free old objects. + } + set_alloc_checking_on(*this); +} + +void TSD_st::S_cleanup_routine(void* arg) throw() +{ + TSD_st* obj = reinterpret_cast<TSD_st*>(arg); + obj->cleanup_routine(); } #endif // LIBCWD_USE_POSIX_THREADS || LIBCWD_USE_LINUXTHREADS ----------------------- End of diff ----------------------- |
From: Carlo W. <li...@us...> - 2002-02-08 04:03:59
|
CVSROOT : /cvsroot/libcw Module : src Commit time: 2002-01-08 04:03:58 UTC Modified files: libcwd/NEWS libcwd/debug.cc libcwd/demangle3.cc libcwd/threading.cc libcwd/wrapcnclpnts.cc libcwd/documentation/html.footer libcwd/documentation/doxygen-examples/markers.cc libcwd/documentation/tutorial/channel.cc libcwd/documentation/tutorial/faq.m4 libcwd/documentation/tutorial/hello_world.cc libcwd/documentation/tutorial/log_file.cc libcwd/documentation/tutorial/tut1.m4 libcwd/documentation/tutorial/tut2.m4 libcwd/documentation/tutorial/tut3.m4 libcwd/documentation/tutorial/tut6.m4 libcwd/documentation/tutorial/examples5/sys.h libcwd/documentation/tutorial/examples7/sys.h libcwd/example-project/sys.h libcwd/include/libcw/class_debug.h libcwd/include/libcw/private_threading.h libcwd/include/libcw/struct_debug_tsd.h libcwd/include/libcw/sysd.ho.in libcwd/include/libcw/type_info.h libcwd/tests/lines.cc libcwd/tests/stabs.cc libcwd/tests/sys.h libcwd/testsuite/module.cc libcwd/testsuite/libcwd.tst/sys.h Log message: Bug fixes for doxygen. Added debug_ct::keep_tsd Added documentation about the need to define _GNU_SOURCE and updated all sys.h related things. ---------------------- diff included ---------------------- Index: src/libcwd/NEWS diff -u src/libcwd/NEWS:1.65 src/libcwd/NEWS:1.66 --- src/libcwd/NEWS:1.65 Fri Jan 18 21:08:53 2002 +++ src/libcwd/NEWS Thu Feb 7 20:03:46 2002 @@ -61,6 +61,17 @@ Reason: the temporary stringstream that was returned was only valid inside a Dout to begin with. The use of get_os() was dangerous. + You will need to add + #ifndef _GNU_SOURCE + #define _GNU_SOURCE + #endif + to your "sys.h" file, prior to including any other header file, + just before including <libcw/sysd.h>. This is needed because libcwd + uses GNU extensions. Of course, it is not necessary to define + _GNU_SOURCE when CWDEBUG isn't defined, so you may put it inside the + #ifdef CWDEBUG ... #endif. + If you don't understand this, read documentation/html/preparation.html. + Bug fixes: When using .stabs, each first line of code after a source file scope change Index: src/libcwd/debug.cc diff -u src/libcwd/debug.cc:1.62 src/libcwd/debug.cc:1.63 --- src/libcwd/debug.cc:1.62 Tue Feb 5 16:46:07 2002 +++ src/libcwd/debug.cc Thu Feb 7 20:03:46 2002 @@ -1,4 +1,4 @@ -// $Header: /cvsroot/l/li/libcw/src/libcwd/debug.cc,v 1.62 2002/02/06 00:46:07 libcw Exp $ +// $Header: /cvsroot/l/li/libcw/src/libcwd/debug.cc,v 1.63 2002/02/08 04:03:46 libcw Exp $ // // Copyright (C) 2000 - 2001, by // @@ -284,6 +284,7 @@ channels::dc::system.NS_initialize("SYSTEM"); libcw_do.NS_init(); // Initialize debug code. + libcw_do.keep_tsd(true); // Unlimit core size. #ifdef RLIMIT_CORE @@ -1069,7 +1070,7 @@ } /** - * \fn void list_channels_on(debug_ct const& debug_object) + * \fn void list_channels_on(debug_ct& debug_object) * \ingroup group_special * * \brief List all %debug %channels to a given %debug object. @@ -1425,6 +1426,16 @@ core_dump(); // off() and on() where called and not in equal pairs. LIBCWD_TSD_MEMBER_OFF = state._off; // Restore. } + +#ifdef LIBCWD_THREAD_SAFE + bool debug_ct::keep_tsd(bool keep) + { + LIBCWD_TSD_DECLARATION + bool old = LIBCWD_TSD_MEMBER(tsd_keep); + LIBCWD_TSD_MEMBER(tsd_keep) = keep; + return old; + } +#endif void channel_ct::force_on(channel_ct::OnOffState& state, char const* label) { Index: src/libcwd/demangle3.cc diff -u src/libcwd/demangle3.cc:1.13 src/libcwd/demangle3.cc:1.14 --- src/libcwd/demangle3.cc:1.13 Wed Jan 9 08:16:04 2002 +++ src/libcwd/demangle3.cc Thu Feb 7 20:03:46 2002 @@ -1,4 +1,4 @@ -// $Header: /cvsroot/l/li/libcw/src/libcwd/demangle3.cc,v 1.13 2002/01/09 16:16:04 libcw Exp $ +// $Header: /cvsroot/l/li/libcw/src/libcwd/demangle3.cc,v 1.14 2002/02/08 04:03:46 libcw Exp $ // // Copyright (C) 2001, by // @@ -249,7 +249,7 @@ }; enum param_qualifier_nt { - vendor_extention = 'U', + vendor_extension = 'U', array = 'A', pointer_to_member = 'M' }; @@ -1240,7 +1240,7 @@ failure = true; break; } - qualifiers->add_qualifier_start(vendor_extention, start_pos, source_name, M_inside_substitution); + qualifiers->add_qualifier_start(vendor_extension, start_pos, source_name, M_inside_substitution); continue; } case 'A': @@ -1816,7 +1816,7 @@ || (M_pos += decode_encoding(M_str + M_pos, output)) < 0) FAILURE; RETURN; - case 'C': // GNU extention? + case 'C': // GNU extension? { internal_string first; output += "construction vtable for "; Index: src/libcwd/documentation/doxygen-examples/markers.cc diff -u src/libcwd/documentation/doxygen-examples/markers.cc:1.2 src/libcwd/documentation/doxygen-examples/markers.cc:1.3 --- src/libcwd/documentation/doxygen-examples/markers.cc:1.2 Sat Dec 29 20:17:47 2001 +++ src/libcwd/documentation/doxygen-examples/markers.cc Thu Feb 7 20:03:47 2002 @@ -1,3 +1,4 @@ +#define _GNU_SOURCE #include <libcw/sysd.h> #include <libcw/debug.h> Index: src/libcwd/documentation/html.footer diff -u src/libcwd/documentation/html.footer:1.2 src/libcwd/documentation/html.footer:1.3 --- src/libcwd/documentation/html.footer:1.2 Sat Dec 29 20:17:47 2001 +++ src/libcwd/documentation/html.footer Thu Feb 7 20:03:47 2002 @@ -1,4 +1,4 @@ -<ADDRESS>Copyright © 2001 Carlo Wood. All rights reserved.</ADDRESS> +<ADDRESS>Copyright © 2001, 2002 Carlo Wood. All rights reserved.</ADDRESS> </DIV> </BODY> Index: src/libcwd/documentation/tutorial/channel.cc diff -u src/libcwd/documentation/tutorial/channel.cc:1.2 src/libcwd/documentation/tutorial/channel.cc:1.3 --- src/libcwd/documentation/tutorial/channel.cc:1.2 Sat Dec 29 20:17:49 2001 +++ src/libcwd/documentation/tutorial/channel.cc Thu Feb 7 20:03:47 2002 @@ -2,17 +2,16 @@ // Please see the "example-project" in the source distribution of libcwd // for a better Real Life example. +#define _GNU_SOURCE #include <libcw/sysd.h> #define DEBUGCHANNELS ::example // Where we'll put our namespace dc #include <libcw/debug.h> -#ifdef CWDEBUG namespace example { // namespace dc cannot be put in :: namespace dc { libcw::debug::channel_ct ghost("GHOST"); // Create our own Debug Channel } } -#endif int main(void) { Index: src/libcwd/documentation/tutorial/examples5/sys.h diff -u src/libcwd/documentation/tutorial/examples5/sys.h:1.1 src/libcwd/documentation/tutorial/examples5/sys.h:1.2 --- src/libcwd/documentation/tutorial/examples5/sys.h:1.1 Sat Dec 29 17:22:09 2001 +++ src/libcwd/documentation/tutorial/examples5/sys.h Thu Feb 7 20:03:47 2002 @@ -1,6 +1,11 @@ -#ifdef HAVE_CONFIG_H // This is just an example of what you could do -#include "config.h" // when using autoconf for your project. +// This is just an example of what you could do when using autoconf for your project. +#ifdef HAVE_CONFIG_H +#include "config.h" #endif -#ifdef CWDEBUG // This is needed so that others can compile -#include <libcw/sysd.h> // your application without having libcwd installed. +// This is needed so that others can compile your application without having libcwd installed. +#ifdef CWDEBUG +#ifndef _GNU_SOURCE +#define _GNU_SOURCE // Libcwd uses GNU extensions. +#endif +#include <libcw/sysd.h> #endif Index: src/libcwd/documentation/tutorial/examples7/sys.h diff -u src/libcwd/documentation/tutorial/examples7/sys.h:1.2 src/libcwd/documentation/tutorial/examples7/sys.h:1.3 --- src/libcwd/documentation/tutorial/examples7/sys.h:1.2 Sat Dec 29 20:17:49 2001 +++ src/libcwd/documentation/tutorial/examples7/sys.h Thu Feb 7 20:03:47 2002 @@ -1,3 +1,10 @@ +#ifdef CWDEBUG +#ifndef _GNU_SOURCE +#define _GNU_SOURCE +#endif +#include <libcw/sysd.h> +#endif + // Bug workaround for libstdc++, avoid warnings like // /usr/include/g++-3/iostream.h:253:5: "_G_CLOG_CONFLICT" is not defined #include <_G_config.h> @@ -6,8 +13,4 @@ #endif #ifndef _G_HAS_LABS #define _G_HAS_LABS 1 -#endif - -#ifdef CWDEBUG -#include <libcw/sysd.h> #endif Index: src/libcwd/documentation/tutorial/faq.m4 diff -u src/libcwd/documentation/tutorial/faq.m4:1.3 src/libcwd/documentation/tutorial/faq.m4:1.4 --- src/libcwd/documentation/tutorial/faq.m4:1.3 Fri Jan 18 21:08:54 2002 +++ src/libcwd/documentation/tutorial/faq.m4 Thu Feb 7 20:03:47 2002 @@ -14,8 +14,22 @@ <HR SIZE=1 NOSHADE> +<A name="GNU_SOURCE"></A> +<H3>1. Won't this define make my code non-portable?</H3> + +<P>No, not unless you actually use the GNU extensions in parts of your +application that need to be portable (like non-debugging code). +While debugging the application you will only benefit from using as +much compiler support as you can get, allowing the compiler to tell you +what could possibly be wrong with your code. +Once the application works, you don't have to define _GNU_SOURCE +because you won't be including the debug code anymore, nor link with +libcwd. Of course, when you are not sure whether or not new code +that you added is a GNU extension or not, you should try to compile it +with CWDEBUG undefined.</P> + <A name="sysd.h"></A> -<H3>1. Why do I have to include "libcw/sysd.h" as first header file?</H3> +<H3>2. Why do I have to include "libcw/sysd.h" as first header file?</H3> <P>This header file is used to fix operating systems bugs, including bugs in the system header files. The only way it can do this is when it @@ -32,7 +46,7 @@ will definitely lead to compile errors in that header file. </P> <A name="libcwd"></A> -<H3>2. What is this <SPAN class="H3code">libcw</SPAN> talk? +<H3>3. What is this <SPAN class="H3code">libcw</SPAN> talk? Aren't you forgetting the <U><SPAN class="H3code">d</SPAN></U> of <SPAN class="H3code">libcw<U>d</U></SPAN>?</H3> @@ -49,7 +63,7 @@ guessed that ;) ].</P> <A name="dir"></A> -<H3>3. Why do I need to type "<SPAN class="H3code">libcw/sysd.h</SPAN>" +<H3>4. Why do I need to type "<SPAN class="H3code">libcw/sysd.h</SPAN>" and not just "<SPAN class="H3code">sysd.h</SPAN>"?</H3> <P>The header file names of libcw are not unique. In order to uniquely @@ -63,20 +77,20 @@ collision in that case.</P> <A name="debug.h"></A> -<H3>4. What is defined <EM>exactly</EM> in <SPAN class="H3code">libcw/debug.h</SPAN>?</H3> +<H3>5. What is defined <EM>exactly</EM> in <SPAN class="H3code">libcw/debug.h</SPAN>?</H3> <P>Everything. Go and read the <A HREF="../html/reference.html>Reference Manual</A> to get <EM>all</EM> gory details if you dare.</P> <A name="macros"></A> -<H3>5. Why are you using macros for <SPAN class="H3code">Debug</SPAN> and <SPAN class="H3code">Dout</SPAN>?</H3> +<H3>6. Why are you using macros for <SPAN class="H3code">Debug</SPAN> and <SPAN class="H3code">Dout</SPAN>?</H3> <P>Because it is the only way to easy remove debugging code from an application as function of a macro and because it allows for the fastest possible code even without optimisation, which is often the case while debugging. A more detailed explanation is given in the <A HREF="../html/page_why_macro.html">Reference Manual</A>.</P> <A name="Debug"></A> -<H3>6. Why do I need to type the <SPAN class="H3code">Debug( )</SPAN> around it?</H3> +<H3>7. Why do I need to type the <SPAN class="H3code">Debug( )</SPAN> around it?</H3> <P>The macro <SPAN class="code">Debug()</SPAN> is used for two things. 1) The code inside it is only included when the macro <SPAN class="code">CWDEBUG</SPAN> is defined. 2) It includes the namespace <SPAN class="code">libcw::debug</SPAN>.</P> @@ -101,7 +115,7 @@ explanation of <SPAN class="code">DEBUGCHANNELS</SPAN>.</P> <A name="DebugChannels"></A> -<H3>7. Which Debug Channels exist? Can I make my own?</H3> +<H3>8. Which Debug Channels exist? Can I make my own?</H3> <P>This question is covered in chapter <A HREF="../html/group__group__debug__channels.html">Controlling The Output Level (Debug Channels)</A> @@ -139,7 +153,7 @@ with the source distribution of libcwd for a Real Life example.</P> <A name="recursive"></A> -<H3>8. Can I turn Debug Channels off again? Can I do that recursively?</H3> +<H3>9. Can I turn Debug Channels off again? Can I do that recursively?</H3> <P>Debug channels can be switched on and off at any time. At the start of your program you should turn on the channels of your choice by calling <SPAN class="code">Debug(dc::<EM>channel</EM>.on())</SPAN> @@ -163,7 +177,7 @@ <SPAN class="code">off()</SPAN> and <SPAN class="code">on()</SPAN> only respectively increment and decrement a counter.</P> <A name="Channel"></A> -<H3>9. Why do you call it a Debug <EM>Channel</EM>? What <EM>is</EM> a Debug Channel?</H3> +<H3>10. Why do you call it a Debug <EM>Channel</EM>? What <EM>is</EM> a Debug Channel?</H3> <P>A Debug Channel is a fictious "news channel". It should contain information of a certain kind that is interesting or not interesting as a whole. A Debug Channel is not a device or stream, a single debug channel is best @@ -173,7 +187,7 @@ to the output stream of the underlaying debug object.</P> <A name="OwnDebugObject"></A> -<H3>10. Can I make my own Debug Object?</H3> +<H3>11. Can I make my own Debug Object?</H3> <P><A HREF="../html/group__chapter__custom__do.html">Yes</A>, you can make as many debug objects as you like. Each debug object is associated with one ostream. However, the default debug output macros <CODE>Dout</CODE> and @@ -193,7 +207,7 @@ </PRE> <A name="recursive2"></A> -<H3>11. Can I turn Debug Objects off again? Can I do that recursively?</H3> +<H3>12. Can I turn Debug Objects off again? Can I do that recursively?</H3> <P>Debug objects can be switched on and off at any time. At the start of your program you should turn on the debug object(s) by calling <SPAN class="code">Debug(<EM>debugobject</EM>.on())</SPAN> @@ -214,7 +228,7 @@ <SPAN class="code">off()</SPAN> and <SPAN class="code">on()</SPAN> only respectively increment and decrement a counter.</P> <A name="SetOstream"></A> -<H3>12. How do I set a new <SPAN class="H3code">ostream</SPAN> for a given Debug Object?</H3> +<H3>13. How do I set a new <SPAN class="H3code">ostream</SPAN> for a given Debug Object?</H3> <P>You can change the <SPAN class="code">ostream</SPAN> that is associated with a Debug Object at any time. For example, changing the <SPAN class="code">ostream</SPAN> of <SPAN class="code">libcw_do</SPAN> from the @@ -227,7 +241,7 @@ <P>See also <A HREF="tut3.html">tutorial 3</A>.</P> <A name="WhyOff"></A> -<H3>13. Why are Debug Objects turned off at creation?</H3> +<H3>14. Why are Debug Objects turned off at creation?</H3> <P>The Debug Objects and Debug Channels are global objects. Because libcwd could not be dependant of libcw, they do not use libcw's <CODE>Global<></CODE> template. @@ -239,7 +253,7 @@ in the state <EM>off</EM>.</P> <A name="Order"></A> -<H3>14. Why do you turn on the debug object after you enable a debug channel, why not the other way around?</H3> +<H3>15. Why do you turn on the debug object after you enable a debug channel, why not the other way around?</H3> <P>The order in which Debug Channels and Debug Objects are turned on does not matter at all. At most, when you think about the Debug Object as the «main switch» then it seems to make @@ -248,7 +262,7 @@ <EM>on</EM> before I forget it. That is a bit <EM>too</EM> fuzzy (logic) for me though ;)</P> <A name="Object"></A> -<H3>15. Why do you call it a Debug <EM>Object</EM>? What <EM>is</EM> a Debug Object?</H3> +<H3>16. Why do you call it a Debug <EM>Object</EM>? What <EM>is</EM> a Debug Object?</H3> <P>Good question. It can't be because I wasn't creative, I am very creative. Note that I didn't think of <EM>Object</EM> as in OOP (<EM>that</EM> would be uncreative) @@ -263,7 +277,7 @@ <SPAN class="code">ostream</SPAN>.</P> <A name="semicolon"></A> -<H3>16. Do I need to type that semi-colon after the macro? Why isn't it part of the macro?</H3> +<H3>17. Do I need to type that semi-colon after the macro? Why isn't it part of the macro?</H3> <P>Yes, that colon needs to be there. It was chosen not to include the semi-colon in the macro because this way it looks @@ -309,7 +323,7 @@ </PRE> <A name="LibcwDout"></A> -<H3>17. I made my own Debug Object, can I still use <SPAN class="H3code">Dout</SPAN>?</H3> +<H3>18. I made my own Debug Object, can I still use <SPAN class="H3code">Dout</SPAN>?</H3> <P>No, macro <SPAN class="code">Dout</SPAN> et al. use exclusively the debug object that comes with libcwd. It is easy to define your own macros however (see <A HREF="#OwnDebugObject">above</A>). @@ -319,7 +333,7 @@ to redefine it).</P> <A name="evaluation"></A> -<H3>18. Is the second field of the macro still evaluated when the Debug Channel and/or Debug Object are turned off?</H3> +<H3>19. Is the second field of the macro still evaluated when the Debug Channel and/or Debug Object are turned off?</H3> <P>No! And that is a direct result of the fact that <SPAN class="code">Dout</SPAN> et al. are <EM>macros</EM>. Indeed this fact could therefore be a little confusing. @@ -338,19 +352,19 @@ In the production version of your application all debug code will be removed and you don't want it to behave differently then!</P> <A name="suppress"></A> -<H3>19. Can I suppress that new-line character?</H3> +<H3>20. Can I suppress that new-line character?</H3> <P>Yes, and a lot more. See <A HREF="tut5.html#Formatting">tutorial 5.4</A>.</P> <A name="label"></A> -<H3>20. What is the maximum length of a label?</H3> +<H3>21. What is the maximum length of a label?</H3> <P>The maximum length of the label of a new Debug Channel is given by the constant<SPAN class="code"> libcw::debug::max_label_len_c</SPAN>. At this moment that is 16.</P> <A name="prefix"></A> -<H3>21. Why do I have to use the <SPAN class="H3code">dc::</SPAN> prefix?</H3> +<H3>22. Why do I have to use the <SPAN class="H3code">dc::</SPAN> prefix?</H3> <P>This is a complex reason. Basically because of a flaw in the design of namespaces in C++. Namespaces have been introduced in order to avoid name collisions, which was a good thing. @@ -422,13 +436,13 @@ in the <A HREF="../html/group__group__debug__channels.html">Reference Manual</A>.</P> <A name="ownnamespace"></A> -<H3>22. Can I put my debug channels in my own name space?</H3> +<H3>23. Can I put my debug channels in my own name space?</H3> <P>Yes. How, is described in the <A HREF="../html/group__group__debug__channels.html">Reference Manual</A>. For some background information on why this has to be so complex, please read the <A HREF="#prefix">previous question</A>.</P> <A name="labelwidth"></A> -<H3>23. Why does it print spaces between the label and the colon? How is the field width of the label determined?</H3> +<H3>24. Why does it print spaces between the label and the colon? How is the field width of the label determined?</H3> <P>The colon is indented so it ends up in the same column for all existing debug channels. Hence, the longest label of all existing/created debug channels determines the number of spaces. Index: src/libcwd/documentation/tutorial/hello_world.cc diff -u src/libcwd/documentation/tutorial/hello_world.cc:1.2 src/libcwd/documentation/tutorial/hello_world.cc:1.3 --- src/libcwd/documentation/tutorial/hello_world.cc:1.2 Sat Dec 29 20:17:49 2001 +++ src/libcwd/documentation/tutorial/hello_world.cc Thu Feb 7 20:03:47 2002 @@ -1,3 +1,4 @@ +#define _GNU_SOURCE #include <libcw/sysd.h> // This must be the first header file #include <libcw/debug.h> Index: src/libcwd/documentation/tutorial/log_file.cc diff -u src/libcwd/documentation/tutorial/log_file.cc:1.2 src/libcwd/documentation/tutorial/log_file.cc:1.3 --- src/libcwd/documentation/tutorial/log_file.cc:1.2 Sat Dec 29 20:17:49 2001 +++ src/libcwd/documentation/tutorial/log_file.cc Thu Feb 7 20:03:47 2002 @@ -1,3 +1,4 @@ +#define _GNU_SOURCE #include <libcw/sysd.h> #include <fstream> #include <libcw/debug.h> Index: src/libcwd/documentation/tutorial/tut1.m4 diff -u src/libcwd/documentation/tutorial/tut1.m4:1.2 src/libcwd/documentation/tutorial/tut1.m4:1.3 --- src/libcwd/documentation/tutorial/tut1.m4:1.2 Sat Dec 29 20:17:49 2001 +++ src/libcwd/documentation/tutorial/tut1.m4 Thu Feb 7 20:03:47 2002 @@ -13,7 +13,8 @@ <P>Compile as: <SPAN class="shell-command">g++ -g -DCWDEBUG hello_world.cc -lcwd -o hello_world</SPAN></P> <PRE> -#include <libcw/sysd.h> // This must be the first header file +#define _GNU_SOURCE // This must be defined before including <libcw/sysd.h> +#include <libcw/sysd.h> // This must be the first header file #include <libcw/debug.h> int main(void) @@ -28,6 +29,22 @@ </PRE> <P>Each of the lines of code in this first example program are explained below:</P> + +<H3><CODE>#define _GNU_SOURCE</CODE></H3> + +<P>This define is necessary to tell the system headers that you +want to use the GNU extensions (see /usr/include/features.h). +In order to make you explicitely aware of the fact that it is +defined, libcwd does not define this macro itself (which it could do inside <libcw/sysd.h>), +but forces you to define it when using libcwd. +Note you only really have to define it when you compiled libcwd with +threading support. +If you do not define this macro and libcwd needs it, then you will get +a compile error in <libcw/sysd.h> telling you so.</P> + +<DIV class="faq-frame"><H4>FAQ</H4><UL class="faq"> +<LI><A HREF="faq.html#GNU_SOURCE">Won't this define make my code non-portable?</LI> +</UL></DIV> <H3><CODE>#include <libcw/sysd.h></CODE></H3> Index: src/libcwd/documentation/tutorial/tut2.m4 diff -u src/libcwd/documentation/tutorial/tut2.m4:1.2 src/libcwd/documentation/tutorial/tut2.m4:1.3 --- src/libcwd/documentation/tutorial/tut2.m4:1.2 Sat Dec 29 20:17:49 2001 +++ src/libcwd/documentation/tutorial/tut2.m4 Thu Feb 7 20:03:47 2002 @@ -17,6 +17,9 @@ #include "config.h" // when using autoconf for your project. #endif #ifdef CWDEBUG // This is needed so that others can compile +#ifndef _GNU_SOURCE +#define _GNU_SOURCE +#endif #include <libcw/sysd.h> // your application without having libcwd installed. #endif </PRE> Index: src/libcwd/documentation/tutorial/tut3.m4 diff -u src/libcwd/documentation/tutorial/tut3.m4:1.2 src/libcwd/documentation/tutorial/tut3.m4:1.3 --- src/libcwd/documentation/tutorial/tut3.m4:1.2 Sat Dec 29 20:17:49 2001 +++ src/libcwd/documentation/tutorial/tut3.m4 Thu Feb 7 20:03:47 2002 @@ -13,6 +13,7 @@ <P>Compile as: <CODE>g++ -DCWDEBUG log_file.cc -lcwd -o log_file</CODE></P> <PRE> +#define _GNU_SOURCE #include <libcw/sysd.h> #include <fstream> #include <libcw/debug.h> Index: src/libcwd/documentation/tutorial/tut6.m4 diff -u src/libcwd/documentation/tutorial/tut6.m4:1.2 src/libcwd/documentation/tutorial/tut6.m4:1.3 --- src/libcwd/documentation/tutorial/tut6.m4:1.2 Sat Dec 29 20:17:49 2001 +++ src/libcwd/documentation/tutorial/tut6.m4 Thu Feb 7 20:03:47 2002 @@ -59,6 +59,7 @@ <P>Compile as: <CODE>g++ -DCWDEBUG amo.cc -lcwd -o amo</CODE></P> <PRE> +#define _GNU_SOURCE #include <libcw/sysd.h> #include <libcw/debug.h> @@ -84,6 +85,7 @@ <P>Now let us actually allocate some memory:</P> <PRE> +#define _GNU_SOURCE #include <libcw/sysd.h> #include <libcw/debug.h> @@ -115,6 +117,7 @@ In order to find out what is wrong, we <EM>also turn on debug channel</EM><CODE> dc::bfd</CODE>:</P> <PRE> +#define _GNU_SOURCE #include <libcw/sysd.h> #include <libcw/debug.h> @@ -180,6 +183,7 @@ your program is doing:</P> <PRE> +#define _GNU_SOURCE #include <libcw/sysd.h> #include <libcw/debug.h> @@ -215,6 +219,7 @@ <P>Consider the following code:</P> <PRE> +#define _GNU_SOURCE #include <libcw/sysd.h> #include <libcw/debug.h> @@ -254,6 +259,7 @@ <CODE>AllocTag_dynamic_description()</CODE>, which <EM>will</EM> work.</P> <PRE> +#define _GNU_SOURCE #include <libcw/sysd.h> #include <libcw/debug.h> @@ -299,6 +305,7 @@ <CODE>AllocTag1(p)</CODE>:</P> <PRE> +#define _GNU_SOURCE #include <libcw/sysd.h> #include <libcw/debug.h> Index: src/libcwd/example-project/sys.h diff -u src/libcwd/example-project/sys.h:1.4 src/libcwd/example-project/sys.h:1.5 --- src/libcwd/example-project/sys.h:1.4 Sat Dec 29 20:17:49 2001 +++ src/libcwd/example-project/sys.h Thu Feb 7 20:03:47 2002 @@ -7,7 +7,10 @@ #define CWDEBUG #endif // The following is the mandatory part of the custom "sys.h". -// This must be included *before* any system header file is included. +// This must be included *before* any system header file is included! #ifdef CWDEBUG +#ifndef _GNU_SOURCE +#define _GNU_SOURCE +#endif #include <libcw/sysd.h> #endif Index: src/libcwd/include/libcw/class_debug.h diff -u src/libcwd/include/libcw/class_debug.h:1.8 src/libcwd/include/libcw/class_debug.h:1.9 --- src/libcwd/include/libcw/class_debug.h:1.8 Tue Jan 22 20:03:44 2002 +++ src/libcwd/include/libcw/class_debug.h Thu Feb 7 20:03:47 2002 @@ -1,4 +1,4 @@ -// $Header: /cvsroot/l/li/libcw/src/libcwd/include/libcw/class_debug.h,v 1.8 2002/01/23 04:03:44 libcw Exp $ +// $Header: /cvsroot/l/li/libcw/src/libcwd/include/libcw/class_debug.h,v 1.9 2002/02/08 04:03:47 libcw Exp $ // // Copyright (C) 2000 - 2002, by // @@ -200,6 +200,42 @@ void force_on(OnOffState& state); void restore(OnOffState const& state); + +#ifdef LIBCWD_THREAD_SAFE + /** + * \brief Keep Thread Specific Data after thread exit. + * + * Each %debug object has an array (of size PTHREAD_THREADS_MAX (= 1024)) + * with pointers to the Thread Specific Data (TSD) for each thread id. + * The size of this TSD is about 640 bytes. + * + * When this data would not be freed when a thread exits, and when + * an application constantly creates new threads, then all 1024 entries + * will become used, causing in total 1024 * 640 bytes of memory to be used + * per %debug object instead of <i>number of running threads</i> * 640 bytes. + * + * However, freeing the Thread Specific Data can not be done at the + * very very last moment (for which there is a complicated reason). + * Therefore, libcwd deletes the TSD of %debug objects in <code>__pthread_destroy_specifics()</code>, + * which is called directly after <code>__pthread_perform_cleanup()</code> in <code>pthread_exit()</code>. + * <code>__pthread_destroy_specifics()</code> calls the destruction routines as set + * by <code>pthread_key_create()</code>. + * As you should know, the order in which these destruction routines + * are called is not specified. + * Therefore it is possible that additional %debug output done + * in other key destruction routines is lost. + * + * By calling <code>keep_tsd(true)</code>, the TSD is not deleted and %debug output + * will stay enabled till the very end. + * Because of the disadvantage that this costs about 640 kb of (swappable) memory, + * the default is <code>false</code> and the TSD will be freed, except for the + * default %debug object \ref libcw_do, allowing for the printing of calls to + * <code>%free()</code> done after the key destruction phase. + * + * \returns The previous value. + */ + bool keep_tsd(bool keep); +#endif }; } // namespace debug Index: src/libcwd/include/libcw/private_threading.h diff -u src/libcwd/include/libcw/private_threading.h:1.20 src/libcwd/include/libcw/private_threading.h:1.21 --- src/libcwd/include/libcw/private_threading.h:1.20 Wed Feb 6 16:38:38 2002 +++ src/libcwd/include/libcw/private_threading.h Thu Feb 7 20:03:47 2002 @@ -1,4 +1,4 @@ -// $Header: /cvsroot/l/li/libcw/src/libcwd/include/libcw/private_threading.h,v 1.20 2002/02/07 00:38:38 libcw Exp $ +// $Header: /cvsroot/l/li/libcw/src/libcwd/include/libcw/private_threading.h,v 1.21 2002/02/08 04:03:47 libcw Exp $ // // Copyright (C) 2001 - 2002, by // @@ -41,8 +41,10 @@ #endif #ifdef LIBCWD_HAVE_PTHREAD +#ifndef __USE_GNU +#error "__USE_GNU is not defined!" +#endif #include <pthread.h> -#include <semaphore.h> #if defined(PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP) && defined(PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP) #define LIBCWD_USE_LINUXTHREADS 1 #else @@ -403,6 +405,7 @@ private: static pthread_cond_t S_condition; #if defined(DEBUGDEBUGTHREADS) || !LIBCWD_USE_LINUXTHREADS + static bool S_initialized; private: static void S_initialize(void) throw(); #endif @@ -445,7 +448,7 @@ } #endif // !LIBCWD_USE_LINUXTHREADS -#if !LIBCWD_USE_LINUXTHREADS +#if defined(DEBUGDEBUGTHREADS) || !LIBCWD_USE_LINUXTHREADS template <int instance> bool cond_tct<instance>::S_initialized = false; #endif Index: src/libcwd/include/libcw/struct_debug_tsd.h diff -u src/libcwd/include/libcw/struct_debug_tsd.h:1.6 src/libcwd/include/libcw/struct_debug_tsd.h:1.7 --- src/libcwd/include/libcw/struct_debug_tsd.h:1.6 Tue Feb 5 16:46:08 2002 +++ src/libcwd/include/libcw/struct_debug_tsd.h Thu Feb 7 20:03:47 2002 @@ -1,4 +1,4 @@ -// $Header: /cvsroot/l/li/libcw/src/libcwd/include/libcw/struct_debug_tsd.h,v 1.6 2002/02/06 00:46:08 libcw Exp $ +// $Header: /cvsroot/l/li/libcw/src/libcwd/include/libcw/struct_debug_tsd.h,v 1.7 2002/02/08 04:03:47 libcw Exp $ // // Copyright (C) 2002, by // @@ -62,6 +62,10 @@ bool tsd_initialized; // Set after initialization is completed. + + bool tsd_keep; + // Do not disable debug output and delete the TSD of the this debug object + // during the pthread key destruction phase. #ifdef DEBUGDEBUGOUTPUT // Since with DEBUGDEBUG defined we start with _off is -1 instead of 0, @@ -108,9 +112,9 @@ // A value of 0 means directly behind the marker. // Accessed from LibcwdDout. - void start(debug_ct&, channel_set_data_st& LIBCWD_COMMA_TSD_PARAM); - void finish(debug_ct&, channel_set_data_st& LIBCWD_COMMA_TSD_PARAM); - void fatal_finish(debug_ct&, channel_set_data_st& LIBCWD_COMMA_TSD_PARAM) __attribute__ ((__noreturn__)); + void start(debug_ct& debug_object, channel_set_data_st& channel_set LIBCWD_COMMA_TSD_PARAM); + void finish(debug_ct& debug_object, channel_set_data_st& channel_set LIBCWD_COMMA_TSD_PARAM); + void fatal_finish(debug_ct& debug_object, channel_set_data_st& channel_set LIBCWD_COMMA_TSD_PARAM) __attribute__ ((__noreturn__)); // Initialization and de-initialization. void init(void); @@ -118,7 +122,7 @@ #ifndef LIBCWD_THREAD_SAFE _off(0), #endif - tsd_initialized(false) { } + tsd_initialized(false), tsd_keep(false) { } ~debug_tsd_st(); }; Index: src/libcwd/include/libcw/sysd.ho.in diff -u src/libcwd/include/libcw/sysd.ho.in:1.5 src/libcwd/include/libcw/sysd.ho.in:1.6 --- src/libcwd/include/libcw/sysd.ho.in:1.5 Tue Jan 8 15:04:59 2002 +++ src/libcwd/include/libcw/sysd.ho.in Thu Feb 7 20:03:47 2002 @@ -1,5 +1,5 @@ // @configure_input@ -// $Header: /cvsroot/l/li/libcw/src/libcwd/include/libcw/sysd.ho.in,v 1.5 2002/01/08 23:04:59 libcw Exp $ +// $Header: /cvsroot/l/li/libcw/src/libcwd/include/libcw/sysd.ho.in,v 1.6 2002/02/08 04:03:47 libcw Exp $ // // Copyright (C) 2000 - 2001, by // @@ -57,7 +57,7 @@ // Abort when someone tries to use MT with libcwd without MT support. #@CW_CONFIG_THREAD_SAFE@ LIBCWD_TMP_THREAD_SAFE #if defined(_REENTRANT) && !defined(LIBCWD_TMP_THREAD_SAFE) -#error "Recompile libcwd with --enable-threading to enable support for Multi-Threading." +#error "Recompile libcwd with --enable-libcwd-threading to enable support for Multi-Threading." #endif #ifdef LIBCWD_TMP_THREAD_SAFE @@ -67,7 +67,13 @@ #define LIBCWD_MT_VOLATILE #endif -// Was only needed for the two tests above. +#if defined(LIBCWD_TMP_THREAD_SAFE) && !defined(_GNU_SOURCE) +#error "Sorry, libcwd with --enable-libcwd-threading uses GNU extensions, also in the header files. " + "Therefore you must also define _GNU_SOURCE when you are linking with libcwd. " + "Please add #define _GNU_SOURCE to your \"sys.h\", see html/preparation.html#preparation_step2." +#endif + +// Was only needed for the three tests above. #undef LIBCWD_TMP_THREAD_SAFE #endif /* LIBCW_SYSD_H */ Index: src/libcwd/include/libcw/type_info.h diff -u src/libcwd/include/libcw/type_info.h:1.18 src/libcwd/include/libcw/type_info.h:1.19 --- src/libcwd/include/libcw/type_info.h:1.18 Wed Jan 30 20:42:08 2002 +++ src/libcwd/include/libcw/type_info.h Thu Feb 7 20:03:47 2002 @@ -1,4 +1,4 @@ -// $Header: /cvsroot/l/li/libcw/src/libcwd/include/libcw/type_info.h,v 1.18 2002/01/31 04:42:08 libcw Exp $ +// $Header: /cvsroot/l/li/libcw/src/libcwd/include/libcw/type_info.h,v 1.19 2002/02/08 04:03:47 libcw Exp $ // // Copyright (C) 2000 - 2001, by // @@ -220,19 +220,13 @@ { LIBCWD_TSD_DECLARATION #ifdef LIBCWD_THREAD_SAFE - // MT: The critical area of spinlock contains no cancellation points: - // extract_exact_name() doesn't and even the constructor of type_info_ct - // that calls make_label, which calls demangle_type, do not print output. - // However, if we are a-synchrone then cancellation can happen at any - // point. Therefore we set the cancellation type to defer. - int oldstate; - pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, &oldstate); - _private_::cancel_buffer_t buffer; - _private_::mutex_tct<_private_::type_info_of_instance>::lock(buffer); + LIBCWD_DEFER_CANCEL + _private_::mutex_tct<_private_::type_info_of_instance>::initialize(); + _private_::mutex_tct<_private_::type_info_of_instance>::lock(); volatile static bool spin_lock = false; while(spin_lock); spin_lock = true; - _private_::mutex_tct<_private_::type_info_of_instance>::unlock(buffer); + _private_::mutex_tct<_private_::type_info_of_instance>::unlock(); if (::libcwd_type_info_exact<T>::value_c.size() == 0) // Recheck now that we acquired the lock. #endif { @@ -241,7 +235,7 @@ } #ifdef LIBCWD_THREAD_SAFE spin_lock = false; - pthread_setcanceltype(oldstate, NULL); + LIBCWD_RESTORE_CANCEL #endif } #endif // __GNUC__ == 2 && __GNUC_MINOR__ < 97 Index: src/libcwd/tests/lines.cc diff -u src/libcwd/tests/lines.cc:1.1 src/libcwd/tests/lines.cc:1.2 --- src/libcwd/tests/lines.cc:1.1 Thu Jan 31 21:12:16 2002 +++ src/libcwd/tests/lines.cc Thu Feb 7 20:03:47 2002 @@ -1,3 +1,4 @@ +#define _GNU_SOURCE #include <libcw/sysd.h> #include <libcw/debug.h> Index: src/libcwd/tests/stabs.cc diff -u src/libcwd/tests/stabs.cc:1.2 src/libcwd/tests/stabs.cc:1.3 --- src/libcwd/tests/stabs.cc:1.2 Sat Dec 29 20:17:50 2001 +++ src/libcwd/tests/stabs.cc Thu Feb 7 20:03:47 2002 @@ -1,3 +1,4 @@ +#define _GNU_SOURCE #include <libcw/sysd.h> #include <libcw/debug.h> Index: src/libcwd/tests/sys.h diff -u src/libcwd/tests/sys.h:1.2 src/libcwd/tests/sys.h:1.3 --- src/libcwd/tests/sys.h:1.2 Wed Sep 19 16:34:50 2001 +++ src/libcwd/tests/sys.h Thu Feb 7 20:03:47 2002 @@ -1,10 +1,13 @@ +#ifdef CWDEBUG +#ifndef _GNU_SOURCE +#define _GNU_SOURCE +#endif +#include <libcw/sysd.h> +#endif #include <_G_config.h> #ifndef _G_CLOG_CONFLICT #define _G_CLOG_CONFLICT 0 #endif #ifndef _G_HAS_LABS #define _G_HAS_LABS 0 -#endif -#ifdef CWDEBUG -#include <libcw/sysd.h> #endif Index: src/libcwd/testsuite/libcwd.tst/sys.h diff -u src/libcwd/testsuite/libcwd.tst/sys.h:1.3 src/libcwd/testsuite/libcwd.tst/sys.h:1.4 --- src/libcwd/testsuite/libcwd.tst/sys.h:1.3 Sun Dec 30 13:26:31 2001 +++ src/libcwd/testsuite/libcwd.tst/sys.h Thu Feb 7 20:03:47 2002 @@ -1,4 +1,4 @@ -// $Header: /cvsroot/l/li/libcw/src/libcwd/testsuite/libcwd.tst/sys.h,v 1.3 2001/12/30 21:26:31 libcw Exp $ +// $Header: /cvsroot/l/li/libcw/src/libcwd/testsuite/libcwd.tst/sys.h,v 1.4 2002/02/08 04:03:47 libcw Exp $ // // Copyright (C) 2000 - 2001, by // @@ -14,6 +14,11 @@ #ifndef TESTSUITE_SYS_H #define TESTSUITE_SYS_H +#ifndef _GNU_SOURCE +#define _GNU_SOURCE +#endif +#include <libcw/sysd.h> + #include "../../config.h" #ifdef HAVE__G_CONFIG_H #include <_G_config.h> @@ -24,7 +29,5 @@ #define _G_HAS_LABS 1 #endif #endif // HAVE__G_CONFIG_H - -#include <libcw/sysd.h> #endif // TESTSUITE_SYS_H Index: src/libcwd/testsuite/module.cc diff -u src/libcwd/testsuite/module.cc:1.3 src/libcwd/testsuite/module.cc:1.4 --- src/libcwd/testsuite/module.cc:1.3 Sat Dec 29 20:17:50 2001 +++ src/libcwd/testsuite/module.cc Thu Feb 7 20:03:47 2002 @@ -1,4 +1,5 @@ // A shared library +#define _GNU_SOURCE #include <libcw/sysd.h> #include <libcw/debug.h> Index: src/libcwd/threading.cc diff -u src/libcwd/threading.cc:1.7 src/libcwd/threading.cc:1.8 --- src/libcwd/threading.cc:1.7 Wed Feb 6 16:38:38 2002 +++ src/libcwd/threading.cc Thu Feb 7 20:03:46 2002 @@ -1,4 +1,4 @@ -// $Header: /cvsroot/l/li/libcw/src/libcwd/threading.cc,v 1.7 2002/02/07 00:38:38 libcw Exp $ +// $Header: /cvsroot/l/li/libcw/src/libcwd/threading.cc,v 1.8 2002/02/08 04:03:46 libcw Exp $ // // Copyright (C) 2001, by // @@ -105,15 +105,16 @@ void TSD_st::cleanup_routine(void) throw() { - Dout(dc::always, "Thread " << tid << " is exiting."); set_alloc_checking_off(*this); for (int i = 0; i < LIBCWD_DO_MAX; ++i) if (do_array[i]) { - do_off_array[i] = 0; // Turn all debugging off! Now, hopefully, we won't use do_array[i] anymore. debug_tsd_st* ptr = do_array[i]; - do_array[i] = NULL; // Be paranoid. - delete ptr; // Free old objects. + if (ptr->tsd_keep) + continue; + do_off_array[i] = 0; // Turn all debugging off! Now, hopefully, we won't use do_array[i] anymore. + do_array[i] = NULL; // So we won't free it again. + delete ptr; // Free debug object TSD. } set_alloc_checking_on(*this); } Index: src/libcwd/wrapcnclpnts.cc diff -u src/libcwd/wrapcnclpnts.cc:1.1 src/libcwd/wrapcnclpnts.cc:1.2 --- src/libcwd/wrapcnclpnts.cc:1.1 Sun Feb 3 19:50:36 2002 +++ src/libcwd/wrapcnclpnts.cc Thu Feb 7 20:03:46 2002 @@ -1,4 +1,4 @@ -// $Header: /cvsroot/l/li/libcw/src/libcwd/wrapcnclpnts.cc,v 1.1 2002/02/04 03:50:36 libcw Exp $ +// $Header: /cvsroot/l/li/libcw/src/libcwd/wrapcnclpnts.cc,v 1.2 2002/02/08 04:03:46 libcw Exp $ // // Copyright (C) 2002, by // @@ -13,7 +13,7 @@ #define _LARGEFILE64_SOURCE -#include <libcw/sysd.h> +#include "sys.h" #include <libcw/debug_config.h> // Needed for DEBUGDEBUGTHREADS #ifdef DEBUGDEBUGTHREADS ----------------------- End of diff ----------------------- |
From: Carlo W. <li...@us...> - 2002-02-08 21:32:25
|
CVSROOT : /cvsroot/libcw Module : src Commit time: 2002-01-08 21:32:23 UTC Modified files: libcwd/documentation/tutorial/tut1.m4 Log message: Little fix. ---------------------- diff included ---------------------- Index: src/libcwd/documentation/tutorial/tut1.m4 diff -u src/libcwd/documentation/tutorial/tut1.m4:1.3 src/libcwd/documentation/tutorial/tut1.m4:1.4 --- src/libcwd/documentation/tutorial/tut1.m4:1.3 Thu Feb 7 20:03:47 2002 +++ src/libcwd/documentation/tutorial/tut1.m4 Fri Feb 8 13:32:13 2002 @@ -43,7 +43,7 @@ a compile error in <libcw/sysd.h> telling you so.</P> <DIV class="faq-frame"><H4>FAQ</H4><UL class="faq"> -<LI><A HREF="faq.html#GNU_SOURCE">Won't this define make my code non-portable?</LI> +<LI><A HREF="faq.html#GNU_SOURCE">Won't this define make my code non-portable?</A></LI> </UL></DIV> <H3><CODE>#include <libcw/sysd.h></CODE></H3> ----------------------- End of diff ----------------------- |
From: Carlo W. <li...@us...> - 2002-02-08 22:29:42
|
CVSROOT : /cvsroot/libcw Module : src Commit time: 2002-01-08 22:29:40 UTC Modified files: libcwd/Makefile.am libcwd/NEWS libcwd/bfd.cc libcwd/debug.cc libcwd/include/libcw/Makefile.am libcwd/include/libcw/debug.h Log message: Added two environment variables to suppress (or enable) debug output during initialization. This was requested by a user in order to be able to suppress *all* debug output. ---------------------- diff included ---------------------- Index: src/libcwd/Makefile.am diff -u src/libcwd/Makefile.am:1.45 src/libcwd/Makefile.am:1.46 --- src/libcwd/Makefile.am:1.45 Sat Feb 2 20:15:11 2002 +++ src/libcwd/Makefile.am Fri Feb 8 14:29:29 2002 @@ -21,6 +21,7 @@ libcwd_la_SOURCES = \ threading.cc \ elf32.cc \ + environ.cc \ bfd.cc \ debug.cc \ debugmalloc.cc \ Index: src/libcwd/NEWS diff -u src/libcwd/NEWS:1.66 src/libcwd/NEWS:1.67 --- src/libcwd/NEWS:1.66 Thu Feb 7 20:03:46 2002 +++ src/libcwd/NEWS Fri Feb 8 14:29:29 2002 @@ -10,6 +10,13 @@ allow the use of the testsuite together with --enable-libcwd-debug. (You shouldn't use either unless you are hacking libcwd itself). + New are environment variables that influence libcwd. + At the moment there are two: + LIBCWD_NO_STARTUP_MSGS : Don't print anything before main(). + LIBCWD_ALWAYS_PRINT_LOADING : Print messages about loading + the shared libraries, even when this is done before libcw_do + is turned on (except when LIBCWD_NO_STARTUP_MSGS is defined). + Miscellaneous: - The configuration option --disable-libcwd-location is fixed. - Automake-1.5 now works. Index: src/libcwd/bfd.cc diff -u src/libcwd/bfd.cc:1.99 src/libcwd/bfd.cc:1.100 --- src/libcwd/bfd.cc:1.99 Sat Feb 2 20:15:11 2002 +++ src/libcwd/bfd.cc Fri Feb 8 14:29:29 2002 @@ -1,4 +1,4 @@ -// $Header: /cvsroot/l/li/libcw/src/libcwd/bfd.cc,v 1.99 2002/02/03 04:15:11 libcw Exp $ +// $Header: /cvsroot/l/li/libcw/src/libcwd/bfd.cc,v 1.100 2002/02/08 22:29:29 libcw Exp $ // // Copyright (C) 2000 - 2001, by // @@ -11,7 +11,6 @@ // packaging of this file. // -#define ALWAYS_PRINT_LOADING // Define to temporally turn on dc::bfd in order to print the "Loading debug info from ..." lines. #undef DEBUGDEBUGBFD // Define to add debug code for this file. #include <libcw/debug_config.h> @@ -964,13 +963,14 @@ init_debugmalloc(); #endif -#ifdef ALWAYS_PRINT_LOADING - // We want debug output to BFD libcw::debug::debug_ct::OnOffState state; - Debug( libcw_do.force_on(state) ); libcw::debug::channel_ct::OnOffState state2; - Debug( dc::bfd.force_on(state2, "BFD") ); -#endif + if (_private_::always_print_loading && !_private_::suppress_startup_msgs) + { + // We want debug output to BFD + Debug( libcw_do.force_on(state) ); + Debug( dc::bfd.force_on(state2, "BFD") ); + } // Initialize object files list, we don't really need the // write lock because this function is Single Threaded. @@ -1054,10 +1054,11 @@ // We put this outside the 'internal' region because it might call __pthread_do_exit. LIBCWD_CLEANUP_POP_RESTORE(false) -#ifdef ALWAYS_PRINT_LOADING - Debug( dc::bfd.restore(state2) ); - Debug( libcw_do.restore(state) ); -#endif + if (_private_::always_print_loading) + { + Debug( dc::bfd.restore(state2) ); + Debug( libcw_do.restore(state) ); + } WST_initialized = true; // MT: Safe, this function is Single Threaded. Index: src/libcwd/debug.cc diff -u src/libcwd/debug.cc:1.63 src/libcwd/debug.cc:1.64 --- src/libcwd/debug.cc:1.63 Thu Feb 7 20:03:46 2002 +++ src/libcwd/debug.cc Fri Feb 8 14:29:29 2002 @@ -1,4 +1,4 @@ -// $Header: /cvsroot/l/li/libcw/src/libcwd/debug.cc,v 1.63 2002/02/08 04:03:46 libcw Exp $ +// $Header: /cvsroot/l/li/libcw/src/libcwd/debug.cc,v 1.64 2002/02/08 22:29:29 libcw Exp $ // // Copyright (C) 2000 - 2001, by // @@ -265,6 +265,7 @@ #ifdef LIBCWD_THREAD_SAFE _private_::initialize_global_mutexes(); #endif + _private_::process_environment_variables(); // Fatal channels need to be marked fatal, otherwise we get into an endless loop // when they are used before they are created. @@ -292,7 +293,7 @@ if (getrlimit(RLIMIT_CORE, &corelim)) DoutFatal(dc::fatal|error_cf, "getrlimit(RLIMIT_CORE, &corelim)"); corelim.rlim_cur = corelim.rlim_max; - if (corelim.rlim_max != RLIM_INFINITY) + if (corelim.rlim_max != RLIM_INFINITY && !_private_::suppress_startup_msgs) { debug_ct::OnOffState state; libcw_do.force_on(state); @@ -304,10 +305,13 @@ if (setrlimit(RLIMIT_CORE, &corelim)) DoutFatal(dc::fatal|error_cf, "unlimit core size failed"); #else - debug_ct::OnOffState state; - libcw_do.force_on(state); - Dout(dc::warning, "Please unlimit core size manually"); - libcw_do.restore(state); + if (!_private_::suppress_startup_msgs) + { + debug_ct::OnOffState state; + libcw_do.force_on(state); + Dout(dc::warning, "Please unlimit core size manually"); + libcw_do.restore(state); + } #endif #ifdef DEBUGUSEBFD Index: src/libcwd/include/libcw/Makefile.am diff -u src/libcwd/include/libcw/Makefile.am:1.22 src/libcwd/include/libcw/Makefile.am:1.23 --- src/libcwd/include/libcw/Makefile.am:1.22 Thu Jan 24 13:16:09 2002 +++ src/libcwd/include/libcw/Makefile.am Fri Feb 8 14:29:29 2002 @@ -39,6 +39,7 @@ private_allocator.h \ private_assert.h \ private_debug_stack.h \ + private_environ.h \ private_internal_string.h \ private_internal_stringstream.h \ private_internal_vector.h \ Index: src/libcwd/include/libcw/debug.h diff -u src/libcwd/include/libcw/debug.h:1.40 src/libcwd/include/libcw/debug.h:1.41 --- src/libcwd/include/libcw/debug.h:1.40 Fri Jan 18 21:08:54 2002 +++ src/libcwd/include/libcw/debug.h Fri Feb 8 14:29:29 2002 @@ -1,4 +1,4 @@ -// $Header: /cvsroot/l/li/libcw/src/libcwd/include/libcw/debug.h,v 1.40 2002/01/19 05:08:54 libcw Exp $ +// $Header: /cvsroot/l/li/libcw/src/libcwd/include/libcw/debug.h,v 1.41 2002/02/08 22:29:29 libcw Exp $ // // Copyright (C) 2000 - 2001, by // @@ -226,6 +226,7 @@ #include <libcw/macro_ForAllDebugChannels.h> #include <libcw/macro_ForAllDebugObjects.h> +#include <libcw/private_environ.h> // Include the inline functions. #include <libcw/class_channel.inl> // Debug channels. ----------------------- End of diff ----------------------- |
From: Carlo W. <li...@us...> - 2002-02-08 22:33:38
|
CVSROOT : /cvsroot/libcw Module : src Commit time: 2002-01-08 22:33:38 UTC Added files: libcwd/environ.cc libcwd/include/libcw/private_environ.h Log message: And the two new files that go with it... ---------------------- diff included ---------------------- Index: src/libcwd/environ.cc diff -u /dev/null src/libcwd/environ.cc:1.1 --- /dev/null Fri Feb 8 14:33:38 2002 +++ src/libcwd/environ.cc Fri Feb 8 14:33:27 2002 @@ -0,0 +1,33 @@ +// $Header: /cvsroot/l/li/libcw/src/libcwd/environ.cc,v 1.1 2002/02/08 22:33:27 libcw Exp $ +// +// Copyright (C) 2002, by +// +// Carlo Wood, Run on IRC <ca...@al...> +// RSA-1024 0x624ACAD5 1997-01-26 Sign & Encrypt +// Fingerprint16 = 32 EC A7 B6 AC DB 65 A6 F6 F6 55 DD 1C DC FF 61 +// +// This file may be distributed under the terms of the Q Public License +// version 1.0 as appearing in the file LICENSE.QPL included in the +// packaging of this file. +// + +#include "sys.h" +#include <cstdlib> +#include "cwd_debug.h" + +namespace libcw { + namespace debug { + namespace _private_ { + +bool always_print_loading = false; +bool suppress_startup_msgs = false; + +void process_environment_variables(void) +{ + always_print_loading = (getenv("LIBCWD_PRINT_LOADING") != NULL); + suppress_startup_msgs = (getenv("LIBCWD_NO_STARTUP_MSGS") != NULL); +} + + } // namespace _private_ + } // namespace debug +} // namespace libcw Index: src/libcwd/include/libcw/private_environ.h diff -u /dev/null src/libcwd/include/libcw/private_environ.h:1.1 --- /dev/null Fri Feb 8 14:33:38 2002 +++ src/libcwd/include/libcw/private_environ.h Fri Feb 8 14:33:28 2002 @@ -0,0 +1,43 @@ +// $Header: /cvsroot/l/li/libcw/src/libcwd/include/libcw/private_environ.h,v 1.1 2002/02/08 22:33:28 libcw Exp $ +// +// Copyright (C) 2002, by +// +// Carlo Wood, Run on IRC <ca...@al...> +// RSA-1024 0x624ACAD5 1997-01-26 Sign & Encrypt +// Fingerprint16 = 32 EC A7 B6 AC DB 65 A6 F6 F6 55 DD 1C DC FF 61 +// +// This file may be distributed under the terms of the Q Public License +// version 1.0 as appearing in the file LICENSE.QPL included in the +// packaging of this file. +// + +#ifndef LIBCW_PRIVATE_FUNCTIONS_H +#define LIBCW_PRIVATE_FUNCTIONS_H + +#ifndef LIBCW_SYSD_H +#error "You need to #include "sys.h" at the top of every source file (which in turn should #include <libcw/sysd.h>)." +#endif + +namespace libcw { + namespace debug { + namespace _private_ { + +extern void process_environment_variables(void); + +// Environment variable: LIBCWD_PRINT_LOADING +// Print the list with "BFD : Loading debug info from /lib/libc.so.6 (0x40271000) ... done (4189 symbols)" etc. +// at the start of the program *even* when this happens before main() is reached and libcw_do and dc::bfd are +// still turned off. +extern bool always_print_loading; + +// Environment variable: LIBCWD_NO_STARTUP_MSGS +// This will suppress all messages that normally could be printed +// before reaching main, including warning messages. +// This overrides LIBCWD_PRINT_LOADING. +extern bool suppress_startup_msgs; + + } // namespace _private_ + } // namespace debug +} // namespace libcw + +#endif // LIBCW_PRIVATE_FUNCTIONS_H ----------------------- End of diff ----------------------- |
From: Carlo W. <li...@us...> - 2002-02-09 03:23:11
|
CVSROOT : /cvsroot/libcw Module : src Commit time: 2002-01-09 03:23:09 UTC Modified files: libcwd/configure.in libcwd/debugmalloc.cc libcwd/include/libcw/debug_config.ho.in Log message: Support _libc_malloc et al too. ---------------------- diff included ---------------------- Index: src/libcwd/configure.in diff -u src/libcwd/configure.in:1.101 src/libcwd/configure.in:1.102 --- src/libcwd/configure.in:1.101 Sat Feb 2 20:15:11 2002 +++ src/libcwd/configure.in Fri Feb 8 19:22:59 2002 @@ -1,5 +1,5 @@ dnl Process this file with autoconf to produce a configure script. -AC_REVISION($Revision: 1.101 $)dnl +AC_REVISION($Revision: 1.102 $)dnl dnl General intialization of `autoconf' varaibles. dnl Ensure that the directory specified with --srcdir was correct @@ -220,6 +220,8 @@ CW_CONFIG_DEBUGMARKER=undef AC_SUBST(CW_CONFIG_HAVE___LIBC_MALLOC) CW_CONFIG_HAVE___LIBC_MALLOC=undef +AC_SUBST(CW_CONFIG_HAVE__LIBC_MALLOC) +CW_CONFIG_HAVE__LIBC_MALLOC=undef AC_SUBST(CW_CONFIG_HAVE_DLOPEN) CW_CONFIG_HAVE_DLOPEN=undef @@ -431,11 +433,13 @@ AC_C_BIGENDIAN dnl Check for library functions. -AC_CHECK_FUNCS(getgid getegid getgroups __libc_malloc wmemcpy) +AC_CHECK_FUNCS(getgid getegid getgroups __libc_malloc _libc_malloc wmemcpy) if test "$ac_cv_func___libc_malloc" = "yes"; then CW_CONFIG_HAVE___LIBC_MALLOC=define -fi +else if test "$ac_cv_func__libc_malloc" = "yes"; then + CW_CONFIG_HAVE__LIBC_MALLOC=define +fi fi dnl Check for system services. Index: src/libcwd/debugmalloc.cc diff -u src/libcwd/debugmalloc.cc:1.81 src/libcwd/debugmalloc.cc:1.82 --- src/libcwd/debugmalloc.cc:1.81 Wed Feb 6 16:38:38 2002 +++ src/libcwd/debugmalloc.cc Fri Feb 8 19:22:59 2002 @@ -1,4 +1,4 @@ -// $Header: /cvsroot/l/li/libcw/src/libcwd/debugmalloc.cc,v 1.81 2002/02/07 00:38:38 libcw Exp $ +// $Header: /cvsroot/l/li/libcw/src/libcwd/debugmalloc.cc,v 1.82 2002/02/09 03:22:59 libcw Exp $ // // Copyright (C) 2000 - 2001, by // @@ -198,6 +198,12 @@ #define __libcwd_realloc realloc #define __libcwd_free free #define dc_malloc dc::malloc +#ifdef LIBCWD_HAVE__LIBC_MALLOC +#define __libc_malloc _libc_malloc +#define __libc_calloc _libc_calloc +#define __libc_realloc _libc_realloc +#define __libc_free _libc_free +#endif #else #define __libc_malloc malloc #define __libc_calloc calloc Index: src/libcwd/include/libcw/debug_config.ho.in diff -u src/libcwd/include/libcw/debug_config.ho.in:1.18 src/libcwd/include/libcw/debug_config.ho.in:1.19 --- src/libcwd/include/libcw/debug_config.ho.in:1.18 Tue Feb 5 16:46:08 2002 +++ src/libcwd/include/libcw/debug_config.ho.in Fri Feb 8 19:22:59 2002 @@ -1,5 +1,5 @@ // @configure_input@ -// $Header: /cvsroot/l/li/libcw/src/libcwd/include/libcw/debug_config.ho.in,v 1.18 2002/02/06 00:46:08 libcw Exp $ +// $Header: /cvsroot/l/li/libcw/src/libcwd/include/libcw/debug_config.ho.in,v 1.19 2002/02/09 03:22:59 libcw Exp $ // // Copyright (C) 2000 - 2001, by // @@ -267,7 +267,11 @@ // #ifdef DEBUGMALLOC -#@CW_CONFIG_HAVE___LIBC_MALLOC@ DEBUGMALLOCEXTERNALCLINKAGE +#@CW_CONFIG_HAVE___LIBC_MALLOC@ LIBCWD_HAVE___LIBC_MALLOC +#@CW_CONFIG_HAVE__LIBC_MALLOC@ LIBCWD_HAVE__LIBC_MALLOC +#if defined(LIBCWD_HAVE___LIBC_MALLOC) || defined(LIBCWD_HAVE__LIBC_MALLOC) +#define DEBUGMALLOCEXTERNALCLINKAGE +#endif #endif #ifdef DEBUGUSEBFD ----------------------- End of diff ----------------------- |
From: Carlo W. <li...@us...> - 2002-02-10 02:42:28
|
CVSROOT : /cvsroot/libcw Module : src Commit time: 2002-01-10 02:42:27 UTC Modified files: libcwd/INSTALL libcwd/bfd.cc libcwd/debug.cc libcwd/documentation/doxygen.config libcwd/documentation/location.dox libcwd/documentation/reference.dox Added files: libcwd/documentation/environment.dox Log message: Documentation update and fixes. ---------------------- diff included ---------------------- Index: src/libcwd/INSTALL diff -u src/libcwd/INSTALL:1.23 src/libcwd/INSTALL:1.24 --- src/libcwd/INSTALL:1.23 Tue Jan 8 10:14:37 2002 +++ src/libcwd/INSTALL Sat Feb 9 18:42:16 2002 @@ -27,7 +27,7 @@ i) The GNU compiler, version 2.95.1 or higher. Location: gnu/gcc/ - Current version: 3.0.2 + Current version: 3.0.4 Alternatively you can install only ia) gnu/gcc/gcc-core-<version>.tar.gz and @@ -55,7 +55,7 @@ Don't delete those libraries if you have them though since existing binaries might need to link with them. -libcwd-0.99.16 was tested with gcc-2.95.x, gcc-2.96-97 (RedHat) +libcwd-0.99.16 was tested with gcc-2.95.x, gcc-2.96-98 (RedHat) and gcc-3.0.x. Packages needed to run the testsuite @@ -125,10 +125,10 @@ If it can't find one (it will only find one when there is a g++ or c++ in your PATH), then you can specify the right path during configuration. For example, I configure libcwd as follows to compile with the latest CVS -version of g++, which I installed in /usr/local/bin/g++-cvs (and +version of g++, which I installed in /usr/local/bin/g++-cvs-3.0 (and /usr/local/bin is in my PATH): -CC="gcc-cvs" CXX="g++-cvs" ./configure +CC="gcc-cvs-3.0" CXX="g++-cvs-3.0" ./configure -=iii=- @@ -168,7 +168,7 @@ make tar // Create tar ball make rpm // Create rpms make ChangeLog // Generate ChangeLog from cvs database -make CC="gcc-3.0.2" CXX="g++-3.0.2" reconfig // Switch compilers keeping the same configuration +make CC="gcc-3.0.4" CXX="g++-3.0.4" reconfig // Switch compilers keeping the same configuration make full-check // Iterate over all configurations and all compiler versions It is not garanteed that these work on another machine than mine however. Index: src/libcwd/bfd.cc diff -u src/libcwd/bfd.cc:1.100 src/libcwd/bfd.cc:1.101 --- src/libcwd/bfd.cc:1.100 Fri Feb 8 14:29:29 2002 +++ src/libcwd/bfd.cc Sat Feb 9 18:42:16 2002 @@ -1,4 +1,4 @@ -// $Header: /cvsroot/l/li/libcw/src/libcwd/bfd.cc,v 1.100 2002/02/08 22:29:29 libcw Exp $ +// $Header: /cvsroot/l/li/libcw/src/libcwd/bfd.cc,v 1.101 2002/02/10 02:42:16 libcw Exp $ // // Copyright (C) 2000 - 2001, by // @@ -1368,7 +1368,7 @@ } /** - * \brief Move \p prototype to this location object; + * \brief Move \p prototype to this location object * * \p prototype must be \ref is_known "known" and the current object \ref is_known "unknown"; * \p prototype is clear()-ed afterwards. Index: src/libcwd/debug.cc diff -u src/libcwd/debug.cc:1.64 src/libcwd/debug.cc:1.65 --- src/libcwd/debug.cc:1.64 Fri Feb 8 14:29:29 2002 +++ src/libcwd/debug.cc Sat Feb 9 18:42:16 2002 @@ -1,4 +1,4 @@ -// $Header: /cvsroot/l/li/libcw/src/libcwd/debug.cc,v 1.64 2002/02/08 22:29:29 libcw Exp $ +// $Header: /cvsroot/l/li/libcw/src/libcwd/debug.cc,v 1.65 2002/02/10 02:42:16 libcw Exp $ // // Copyright (C) 2000 - 2001, by // @@ -131,7 +131,7 @@ /** * \brief The default %debug object. * - * The %debug object that is used by default by Dout and DoutFatal, the only %debug object used by libcwd itself. + * The %debug object that is used by default by \ref Dout and \ref DoutFatal, the only %debug object used by libcwd itself. * \sa \ref chapter_custom_do */ @@ -197,7 +197,7 @@ * * This channel is <EM>%always</EM> on; * it can not be turned off. - * It is not in the list of debug channels. + * It is not in the list of \ref ForAllDebugChannels "debug channels". * When used with a label it will print as many '>' * characters as the size of the largest real channel. */ Index: src/libcwd/documentation/doxygen.config diff -u src/libcwd/documentation/doxygen.config:1.2 src/libcwd/documentation/doxygen.config:1.3 --- src/libcwd/documentation/doxygen.config:1.2 Sat Dec 29 20:17:47 2001 +++ src/libcwd/documentation/doxygen.config Sat Feb 9 18:42:16 2002 @@ -16,8 +16,8 @@ REPEAT_BRIEF = YES ALWAYS_DETAILED_SEC = NO FULL_PATH_NAMES = YES -STRIP_FROM_PATH = /home/carlo/c++/libcw_branch-threading/src/libcwd/include/ \ - /home/carlo/c++/libcw_branch-threading/src/libcwd/ +STRIP_FROM_PATH = /home/carlo/c++/libcw/src/libcwd/include/ \ + /home/carlo/c++/libcw/src/libcwd/ INTERNAL_DOCS = NO STRIP_CODE_COMMENTS = YES CASE_SENSE_NAMES = YES Index: src/libcwd/documentation/environment.dox diff -u /dev/null src/libcwd/documentation/environment.dox:1.1 --- /dev/null Sat Feb 9 18:42:27 2002 +++ src/libcwd/documentation/environment.dox Sat Feb 9 18:42:16 2002 @@ -0,0 +1,18 @@ +/*! +\defgroup chapter_environment Environment Variables +\ingroup book_start +*/ +/*! +\page page_environment +\ingroup chapter_environment + +<dl compact> +<dt>LIBCWD_NO_STARTUP_MSGS<dd>Don't print anything before main(). + +<dt>LIBCWD_ALWAYS_PRINT_LOADING<dd>Print messages about loading +the shared libraries, even when this is done before libcw_do +is turned on (except when LIBCWD_NO_STARTUP_MSGS is defined). +</dl> + +*/ + Index: src/libcwd/documentation/location.dox diff -u src/libcwd/documentation/location.dox:1.2 src/libcwd/documentation/location.dox:1.3 --- src/libcwd/documentation/location.dox:1.2 Sat Dec 29 20:17:47 2001 +++ src/libcwd/documentation/location.dox Sat Feb 9 18:42:17 2002 @@ -9,10 +9,10 @@ \section section_The_BFD_library The BFD library Libcwd attempts to determine the source file and line number where memory is allocated. -It does this by directly reading the .stabs section of the ELF32 object files. -If you are using an Operating System that isn't ELF then you need to enable the use of libbfd for +It does this by directly reading the .debug_line (DWARF2) or .stabs (STABS) section of the ELF32 object files. +If you are using an Operating System that isn't ELF32 then you need to enable the use of GNU libbfd for this to work by configuring libcwd with \link enable_libcwd_libbfd --enable-libcwd-libbfd \endlink. -If you don't have an ELF system and you don't have libbfd installed and are not able to install it +If you don't have an ELF32 system and you don't have GNU libbfd installed and are not able to install it yourself (note: you also need libiberty and libdl) then you can disable it using \link enable_libcwd_location --disable-libcwd-location \endlink. There is a seperate page that deals with libcwd and \link group_locations location \endlink support. Index: src/libcwd/documentation/reference.dox diff -u src/libcwd/documentation/reference.dox:1.2 src/libcwd/documentation/reference.dox:1.3 --- src/libcwd/documentation/reference.dox:1.2 Sat Dec 29 20:17:47 2001 +++ src/libcwd/documentation/reference.dox Sat Feb 9 18:42:17 2002 @@ -50,6 +50,7 @@ <li>\ref chapter_custom_debug_h <li>\ref chapter_alloc_locations <li>\ref group_configuration + <li>\ref chapter_environment </ul> */ ----------------------- End of diff ----------------------- |
From: Carlo W. <li...@us...> - 2002-02-10 05:42:10
|
CVSROOT : /cvsroot/libcw Module : src Commit time: 2002-01-10 05:42:08 UTC Modified files: libcwd/debug.cc libcwd/maintMakefile.in libcwd/threading.cc libcwd/include/libcw/private_struct_TSD.h libcwd/testsuite/module.cc libcwd/testsuite/libcwd.tst/dlopen.re Log message: Several fixes, trying to get 'make full-check' working again. ---------------------- diff included ---------------------- Index: src/libcwd/debug.cc diff -u src/libcwd/debug.cc:1.65 src/libcwd/debug.cc:1.66 --- src/libcwd/debug.cc:1.65 Sat Feb 9 18:42:16 2002 +++ src/libcwd/debug.cc Sat Feb 9 21:41:58 2002 @@ -1,4 +1,4 @@ -// $Header: /cvsroot/l/li/libcw/src/libcwd/debug.cc,v 1.65 2002/02/10 02:42:16 libcw Exp $ +// $Header: /cvsroot/l/li/libcw/src/libcwd/debug.cc,v 1.66 2002/02/10 05:41:58 libcw Exp $ // // Copyright (C) 2000 - 2001, by // @@ -285,7 +285,9 @@ channels::dc::system.NS_initialize("SYSTEM"); libcw_do.NS_init(); // Initialize debug code. +#ifdef LIBCWD_THREAD_SAFE libcw_do.keep_tsd(true); +#endif // Unlimit core size. #ifdef RLIMIT_CORE @@ -989,6 +991,7 @@ tsd_initialized = true; } +#ifdef LIBCWD_THREAD_SAFE namespace _private_ { void debug_tsd_init(LIBCWD_TSD_PARAM) { @@ -1002,6 +1005,7 @@ ); } } +#endif debug_tsd_st::~debug_tsd_st() { Index: src/libcwd/include/libcw/private_struct_TSD.h diff -u src/libcwd/include/libcw/private_struct_TSD.h:1.6 src/libcwd/include/libcw/private_struct_TSD.h:1.7 --- src/libcwd/include/libcw/private_struct_TSD.h:1.6 Wed Feb 6 16:38:38 2002 +++ src/libcwd/include/libcw/private_struct_TSD.h Sat Feb 9 21:41:58 2002 @@ -1,4 +1,4 @@ -// $Header: /cvsroot/l/li/libcw/src/libcwd/include/libcw/private_struct_TSD.h,v 1.6 2002/02/07 00:38:38 libcw Exp $ +// $Header: /cvsroot/l/li/libcw/src/libcwd/include/libcw/private_struct_TSD.h,v 1.7 2002/02/10 05:41:58 libcw Exp $ // // Copyright (C) 2001, by // @@ -157,8 +157,8 @@ int do_off_array[LIBCWD_DO_MAX]; // Thread Specific on/off counter for Debug Objects. debug_tsd_st* do_array[LIBCWD_DO_MAX];// Thread Specific Data of Debug Objects or NULL when no debug object. void cleanup_routine(void) throw(); -#endif int off_cnt_array[LIBCWD_DC_MAX]; // Thread Specific Data of Debug Channels. +#endif void S_initialize(void) throw(); Index: src/libcwd/maintMakefile.in diff -u src/libcwd/maintMakefile.in:1.19 src/libcwd/maintMakefile.in:1.20 --- src/libcwd/maintMakefile.in:1.19 Thu Jan 10 18:23:32 2002 +++ src/libcwd/maintMakefile.in Sat Feb 9 21:41:58 2002 @@ -104,12 +104,15 @@ @( \ for c in \ '--enable-maintainer-mode --enable-libcwd-threading --enable-libcwd-debugm --enable-libcwd-debug --disable-libcwd-debug-output --compilers=3.0.3,2.96,2.95.3' \ + '--enable-maintainer-mode --enable-libcwd-threading --enable-libcwd-debugt --enable-libcwd-debugm --enable-libcwd-debug --disable-libcwd-debug-output --compilers=3.0.3,2.96,2.95.3' \ '--enable-maintainer-mode --enable-libcwd-debugm --enable-libcwd-debug --disable-libcwd-debug-output --compilers=3.0.3,2.96,2.95.3' \ '--enable-maintainer-mode --enable-libcwd-threading --enable-libcwd-debugm --compilers=3.0.3,2.96,2.95.3' \ '--enable-maintainer-mode --enable-libcwd-debugm --compilers=3.0.3,2.96,2.95.3' \ '--enable-maintainer-mode --enable-libcwd-threading --enable-libcwd-debug --disable-libcwd-debug-output --compilers=3.0.3,2.96,2.95.3' \ + '--enable-maintainer-mode --enable-libcwd-threading --enable-libcwd-debugt --enable-libcwd-debug --disable-libcwd-debug-output --compilers=3.0.3,2.96,2.95.3' \ '--enable-maintainer-mode --enable-libcwd-debug --disable-libcwd-debug-output --compilers=3.0.3,2.96,2.95.3' \ '--enable-maintainer-mode --enable-libcwd-threading --enable-libcwd-debugm --enable-libcwd-debug --compilers=3.0.3,2.96,2.95.3' \ + '--enable-maintainer-mode --enable-libcwd-threading --enable-libcwd-debugt --enable-libcwd-debugm --enable-libcwd-debug --compilers=3.0.3,2.96,2.95.3' \ '--enable-maintainer-mode --enable-libcwd-debugm --enable-libcwd-debug --compilers=3.0.3,2.96,2.95.3' \ '--enable-maintainer-mode --enable-libcwd-threading --compilers=3.0.3,3.0.2,3.0.1,2.96,2.95.3,2.95.2' \ '--enable-maintainer-mode --compilers=3.0.3,3.0.2,3.0.1,2.96,2.95.3,2.95.2' \ Index: src/libcwd/testsuite/libcwd.tst/dlopen.re diff -u src/libcwd/testsuite/libcwd.tst/dlopen.re:1.10 src/libcwd/testsuite/libcwd.tst/dlopen.re:1.11 --- src/libcwd/testsuite/libcwd.tst/dlopen.re:1.10 Fri Jan 4 20:34:22 2002 +++ src/libcwd/testsuite/libcwd.tst/dlopen.re Sat Feb 9 21:41:58 2002 @@ -8,14 +8,14 @@ (.* )* MALLOC : malloc\(310\) = <unfinished> -BFD : address 0x[0-9a-f]* corresponds to module.cc:16 +BFD : address 0x[0-9a-f]* corresponds to module.cc:19 MALLOC : <continued> 0x[0-9a-f]* MALLOC : malloc\(300\) = <unfinished> -BFD : address 0x[0-9a-f]* corresponds to module.cc:7 +BFD : address 0x[0-9a-f]* corresponds to module.cc:10 MALLOC : <continued> 0x[0-9a-f]* MALLOC : Allocated memory: [0-9]* bytes in [0-9]* blocks\. -malloc 0x[0-9a-f]* module\.cc:7 void\*; \(sz = 300\) Allocated inside static_test_symbol -malloc 0x[0-9a-f]* module\.cc:16 void\*; \(sz = 310\) Allocated inside global_test_symbol +malloc 0x[0-9a-f]* module\.cc:10 void\*; \(sz = 300\) Allocated inside static_test_symbol +malloc 0x[0-9a-f]* module\.cc:19 void\*; \(sz = 310\) Allocated inside global_test_symbol // input lines 2 // output till ^NOTICE (malloc 0x[0-9a-f]* *(dl-[a-z]*\.c|stl_alloc\.h|specific\.c|dlerror\.c):[0-9]* *<unknown type>; \(sz = [0-9]*\) Index: src/libcwd/testsuite/module.cc diff -u src/libcwd/testsuite/module.cc:1.4 src/libcwd/testsuite/module.cc:1.5 --- src/libcwd/testsuite/module.cc:1.4 Thu Feb 7 20:03:47 2002 +++ src/libcwd/testsuite/module.cc Sat Feb 9 21:41:58 2002 @@ -1,5 +1,7 @@ // A shared library +#ifndef _GNU_SOURCE #define _GNU_SOURCE +#endif #include <libcw/sysd.h> #include <libcw/debug.h> Index: src/libcwd/threading.cc diff -u src/libcwd/threading.cc:1.8 src/libcwd/threading.cc:1.9 --- src/libcwd/threading.cc:1.8 Thu Feb 7 20:03:46 2002 +++ src/libcwd/threading.cc Sat Feb 9 21:41:58 2002 @@ -1,4 +1,4 @@ -// $Header: /cvsroot/l/li/libcw/src/libcwd/threading.cc,v 1.8 2002/02/08 04:03:46 libcw Exp $ +// $Header: /cvsroot/l/li/libcw/src/libcwd/threading.cc,v 1.9 2002/02/10 05:41:58 libcw Exp $ // // Copyright (C) 2001, by // @@ -84,7 +84,7 @@ tid = pthread_self(); initialize_global_mutexes(); // This is a good moment to initialize all pthread mutexes. mutex_tct<tsd_initialization_instance>::unlock(); - if (WST_multi_threaded) // Is this a second (or later) thread? + if (thread_index(pthread_self()) != 0) // Is this a second (or later) thread? { set_alloc_checking_off(*this); for (int i = 0; i < LIBCWD_DO_MAX; ++i) ----------------------- End of diff ----------------------- |
From: Carlo W. <li...@us...> - 2002-02-11 03:00:36
|
CVSROOT : /cvsroot/libcw Module : src Commit time: 2002-01-11 03:00:35 UTC Modified files: libcwd/NEWS libcwd/acconfig.h libcwd/include/libcw/macro_AllocTag.h libcwd/include/libcw/macro_Libcwd_macros.h Log message: make full-test now runs without errors. Update of NEWS ---------------------- diff included ---------------------- Index: src/libcwd/NEWS diff -u src/libcwd/NEWS:1.67 src/libcwd/NEWS:1.68 --- src/libcwd/NEWS:1.67 Fri Feb 8 14:29:29 2002 +++ src/libcwd/NEWS Sun Feb 10 19:00:24 2002 @@ -27,33 +27,31 @@ IMPORTANT: 'channel_ct const' -> 'channel_ct'. Debug channels should no longer be declared constant. - Declarations like - libcw::debug::channel_ct const my_channel("FOO"); - will have to be changed to - libcw::debug::selector_ct my_channel("FOO"); - removing the `const'. + [ "libcw::debug::channel_ct const my_channel("FOO");" --> + "libcw::debug::selector_ct my_channel("FOO");" ] `long memblks()' has been renamed to `unsigned long mem_blocks()'. + [ "memblks()" --> "mem_blocks()" ] - In debug_ct, set_margin, get_margin, set_marker and get_marker are - a bit slow for heavy swapping of the margin and marker (std::string - is 'slow'); therefore (using internal allocations, which is not - possible with std::string (see bug fixes below)) public access - to members debug_ct::margin and debug_ct::marker is now granted, - providing the following methods of the returned object: size(), - c_str() (the terminating zero is already there, this just returns - an internal pointer), reserve(), capacity(), append(), prepend() - and assign() - all with meanings borrowed from std::string. - For example, when capacity() returns a value larger or equal to - the length of a string that would result from a call to append(), - then calling append is garanteed not to invalidate the pointer - returned by c_str(). The default capacity can be set with `reserve'. - append/prepend/assign accept both a std::string reference or a - char*/size_t pair. - Finally, the following methods are added to debug_ct directly: - `push_margin', `pop_margin', `push_marker' and `pop_marker'. + The margin and marker are no longer using std::string, which is + a bit slow. Access to the margin and marker is now granted through + debug_ct::margin() and debug_ct::marker(). The returned objects + provide the following methods: size(), c_str() (this just returns + an internal pointer, the termination zero is already there), + reserve(), capacity(), append(), prepend() and assign() - all with + their meanings borrowed from std::string. For example, when + capacity() returns a value larger or equal to the length of a string + that would result from a call to append(), then calling append is + garanteed not to invalidate the pointer returned by c_str(). The + default capacity can be set with `reserve'. append/prepend/assign + accept both a std::string reference or a char*/size_t pair. + Finally, the following methods are added to debug_ct: + `push_margin()', `pop_margin()', `push_marker()' and `pop_marker()'. These functions can be used to quickly store and restore the respective formatting strings. + [ "Debug( libcw_do.set_margin(std::string(buf, len)) );" --> + "Debug( libcw_do.margin().assign(buf, len) );" ] + A debug function for internal use (by the maintainers): `debugdebugcheckpoint()' has been removed. If you need a user @@ -63,6 +61,7 @@ CWASSERT was renamed to LIBCWD_ASSERT; Note that all macros that start with LIBCWD_ should NOT be used by the user, they are for internal use by libcwd. + [ "CWASSERT( i == 1 );" --> "assert( i == 1);" ] debug_ct::get_os() has been removed. Use cwprint or cwprint_using. Reason: the temporary stringstream that was returned was only valid Index: src/libcwd/acconfig.h diff -u src/libcwd/acconfig.h:1.10 src/libcwd/acconfig.h:1.11 --- src/libcwd/acconfig.h:1.10 Fri Jan 25 18:06:32 2002 +++ src/libcwd/acconfig.h Sun Feb 10 19:00:24 2002 @@ -7,9 +7,6 @@ #ifndef LIBCW_CONFIG_H #define LIBCW_CONFIG_H @TOP@ -// Defined when RETSIGTYPE is `int'. -#undef CW_RETSIGTYPE_IS_INT - // Full path to the `ps' executable. #undef CW_PATH_PROG_PS Index: src/libcwd/include/libcw/macro_AllocTag.h diff -u src/libcwd/include/libcw/macro_AllocTag.h:1.6 src/libcwd/include/libcw/macro_AllocTag.h:1.7 --- src/libcwd/include/libcw/macro_AllocTag.h:1.6 Wed Jan 30 20:42:08 2002 +++ src/libcwd/include/libcw/macro_AllocTag.h Sun Feb 10 19:00:24 2002 @@ -1,4 +1,4 @@ -// $Header: /cvsroot/l/li/libcw/src/libcwd/include/libcw/macro_AllocTag.h,v 1.6 2002/01/31 04:42:08 libcw Exp $ +// $Header: /cvsroot/l/li/libcw/src/libcwd/include/libcw/macro_AllocTag.h,v 1.7 2002/02/11 03:00:24 libcw Exp $ // // Copyright (C) 2000 - 2001, by // @@ -185,7 +185,7 @@ desc = new char [size]; \ buf.rdbuf()->sgetn(desc, size); \ } \ - ::libcw::debug::_private:::set_alloc_checking_on(LIBCWD_TSD); \ + ::libcw::debug::_private_::set_alloc_checking_on(LIBCWD_TSD); \ ::libcw::debug::set_alloc_label(p, ::libcw::debug::type_info_of(p), \ ::libcw::lockable_auto_ptr<char, true>(desc)); \ } while(0) Index: src/libcwd/include/libcw/macro_Libcwd_macros.h diff -u src/libcwd/include/libcw/macro_Libcwd_macros.h:1.5 src/libcwd/include/libcw/macro_Libcwd_macros.h:1.6 --- src/libcwd/include/libcw/macro_Libcwd_macros.h:1.5 Tue Feb 5 16:46:08 2002 +++ src/libcwd/include/libcw/macro_Libcwd_macros.h Sun Feb 10 19:00:24 2002 @@ -1,4 +1,4 @@ -// $Header: /cvsroot/l/li/libcw/src/libcwd/include/libcw/macro_Libcwd_macros.h,v 1.5 2002/02/06 00:46:08 libcw Exp $ +// $Header: /cvsroot/l/li/libcw/src/libcwd/include/libcw/macro_Libcwd_macros.h,v 1.6 2002/02/11 03:00:24 libcw Exp $ // // Copyright (C) 2000 - 2002, by // @@ -58,7 +58,7 @@ #define LIBCWD_STR1(x) #x #define LIBCWD_STR2(x) LIBCWD_STR1(x) #define LIBCWD_STR3 "LibcwDout at " __FILE__ ":" LIBCWD_STR2(__LINE__) "\n" -#define DEBUGDEBUGLIBCWDOUTMARKER ::write(2, LIBCWD_STR3, sizeof(LIBCWD_STR3) - 1); +#define DEBUGDEBUGLIBCWDOUTMARKER LibcwDebugThreads( ++__libcwd_tsd.internal_debugging_code ); ::write(2, LIBCWD_STR3, sizeof(LIBCWD_STR3) - 1); LibcwDebugThreads( --__libcwd_tsd.internal_debugging_code ); #else // !DEBUGDEBUGOUTPUT #define DEBUGDEBUGLIBCWDOUTMARKER #endif // !DEBUGDEBUGOUTPUT @@ -80,8 +80,8 @@ #define LibcwDoutScopeBegin( dc_namespace, debug_obj, cntrl ) \ do \ { \ - DEBUGDEBUGLIBCWDOUTMARKER \ LIBCWD_TSD_DECLARATION \ + DEBUGDEBUGLIBCWDOUTMARKER \ if (LIBCWD_DO_TSD_MEMBER_OFF(debug_obj) < 0) \ { \ using namespace ::libcw::debug; \ @@ -114,7 +114,7 @@ #ifndef DEBUGDEBUGLIBCWDOUTFATALMARKER #ifdef DEBUGDEBUGOUTPUT #define LIBCWD_STR4 "LibcwDoutFatal at " __FILE__ ":" LIBCWD_STR2(__LINE__) "\n" -#define DEBUGDEBUGLIBCWDOUTFATALMARKER ::write(2, LIBCWD_STR4, sizeof(LIBCWD_STR4) - 1); +#define DEBUGDEBUGLIBCWDOUTFATALMARKER LibcwDebugThreads( ++__libcwd_tsd.internal_debugging_code ); ::write(2, LIBCWD_STR4, sizeof(LIBCWD_STR4) - 1); LibcwDebugThreads( --__libcwd_tsd.internal_debugging_code ); #else #define DEBUGDEBUGLIBCWDOUTFATALMARKER #endif @@ -136,8 +136,8 @@ #define LibcwDoutFatalScopeBegin( dc_namespace, debug_obj, cntrl ) \ do \ { \ - DEBUGDEBUGLIBCWDOUTFATALMARKER \ LIBCWD_TSD_DECLARATION \ + DEBUGDEBUGLIBCWDOUTFATALMARKER \ using namespace ::libcw::debug; \ ::libcw::debug::channel_set_bootstrap_st __libcwd_channel_set(LIBCWD_DO_TSD(debug_obj) LIBCWD_COMMA_TSD); \ { \ ----------------------- End of diff ----------------------- |