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