This is the mail archive of the
libstdc++@gcc.gnu.org
mailing list for the libstdc++ project.
Re: PATCH: profile mode fix for threads on solaris and cleanup
On Tue, May 11, 2010 at 3:25 AM, Paolo Carlini <paolo.carlini@oracle.com> wrote:
> I applied to mainline this slightly tweaked version (a few redundant
> includes removed, formatting fixes...)
>
> Thanks,
> Paolo.
Great!
Attached is the requested patch containing only the requested fixes
for the gcc-4_5-branch. I am running the test suite right now just in
case, but I validated it already on a couple of comprehensive tests.
Thank you,
Silvius
Index: libstdc++-v3/include/profile/impl/profiler_trace.h
===================================================================
--- libstdc++-v3/include/profile/impl/profiler_trace.h (revision 159251)
+++ libstdc++-v3/include/profile/impl/profiler_trace.h (working copy)
@@ -53,43 +53,30 @@
#define _GLIBCXX_IMPL_UNORDERED_MAP std::tr1::unordered_map
#endif
+#include <ext/concurrence.h>
#include <fstream>
#include <string>
#include <utility>
#include <bits/stl_heap.h> // for std::make_heap, std::sort_heap
-#if (defined _GLIBCXX_PROFILE_THREADS) && !(defined _GLIBCXX_HAVE_TLS)
-#error You do not seem to have TLS support, which is required by the profile \
- mode. If your program is not multithreaded, recompile with \
- -D_GLIBCXX_PROFILE_NO_THREADS
-#endif
-
-#if defined _GLIBCXX_PROFILE_THREADS && defined _GLIBCXX_HAVE_TLS
-#include <pthread.h>
-#endif
-
#include "profile/impl/profiler_state.h"
#include "profile/impl/profiler_node.h"
namespace __gnu_profile
{
+/** @brief Internal environment. Values can be set one of two ways:
+ 1. In config file "var = value". The default config file path is
+ libstdcxx-profile.conf.
+ 2. By setting process environment variables. For instance, in a Bash
+ shell you can set the unit cost of iterating through a map like this:
+ export __map_iterate_cost_factor=5.0.
+ If a value is set both in the input file and through an environment
+ variable, the environment value takes precedence. */
+typedef _GLIBCXX_IMPL_UNORDERED_MAP<std::string, std::string> __env_t;
+_GLIBCXX_PROFILE_DEFINE_UNINIT_DATA(__env_t, __env);
-#if defined _GLIBCXX_PROFILE_THREADS && defined _GLIBCXX_HAVE_TLS
-#define _GLIBCXX_IMPL_MUTEX_INITIALIZER PTHREAD_MUTEX_INITIALIZER
-typedef pthread_mutex_t __mutex_t;
-/** @brief Pthread mutex wrapper. */
-_GLIBCXX_PROFILE_DEFINE_DATA(__mutex_t, __global_lock,
- PTHREAD_MUTEX_INITIALIZER);
-inline void __lock(__mutex_t& __m) { pthread_mutex_lock(&__m); }
-inline void __unlock(__mutex_t& __m) { pthread_mutex_unlock(&__m); }
-#else
-typedef int __mutex_t;
-/** @brief Mock mutex interface. */
-#define _GLIBCXX_IMPL_MUTEX_INITIALIZER 0
-_GLIBCXX_PROFILE_DEFINE_DATA(__mutex_t, __global_lock, 0);
-inline void __lock(__mutex_t& __m) {}
-inline void __unlock(__mutex_t& __m) {}
-#endif
+/** @brief Master lock. */
+_GLIBCXX_PROFILE_DEFINE_UNINIT_DATA(__gnu_cxx::__mutex, __global_lock);
/** @brief Representation of a warning. */
struct __warning_data
@@ -228,14 +215,9 @@
void __write(FILE* f);
void __collect_warnings(__warning_vector_t& __warnings);
- void __lock_object_table();
- void __lock_stack_table();
- void __unlock_object_table();
- void __unlock_stack_table();
-
private:
- __mutex_t __object_table_lock;
- __mutex_t __stack_table_lock;
+ __gnu_cxx::__mutex __object_table_lock;
+ __gnu_cxx::__mutex __stack_table_lock;
typedef _GLIBCXX_IMPL_UNORDERED_MAP<__object_t,
__object_info> __object_table_t;
typedef _GLIBCXX_IMPL_UNORDERED_MAP<__stack_t, __stack_info, __stack_hash,
@@ -263,30 +245,6 @@
}
template <typename __object_info, typename __stack_info>
-void __trace_base<__object_info, __stack_info>::__lock_object_table()
-{
- __lock(this->__object_table_lock);
-}
-
-template <typename __object_info, typename __stack_info>
-void __trace_base<__object_info, __stack_info>::__lock_stack_table()
-{
- __lock(this->__stack_table_lock);
-}
-
-template <typename __object_info, typename __stack_info>
-void __trace_base<__object_info, __stack_info>::__unlock_object_table()
-{
- __unlock(this->__object_table_lock);
-}
-
-template <typename __object_info, typename __stack_info>
-void __trace_base<__object_info, __stack_info>::__unlock_stack_table()
-{
- __unlock(this->__stack_table_lock);
-}
-
-template <typename __object_info, typename __stack_info>
__trace_base<__object_info, __stack_info>::__trace_base()
{
// Do not pick the initial size too large, as we don't know which diagnostics
@@ -295,7 +253,6 @@
__stack_table.rehash(10000);
__stack_table_byte_size = 0;
__id = NULL;
- __object_table_lock = __stack_table_lock = _GLIBCXX_IMPL_MUTEX_INITIALIZER;
}
template <typename __object_info, typename __stack_info>
@@ -304,10 +261,10 @@
{
if (__max_mem() == 0
|| __object_table.size() * sizeof(__object_info) <= __max_mem()) {
- __lock_object_table();
+ this->__object_table_lock.lock();
__object_table.insert(
typename __object_table_t::value_type(__object, __info));
- __unlock_object_table();
+ this->__object_table_lock.unlock();
}
}
@@ -318,14 +275,14 @@
// XXX: Revisit this to see if we can decrease mutex spans.
// Without this mutex, the object table could be rehashed during an
// insertion on another thread, which could result in a segfault.
- __lock_object_table();
+ this->__object_table_lock.lock();
typename __object_table_t::iterator __object_it =
__object_table.find(__object);
if (__object_it == __object_table.end()){
- __unlock_object_table();
+ this->__object_table_lock.unlock();
return NULL;
} else {
- __unlock_object_table();
+ this->__object_table_lock.unlock();
return &__object_it->second;
}
}
@@ -334,8 +291,8 @@
void __trace_base<__object_info, __stack_info>::__retire_object(
__object_t __object)
{
- __lock_object_table();
- __lock_stack_table();
+ this->__object_table_lock.lock();
+ this->__stack_table_lock.lock();
typename __object_table_t::iterator __object_it =
__object_table.find(__object);
if (__object_it != __object_table.end()){
@@ -358,8 +315,8 @@
}
__object_table.erase(__object);
}
- __unlock_stack_table();
- __unlock_object_table();
+ this->__object_table_lock.unlock();
+ this->__stack_table_lock.unlock();
}
template <typename __object_info, typename __stack_info>
@@ -451,7 +408,7 @@
*/
inline void __report(void)
{
- __lock(_GLIBCXX_PROFILE_DATA(__global_lock));
+ _GLIBCXX_PROFILE_DATA(__global_lock).lock();
__warning_vector_t __warnings;
@@ -493,7 +450,7 @@
fclose(__warn_file);
- __unlock(_GLIBCXX_PROFILE_DATA(__global_lock));
+ _GLIBCXX_PROFILE_DATA(__global_lock).unlock();
}
inline void __set_trace_path()
@@ -559,7 +516,7 @@
std::string::size_type __end = __line.find_first_of(";\n");
std::string __factor_value = __line.substr(__pos + 1, __end - __pos);
- setenv(__factor_name.c_str(), __factor_value.c_str(), 0);
+ _GLIBCXX_PROFILE_DATA(__env)[__factor_name] = __factor_value;
}
}
}
@@ -611,13 +568,23 @@
for (__decltype(_GLIBCXX_PROFILE_DATA(__cost_factors)->begin()) __it
= _GLIBCXX_PROFILE_DATA(__cost_factors)->begin();
__it != _GLIBCXX_PROFILE_DATA(__cost_factors)->end(); ++__it)
- if (char* __env_cost_factor = getenv((*__it)->__env_var))
- (*__it)->__value = atof(__env_cost_factor);
+ {
+ const char* __env_cost_factor = getenv((*__it)->__env_var);
+ if (!__env_cost_factor)
+ {
+ __env_t::iterator __found = _GLIBCXX_PROFILE_DATA(__env).find(
+ (*__it)->__env_var);
+ if (__found != _GLIBCXX_PROFILE_DATA(__env).end())
+ __env_cost_factor = (*__found).second.c_str();
+ }
+ if (__env_cost_factor)
+ (*__it)->__value = atof(__env_cost_factor);
+ }
}
inline void __profcxx_init_unconditional()
{
- __lock(_GLIBCXX_PROFILE_DATA(__global_lock));
+ _GLIBCXX_PROFILE_DATA(__global_lock).lock();
if (__is_invalid()) {
@@ -651,7 +618,7 @@
}
}
- __unlock(_GLIBCXX_PROFILE_DATA(__global_lock));
+ _GLIBCXX_PROFILE_DATA(__global_lock).unlock();
}
/** @brief This function must be called by each instrumentation point.
Index: libstdc++-v3/include/profile/impl/profiler.h
===================================================================
--- libstdc++-v3/include/profile/impl/profiler.h (revision 159251)
+++ libstdc++-v3/include/profile/impl/profiler.h (working copy)
@@ -44,6 +44,13 @@
#endif
// Mechanism to define data with inline linkage.
+#define _GLIBCXX_PROFILE_DEFINE_UNINIT_DATA(__type, __name) \
+ inline __type& \
+ __get_##__name() \
+ { \
+ static __type __name; \
+ return __name; \
+ }
#define _GLIBCXX_PROFILE_DEFINE_DATA(__type, __name, __initial_value...) \
inline __type& __get_##__name() { \
static __type __name(__initial_value); \
@@ -362,11 +369,6 @@
#define __profcxx_map_to_unordered_map_find(__x...)
#endif
-// Run multithreaded unless instructed not to do so.
-#ifndef _GLIBCXX_PROFILE_NO_THREADS
-#define _GLIBCXX_PROFILE_THREADS
-#endif
-
// Set default values for compile-time customizable variables.
#ifndef _GLIBCXX_PROFILE_TRACE_PATH_ROOT
#define _GLIBCXX_PROFILE_TRACE_PATH_ROOT "libstdcxx-profile"