|
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 -----------------------
|