1// -*- C++ -*-
2//
3// Copyright (C) 2009-2014 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.h
25 *  @brief Interface of the profiling runtime library.
26 */
27
28// Written by Lixia Liu and Silvius Rus.
29
30#ifndef _GLIBCXX_PROFILE_PROFILER_H
31#define _GLIBCXX_PROFILE_PROFILER_H 1
32
33#include <bits/c++config.h>
34
35// Mechanism to define data with inline linkage.
36#define _GLIBCXX_PROFILE_DEFINE_UNINIT_DATA(__type, __name)             \
37  inline __type&                                                        \
38  __get_##__name()                                                      \
39  {                                                                     \
40    static __type __name;                                               \
41    return __name;                                                      \
42  }
43#define _GLIBCXX_PROFILE_DEFINE_DATA(__type, __name, __initial_value...) \
44  inline __type& __get_##__name() {                                      \
45    static __type __name(__initial_value);                               \
46    return __name;                                                       \
47  }
48#define _GLIBCXX_PROFILE_DATA(__name) \
49  __get_##__name()
50
51namespace __gnu_profile
52{
53  /** @brief Reentrance guard.
54   *
55   * Mechanism to protect all __gnu_profile operations against recursion,
56   * multithreaded and exception reentrance.
57   */
58  struct __reentrance_guard
59  {
60    static bool
61    __get_in()
62    {
63      if (__inside() == true)
64	return false;
65      else
66	{
67	  __inside() = true;
68	  return true;
69	}
70    }
71
72    static bool&
73    __inside()
74    {
75      static __thread bool _S_inside(false);
76      return _S_inside;
77    }
78
79    __reentrance_guard() { }
80    ~__reentrance_guard() { __inside() = false; }
81  };
82
83#define _GLIBCXX_PROFILE_REENTRANCE_GUARD(__x...)	      	\
84  {                                                             \
85    if (__gnu_profile::__reentrance_guard::__get_in())          \
86    {                                                           \
87      __gnu_profile::__reentrance_guard __get_out; 		\
88      __x;                                                      \
89    }                                                           \
90  }
91
92  // Forward declarations of implementation functions.
93  // Don't use any __gnu_profile:: in user code.
94  // Instead, use the __profcxx... macros, which offer guarded access.
95  bool __turn_on();
96  bool __turn_off();
97  bool __is_invalid();
98  bool __is_on();
99  bool __is_off();
100  void __report(void);
101  void __trace_hashtable_size_resize(const void*, std::size_t, std::size_t);
102  void __trace_hashtable_size_destruct(const void*, std::size_t, std::size_t);
103  void __trace_hashtable_size_construct(const void*, std::size_t);
104  void __trace_vector_size_resize(const void*, std::size_t, std::size_t);
105  void __trace_vector_size_destruct(const void*, std::size_t, std::size_t);
106  void __trace_vector_size_construct(const void*, std::size_t);
107  void __trace_hash_func_destruct(const void*, std::size_t, std::size_t,
108				  std::size_t);
109  void __trace_hash_func_construct(const void*);
110  void __trace_vector_to_list_destruct(const void*);
111  void __trace_vector_to_list_construct(const void*);
112  void __trace_vector_to_list_insert(const void*, std::size_t, std::size_t);
113  void __trace_vector_to_list_iterate(const void*, std::size_t);
114  void __trace_vector_to_list_invalid_operator(const void*);
115  void __trace_vector_to_list_resize(const void*, std::size_t, std::size_t);
116  void __trace_vector_to_list_find(const void*, std::size_t);
117
118  void __trace_list_to_slist_destruct(const void*);
119  void __trace_list_to_slist_construct(const void*);
120  void __trace_list_to_slist_rewind(const void*);
121  void __trace_list_to_slist_operation(const void*);
122
123  void __trace_list_to_vector_destruct(const void*);
124  void __trace_list_to_vector_construct(const void*);
125  void __trace_list_to_vector_insert(const void*, std::size_t, std::size_t);
126  void __trace_list_to_vector_iterate(const void*, std::size_t);
127  void __trace_list_to_vector_invalid_operator(const void*);
128  void __trace_list_to_vector_resize(const void*, std::size_t, std::size_t);
129
130  void __trace_list_to_set_destruct(const void*);
131  void __trace_list_to_set_construct(const void*);
132  void __trace_list_to_set_insert(const void*, std::size_t, std::size_t);
133  void __trace_list_to_set_iterate(const void*, std::size_t);
134  void __trace_list_to_set_invalid_operator(const void*);
135  void __trace_list_to_set_find(const void*, std::size_t);
136
137  void __trace_map_to_unordered_map_construct(const void*);
138  void __trace_map_to_unordered_map_invalidate(const void*);
139  void __trace_map_to_unordered_map_insert(const void*, std::size_t,
140					   std::size_t);
141  void __trace_map_to_unordered_map_erase(const void*, std::size_t,
142					  std::size_t);
143  void __trace_map_to_unordered_map_iterate(const void*, std::size_t);
144  void __trace_map_to_unordered_map_find(const void*, std::size_t);
145  void __trace_map_to_unordered_map_destruct(const void*);
146} // namespace __gnu_profile
147
148// Master switch turns on all diagnostics that are not explicitly turned off.
149#ifdef _GLIBCXX_PROFILE
150#ifndef _GLIBCXX_PROFILE_NO_HASHTABLE_TOO_SMALL
151#define _GLIBCXX_PROFILE_HASHTABLE_TOO_SMALL
152#endif
153#ifndef _GLIBCXX_PROFILE_NO_HASHTABLE_TOO_LARGE
154#define _GLIBCXX_PROFILE_HASHTABLE_TOO_LARGE
155#endif
156#ifndef _GLIBCXX_PROFILE_NO_VECTOR_TOO_SMALL
157#define _GLIBCXX_PROFILE_VECTOR_TOO_SMALL
158#endif
159#ifndef _GLIBCXX_PROFILE_NO_VECTOR_TOO_LARGE
160#define _GLIBCXX_PROFILE_VECTOR_TOO_LARGE
161#endif
162#ifndef _GLIBCXX_PROFILE_NO_INEFFICIENT_HASH
163#define _GLIBCXX_PROFILE_INEFFICIENT_HASH
164#endif
165#ifndef _GLIBCXX_PROFILE_NO_VECTOR_TO_LIST
166#define _GLIBCXX_PROFILE_VECTOR_TO_LIST
167#endif
168#ifndef _GLIBCXX_PROFILE_NO_LIST_TO_SLIST
169#define _GLIBCXX_PROFILE_LIST_TO_SLIST
170#endif
171#ifndef _GLIBCXX_PROFILE_NO_LIST_TO_VECTOR
172#define _GLIBCXX_PROFILE_LIST_TO_VECTOR
173#endif
174#ifndef _GLIBCXX_PROFILE_NO_MAP_TO_UNORDERED_MAP
175#define _GLIBCXX_PROFILE_MAP_TO_UNORDERED_MAP
176#endif
177#endif
178
179// Expose global management routines to user code.
180#ifdef _GLIBCXX_PROFILE
181#define __profcxx_report() \
182  _GLIBCXX_PROFILE_REENTRANCE_GUARD(__gnu_profile::__report())
183#define __profcxx_turn_on() \
184  _GLIBCXX_PROFILE_REENTRANCE_GUARD(__gnu_profile::__turn_on())
185#define __profcxx_turn_off() \
186  _GLIBCXX_PROFILE_REENTRANCE_GUARD(__gnu_profile::__turn_off())
187#define __profcxx_is_invalid() \
188  _GLIBCXX_PROFILE_REENTRANCE_GUARD(__gnu_profile::__is_invalid())
189#define __profcxx_is_on() \
190  _GLIBCXX_PROFILE_REENTRANCE_GUARD(__gnu_profile::__is_on())
191#define __profcxx_is_off() \
192  _GLIBCXX_PROFILE_REENTRANCE_GUARD(__gnu_profile::__is_off())
193#else
194#define __profcxx_report()
195#define __profcxx_turn_on()
196#define __profcxx_turn_off()
197#define __profcxx_is_invalid()
198#define __profcxx_is_on()
199#define __profcxx_is_off()
200#endif
201
202// Turn on/off instrumentation for HASHTABLE_TOO_SMALL and HASHTABLE_TOO_LARGE.
203#if (defined(_GLIBCXX_PROFILE_HASHTABLE_TOO_SMALL) \
204     || defined(_GLIBCXX_PROFILE_HASHTABLE_TOO_LARGE))
205#define __profcxx_hashtable_resize(__x...) \
206  _GLIBCXX_PROFILE_REENTRANCE_GUARD( \
207      __gnu_profile::__trace_hashtable_size_resize(__x))
208#define __profcxx_hashtable_destruct(__x...) \
209  _GLIBCXX_PROFILE_REENTRANCE_GUARD( \
210      __gnu_profile::__trace_hashtable_size_destruct(__x))
211#define __profcxx_hashtable_construct(__x...) \
212  _GLIBCXX_PROFILE_REENTRANCE_GUARD( \
213      __gnu_profile::__trace_hashtable_size_construct(__x))
214#else
215#define __profcxx_hashtable_resize(__x...)
216#define __profcxx_hashtable_destruct(__x...)
217#define __profcxx_hashtable_construct(__x...)
218#endif
219
220// Turn on/off instrumentation for VECTOR_TOO_SMALL and VECTOR_TOO_LARGE.
221#if (defined(_GLIBCXX_PROFILE_VECTOR_TOO_SMALL) \
222     || defined(_GLIBCXX_PROFILE_VECTOR_TOO_LARGE))
223#define __profcxx_vector_resize(__x...) \
224  _GLIBCXX_PROFILE_REENTRANCE_GUARD( \
225      __gnu_profile::__trace_vector_size_resize(__x))
226#define __profcxx_vector_destruct(__x...) \
227  _GLIBCXX_PROFILE_REENTRANCE_GUARD( \
228      __gnu_profile::__trace_vector_size_destruct(__x))
229#define __profcxx_vector_construct(__x...) \
230  _GLIBCXX_PROFILE_REENTRANCE_GUARD( \
231      __gnu_profile::__trace_vector_size_construct(__x))
232#else
233#define __profcxx_vector_resize(__x...)
234#define __profcxx_vector_destruct(__x...)
235#define __profcxx_vector_construct(__x...)
236#endif
237
238// Turn on/off instrumentation for INEFFICIENT_HASH.
239#if defined(_GLIBCXX_PROFILE_INEFFICIENT_HASH)
240#define __profcxx_inefficient_hash_is_on() \
241  __gnu_profile::__is_on()
242#define __profcxx_hashtable_construct2(__x...) \
243  _GLIBCXX_PROFILE_REENTRANCE_GUARD( \
244      __gnu_profile::__trace_hash_func_construct(__x))
245#define __profcxx_hashtable_destruct2(__x...) \
246  _GLIBCXX_PROFILE_REENTRANCE_GUARD( \
247      __gnu_profile::__trace_hash_func_destruct(__x))
248#else
249#define __profcxx_inefficient_hash_is_on() false
250#define __profcxx_hashtable_destruct2(__x...)
251#define __profcxx_hashtable_construct2(__x...)
252#endif
253
254// Turn on/off instrumentation for VECTOR_TO_LIST.
255#if defined(_GLIBCXX_PROFILE_VECTOR_TO_LIST)
256#define __profcxx_vector_construct2(__x...) \
257  _GLIBCXX_PROFILE_REENTRANCE_GUARD( \
258      __gnu_profile::__trace_vector_to_list_construct(__x))
259#define __profcxx_vector_destruct2(__x...) \
260  _GLIBCXX_PROFILE_REENTRANCE_GUARD( \
261      __gnu_profile::__trace_vector_to_list_destruct(__x))
262#define __profcxx_vector_insert(__x...) \
263  _GLIBCXX_PROFILE_REENTRANCE_GUARD( \
264      __gnu_profile::__trace_vector_to_list_insert(__x))
265#define __profcxx_vector_iterate(__x...) \
266  _GLIBCXX_PROFILE_REENTRANCE_GUARD( \
267      __gnu_profile::__trace_vector_to_list_iterate(__x))
268#define __profcxx_vector_invalid_operator(__x...) \
269  _GLIBCXX_PROFILE_REENTRANCE_GUARD( \
270      __gnu_profile::__trace_vector_to_list_invalid_operator(__x))
271#define __profcxx_vector_resize2(__x...) \
272  _GLIBCXX_PROFILE_REENTRANCE_GUARD( \
273      __gnu_profile::__trace_vector_to_list_resize(__x))
274#define __profcxx_vector_find(__x...) \
275  _GLIBCXX_PROFILE_REENTRANCE_GUARD( \
276      __gnu_profile::__trace_vector_to_list_find(__x))
277#else
278#define __profcxx_vector_destruct2(__x...)
279#define __profcxx_vector_construct2(__x...)
280#define __profcxx_vector_insert(__x...)
281#define __profcxx_vector_iterate(__x...)
282#define __profcxx_vector_invalid_operator(__x...)
283#define __profcxx_vector_resize2(__x...)
284#define __profcxx_vector_find(__x...)
285#endif
286
287// Turn on/off instrumentation for LIST_TO_VECTOR.
288#if defined(_GLIBCXX_PROFILE_LIST_TO_VECTOR)
289#define __profcxx_list_construct2(__x...) \
290  _GLIBCXX_PROFILE_REENTRANCE_GUARD( \
291      __gnu_profile::__trace_list_to_vector_construct(__x))
292#define __profcxx_list_destruct2(__x...) \
293  _GLIBCXX_PROFILE_REENTRANCE_GUARD( \
294      __gnu_profile::__trace_list_to_vector_destruct(__x))
295#define __profcxx_list_insert(__x...) \
296  _GLIBCXX_PROFILE_REENTRANCE_GUARD( \
297      __gnu_profile::__trace_list_to_vector_insert(__x))
298#define __profcxx_list_iterate(__x...) \
299  _GLIBCXX_PROFILE_REENTRANCE_GUARD( \
300      __gnu_profile::__trace_list_to_vector_iterate(__x))
301#define __profcxx_list_invalid_operator(__x...) \
302  _GLIBCXX_PROFILE_REENTRANCE_GUARD( \
303      __gnu_profile::__trace_list_to_vector_invalid_operator(__x))
304#else
305#define __profcxx_list_destruct2(__x...)
306#define __profcxx_list_construct2(__x...)
307#define __profcxx_list_insert(__x...)
308#define __profcxx_list_iterate(__x...)
309#define __profcxx_list_invalid_operator(__x...)
310#endif
311
312// Turn on/off instrumentation for LIST_TO_SLIST.
313#if defined(_GLIBCXX_PROFILE_LIST_TO_SLIST)
314#define __profcxx_list_rewind(__x...) \
315  _GLIBCXX_PROFILE_REENTRANCE_GUARD( \
316      __gnu_profile::__trace_list_to_slist_rewind(__x))
317#define __profcxx_list_operation(__x...) \
318  _GLIBCXX_PROFILE_REENTRANCE_GUARD( \
319      __gnu_profile::__trace_list_to_slist_operation(__x))
320#define __profcxx_list_destruct(__x...) \
321  _GLIBCXX_PROFILE_REENTRANCE_GUARD( \
322      __gnu_profile::__trace_list_to_slist_destruct(__x))
323#define __profcxx_list_construct(__x...) \
324  _GLIBCXX_PROFILE_REENTRANCE_GUARD( \
325      __gnu_profile::__trace_list_to_slist_construct(__x))
326#else
327#define __profcxx_list_rewind(__x...)
328#define __profcxx_list_operation(__x...)
329#define __profcxx_list_destruct(__x...)
330#define __profcxx_list_construct(__x...)
331#endif
332
333// Turn on/off instrumentation for MAP_TO_UNORDERED_MAP.
334#if defined(_GLIBCXX_PROFILE_MAP_TO_UNORDERED_MAP)
335#define __profcxx_map_to_unordered_map_construct(__x...) \
336  _GLIBCXX_PROFILE_REENTRANCE_GUARD( \
337      __gnu_profile::__trace_map_to_unordered_map_construct(__x))
338#define __profcxx_map_to_unordered_map_destruct(__x...) \
339  _GLIBCXX_PROFILE_REENTRANCE_GUARD( \
340      __gnu_profile::__trace_map_to_unordered_map_destruct(__x))
341#define __profcxx_map_to_unordered_map_insert(__x...) \
342  _GLIBCXX_PROFILE_REENTRANCE_GUARD( \
343      __gnu_profile::__trace_map_to_unordered_map_insert(__x))
344#define __profcxx_map_to_unordered_map_erase(__x...) \
345  _GLIBCXX_PROFILE_REENTRANCE_GUARD( \
346      __gnu_profile::__trace_map_to_unordered_map_erase(__x))
347#define __profcxx_map_to_unordered_map_iterate(__x...) \
348  _GLIBCXX_PROFILE_REENTRANCE_GUARD( \
349      __gnu_profile::__trace_map_to_unordered_map_iterate(__x))
350#define __profcxx_map_to_unordered_map_invalidate(__x...) \
351  _GLIBCXX_PROFILE_REENTRANCE_GUARD( \
352      __gnu_profile::__trace_map_to_unordered_map_invalidate(__x))
353#define __profcxx_map_to_unordered_map_find(__x...) \
354  _GLIBCXX_PROFILE_REENTRANCE_GUARD( \
355      __gnu_profile::__trace_map_to_unordered_map_find(__x))
356#else
357#define __profcxx_map_to_unordered_map_construct(__x...) \
358
359#define __profcxx_map_to_unordered_map_destruct(__x...)
360#define __profcxx_map_to_unordered_map_insert(__x...)
361#define __profcxx_map_to_unordered_map_erase(__x...)
362#define __profcxx_map_to_unordered_map_iterate(__x...)
363#define __profcxx_map_to_unordered_map_invalidate(__x...)
364#define __profcxx_map_to_unordered_map_find(__x...)
365#endif
366
367// Set default values for compile-time customizable variables.
368#ifndef _GLIBCXX_PROFILE_TRACE_PATH_ROOT
369#define _GLIBCXX_PROFILE_TRACE_PATH_ROOT "libstdcxx-profile"
370#endif
371#ifndef _GLIBCXX_PROFILE_TRACE_ENV_VAR
372#define _GLIBCXX_PROFILE_TRACE_ENV_VAR "_GLIBCXX_PROFILE_TRACE_PATH_ROOT"
373#endif
374#ifndef _GLIBCXX_PROFILE_MAX_WARN_COUNT_ENV_VAR
375#define _GLIBCXX_PROFILE_MAX_WARN_COUNT_ENV_VAR \
376  "_GLIBCXX_PROFILE_MAX_WARN_COUNT"
377#endif
378#ifndef _GLIBCXX_PROFILE_MAX_WARN_COUNT
379#define _GLIBCXX_PROFILE_MAX_WARN_COUNT 10
380#endif
381#ifndef _GLIBCXX_PROFILE_MAX_STACK_DEPTH
382#define _GLIBCXX_PROFILE_MAX_STACK_DEPTH 32
383#endif
384#ifndef _GLIBCXX_PROFILE_MAX_STACK_DEPTH_ENV_VAR
385#define _GLIBCXX_PROFILE_MAX_STACK_DEPTH_ENV_VAR \
386  "_GLIBCXX_PROFILE_MAX_STACK_DEPTH"
387#endif
388#ifndef _GLIBCXX_PROFILE_MEM_PER_DIAGNOSTIC
389#define _GLIBCXX_PROFILE_MEM_PER_DIAGNOSTIC (1 << 28)
390#endif
391#ifndef _GLIBCXX_PROFILE_MEM_PER_DIAGNOSTIC_ENV_VAR
392#define _GLIBCXX_PROFILE_MEM_PER_DIAGNOSTIC_ENV_VAR \
393  "_GLIBCXX_PROFILE_MEM_PER_DIAGNOSTIC"
394#endif
395
396// Instrumentation hook implementations.
397#include "profile/impl/profiler_hash_func.h"
398#include "profile/impl/profiler_hashtable_size.h"
399#include "profile/impl/profiler_map_to_unordered_map.h"
400#include "profile/impl/profiler_vector_size.h"
401#include "profile/impl/profiler_vector_to_list.h"
402#include "profile/impl/profiler_list_to_slist.h"
403#include "profile/impl/profiler_list_to_vector.h"
404
405#endif // _GLIBCXX_PROFILE_PROFILER_H
406