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