• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /asuswrt-rt-n18u-9.0.0.4.380.2695/release/src-rt-6.x.4708/toolchains/hndtools-armeabi-2011.09/arm-none-eabi/include/c++/4.6.1/profile/impl/
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
62namespace __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 */
667