]> rtime.felk.cvut.cz Git - l4.git/blob - l4/pkg/libstdc++-v3/contrib/libstdc++-v3-4.7/include/profile/impl/profiler_trace.h
update
[l4.git] / l4 / pkg / libstdc++-v3 / contrib / libstdc++-v3-4.7 / include / profile / impl / profiler_trace.h
1 // -*- C++ -*-
2 //
3 // Copyright (C) 2009, 2010 Free Software Foundation, Inc.
4 //
5 // This file is part of the GNU ISO C++ Library.  This library is free
6 // software; you can redistribute it and/or modify it under the
7 // terms of the GNU General Public License as published by the
8 // Free Software Foundation; either version 3, or (at your option)
9 // any later version.
10 //
11 // This library is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 // GNU General Public License for more details.
15
16 // Under Section 7 of GPL version 3, you are granted additional
17 // permissions described in the GCC Runtime Library Exception, version
18 // 3.1, as published by the Free Software Foundation.
19
20 // You should have received a copy of the GNU General Public License along
21 // with this library; see the file COPYING3.  If not see
22 // <http://www.gnu.org/licenses/>.
23
24 /** @file profile/impl/profiler_trace.h
25  *  @brief Data structures to represent profiling traces.
26  */
27
28 // Written by Lixia Liu and Silvius Rus.
29
30 #ifndef _GLIBCXX_PROFILE_PROFILER_TRACE_H
31 #define _GLIBCXX_PROFILE_PROFILER_TRACE_H 1
32
33 #include <cstdio>  // fopen, fclose, fprintf, FILE
34 #include <cerrno>
35 #include <cstdlib> // atof, atoi, strtol, getenv, atexit, abort
36
37 #ifdef __GXX_EXPERIMENTAL_CXX0X__
38 #define _GLIBCXX_IMPL_UNORDERED_MAP std::_GLIBCXX_STD_C::unordered_map
39 #include <unordered_map>
40 #else
41 #include <tr1/unordered_map>
42 #define _GLIBCXX_IMPL_UNORDERED_MAP std::tr1::unordered_map
43 #endif
44
45 #include <ext/concurrence.h>
46 #include <fstream>
47 #include <string>
48 #include <utility>
49 #include <vector>
50
51 #include "profile/impl/profiler_algos.h"
52 #include "profile/impl/profiler_state.h"
53 #include "profile/impl/profiler_node.h"
54
55 namespace __gnu_profile
56 {
57   /** @brief Internal environment.  Values can be set one of two ways:
58       1. In config file "var = value".  The default config file path is 
59          libstdcxx-profile.conf.
60       2. By setting process environment variables.  For instance, in a Bash
61          shell you can set the unit cost of iterating through a map like this:
62          export __map_iterate_cost_factor=5.0.
63          If a value is set both in the input file and through an environment
64          variable, the environment value takes precedence.  */
65   typedef _GLIBCXX_IMPL_UNORDERED_MAP<std::string, std::string> __env_t;
66
67   _GLIBCXX_PROFILE_DEFINE_UNINIT_DATA(__env_t, __env);
68
69   /** @brief Master lock.  */
70   _GLIBCXX_PROFILE_DEFINE_UNINIT_DATA(__gnu_cxx::__mutex, __global_lock);
71
72   /** @brief Representation of a warning.  */
73   struct __warning_data
74   {
75     float __magnitude;
76     __stack_t __context;
77     const char* __warning_id;
78     std::string __warning_message;
79
80     __warning_data()
81     : __magnitude(0.0), __context(0), __warning_id(0) { }
82
83     __warning_data(float __m, __stack_t __c, const char* __id, 
84                    const std::string& __msg)
85     : __magnitude(__m), __context(__c), __warning_id(__id), 
86       __warning_message(__msg) { }
87
88     bool
89     operator<(const __warning_data& __other) const
90     { return __magnitude < __other.__magnitude; }
91   };
92
93   typedef std::_GLIBCXX_STD_C::vector<__warning_data> __warning_vector_t;
94
95   // Defined in profiler_<diagnostic name>.h.
96   class __trace_hash_func;
97   class __trace_hashtable_size;
98   class __trace_map2umap;
99   class __trace_vector_size;
100   class __trace_vector_to_list;
101   class __trace_list_to_slist; 
102   class __trace_list_to_vector; 
103   void __trace_vector_size_init();
104   void __trace_hashtable_size_init();
105   void __trace_hash_func_init();
106   void __trace_vector_to_list_init();
107   void __trace_list_to_slist_init();  
108   void __trace_list_to_vector_init();  
109   void __trace_map_to_unordered_map_init();
110   void __trace_vector_size_report(FILE*, __warning_vector_t&);
111   void __trace_hashtable_size_report(FILE*, __warning_vector_t&);
112   void __trace_hash_func_report(FILE*, __warning_vector_t&);
113   void __trace_vector_to_list_report(FILE*, __warning_vector_t&);
114   void __trace_list_to_slist_report(FILE*, __warning_vector_t&); 
115   void __trace_list_to_vector_report(FILE*, __warning_vector_t&);
116   void __trace_map_to_unordered_map_report(FILE*, __warning_vector_t&);
117
118   struct __cost_factor
119   {
120     const char* __env_var;
121     float __value;
122   };
123
124   typedef std::_GLIBCXX_STD_C::vector<__cost_factor*> __cost_factor_vector;
125
126   _GLIBCXX_PROFILE_DEFINE_DATA(__trace_hash_func*, _S_hash_func, 0);
127   _GLIBCXX_PROFILE_DEFINE_DATA(__trace_hashtable_size*, _S_hashtable_size, 0);
128   _GLIBCXX_PROFILE_DEFINE_DATA(__trace_map2umap*, _S_map2umap, 0);
129   _GLIBCXX_PROFILE_DEFINE_DATA(__trace_vector_size*, _S_vector_size, 0);
130   _GLIBCXX_PROFILE_DEFINE_DATA(__trace_vector_to_list*, _S_vector_to_list, 0);
131   _GLIBCXX_PROFILE_DEFINE_DATA(__trace_list_to_slist*, _S_list_to_slist, 0); 
132   _GLIBCXX_PROFILE_DEFINE_DATA(__trace_list_to_vector*, _S_list_to_vector, 0);
133
134   _GLIBCXX_PROFILE_DEFINE_DATA(__cost_factor, __vector_shift_cost_factor, 
135                                {"__vector_shift_cost_factor", 1.0});
136   _GLIBCXX_PROFILE_DEFINE_DATA(__cost_factor, __vector_iterate_cost_factor,
137                                {"__vector_iterate_cost_factor", 1.0});
138   _GLIBCXX_PROFILE_DEFINE_DATA(__cost_factor, __vector_resize_cost_factor,
139                                {"__vector_resize_cost_factor", 1.0}); 
140   _GLIBCXX_PROFILE_DEFINE_DATA(__cost_factor, __list_shift_cost_factor,
141                                {"__list_shift_cost_factor", 0.0});
142   _GLIBCXX_PROFILE_DEFINE_DATA(__cost_factor, __list_iterate_cost_factor,
143                                {"__list_iterate_cost_factor", 10.0}); 
144   _GLIBCXX_PROFILE_DEFINE_DATA(__cost_factor, __list_resize_cost_factor,
145                                {"__list_resize_cost_factor", 0.0}); 
146   _GLIBCXX_PROFILE_DEFINE_DATA(__cost_factor, __map_insert_cost_factor,
147                                {"__map_insert_cost_factor", 1.5});
148   _GLIBCXX_PROFILE_DEFINE_DATA(__cost_factor, __map_erase_cost_factor,
149                                {"__map_erase_cost_factor", 1.5});
150   _GLIBCXX_PROFILE_DEFINE_DATA(__cost_factor, __map_find_cost_factor,
151                                {"__map_find_cost_factor", 1});
152   _GLIBCXX_PROFILE_DEFINE_DATA(__cost_factor, __map_iterate_cost_factor,
153                                {"__map_iterate_cost_factor", 2.3});
154   _GLIBCXX_PROFILE_DEFINE_DATA(__cost_factor, __umap_insert_cost_factor,
155                                {"__umap_insert_cost_factor", 12.0});
156   _GLIBCXX_PROFILE_DEFINE_DATA(__cost_factor, __umap_erase_cost_factor,
157                                {"__umap_erase_cost_factor", 12.0});
158   _GLIBCXX_PROFILE_DEFINE_DATA(__cost_factor, __umap_find_cost_factor,
159                                {"__umap_find_cost_factor", 10.0});
160   _GLIBCXX_PROFILE_DEFINE_DATA(__cost_factor, __umap_iterate_cost_factor,
161                                {"__umap_iterate_cost_factor", 1.7});
162   _GLIBCXX_PROFILE_DEFINE_DATA(__cost_factor_vector*, __cost_factors, 0);
163
164   _GLIBCXX_PROFILE_DEFINE_DATA(const char*, _S_trace_file_name,
165                                _GLIBCXX_PROFILE_TRACE_PATH_ROOT);
166   _GLIBCXX_PROFILE_DEFINE_DATA(std::size_t, _S_max_warn_count,
167                                _GLIBCXX_PROFILE_MAX_WARN_COUNT);
168   _GLIBCXX_PROFILE_DEFINE_DATA(std::size_t, _S_max_stack_depth,
169                                _GLIBCXX_PROFILE_MAX_STACK_DEPTH);
170   _GLIBCXX_PROFILE_DEFINE_DATA(std::size_t, _S_max_mem,
171                                _GLIBCXX_PROFILE_MEM_PER_DIAGNOSTIC);
172
173   inline std::size_t
174   __stack_max_depth()
175   { return _GLIBCXX_PROFILE_DATA(_S_max_stack_depth); }
176
177   inline std::size_t
178   __max_mem()
179   { return _GLIBCXX_PROFILE_DATA(_S_max_mem); }
180
181   /** @brief Base class for all trace producers.  */
182   template<typename __object_info, typename __stack_info>
183     class __trace_base
184     {
185     public:
186       // Do not pick the initial size too large, as we don't know which
187       // diagnostics are more active.
188       __trace_base()
189       : __object_table(10000), __stack_table(10000),
190         __stack_table_byte_size(0), __id(0) { }
191
192       virtual ~__trace_base() { }
193
194       void __add_object(__object_t object, __object_info __info);
195       __object_info* __get_object_info(__object_t __object);
196       void __retire_object(__object_t __object);
197       void __write(FILE* __f);
198       void __collect_warnings(__warning_vector_t& __warnings);
199
200     private:
201       __gnu_cxx::__mutex __object_table_lock;
202       __gnu_cxx::__mutex __stack_table_lock;
203       typedef _GLIBCXX_IMPL_UNORDERED_MAP<__object_t, 
204                                           __object_info> __object_table_t;
205       typedef _GLIBCXX_IMPL_UNORDERED_MAP<__stack_t, __stack_info,
206                                           __stack_hash, 
207                                           __stack_hash> __stack_table_t;
208       __object_table_t __object_table;
209       __stack_table_t __stack_table;
210       std::size_t __stack_table_byte_size;
211
212     protected:
213       const char* __id;
214     };
215
216   template<typename __object_info, typename __stack_info>
217     void
218     __trace_base<__object_info, __stack_info>::
219     __collect_warnings(__warning_vector_t& __warnings)
220     {
221       for (typename __stack_table_t::iterator __it
222              = __stack_table.begin(); __it != __stack_table.end(); ++__it)
223         __warnings.push_back(__warning_data((*__it).second.__magnitude(),
224                                             (*__it).first, __id,
225                                             (*__it).second.__advice()));
226     }
227
228   template<typename __object_info, typename __stack_info>
229     void
230     __trace_base<__object_info, __stack_info>::
231     __add_object(__object_t __object, __object_info __info)
232     {
233       if (__max_mem() == 0 
234           || __object_table.size() * sizeof(__object_info) <= __max_mem())
235         {
236           this->__object_table_lock.lock();
237           __object_table.insert(typename __object_table_t::
238                                 value_type(__object, __info));
239           this->__object_table_lock.unlock();
240         }
241     }
242
243   template<typename __object_info, typename __stack_info>
244     __object_info*
245     __trace_base<__object_info, __stack_info>::
246     __get_object_info(__object_t __object)
247     {
248       // XXX: Revisit this to see if we can decrease mutex spans.
249       // Without this mutex, the object table could be rehashed during an
250       // insertion on another thread, which could result in a segfault.
251       this->__object_table_lock.lock();
252       typename __object_table_t::iterator __object_it
253         =  __object_table.find(__object);
254
255       if (__object_it == __object_table.end())
256         {
257           this->__object_table_lock.unlock();
258           return 0;
259         }
260       else
261         {
262           this->__object_table_lock.unlock();
263           return &__object_it->second;
264         }
265     }
266
267   template<typename __object_info, typename __stack_info>
268     void
269     __trace_base<__object_info, __stack_info>::
270     __retire_object(__object_t __object)
271     {
272       this->__object_table_lock.lock();
273       this->__stack_table_lock.lock();
274       typename __object_table_t::iterator __object_it
275         = __object_table.find(__object);
276   
277       if (__object_it != __object_table.end())
278         {
279           const __object_info& __info = __object_it->second;
280           const __stack_t& __stack = __info.__stack();
281           typename __stack_table_t::iterator __stack_it
282             = __stack_table.find(__stack);
283     
284           if (__stack_it == __stack_table.end())
285             {
286               // First occurence of this call context.
287               if (__max_mem() == 0 || __stack_table_byte_size < __max_mem()) 
288                 {
289                   __stack_table_byte_size 
290                     += (sizeof(__instruction_address_t) * __size(__stack)
291                         + sizeof(__stack) + sizeof(__stack_info));
292                   __stack_table.insert(make_pair(__stack,
293                                                  __stack_info(__info)));
294                 }
295             }
296           else
297             {
298               // Merge object info into info summary for this call context.
299               __stack_it->second.__merge(__info);
300               delete __stack;
301             }
302           __object_table.erase(__object);
303         }
304
305       this->__object_table_lock.unlock();
306       this->__stack_table_lock.unlock();
307     }
308
309   template<typename __object_info, typename __stack_info>
310     void
311     __trace_base<__object_info, __stack_info>::
312     __write(FILE* __f)
313     {
314       for (typename __stack_table_t::iterator __it
315              = __stack_table.begin(); __it != __stack_table.end(); ++__it)
316         if (__it->second.__is_valid())
317           {
318             std::fprintf(__f, __id);
319             std::fprintf(__f, "|");
320             __gnu_profile::__write(__f, __it->first);
321             std::fprintf(__f, "|");
322             __it->second.__write(__f);
323           }
324     }
325
326   inline std::size_t
327   __env_to_size_t(const char* __env_var, std::size_t __default_value)
328   {
329     char* __env_value = std::getenv(__env_var);
330     if (__env_value)
331       {
332         errno = 0;
333         long __converted_value = std::strtol(__env_value, 0, 10);
334         if (errno || __converted_value < 0)
335           {
336             std::fprintf(stderr,
337                          "Bad value for environment variable '%s'.\n",
338                          __env_var);
339             std::abort();
340           }
341         else
342           return static_cast<std::size_t>(__converted_value);
343       }
344     else
345       return __default_value;
346   }
347
348   inline void
349   __set_max_stack_trace_depth()
350   {
351     _GLIBCXX_PROFILE_DATA(_S_max_stack_depth)
352       = __env_to_size_t(_GLIBCXX_PROFILE_MAX_STACK_DEPTH_ENV_VAR,
353                         _GLIBCXX_PROFILE_DATA(_S_max_stack_depth));
354   }
355
356   inline void
357   __set_max_mem()
358   {
359     _GLIBCXX_PROFILE_DATA(_S_max_mem) 
360       = __env_to_size_t(_GLIBCXX_PROFILE_MEM_PER_DIAGNOSTIC_ENV_VAR,
361                         _GLIBCXX_PROFILE_DATA(_S_max_mem));
362   }
363
364   inline int
365   __log_magnitude(float __f)
366   {
367     const float __log_base = 10.0;
368     int __result = 0;
369     int __sign = 1;
370
371     if (__f < 0) 
372       {
373         __f = -__f;
374         __sign = -1;
375       }
376
377     while (__f > __log_base) 
378       {
379         ++__result;
380         __f /= 10.0;
381       }
382     return __sign * __result;
383   }
384
385   inline FILE* 
386   __open_output_file(const char* __extension)
387   {
388     // The path is made of _S_trace_file_name + "." + extension.
389     std::size_t __root_len 
390       = __builtin_strlen(_GLIBCXX_PROFILE_DATA(_S_trace_file_name));
391     std::size_t __ext_len = __builtin_strlen(__extension);
392     char* __file_name = new char[__root_len + 1 + __ext_len + 1];
393     __builtin_memcpy(__file_name,
394                      _GLIBCXX_PROFILE_DATA(_S_trace_file_name),
395                      __root_len);
396     *(__file_name + __root_len) = '.';
397     __builtin_memcpy(__file_name + __root_len + 1,
398                      __extension, __ext_len + 1);
399
400     FILE* __out_file = std::fopen(__file_name, "w");
401     if (!__out_file)
402       {
403         std::fprintf(stderr, "Could not open trace file '%s'.\n",
404                      __file_name);
405         std::abort();
406       }
407
408     delete[] __file_name;
409     return __out_file;
410   }
411
412   struct __warn
413   {
414     FILE* __file;
415
416     __warn(FILE* __f)
417     { __file = __f; }
418
419     void
420     operator()(const __warning_data& __info)
421     {
422       std::fprintf(__file,  __info.__warning_id);
423       std::fprintf(__file, ": improvement = %d",
424                    __log_magnitude(__info.__magnitude));
425       std::fprintf(__file, ": call stack = ");
426       __gnu_profile::__write(__file, __info.__context);
427       std::fprintf(__file, ": advice = %s\n",
428                    __info.__warning_message.c_str());
429     }
430   };
431
432   /** @brief Final report method, registered with @b atexit.
433    *
434    * This can also be called directly by user code, including signal handlers.
435    * It is protected against deadlocks by the reentrance guard in profiler.h.
436    * However, when called from a signal handler that triggers while within
437    * __gnu_profile (under the guarded zone), no output will be produced.
438    */
439   inline void
440   __report(void)
441   {
442     _GLIBCXX_PROFILE_DATA(__global_lock).lock();
443
444     __warning_vector_t __warnings, __top_warnings;
445
446     FILE* __raw_file = __open_output_file("raw");
447     __trace_vector_size_report(__raw_file, __warnings);
448     __trace_hashtable_size_report(__raw_file, __warnings);
449     __trace_hash_func_report(__raw_file, __warnings);
450     __trace_vector_to_list_report(__raw_file, __warnings);
451     __trace_list_to_slist_report(__raw_file, __warnings);
452     __trace_list_to_vector_report(__raw_file, __warnings);
453     __trace_map_to_unordered_map_report(__raw_file, __warnings);
454     std::fclose(__raw_file);
455
456     // Sort data by magnitude, keeping just top N.
457     std::size_t __cutoff = std::min(_GLIBCXX_PROFILE_DATA(_S_max_warn_count),
458                                     __warnings.size());
459     __top_n(__warnings, __top_warnings, __cutoff);
460
461     FILE* __warn_file = __open_output_file("txt");
462     __for_each(__top_warnings.begin(), __top_warnings.end(),
463                __warn(__warn_file));
464     std::fclose(__warn_file);
465
466     _GLIBCXX_PROFILE_DATA(__global_lock).unlock();
467   }
468
469   inline void
470   __set_trace_path()
471   {
472     char* __env_trace_file_name = std::getenv(_GLIBCXX_PROFILE_TRACE_ENV_VAR);
473
474     if (__env_trace_file_name)
475       _GLIBCXX_PROFILE_DATA(_S_trace_file_name) = __env_trace_file_name;
476
477     // Make sure early that we can create the trace file.
478     std::fclose(__open_output_file("txt"));
479   }
480
481   inline void
482   __set_max_warn_count()
483   {
484     char* __env_max_warn_count_str
485       = std::getenv(_GLIBCXX_PROFILE_MAX_WARN_COUNT_ENV_VAR);
486
487     if (__env_max_warn_count_str)
488       _GLIBCXX_PROFILE_DATA(_S_max_warn_count)
489         = static_cast<std::size_t>(std::atoi(__env_max_warn_count_str));
490   }
491
492   inline void
493   __read_cost_factors()
494   {
495     std::string __conf_file_name(_GLIBCXX_PROFILE_DATA(_S_trace_file_name));
496     __conf_file_name += ".conf";
497
498     std::ifstream __conf_file(__conf_file_name.c_str());
499
500     if (__conf_file.is_open())
501       {
502         std::string __line;
503
504         while (std::getline(__conf_file, __line))
505           {
506             std::string::size_type __i = __line.find_first_not_of(" \t\n\v");
507
508             if (__line.length() <= 0 || __line[__i] == '#')
509               // Skip empty lines or comments.
510               continue;
511           }
512
513         // Trim.
514         __line.erase(__remove(__line.begin(), __line.end(), ' '),
515                      __line.end());
516         std::string::size_type __pos = __line.find("=");
517         std::string __factor_name = __line.substr(0, __pos);
518         std::string::size_type __end = __line.find_first_of(";\n");
519         std::string __factor_value = __line.substr(__pos + 1, __end - __pos);
520
521         _GLIBCXX_PROFILE_DATA(__env)[__factor_name] = __factor_value;
522       }
523   }
524
525   struct __cost_factor_writer
526   {
527     FILE* __file;
528
529     __cost_factor_writer(FILE* __f)
530     : __file(__f) { }
531
532     void
533     operator() (const __cost_factor* __factor)
534     { std::fprintf(__file, "%s = %f\n", __factor->__env_var,
535                    __factor->__value); }
536   };
537
538   inline void
539   __write_cost_factors()
540   {
541     FILE* __file = __open_output_file("conf.out");
542     __for_each(_GLIBCXX_PROFILE_DATA(__cost_factors)->begin(),
543                _GLIBCXX_PROFILE_DATA(__cost_factors)->end(),
544                __cost_factor_writer(__file));
545     std::fclose(__file);
546   }
547
548   struct __cost_factor_setter
549   {
550     void
551     operator()(__cost_factor* __factor)
552     {
553       // Look it up in the process environment first.
554       const char* __env_value = std::getenv(__factor->__env_var);
555
556       if (!__env_value)
557         {
558           // Look it up in the config file.
559           __env_t::iterator __it 
560             = _GLIBCXX_PROFILE_DATA(__env).find(__factor->__env_var);
561           if (__it != _GLIBCXX_PROFILE_DATA(__env).end())
562             __env_value = (*__it).second.c_str();
563         }
564
565       if (__env_value)
566         __factor->__value = std::atof(__env_value);
567     }
568   };
569
570   inline void
571   __set_cost_factors()
572   {
573     _GLIBCXX_PROFILE_DATA(__cost_factors) = new __cost_factor_vector;
574     _GLIBCXX_PROFILE_DATA(__cost_factors)->
575       push_back(&_GLIBCXX_PROFILE_DATA(__vector_shift_cost_factor));
576     _GLIBCXX_PROFILE_DATA(__cost_factors)->
577       push_back(&_GLIBCXX_PROFILE_DATA(__vector_iterate_cost_factor));
578     _GLIBCXX_PROFILE_DATA(__cost_factors)->
579       push_back(&_GLIBCXX_PROFILE_DATA(__vector_resize_cost_factor));
580     _GLIBCXX_PROFILE_DATA(__cost_factors)->
581       push_back(&_GLIBCXX_PROFILE_DATA(__list_shift_cost_factor));
582     _GLIBCXX_PROFILE_DATA(__cost_factors)->
583       push_back(&_GLIBCXX_PROFILE_DATA(__list_iterate_cost_factor));
584     _GLIBCXX_PROFILE_DATA(__cost_factors)->
585       push_back(&_GLIBCXX_PROFILE_DATA(__list_resize_cost_factor));
586     _GLIBCXX_PROFILE_DATA(__cost_factors)->
587       push_back(&_GLIBCXX_PROFILE_DATA(__map_insert_cost_factor));
588     _GLIBCXX_PROFILE_DATA(__cost_factors)->
589       push_back(&_GLIBCXX_PROFILE_DATA(__map_erase_cost_factor));
590     _GLIBCXX_PROFILE_DATA(__cost_factors)->
591       push_back(&_GLIBCXX_PROFILE_DATA(__map_find_cost_factor));
592     _GLIBCXX_PROFILE_DATA(__cost_factors)->
593       push_back(&_GLIBCXX_PROFILE_DATA(__map_iterate_cost_factor));
594     _GLIBCXX_PROFILE_DATA(__cost_factors)->
595       push_back(&_GLIBCXX_PROFILE_DATA(__umap_insert_cost_factor));
596     _GLIBCXX_PROFILE_DATA(__cost_factors)->
597       push_back(&_GLIBCXX_PROFILE_DATA(__umap_erase_cost_factor));
598     _GLIBCXX_PROFILE_DATA(__cost_factors)->
599       push_back(&_GLIBCXX_PROFILE_DATA(__umap_find_cost_factor));
600     _GLIBCXX_PROFILE_DATA(__cost_factors)->
601       push_back(&_GLIBCXX_PROFILE_DATA(__umap_iterate_cost_factor));
602     __for_each(_GLIBCXX_PROFILE_DATA(__cost_factors)->begin(),
603                _GLIBCXX_PROFILE_DATA(__cost_factors)->end(),
604                __cost_factor_setter());
605   }
606
607   inline void
608   __profcxx_init_unconditional()
609   {
610     _GLIBCXX_PROFILE_DATA(__global_lock).lock();
611
612     if (__is_invalid())
613       {
614         __set_max_warn_count();
615
616         if (_GLIBCXX_PROFILE_DATA(_S_max_warn_count) == 0)
617           __turn_off();
618         else
619           {
620             __set_max_stack_trace_depth();
621             __set_max_mem();
622             __set_trace_path();
623             __read_cost_factors(); 
624             __set_cost_factors();
625             __write_cost_factors();
626
627             __trace_vector_size_init();
628             __trace_hashtable_size_init();
629             __trace_hash_func_init();
630             __trace_vector_to_list_init();
631             __trace_list_to_slist_init(); 
632             __trace_list_to_vector_init();
633             __trace_map_to_unordered_map_init();
634
635             std::atexit(__report);
636
637             __turn_on();
638           }
639       }
640
641     _GLIBCXX_PROFILE_DATA(__global_lock).unlock();
642   }
643
644   /** @brief This function must be called by each instrumentation point.
645    *
646    * The common path is inlined fully.
647    */
648   inline bool
649   __profcxx_init()
650   {
651     if (__is_invalid())
652       __profcxx_init_unconditional();
653
654     return __is_on();
655   }
656
657 } // namespace __gnu_profile
658
659 #endif /* _GLIBCXX_PROFILE_PROFILER_TRACE_H */