1 #ifndef Py_INTERNAL_TRACEMALLOC_H
2 #define Py_INTERNAL_TRACEMALLOC_H
3 #ifdef __cplusplus
4 extern "C" {
5 #endif
6
7 #ifndef Py_BUILD_CORE
8 # error "this header requires Py_BUILD_CORE define"
9 #endif
10
11 #include "pycore_hashtable.h" // _Py_hashtable_t
12
13
14 /* Trace memory blocks allocated by PyMem_RawMalloc() */
15 #define TRACE_RAW_MALLOC
16
17
18 struct _PyTraceMalloc_Config {
19 /* Module initialized?
20 Variable protected by the GIL */
21 enum {
22 TRACEMALLOC_NOT_INITIALIZED,
23 TRACEMALLOC_INITIALIZED,
24 TRACEMALLOC_FINALIZED
25 } initialized;
26
27 /* Is tracemalloc tracing memory allocations?
28 Variable protected by the GIL */
29 int tracing;
30
31 /* limit of the number of frames in a traceback, 1 by default.
32 Variable protected by the GIL. */
33 int max_nframe;
34 };
35
36
37 /* Pack the frame_t structure to reduce the memory footprint on 64-bit
38 architectures: 12 bytes instead of 16. */
39 #if defined(_MSC_VER)
40 #pragma pack(push, 4)
41 #endif
42
43 struct
44 #ifdef __GNUC__
45 __attribute__((packed))
46 #endif
47 tracemalloc_frame {
48 /* filename cannot be NULL: "<unknown>" is used if the Python frame
49 filename is NULL */
50 PyObject *filename;
51 unsigned int lineno;
52 };
53 #ifdef _MSC_VER
54 #pragma pack(pop)
55 #endif
56
57 struct tracemalloc_traceback {
58 Py_uhash_t hash;
59 /* Number of frames stored */
60 uint16_t nframe;
61 /* Total number of frames the traceback had */
62 uint16_t total_nframe;
63 struct tracemalloc_frame frames[1];
64 };
65
66
67 struct _tracemalloc_runtime_state {
68 struct _PyTraceMalloc_Config config;
69
70 /* Protected by the GIL */
71 struct {
72 PyMemAllocatorEx mem;
73 PyMemAllocatorEx raw;
74 PyMemAllocatorEx obj;
75 } allocators;
76
77 #if defined(TRACE_RAW_MALLOC)
78 PyThread_type_lock tables_lock;
79 #endif
80 /* Size in bytes of currently traced memory.
81 Protected by TABLES_LOCK(). */
82 size_t traced_memory;
83 /* Peak size in bytes of traced memory.
84 Protected by TABLES_LOCK(). */
85 size_t peak_traced_memory;
86 /* Hash table used as a set to intern filenames:
87 PyObject* => PyObject*.
88 Protected by the GIL */
89 _Py_hashtable_t *filenames;
90 /* Buffer to store a new traceback in traceback_new().
91 Protected by the GIL. */
92 struct tracemalloc_traceback *traceback;
93 /* Hash table used as a set to intern tracebacks:
94 traceback_t* => traceback_t*
95 Protected by the GIL */
96 _Py_hashtable_t *tracebacks;
97 /* pointer (void*) => trace (trace_t*).
98 Protected by TABLES_LOCK(). */
99 _Py_hashtable_t *traces;
100 /* domain (unsigned int) => traces (_Py_hashtable_t).
101 Protected by TABLES_LOCK(). */
102 _Py_hashtable_t *domains;
103
104 struct tracemalloc_traceback empty_traceback;
105
106 Py_tss_t reentrant_key;
107 };
108
109 #define _tracemalloc_runtime_state_INIT \
110 { \
111 .config = { \
112 .initialized = TRACEMALLOC_NOT_INITIALIZED, \
113 .tracing = 0, \
114 .max_nframe = 1, \
115 }, \
116 .reentrant_key = Py_tss_NEEDS_INIT, \
117 }
118
119
120 #ifdef __cplusplus
121 }
122 #endif
123 #endif // !Py_INTERNAL_TRACEMALLOC_H