• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 // Get the traceback where a memory block was allocated.
121 //
122 // Return a tuple of (filename: str, lineno: int) tuples.
123 //
124 // Return None if the tracemalloc module is disabled or if the memory block
125 // is not tracked by tracemalloc.
126 //
127 // Raise an exception and return NULL on error.
128 //
129 // Export for '_testinternalcapi' shared extension.
130 PyAPI_FUNC(PyObject*) _PyTraceMalloc_GetTraceback(
131     unsigned int domain,
132     uintptr_t ptr);
133 
134 /* Return non-zero if tracemalloc is tracing */
135 extern int _PyTraceMalloc_IsTracing(void);
136 
137 /* Clear the tracemalloc traces */
138 extern void _PyTraceMalloc_ClearTraces(void);
139 
140 /* Clear the tracemalloc traces */
141 extern PyObject* _PyTraceMalloc_GetTraces(void);
142 
143 /* Clear tracemalloc traceback for an object */
144 extern PyObject* _PyTraceMalloc_GetObjectTraceback(PyObject *obj);
145 
146 /* Initialize tracemalloc */
147 extern int _PyTraceMalloc_Init(void);
148 
149 /* Start tracemalloc */
150 extern int _PyTraceMalloc_Start(int max_nframe);
151 
152 /* Stop tracemalloc */
153 extern void _PyTraceMalloc_Stop(void);
154 
155 /* Get the tracemalloc traceback limit */
156 extern int _PyTraceMalloc_GetTracebackLimit(void);
157 
158 /* Get the memory usage of tracemalloc in bytes */
159 extern size_t _PyTraceMalloc_GetMemory(void);
160 
161 /* Get the current size and peak size of traced memory blocks as a 2-tuple */
162 extern PyObject* _PyTraceMalloc_GetTracedMemory(void);
163 
164 /* Set the peak size of traced memory blocks to the current size */
165 extern void _PyTraceMalloc_ResetPeak(void);
166 
167 #ifdef __cplusplus
168 }
169 #endif
170 #endif  // !Py_INTERNAL_TRACEMALLOC_H
171