This is the mail archive of the libstdc++@gcc.gnu.org mailing list for the libstdc++ project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

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"

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]