diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog
index f434a830483..615d83f51d7 100644
--- a/libstdc++-v3/ChangeLog
+++ b/libstdc++-v3/ChangeLog
@@ -1,3 +1,22 @@
+2004-10-08 Benjamin Kosnik
+
+ * acconfig.h: Add _GLIBCXX_USE___CXA_ATEXIT.
+ * acinclude.m4 (GLIBCXX_ENABLE_CXA_ATEXIT): New.
+ * configure.ac: Call GLIBCXX_ENABLE_CXA_EXIT.
+ * configure: Regenerate.
+ * src/mt_allocator.cc (__pool::~__pool): Make conditional on
+ _GLIBCXX_USE___CXA_ATEXIT macro.
+ * docs/html/ext/mt_allocator.html: Add note about deallocation.
+ * testsuite/ext/mt_allocator/deallocate_local-2.cc: Guard checks
+ with _GLIBCXX_USE___CXA_ATEXIT.
+ * testsuite/ext/mt_allocator/deallocate_global_thread-3.cc: Same.
+ * testsuite/ext/mt_allocator/deallocate_global_thread-1.cc: Same.
+ * testsuite/ext/mt_allocator/deallocate_global-4.cc: Same.
+ * testsuite/ext/mt_allocator/deallocate_global-2.cc: Same.
+ * testsuite/ext/mt_allocator/deallocate_local_thread-3.cc: Same.
+ * testsuite/ext/mt_allocator/deallocate_local_thread-1.cc: Same.
+ * testsuite/ext/mt_allocator/deallocate_local-4.cc: Same.
+
2004-10-07 Phil Edwards
* testsuite/lib/libstdc++.exp: Update list of undefined functions.
diff --git a/libstdc++-v3/acconfig.h b/libstdc++-v3/acconfig.h
index cffecbd172f..6a2ba98887d 100644
--- a/libstdc++-v3/acconfig.h
+++ b/libstdc++-v3/acconfig.h
@@ -28,6 +28,9 @@
// Define to use concept checking code from the boost libraries.
#undef _GLIBCXX_CONCEPT_CHECKS
+// Define to use __cxa_atexit.
+#undef _GLIBCXX_USE___CXA_ATEXIT
+
// Define to use symbol versioning in the shared library.
#undef _GLIBCXX_SYMVER
diff --git a/libstdc++-v3/acinclude.m4 b/libstdc++-v3/acinclude.m4
index 0bd4aa645d9..f45845a7249 100644
--- a/libstdc++-v3/acinclude.m4
+++ b/libstdc++-v3/acinclude.m4
@@ -611,6 +611,21 @@ AC_DEFUN([GLIBCXX_ENABLE_FULLY_DYNAMIC_STRING], [
fi
])
+dnl
+dnl Check for --enable-__cxa_atexit
+dnl
+dnl --enable-__cxa_atexit defines _GLIBCXX_USE___CXA_ATEXIT
+dnl --disable-__cxa_atexit doesn't define _GLIBCXX_USE___CXA_ATEXIT
+dnl + Usage: GLIBCXX_ENABLE_FULLY_DYNAMIC_STRING[(DEFAULT)]
+dnl Where DEFAULT is either `yes' or `no'.
+dnl
+AC_DEFUN([GLIBCXX_ENABLE_CXA_ATEXIT], [
+ GLIBCXX_ENABLE(__cxa_atexit,$1,,
+ [Define if __cxa_atexit is to be used instead of atexit.])
+ if test $enable___cxa_atexit = yes; then
+ AC_DEFINE(_GLIBCXX_USE___CXA_ATEXIT)
+ fi
+])
dnl
dnl Does any necessary configuration of the testsuite directory. Generates
diff --git a/libstdc++-v3/config.h.in b/libstdc++-v3/config.h.in
index acb7d732abc..be444e50187 100644
--- a/libstdc++-v3/config.h.in
+++ b/libstdc++-v3/config.h.in
@@ -29,6 +29,9 @@
// Define to use concept checking code from the boost libraries.
#undef _GLIBCXX_CONCEPT_CHECKS
+// Define to use __cxa_atexit.
+#undef _GLIBCXX_USE___CXA_ATEXIT
+
// Define to use symbol versioning in the shared library.
#undef _GLIBCXX_SYMVER
diff --git a/libstdc++-v3/configure b/libstdc++-v3/configure
index b2ca698a0d7..530efa0c646 100755
--- a/libstdc++-v3/configure
+++ b/libstdc++-v3/configure
@@ -856,6 +856,8 @@ Optional Features:
--enable-sjlj-exceptions
force use of builtin_setjmp for exceptions
[default=auto]
+ --enable-__cxa_atexit Define if __cxa_atexit is to be used instead of
+ atexit. [default=no]
--enable-libstdcxx-pch build pre-compiled libstdc++ headers
[default=$is_hosted]
--enable-cstdio=PACKAGE use target-specific I/O package
@@ -4397,7 +4399,7 @@ test x"$pic_mode" = xno && libtool_flags="$libtool_flags --prefer-non-pic"
case $host in
*-*-irix6*)
# Find out which ABI we are using.
- echo '#line 4400 "configure"' > conftest.$ac_ext
+ echo '#line 4402 "configure"' > conftest.$ac_ext
if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
(eval $ac_compile) 2>&5
ac_status=$?
@@ -5018,7 +5020,7 @@ fi;
#
# Fake what AC_TRY_COMPILE does. XXX Look at redoing this new-style.
cat > conftest.$ac_ext << EOF
-#line 5021 "configure"
+#line 5023 "configure"
struct S { ~S(); };
void bar();
void foo()
@@ -5074,6 +5076,29 @@ ac_compiler_gnu=$ac_cv_c_compiler_gnu
echo "${ECHO_T}$ac_exception_model_name" >&6
+ # Check whether --enable-__cxa_atexit or --disable-__cxa_atexit was given.
+if test "${enable___cxa_atexit+set}" = set; then
+ enableval="$enable___cxa_atexit"
+
+ case "$enableval" in
+ yes|no) ;;
+ *) { { echo "$as_me:$LINENO: error: Argument to enable/disable __cxa_atexit must be yes or no" >&5
+echo "$as_me: error: Argument to enable/disable __cxa_atexit must be yes or no" >&2;}
+ { (exit 1); exit 1; }; } ;;
+ esac
+
+else
+ enable___cxa_atexit=no
+fi;
+
+ if test $enable___cxa_atexit = yes; then
+ cat >>confdefs.h <<\_ACEOF
+#define _GLIBCXX_USE___CXA_ATEXIT 1
+_ACEOF
+
+ fi
+
+
echo "$as_me:$LINENO: checking for enabled PCH" >&5
echo $ECHO_N "checking for enabled PCH... $ECHO_C" >&6
# Check whether --enable-libstdcxx-pch or --disable-libstdcxx-pch was given.
diff --git a/libstdc++-v3/configure.ac b/libstdc++-v3/configure.ac
index a11f034120b..9978891ff9b 100644
--- a/libstdc++-v3/configure.ac
+++ b/libstdc++-v3/configure.ac
@@ -78,6 +78,7 @@ GLIBCXX_ENABLE_HOSTED
# Check for support bits and g++ features that don't require linking.
GLIBCXX_ENABLE_SJLJ_EXCEPTIONS
+GLIBCXX_ENABLE_CXA_ATEXIT([no])
GLIBCXX_ENABLE_PCH($is_hosted)
# Enable all the variable C++ runtime options.
diff --git a/libstdc++-v3/docs/html/ext/mt_allocator.html b/libstdc++-v3/docs/html/ext/mt_allocator.html
index 9ddd5a052de..f2f8348ca25 100644
--- a/libstdc++-v3/docs/html/ext/mt_allocator.html
+++ b/libstdc++-v3/docs/html/ext/mt_allocator.html
@@ -265,14 +265,26 @@ The _S_initialize() function:
I.e. _S_bin[ n ].free[ n ] = 0;
- - Initialize the mutex of each bin_record:
- The bin_record->mutex is used to protect the global freelist. This concept
- of a global freelist is explained in more detail in the section
- "A multi threaded example", but basically this mutex is locked whenever
- a block of memory is retrieved or returned to the global freelist for this
- specific bin. This only occurs when a number of blocks are grabbed from the
- global list to a thread specific list or when a thread decides to return
- some blocks to the global freelist.
+ - Initialize the mutex of each bin_record: The bin_record->mutex
+ is used to protect the global freelist. This concept of a global
+ freelist is explained in more detail in the section "A multi
+ threaded example", but basically this mutex is locked whenever a
+ block of memory is retrieved or returned to the global freelist
+ for this specific bin. This only occurs when a number of blocks
+ are grabbed from the global list to a thread specific list or when
+ a thread decides to return some blocks to the global freelist.
+
+
+ Notes about deallocation. On systems with the function
+__cxa_atexit
, the allocator will free all memory
+allocated before program termination. However, because this relies on
+the precise and exactly-conforming ordering of static destructors,
+including those of a static local __pool
object, it is
+not available on systems that don't have the necessary underlying
+support. On those systems, memory debugging programs like valgrind or
+purify may notice leaks: sorry about this inconvenience. However, most
+operating systems actually reclaim this memory at program termination
+anyway.
diff --git a/libstdc++-v3/src/mt_allocator.cc b/libstdc++-v3/src/mt_allocator.cc
index 1e45f4cfb1b..7c3f5a4fa64 100644
--- a/libstdc++-v3/src/mt_allocator.cc
+++ b/libstdc++-v3/src/mt_allocator.cc
@@ -48,6 +48,7 @@ namespace __gnu_cxx
{
__pool::~__pool()
{
+#ifdef _GLIBCXX_USE___CXA_ATEXIT
if (_M_init && !_M_options._M_force_new)
{
for (size_t __n = 0; __n < _M_bin_size; ++__n)
@@ -65,6 +66,7 @@ namespace __gnu_cxx
delete _M_bin;
delete _M_binmap;
}
+#endif
}
void
@@ -174,6 +176,7 @@ namespace __gnu_cxx
#ifdef __GTHREADS
__pool::~__pool()
{
+#ifdef _GLIBCXX_USE___CXA_ATEXIT
if (_M_init && !_M_options._M_force_new)
{
if (__gthread_active_p())
@@ -213,6 +216,7 @@ namespace __gnu_cxx
delete _M_bin;
delete _M_binmap;
}
+#endif
}
void
diff --git a/libstdc++-v3/testsuite/ext/mt_allocator/deallocate_global-2.cc b/libstdc++-v3/testsuite/ext/mt_allocator/deallocate_global-2.cc
index f0484872989..01baada5470 100644
--- a/libstdc++-v3/testsuite/ext/mt_allocator/deallocate_global-2.cc
+++ b/libstdc++-v3/testsuite/ext/mt_allocator/deallocate_global-2.cc
@@ -31,8 +31,10 @@ struct count_check
count_check() {}
~count_check()
{
+#ifdef _GLIBCXX_USE___CXA_ATEXIT
if (count != 0)
throw std::exception();
+#endif
}
};
diff --git a/libstdc++-v3/testsuite/ext/mt_allocator/deallocate_global-4.cc b/libstdc++-v3/testsuite/ext/mt_allocator/deallocate_global-4.cc
index 02c6a4c4c68..3d5b96233f5 100644
--- a/libstdc++-v3/testsuite/ext/mt_allocator/deallocate_global-4.cc
+++ b/libstdc++-v3/testsuite/ext/mt_allocator/deallocate_global-4.cc
@@ -31,8 +31,10 @@ struct count_check
count_check() {}
~count_check()
{
+#ifdef _GLIBCXX_USE___CXA_ATEXIT
if (count != 0)
throw std::runtime_error("count isn't zero");
+#endif
}
};
diff --git a/libstdc++-v3/testsuite/ext/mt_allocator/deallocate_global_thread-1.cc b/libstdc++-v3/testsuite/ext/mt_allocator/deallocate_global_thread-1.cc
index 1f0ac281af7..3ec3abcd6b6 100644
--- a/libstdc++-v3/testsuite/ext/mt_allocator/deallocate_global_thread-1.cc
+++ b/libstdc++-v3/testsuite/ext/mt_allocator/deallocate_global_thread-1.cc
@@ -31,8 +31,10 @@ struct count_check
count_check() {}
~count_check()
{
+#ifdef _GLIBCXX_USE___CXA_ATEXIT
if (count != 0)
throw std::runtime_error("count isn't zero");
+#endif
}
};
diff --git a/libstdc++-v3/testsuite/ext/mt_allocator/deallocate_global_thread-3.cc b/libstdc++-v3/testsuite/ext/mt_allocator/deallocate_global_thread-3.cc
index 10efea66ec6..398ef31d39d 100644
--- a/libstdc++-v3/testsuite/ext/mt_allocator/deallocate_global_thread-3.cc
+++ b/libstdc++-v3/testsuite/ext/mt_allocator/deallocate_global_thread-3.cc
@@ -31,8 +31,10 @@ struct count_check
count_check() {}
~count_check()
{
+#ifdef _GLIBCXX_USE___CXA_ATEXIT
if (count != 0)
throw std::runtime_error("count isn't zero");
+#endif
}
};
diff --git a/libstdc++-v3/testsuite/ext/mt_allocator/deallocate_local-2.cc b/libstdc++-v3/testsuite/ext/mt_allocator/deallocate_local-2.cc
index a6af89f11f0..b8e2784f484 100644
--- a/libstdc++-v3/testsuite/ext/mt_allocator/deallocate_local-2.cc
+++ b/libstdc++-v3/testsuite/ext/mt_allocator/deallocate_local-2.cc
@@ -31,8 +31,10 @@ struct count_check
count_check() {}
~count_check()
{
+#ifdef _GLIBCXX_USE___CXA_ATEXIT
if (count != 0)
throw std::runtime_error("count isn't zero");
+#endif
}
};
diff --git a/libstdc++-v3/testsuite/ext/mt_allocator/deallocate_local-4.cc b/libstdc++-v3/testsuite/ext/mt_allocator/deallocate_local-4.cc
index c194b977d57..1df7fb500cd 100644
--- a/libstdc++-v3/testsuite/ext/mt_allocator/deallocate_local-4.cc
+++ b/libstdc++-v3/testsuite/ext/mt_allocator/deallocate_local-4.cc
@@ -31,8 +31,10 @@ struct count_check
count_check() {}
~count_check()
{
+#ifdef _GLIBCXX_USE___CXA_ATEXIT
if (count != 0)
throw std::runtime_error("count isn't zero");
+#endif
}
};
diff --git a/libstdc++-v3/testsuite/ext/mt_allocator/deallocate_local_thread-1.cc b/libstdc++-v3/testsuite/ext/mt_allocator/deallocate_local_thread-1.cc
index 5664d3caff8..2191264e942 100644
--- a/libstdc++-v3/testsuite/ext/mt_allocator/deallocate_local_thread-1.cc
+++ b/libstdc++-v3/testsuite/ext/mt_allocator/deallocate_local_thread-1.cc
@@ -31,8 +31,10 @@ struct count_check
count_check() {}
~count_check()
{
+#ifdef _GLIBCXX_USE___CXA_ATEXIT
if (count != 0)
throw std::runtime_error("count isn't zero");
+#endif
}
};
diff --git a/libstdc++-v3/testsuite/ext/mt_allocator/deallocate_local_thread-3.cc b/libstdc++-v3/testsuite/ext/mt_allocator/deallocate_local_thread-3.cc
index 973f758d98d..6094a718a0e 100644
--- a/libstdc++-v3/testsuite/ext/mt_allocator/deallocate_local_thread-3.cc
+++ b/libstdc++-v3/testsuite/ext/mt_allocator/deallocate_local_thread-3.cc
@@ -31,8 +31,10 @@ struct count_check
count_check() {}
~count_check()
{
+#ifdef _GLIBCXX_USE___CXA_ATEXIT
if (count != 0)
throw std::runtime_error("count isn't zero");
+#endif
}
};