blob: e07022cce2bc9c609472234e7e88e72e77d07dc3 [file] [log] [blame]
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001#include "Python.h"
2#include "hashtable.h"
3#include "frameobject.h"
4#include "pythread.h"
5#include "osdefs.h"
6
Serhiy Storchakab451f912017-02-04 12:18:38 +02007#include "clinic/_tracemalloc.c.h"
8/*[clinic input]
9module _tracemalloc
10[clinic start generated code]*/
11/*[clinic end generated code: output=da39a3ee5e6b4b0d input=708a98302fc46e5f]*/
12
Victor Stinnered3b0bc2013-11-23 12:27:24 +010013/* Trace memory blocks allocated by PyMem_RawMalloc() */
14#define TRACE_RAW_MALLOC
15
16/* Forward declaration */
17static void tracemalloc_stop(void);
Victor Stinnered3b0bc2013-11-23 12:27:24 +010018static void* raw_malloc(size_t size);
19static void raw_free(void *ptr);
20
21#ifdef Py_DEBUG
22# define TRACE_DEBUG
23#endif
24
Victor Stinnered3b0bc2013-11-23 12:27:24 +010025/* Protected by the GIL */
26static struct {
Victor Stinnerd8f0d922014-06-02 21:57:10 +020027 PyMemAllocatorEx mem;
28 PyMemAllocatorEx raw;
29 PyMemAllocatorEx obj;
Victor Stinnered3b0bc2013-11-23 12:27:24 +010030} allocators;
31
Victor Stinnered3b0bc2013-11-23 12:27:24 +010032static struct {
33 /* Module initialized?
34 Variable protected by the GIL */
35 enum {
36 TRACEMALLOC_NOT_INITIALIZED,
37 TRACEMALLOC_INITIALIZED,
38 TRACEMALLOC_FINALIZED
39 } initialized;
40
Victor Stinnered3b0bc2013-11-23 12:27:24 +010041 /* Is tracemalloc tracing memory allocations?
42 Variable protected by the GIL */
43 int tracing;
44
45 /* limit of the number of frames in a traceback, 1 by default.
46 Variable protected by the GIL. */
47 int max_nframe;
Victor Stinnere492ae52016-03-22 12:58:23 +010048
49 /* use domain in trace key?
50 Variable protected by the GIL. */
51 int use_domain;
Victor Stinner5e14a382016-03-23 22:03:55 +010052} tracemalloc_config = {TRACEMALLOC_NOT_INITIALIZED, 0, 1, 0};
Victor Stinnered3b0bc2013-11-23 12:27:24 +010053
Antoine Pitroua6a4dc82017-09-07 18:56:24 +020054#if defined(TRACE_RAW_MALLOC)
Victor Stinnered3b0bc2013-11-23 12:27:24 +010055/* This lock is needed because tracemalloc_free() is called without
56 the GIL held from PyMem_RawFree(). It cannot acquire the lock because it
57 would introduce a deadlock in PyThreadState_DeleteCurrent(). */
58static PyThread_type_lock tables_lock;
59# define TABLES_LOCK() PyThread_acquire_lock(tables_lock, 1)
60# define TABLES_UNLOCK() PyThread_release_lock(tables_lock)
61#else
62 /* variables are protected by the GIL */
63# define TABLES_LOCK()
64# define TABLES_UNLOCK()
65#endif
66
Victor Stinnere492ae52016-03-22 12:58:23 +010067
68#define DEFAULT_DOMAIN 0
69
Victor Stinnere492ae52016-03-22 12:58:23 +010070/* Pack the frame_t structure to reduce the memory footprint. */
71typedef struct
72#ifdef __GNUC__
73__attribute__((packed))
74#endif
75{
Benjamin Petersonca470632016-09-06 13:47:26 -070076 uintptr_t ptr;
Victor Stinner5ea4c062017-06-20 17:46:36 +020077 unsigned int domain;
Victor Stinnere492ae52016-03-22 12:58:23 +010078} pointer_t;
79
Victor Stinnered3b0bc2013-11-23 12:27:24 +010080/* Pack the frame_t structure to reduce the memory footprint on 64-bit
Victor Stinnere492ae52016-03-22 12:58:23 +010081 architectures: 12 bytes instead of 16. */
Victor Stinnered3b0bc2013-11-23 12:27:24 +010082typedef struct
83#ifdef __GNUC__
84__attribute__((packed))
Victor Stinnerdd382ef2014-02-01 03:43:58 +010085#elif defined(_MSC_VER)
Segev Finer39243772017-07-25 11:47:43 +030086#pragma pack(push, 4)
Victor Stinnered3b0bc2013-11-23 12:27:24 +010087#endif
88{
Victor Stinner7105e9f2016-03-15 14:28:04 +010089 /* filename cannot be NULL: "<unknown>" is used if the Python frame
90 filename is NULL */
Victor Stinnered3b0bc2013-11-23 12:27:24 +010091 PyObject *filename;
Victor Stinner95283342016-03-15 21:57:02 +010092 unsigned int lineno;
Victor Stinnered3b0bc2013-11-23 12:27:24 +010093} frame_t;
Segev Finer39243772017-07-25 11:47:43 +030094#ifdef _MSC_VER
95#pragma pack(pop)
96#endif
Victor Stinnered3b0bc2013-11-23 12:27:24 +010097
Victor Stinnere492ae52016-03-22 12:58:23 +010098
Victor Stinnered3b0bc2013-11-23 12:27:24 +010099typedef struct {
100 Py_uhash_t hash;
101 int nframe;
102 frame_t frames[1];
103} traceback_t;
104
105#define TRACEBACK_SIZE(NFRAME) \
106 (sizeof(traceback_t) + sizeof(frame_t) * (NFRAME - 1))
Victor Stinnerf28ce602013-11-27 22:27:13 +0100107
108#define MAX_NFRAME \
Victor Stinner52aee852014-08-16 15:44:02 +0200109 ((INT_MAX - (int)sizeof(traceback_t)) / (int)sizeof(frame_t) + 1)
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100110
Victor Stinnere492ae52016-03-22 12:58:23 +0100111
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100112static PyObject *unknown_filename = NULL;
113static traceback_t tracemalloc_empty_traceback;
114
Victor Stinner7a5be142013-11-26 01:06:02 +0100115/* Trace of a memory block */
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100116typedef struct {
Victor Stinner7a5be142013-11-26 01:06:02 +0100117 /* Size of the memory block in bytes */
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100118 size_t size;
Victor Stinner7a5be142013-11-26 01:06:02 +0100119
120 /* Traceback where the memory block was allocated */
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100121 traceback_t *traceback;
122} trace_t;
123
Victor Stinnere492ae52016-03-22 12:58:23 +0100124
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100125/* Size in bytes of currently traced memory.
126 Protected by TABLES_LOCK(). */
127static size_t tracemalloc_traced_memory = 0;
128
Victor Stinner3c0481d2013-11-27 21:39:49 +0100129/* Peak size in bytes of traced memory.
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100130 Protected by TABLES_LOCK(). */
Victor Stinner3c0481d2013-11-27 21:39:49 +0100131static size_t tracemalloc_peak_traced_memory = 0;
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100132
Serhiy Storchaka56a6d852014-12-01 18:28:43 +0200133/* Hash table used as a set to intern filenames:
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100134 PyObject* => PyObject*.
135 Protected by the GIL */
136static _Py_hashtable_t *tracemalloc_filenames = NULL;
137
Victor Stinnerf28ce602013-11-27 22:27:13 +0100138/* Buffer to store a new traceback in traceback_new().
139 Protected by the GIL. */
140static traceback_t *tracemalloc_traceback = NULL;
141
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100142/* Hash table used as a set to intern tracebacks:
143 traceback_t* => traceback_t*
144 Protected by the GIL */
145static _Py_hashtable_t *tracemalloc_tracebacks = NULL;
146
147/* pointer (void*) => trace (trace_t).
148 Protected by TABLES_LOCK(). */
149static _Py_hashtable_t *tracemalloc_traces = NULL;
150
Victor Stinnere492ae52016-03-22 12:58:23 +0100151
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100152#ifdef TRACE_DEBUG
153static void
154tracemalloc_error(const char *format, ...)
155{
156 va_list ap;
157 fprintf(stderr, "tracemalloc: ");
158 va_start(ap, format);
159 vfprintf(stderr, format, ap);
160 va_end(ap);
161 fprintf(stderr, "\n");
162 fflush(stderr);
163}
164#endif
165
Victor Stinnere492ae52016-03-22 12:58:23 +0100166
Antoine Pitroua6a4dc82017-09-07 18:56:24 +0200167#if defined(TRACE_RAW_MALLOC)
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100168#define REENTRANT_THREADLOCAL
169
Masayuki Yamamoto731e1892017-10-06 19:41:34 +0900170static Py_tss_t tracemalloc_reentrant_key = Py_tss_NEEDS_INIT;
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100171
172/* Any non-NULL pointer can be used */
173#define REENTRANT Py_True
174
175static int
176get_reentrant(void)
177{
Victor Stinner4a066472016-03-22 17:45:09 +0100178 void *ptr;
179
Masayuki Yamamoto731e1892017-10-06 19:41:34 +0900180 assert(PyThread_tss_is_created(&tracemalloc_reentrant_key));
181 ptr = PyThread_tss_get(&tracemalloc_reentrant_key);
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100182 if (ptr != NULL) {
183 assert(ptr == REENTRANT);
184 return 1;
185 }
186 else
187 return 0;
188}
189
190static void
191set_reentrant(int reentrant)
192{
Victor Stinner2ead3d22013-11-26 01:08:53 +0100193 assert(reentrant == 0 || reentrant == 1);
Masayuki Yamamoto731e1892017-10-06 19:41:34 +0900194 assert(PyThread_tss_is_created(&tracemalloc_reentrant_key));
Victor Stinner4a066472016-03-22 17:45:09 +0100195
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100196 if (reentrant) {
Victor Stinner0cfc0582016-03-22 17:40:07 +0100197 assert(!get_reentrant());
Masayuki Yamamoto731e1892017-10-06 19:41:34 +0900198 PyThread_tss_set(&tracemalloc_reentrant_key, REENTRANT);
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100199 }
200 else {
Victor Stinner0cfc0582016-03-22 17:40:07 +0100201 assert(get_reentrant());
Masayuki Yamamoto731e1892017-10-06 19:41:34 +0900202 PyThread_tss_set(&tracemalloc_reentrant_key, NULL);
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100203 }
204}
205
206#else
207
Antoine Pitroua6a4dc82017-09-07 18:56:24 +0200208/* TRACE_RAW_MALLOC not defined: variable protected by the GIL */
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100209static int tracemalloc_reentrant = 0;
210
211static int
212get_reentrant(void)
213{
214 return tracemalloc_reentrant;
215}
216
217static void
218set_reentrant(int reentrant)
219{
Victor Stinnerd5871e62016-03-23 00:17:04 +0100220 assert(reentrant != tracemalloc_reentrant);
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100221 tracemalloc_reentrant = reentrant;
222}
223#endif
224
Victor Stinnere492ae52016-03-22 12:58:23 +0100225
Victor Stinner285cf0a2016-03-21 22:00:58 +0100226static Py_uhash_t
Victor Stinner5dacbd42016-03-23 09:52:13 +0100227hashtable_hash_pyobject(_Py_hashtable_t *ht, const void *pkey)
Victor Stinner51b846c2016-03-18 21:52:22 +0100228{
Victor Stinner285cf0a2016-03-21 22:00:58 +0100229 PyObject *obj;
230
Victor Stinner5dacbd42016-03-23 09:52:13 +0100231 _Py_HASHTABLE_READ_KEY(ht, pkey, obj);
Victor Stinner285cf0a2016-03-21 22:00:58 +0100232 return PyObject_Hash(obj);
233}
234
Victor Stinnere492ae52016-03-22 12:58:23 +0100235
Victor Stinner285cf0a2016-03-21 22:00:58 +0100236static int
Victor Stinner5dacbd42016-03-23 09:52:13 +0100237hashtable_compare_unicode(_Py_hashtable_t *ht, const void *pkey,
Victor Stinner285cf0a2016-03-21 22:00:58 +0100238 const _Py_hashtable_entry_t *entry)
239{
Victor Stinnere492ae52016-03-22 12:58:23 +0100240 PyObject *key1, *key2;
Victor Stinner285cf0a2016-03-21 22:00:58 +0100241
Victor Stinner5dacbd42016-03-23 09:52:13 +0100242 _Py_HASHTABLE_READ_KEY(ht, pkey, key1);
243 _Py_HASHTABLE_ENTRY_READ_KEY(ht, entry, key2);
Victor Stinner285cf0a2016-03-21 22:00:58 +0100244
Victor Stinnere492ae52016-03-22 12:58:23 +0100245 if (key1 != NULL && key2 != NULL)
246 return (PyUnicode_Compare(key1, key2) == 0);
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100247 else
Victor Stinnere492ae52016-03-22 12:58:23 +0100248 return key1 == key2;
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100249}
250
Victor Stinnere492ae52016-03-22 12:58:23 +0100251
252static Py_uhash_t
Victor Stinner5dacbd42016-03-23 09:52:13 +0100253hashtable_hash_pointer_t(_Py_hashtable_t *ht, const void *pkey)
Victor Stinnere492ae52016-03-22 12:58:23 +0100254{
255 pointer_t ptr;
256 Py_uhash_t hash;
257
Victor Stinner5dacbd42016-03-23 09:52:13 +0100258 _Py_HASHTABLE_READ_KEY(ht, pkey, ptr);
Victor Stinnere492ae52016-03-22 12:58:23 +0100259
260 hash = (Py_uhash_t)_Py_HashPointer((void*)ptr.ptr);
261 hash ^= ptr.domain;
262 return hash;
263}
264
265
doko@ubuntu.combc731502016-05-18 01:06:01 +0200266static int
Victor Stinner5dacbd42016-03-23 09:52:13 +0100267hashtable_compare_pointer_t(_Py_hashtable_t *ht, const void *pkey,
Victor Stinnere492ae52016-03-22 12:58:23 +0100268 const _Py_hashtable_entry_t *entry)
269{
270 pointer_t ptr1, ptr2;
271
Victor Stinner5dacbd42016-03-23 09:52:13 +0100272 _Py_HASHTABLE_READ_KEY(ht, pkey, ptr1);
273 _Py_HASHTABLE_ENTRY_READ_KEY(ht, entry, ptr2);
Victor Stinnere492ae52016-03-22 12:58:23 +0100274
275 /* compare pointer before domain, because pointer is more likely to be
276 different */
277 return (ptr1.ptr == ptr2.ptr && ptr1.domain == ptr2.domain);
278
279}
280
281
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100282static _Py_hashtable_t *
Victor Stinner285cf0a2016-03-21 22:00:58 +0100283hashtable_new(size_t key_size, size_t data_size,
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100284 _Py_hashtable_hash_func hash_func,
285 _Py_hashtable_compare_func compare_func)
286{
Victor Stinnerc9553872016-03-22 12:13:01 +0100287 _Py_hashtable_allocator_t hashtable_alloc = {malloc, free};
Victor Stinner285cf0a2016-03-21 22:00:58 +0100288 return _Py_hashtable_new_full(key_size, data_size, 0,
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100289 hash_func, compare_func,
Victor Stinnerc9553872016-03-22 12:13:01 +0100290 &hashtable_alloc);
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100291}
292
Victor Stinnere492ae52016-03-22 12:58:23 +0100293
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100294static void*
295raw_malloc(size_t size)
296{
297 return allocators.raw.malloc(allocators.raw.ctx, size);
298}
299
300static void
301raw_free(void *ptr)
302{
303 allocators.raw.free(allocators.raw.ctx, ptr);
304}
305
Victor Stinnere492ae52016-03-22 12:58:23 +0100306
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100307static Py_uhash_t
Victor Stinner5dacbd42016-03-23 09:52:13 +0100308hashtable_hash_traceback(_Py_hashtable_t *ht, const void *pkey)
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100309{
Victor Stinnerb32a7ed2016-03-21 23:05:08 +0100310 traceback_t *traceback;
Victor Stinner285cf0a2016-03-21 22:00:58 +0100311
Victor Stinner5dacbd42016-03-23 09:52:13 +0100312 _Py_HASHTABLE_READ_KEY(ht, pkey, traceback);
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100313 return traceback->hash;
314}
315
Victor Stinnere492ae52016-03-22 12:58:23 +0100316
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100317static int
Victor Stinner5dacbd42016-03-23 09:52:13 +0100318hashtable_compare_traceback(_Py_hashtable_t *ht, const void *pkey,
319 const _Py_hashtable_entry_t *entry)
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100320{
Victor Stinner285cf0a2016-03-21 22:00:58 +0100321 traceback_t *traceback1, *traceback2;
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100322 const frame_t *frame1, *frame2;
323 int i;
324
Victor Stinner5dacbd42016-03-23 09:52:13 +0100325 _Py_HASHTABLE_READ_KEY(ht, pkey, traceback1);
326 _Py_HASHTABLE_ENTRY_READ_KEY(ht, entry, traceback2);
Victor Stinner285cf0a2016-03-21 22:00:58 +0100327
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100328 if (traceback1->nframe != traceback2->nframe)
329 return 0;
330
331 for (i=0; i < traceback1->nframe; i++) {
332 frame1 = &traceback1->frames[i];
333 frame2 = &traceback2->frames[i];
334
335 if (frame1->lineno != frame2->lineno)
336 return 0;
337
338 if (frame1->filename != frame2->filename) {
339 assert(PyUnicode_Compare(frame1->filename, frame2->filename) != 0);
340 return 0;
341 }
342 }
343 return 1;
344}
345
Victor Stinnere492ae52016-03-22 12:58:23 +0100346
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100347static void
348tracemalloc_get_frame(PyFrameObject *pyframe, frame_t *frame)
349{
350 PyCodeObject *code;
351 PyObject *filename;
352 _Py_hashtable_entry_t *entry;
Victor Stinner95283342016-03-15 21:57:02 +0100353 int lineno;
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100354
355 frame->filename = unknown_filename;
Victor Stinner95283342016-03-15 21:57:02 +0100356 lineno = PyFrame_GetLineNumber(pyframe);
357 if (lineno < 0)
358 lineno = 0;
359 frame->lineno = (unsigned int)lineno;
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100360
361 code = pyframe->f_code;
362 if (code == NULL) {
363#ifdef TRACE_DEBUG
Victor Stinner4dc74202013-11-26 01:18:52 +0100364 tracemalloc_error("failed to get the code object of the frame");
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100365#endif
366 return;
367 }
368
369 if (code->co_filename == NULL) {
370#ifdef TRACE_DEBUG
371 tracemalloc_error("failed to get the filename of the code object");
372#endif
373 return;
374 }
375
376 filename = code->co_filename;
377 assert(filename != NULL);
378 if (filename == NULL)
379 return;
380
381 if (!PyUnicode_Check(filename)) {
382#ifdef TRACE_DEBUG
Martin Panter6245cb32016-04-15 02:14:19 +0000383 tracemalloc_error("filename is not a unicode string");
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100384#endif
385 return;
386 }
387 if (!PyUnicode_IS_READY(filename)) {
388 /* Don't make a Unicode string ready to avoid reentrant calls
389 to tracemalloc_malloc() or tracemalloc_realloc() */
390#ifdef TRACE_DEBUG
391 tracemalloc_error("filename is not a ready unicode string");
392#endif
393 return;
394 }
395
396 /* intern the filename */
Victor Stinner285cf0a2016-03-21 22:00:58 +0100397 entry = _Py_HASHTABLE_GET_ENTRY(tracemalloc_filenames, filename);
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100398 if (entry != NULL) {
Victor Stinner5dacbd42016-03-23 09:52:13 +0100399 _Py_HASHTABLE_ENTRY_READ_KEY(tracemalloc_filenames, entry, filename);
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100400 }
401 else {
402 /* tracemalloc_filenames is responsible to keep a reference
403 to the filename */
404 Py_INCREF(filename);
Victor Stinner285cf0a2016-03-21 22:00:58 +0100405 if (_Py_HASHTABLE_SET_NODATA(tracemalloc_filenames, filename) < 0) {
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100406 Py_DECREF(filename);
407#ifdef TRACE_DEBUG
408 tracemalloc_error("failed to intern the filename");
409#endif
410 return;
411 }
412 }
413
414 /* the tracemalloc_filenames table keeps a reference to the filename */
415 frame->filename = filename;
416}
417
Victor Stinnere492ae52016-03-22 12:58:23 +0100418
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100419static Py_uhash_t
420traceback_hash(traceback_t *traceback)
421{
422 /* code based on tuplehash() of Objects/tupleobject.c */
Victor Stinner4d8c29c2013-12-16 23:05:13 +0100423 Py_uhash_t x, y; /* Unsigned for defined overflow behavior. */
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100424 int len = traceback->nframe;
425 Py_uhash_t mult = _PyHASH_MULTIPLIER;
426 frame_t *frame;
427
428 x = 0x345678UL;
429 frame = traceback->frames;
430 while (--len >= 0) {
Victor Stinner4d8c29c2013-12-16 23:05:13 +0100431 y = (Py_uhash_t)PyObject_Hash(frame->filename);
432 y ^= (Py_uhash_t)frame->lineno;
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100433 frame++;
434
435 x = (x ^ y) * mult;
436 /* the cast might truncate len; that doesn't change hash stability */
Victor Stinner4d8c29c2013-12-16 23:05:13 +0100437 mult += (Py_uhash_t)(82520UL + len + len);
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100438 }
439 x += 97531UL;
440 return x;
441}
442
Victor Stinnere492ae52016-03-22 12:58:23 +0100443
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100444static void
445traceback_get_frames(traceback_t *traceback)
446{
447 PyThreadState *tstate;
448 PyFrameObject *pyframe;
449
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100450 tstate = PyGILState_GetThisThreadState();
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100451 if (tstate == NULL) {
452#ifdef TRACE_DEBUG
453 tracemalloc_error("failed to get the current thread state");
454#endif
455 return;
456 }
457
458 for (pyframe = tstate->frame; pyframe != NULL; pyframe = pyframe->f_back) {
459 tracemalloc_get_frame(pyframe, &traceback->frames[traceback->nframe]);
460 assert(traceback->frames[traceback->nframe].filename != NULL);
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100461 traceback->nframe++;
462 if (traceback->nframe == tracemalloc_config.max_nframe)
463 break;
464 }
465}
466
Victor Stinnere492ae52016-03-22 12:58:23 +0100467
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100468static traceback_t *
469traceback_new(void)
470{
Victor Stinnerf28ce602013-11-27 22:27:13 +0100471 traceback_t *traceback;
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100472 _Py_hashtable_entry_t *entry;
473
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100474 assert(PyGILState_Check());
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100475
476 /* get frames */
Victor Stinnerf28ce602013-11-27 22:27:13 +0100477 traceback = tracemalloc_traceback;
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100478 traceback->nframe = 0;
479 traceback_get_frames(traceback);
480 if (traceback->nframe == 0)
481 return &tracemalloc_empty_traceback;
482 traceback->hash = traceback_hash(traceback);
483
484 /* intern the traceback */
Victor Stinner285cf0a2016-03-21 22:00:58 +0100485 entry = _Py_HASHTABLE_GET_ENTRY(tracemalloc_tracebacks, traceback);
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100486 if (entry != NULL) {
Victor Stinner5dacbd42016-03-23 09:52:13 +0100487 _Py_HASHTABLE_ENTRY_READ_KEY(tracemalloc_tracebacks, entry, traceback);
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100488 }
489 else {
490 traceback_t *copy;
491 size_t traceback_size;
492
493 traceback_size = TRACEBACK_SIZE(traceback->nframe);
494
495 copy = raw_malloc(traceback_size);
496 if (copy == NULL) {
497#ifdef TRACE_DEBUG
498 tracemalloc_error("failed to intern the traceback: malloc failed");
499#endif
500 return NULL;
501 }
502 memcpy(copy, traceback, traceback_size);
503
Victor Stinner285cf0a2016-03-21 22:00:58 +0100504 if (_Py_HASHTABLE_SET_NODATA(tracemalloc_tracebacks, copy) < 0) {
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100505 raw_free(copy);
506#ifdef TRACE_DEBUG
507 tracemalloc_error("failed to intern the traceback: putdata failed");
508#endif
509 return NULL;
510 }
511 traceback = copy;
512 }
513 return traceback;
514}
515
Victor Stinnere492ae52016-03-22 12:58:23 +0100516
Victor Stinner5e14a382016-03-23 22:03:55 +0100517static int
518tracemalloc_use_domain_cb(_Py_hashtable_t *old_traces,
519 _Py_hashtable_entry_t *entry, void *user_data)
520{
Benjamin Petersonca470632016-09-06 13:47:26 -0700521 uintptr_t ptr;
Victor Stinner5e14a382016-03-23 22:03:55 +0100522 pointer_t key;
523 _Py_hashtable_t *new_traces = (_Py_hashtable_t *)user_data;
524 const void *pdata = _Py_HASHTABLE_ENTRY_PDATA(old_traces, entry);
525
526 _Py_HASHTABLE_ENTRY_READ_KEY(old_traces, entry, ptr);
527 key.ptr = ptr;
528 key.domain = DEFAULT_DOMAIN;
529
530 return _Py_hashtable_set(new_traces,
531 sizeof(key), &key,
532 old_traces->data_size, pdata);
533}
534
535
Benjamin Petersonca470632016-09-06 13:47:26 -0700536/* Convert tracemalloc_traces from compact key (uintptr_t) to pointer_t key.
Victor Stinner5e14a382016-03-23 22:03:55 +0100537 * Return 0 on success, -1 on error. */
538static int
539tracemalloc_use_domain(void)
540{
541 _Py_hashtable_t *new_traces = NULL;
542
543 assert(!tracemalloc_config.use_domain);
544
545 new_traces = hashtable_new(sizeof(pointer_t),
546 sizeof(trace_t),
547 hashtable_hash_pointer_t,
548 hashtable_compare_pointer_t);
549 if (new_traces == NULL) {
550 return -1;
551 }
552
553 if (_Py_hashtable_foreach(tracemalloc_traces, tracemalloc_use_domain_cb,
554 new_traces) < 0)
555 {
556 _Py_hashtable_destroy(new_traces);
557 return -1;
558 }
559
560 _Py_hashtable_destroy(tracemalloc_traces);
561 tracemalloc_traces = new_traces;
562
563 tracemalloc_config.use_domain = 1;
564
565 return 0;
566}
567
568
Victor Stinnere492ae52016-03-22 12:58:23 +0100569static void
Victor Stinner5ea4c062017-06-20 17:46:36 +0200570tracemalloc_remove_trace(unsigned int domain, uintptr_t ptr)
Victor Stinnere492ae52016-03-22 12:58:23 +0100571{
572 trace_t trace;
573 int removed;
574
Victor Stinner10b73e12016-03-22 13:39:05 +0100575 assert(tracemalloc_config.tracing);
576
Victor Stinnere492ae52016-03-22 12:58:23 +0100577 if (tracemalloc_config.use_domain) {
578 pointer_t key = {ptr, domain};
579 removed = _Py_HASHTABLE_POP(tracemalloc_traces, key, trace);
580 }
581 else {
582 removed = _Py_HASHTABLE_POP(tracemalloc_traces, ptr, trace);
583 }
584 if (!removed) {
585 return;
586 }
587
588 assert(tracemalloc_traced_memory >= trace.size);
589 tracemalloc_traced_memory -= trace.size;
590}
591
592#define REMOVE_TRACE(ptr) \
Benjamin Petersonca470632016-09-06 13:47:26 -0700593 tracemalloc_remove_trace(DEFAULT_DOMAIN, (uintptr_t)(ptr))
Victor Stinnere492ae52016-03-22 12:58:23 +0100594
595
Victor Stinner52968672013-11-24 11:37:15 +0100596static int
Victor Stinner5ea4c062017-06-20 17:46:36 +0200597tracemalloc_add_trace(unsigned int domain, uintptr_t ptr,
Victor Stinner10b73e12016-03-22 13:39:05 +0100598 size_t size)
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100599{
Victor Stinnerca79ccd2016-03-23 09:38:54 +0100600 pointer_t key = {ptr, domain};
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100601 traceback_t *traceback;
602 trace_t trace;
Victor Stinnerca79ccd2016-03-23 09:38:54 +0100603 _Py_hashtable_entry_t* entry;
Victor Stinner52968672013-11-24 11:37:15 +0100604 int res;
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100605
Victor Stinner10b73e12016-03-22 13:39:05 +0100606 assert(tracemalloc_config.tracing);
607
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100608 traceback = traceback_new();
Victor Stinnere492ae52016-03-22 12:58:23 +0100609 if (traceback == NULL) {
Victor Stinner52968672013-11-24 11:37:15 +0100610 return -1;
Victor Stinnere492ae52016-03-22 12:58:23 +0100611 }
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100612
Victor Stinner5e14a382016-03-23 22:03:55 +0100613 if (!tracemalloc_config.use_domain && domain != DEFAULT_DOMAIN) {
614 /* first trace using a non-zero domain whereas traces use compact
Benjamin Petersonca470632016-09-06 13:47:26 -0700615 (uintptr_t) keys: switch to pointer_t keys. */
Victor Stinner5e14a382016-03-23 22:03:55 +0100616 if (tracemalloc_use_domain() < 0) {
617 return -1;
618 }
619 }
620
Victor Stinnere492ae52016-03-22 12:58:23 +0100621 if (tracemalloc_config.use_domain) {
Victor Stinnerca79ccd2016-03-23 09:38:54 +0100622 entry = _Py_HASHTABLE_GET_ENTRY(tracemalloc_traces, key);
Victor Stinnere492ae52016-03-22 12:58:23 +0100623 }
624 else {
Victor Stinnerca79ccd2016-03-23 09:38:54 +0100625 entry = _Py_HASHTABLE_GET_ENTRY(tracemalloc_traces, ptr);
Victor Stinnerd606ba72013-11-24 11:28:20 +0100626 }
Victor Stinner52968672013-11-24 11:37:15 +0100627
Victor Stinnerca79ccd2016-03-23 09:38:54 +0100628 if (entry != NULL) {
629 /* the memory block is already tracked */
630 _Py_HASHTABLE_ENTRY_READ_DATA(tracemalloc_traces, entry, trace);
631 assert(tracemalloc_traced_memory >= trace.size);
632 tracemalloc_traced_memory -= trace.size;
633
634 trace.size = size;
635 trace.traceback = traceback;
636 _Py_HASHTABLE_ENTRY_WRITE_DATA(tracemalloc_traces, entry, trace);
637 }
638 else {
639 trace.size = size;
640 trace.traceback = traceback;
641
642 if (tracemalloc_config.use_domain) {
643 res = _Py_HASHTABLE_SET(tracemalloc_traces, key, trace);
644 }
645 else {
646 res = _Py_HASHTABLE_SET(tracemalloc_traces, ptr, trace);
647 }
648 if (res != 0) {
649 return res;
650 }
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100651 }
Victor Stinnere492ae52016-03-22 12:58:23 +0100652
Benjamin Peterson2f8bfef2016-09-07 09:26:18 -0700653 assert(tracemalloc_traced_memory <= SIZE_MAX - size);
Victor Stinnere492ae52016-03-22 12:58:23 +0100654 tracemalloc_traced_memory += size;
655 if (tracemalloc_traced_memory > tracemalloc_peak_traced_memory)
656 tracemalloc_peak_traced_memory = tracemalloc_traced_memory;
657 return 0;
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100658}
659
Victor Stinnere492ae52016-03-22 12:58:23 +0100660#define ADD_TRACE(ptr, size) \
Benjamin Petersonca470632016-09-06 13:47:26 -0700661 tracemalloc_add_trace(DEFAULT_DOMAIN, (uintptr_t)(ptr), size)
Victor Stinnere492ae52016-03-22 12:58:23 +0100662
663
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100664static void*
Victor Stinnerdb067af2014-05-02 22:31:14 +0200665tracemalloc_alloc(int use_calloc, void *ctx, size_t nelem, size_t elsize)
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100666{
Victor Stinnerd8f0d922014-06-02 21:57:10 +0200667 PyMemAllocatorEx *alloc = (PyMemAllocatorEx *)ctx;
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100668 void *ptr;
669
Benjamin Peterson2f8bfef2016-09-07 09:26:18 -0700670 assert(elsize == 0 || nelem <= SIZE_MAX / elsize);
Victor Stinnerdb067af2014-05-02 22:31:14 +0200671
672 if (use_calloc)
673 ptr = alloc->calloc(alloc->ctx, nelem, elsize);
674 else
675 ptr = alloc->malloc(alloc->ctx, nelem * elsize);
Victor Stinner15116802013-12-04 01:29:35 +0100676 if (ptr == NULL)
677 return NULL;
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100678
Victor Stinner88c29872013-12-04 01:47:46 +0100679 TABLES_LOCK();
Victor Stinnere492ae52016-03-22 12:58:23 +0100680 if (ADD_TRACE(ptr, nelem * elsize) < 0) {
Victor Stinner15116802013-12-04 01:29:35 +0100681 /* Failed to allocate a trace for the new memory block */
Victor Stinner88c29872013-12-04 01:47:46 +0100682 TABLES_UNLOCK();
Victor Stinner15116802013-12-04 01:29:35 +0100683 alloc->free(alloc->ctx, ptr);
684 return NULL;
Victor Stinner52968672013-11-24 11:37:15 +0100685 }
Victor Stinner88c29872013-12-04 01:47:46 +0100686 TABLES_UNLOCK();
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100687 return ptr;
688}
689
Victor Stinnere492ae52016-03-22 12:58:23 +0100690
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100691static void*
Victor Stinner15116802013-12-04 01:29:35 +0100692tracemalloc_realloc(void *ctx, void *ptr, size_t new_size)
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100693{
Victor Stinnerd8f0d922014-06-02 21:57:10 +0200694 PyMemAllocatorEx *alloc = (PyMemAllocatorEx *)ctx;
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100695 void *ptr2;
696
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100697 ptr2 = alloc->realloc(alloc->ctx, ptr, new_size);
Victor Stinner15116802013-12-04 01:29:35 +0100698 if (ptr2 == NULL)
699 return NULL;
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100700
Victor Stinner15116802013-12-04 01:29:35 +0100701 if (ptr != NULL) {
702 /* an existing memory block has been resized */
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100703
Victor Stinner88c29872013-12-04 01:47:46 +0100704 TABLES_LOCK();
Victor Stinner42bcf372016-03-23 09:08:08 +0100705
706 /* tracemalloc_add_trace() updates the trace if there is already
707 a trace at address (domain, ptr2) */
708 if (ptr2 != ptr) {
709 REMOVE_TRACE(ptr);
710 }
Victor Stinner08facd22013-11-24 12:27:59 +0100711
Victor Stinnere492ae52016-03-22 12:58:23 +0100712 if (ADD_TRACE(ptr2, new_size) < 0) {
Victor Stinner15116802013-12-04 01:29:35 +0100713 /* Memory allocation failed. The error cannot be reported to
Raymond Hettinger15f44ab2016-08-30 10:47:49 -0700714 the caller, because realloc() may already have shrunk the
Victor Stinner15116802013-12-04 01:29:35 +0100715 memory block and so removed bytes.
716
Serhiy Storchaka6a7b3a72016-04-17 08:32:47 +0300717 This case is very unlikely: a hash entry has just been
Victor Stinner88c29872013-12-04 01:47:46 +0100718 released, so the hash table should have at least one free entry.
719
720 The GIL and the table lock ensures that only one thread is
721 allocating memory. */
Barry Warsawb2e57942017-09-14 18:13:16 -0700722 Py_UNREACHABLE();
Victor Stinner52968672013-11-24 11:37:15 +0100723 }
Victor Stinner88c29872013-12-04 01:47:46 +0100724 TABLES_UNLOCK();
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100725 }
Victor Stinner15116802013-12-04 01:29:35 +0100726 else {
727 /* new allocation */
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100728
Victor Stinner88c29872013-12-04 01:47:46 +0100729 TABLES_LOCK();
Victor Stinnere492ae52016-03-22 12:58:23 +0100730 if (ADD_TRACE(ptr2, new_size) < 0) {
Victor Stinner15116802013-12-04 01:29:35 +0100731 /* Failed to allocate a trace for the new memory block */
Victor Stinner88c29872013-12-04 01:47:46 +0100732 TABLES_UNLOCK();
Victor Stinner15116802013-12-04 01:29:35 +0100733 alloc->free(alloc->ctx, ptr2);
734 return NULL;
735 }
Victor Stinner88c29872013-12-04 01:47:46 +0100736 TABLES_UNLOCK();
Victor Stinner15116802013-12-04 01:29:35 +0100737 }
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100738 return ptr2;
739}
740
Victor Stinnere492ae52016-03-22 12:58:23 +0100741
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100742static void
743tracemalloc_free(void *ctx, void *ptr)
744{
Victor Stinnerd8f0d922014-06-02 21:57:10 +0200745 PyMemAllocatorEx *alloc = (PyMemAllocatorEx *)ctx;
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100746
747 if (ptr == NULL)
748 return;
749
750 /* GIL cannot be locked in PyMem_RawFree() because it would introduce
751 a deadlock in PyThreadState_DeleteCurrent(). */
752
753 alloc->free(alloc->ctx, ptr);
Victor Stinner88c29872013-12-04 01:47:46 +0100754
755 TABLES_LOCK();
Victor Stinnere492ae52016-03-22 12:58:23 +0100756 REMOVE_TRACE(ptr);
Victor Stinner88c29872013-12-04 01:47:46 +0100757 TABLES_UNLOCK();
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100758}
759
Victor Stinnere492ae52016-03-22 12:58:23 +0100760
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100761static void*
Victor Stinnerdb067af2014-05-02 22:31:14 +0200762tracemalloc_alloc_gil(int use_calloc, void *ctx, size_t nelem, size_t elsize)
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100763{
Victor Stinner15116802013-12-04 01:29:35 +0100764 void *ptr;
765
766 if (get_reentrant()) {
Victor Stinnerd8f0d922014-06-02 21:57:10 +0200767 PyMemAllocatorEx *alloc = (PyMemAllocatorEx *)ctx;
Victor Stinnerdb067af2014-05-02 22:31:14 +0200768 if (use_calloc)
769 return alloc->calloc(alloc->ctx, nelem, elsize);
770 else
771 return alloc->malloc(alloc->ctx, nelem * elsize);
Victor Stinner15116802013-12-04 01:29:35 +0100772 }
773
774 /* Ignore reentrant call. PyObjet_Malloc() calls PyMem_Malloc() for
775 allocations larger than 512 bytes, don't trace the same memory
776 allocation twice. */
777 set_reentrant(1);
778
Victor Stinnerdb067af2014-05-02 22:31:14 +0200779 ptr = tracemalloc_alloc(use_calloc, ctx, nelem, elsize);
Victor Stinner15116802013-12-04 01:29:35 +0100780
781 set_reentrant(0);
782 return ptr;
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100783}
784
Victor Stinnere492ae52016-03-22 12:58:23 +0100785
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100786static void*
Victor Stinnerdb067af2014-05-02 22:31:14 +0200787tracemalloc_malloc_gil(void *ctx, size_t size)
788{
789 return tracemalloc_alloc_gil(0, ctx, 1, size);
790}
791
Victor Stinnere492ae52016-03-22 12:58:23 +0100792
Victor Stinnerdb067af2014-05-02 22:31:14 +0200793static void*
794tracemalloc_calloc_gil(void *ctx, size_t nelem, size_t elsize)
795{
796 return tracemalloc_alloc_gil(1, ctx, nelem, elsize);
797}
798
Victor Stinnere492ae52016-03-22 12:58:23 +0100799
Victor Stinnerdb067af2014-05-02 22:31:14 +0200800static void*
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100801tracemalloc_realloc_gil(void *ctx, void *ptr, size_t new_size)
802{
Victor Stinner15116802013-12-04 01:29:35 +0100803 void *ptr2;
804
805 if (get_reentrant()) {
806 /* Reentrant call to PyMem_Realloc() and PyMem_RawRealloc().
807 Example: PyMem_RawRealloc() is called internally by pymalloc
808 (_PyObject_Malloc() and _PyObject_Realloc()) to allocate a new
809 arena (new_arena()). */
Victor Stinnerd8f0d922014-06-02 21:57:10 +0200810 PyMemAllocatorEx *alloc = (PyMemAllocatorEx *)ctx;
Victor Stinner15116802013-12-04 01:29:35 +0100811
812 ptr2 = alloc->realloc(alloc->ctx, ptr, new_size);
Victor Stinner88c29872013-12-04 01:47:46 +0100813 if (ptr2 != NULL && ptr != NULL) {
814 TABLES_LOCK();
Victor Stinnere492ae52016-03-22 12:58:23 +0100815 REMOVE_TRACE(ptr);
Victor Stinner88c29872013-12-04 01:47:46 +0100816 TABLES_UNLOCK();
817 }
Victor Stinner15116802013-12-04 01:29:35 +0100818 return ptr2;
819 }
820
821 /* Ignore reentrant call. PyObjet_Realloc() calls PyMem_Realloc() for
822 allocations larger than 512 bytes. Don't trace the same memory
823 allocation twice. */
824 set_reentrant(1);
825
826 ptr2 = tracemalloc_realloc(ctx, ptr, new_size);
827
828 set_reentrant(0);
829 return ptr2;
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100830}
831
Victor Stinnere492ae52016-03-22 12:58:23 +0100832
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100833#ifdef TRACE_RAW_MALLOC
834static void*
Victor Stinnerdb067af2014-05-02 22:31:14 +0200835tracemalloc_raw_alloc(int use_calloc, void *ctx, size_t nelem, size_t elsize)
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100836{
Victor Stinner15116802013-12-04 01:29:35 +0100837 PyGILState_STATE gil_state;
Victor Stinner15116802013-12-04 01:29:35 +0100838 void *ptr;
839
840 if (get_reentrant()) {
Victor Stinnerd8f0d922014-06-02 21:57:10 +0200841 PyMemAllocatorEx *alloc = (PyMemAllocatorEx *)ctx;
Victor Stinnerdb067af2014-05-02 22:31:14 +0200842 if (use_calloc)
843 return alloc->calloc(alloc->ctx, nelem, elsize);
844 else
845 return alloc->malloc(alloc->ctx, nelem * elsize);
Victor Stinner15116802013-12-04 01:29:35 +0100846 }
847
848 /* Ignore reentrant call. PyGILState_Ensure() may call PyMem_RawMalloc()
849 indirectly which would call PyGILState_Ensure() if reentrant are not
850 disabled. */
851 set_reentrant(1);
852
Victor Stinner15116802013-12-04 01:29:35 +0100853 gil_state = PyGILState_Ensure();
Victor Stinnerdb067af2014-05-02 22:31:14 +0200854 ptr = tracemalloc_alloc(use_calloc, ctx, nelem, elsize);
Victor Stinner15116802013-12-04 01:29:35 +0100855 PyGILState_Release(gil_state);
Victor Stinner15116802013-12-04 01:29:35 +0100856
857 set_reentrant(0);
858 return ptr;
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100859}
860
Victor Stinnere492ae52016-03-22 12:58:23 +0100861
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100862static void*
Victor Stinnerdb067af2014-05-02 22:31:14 +0200863tracemalloc_raw_malloc(void *ctx, size_t size)
864{
865 return tracemalloc_raw_alloc(0, ctx, 1, size);
866}
867
Victor Stinnere492ae52016-03-22 12:58:23 +0100868
Victor Stinnerdb067af2014-05-02 22:31:14 +0200869static void*
870tracemalloc_raw_calloc(void *ctx, size_t nelem, size_t elsize)
871{
872 return tracemalloc_raw_alloc(1, ctx, nelem, elsize);
873}
874
Victor Stinnere492ae52016-03-22 12:58:23 +0100875
Victor Stinnerdb067af2014-05-02 22:31:14 +0200876static void*
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100877tracemalloc_raw_realloc(void *ctx, void *ptr, size_t new_size)
878{
Victor Stinner15116802013-12-04 01:29:35 +0100879 PyGILState_STATE gil_state;
Victor Stinner15116802013-12-04 01:29:35 +0100880 void *ptr2;
881
882 if (get_reentrant()) {
883 /* Reentrant call to PyMem_RawRealloc(). */
Victor Stinnerd8f0d922014-06-02 21:57:10 +0200884 PyMemAllocatorEx *alloc = (PyMemAllocatorEx *)ctx;
Victor Stinner15116802013-12-04 01:29:35 +0100885
886 ptr2 = alloc->realloc(alloc->ctx, ptr, new_size);
Victor Stinner15116802013-12-04 01:29:35 +0100887
Victor Stinner88c29872013-12-04 01:47:46 +0100888 if (ptr2 != NULL && ptr != NULL) {
889 TABLES_LOCK();
Victor Stinnere492ae52016-03-22 12:58:23 +0100890 REMOVE_TRACE(ptr);
Victor Stinner88c29872013-12-04 01:47:46 +0100891 TABLES_UNLOCK();
892 }
Victor Stinner15116802013-12-04 01:29:35 +0100893 return ptr2;
894 }
895
896 /* Ignore reentrant call. PyGILState_Ensure() may call PyMem_RawMalloc()
897 indirectly which would call PyGILState_Ensure() if reentrant calls are
898 not disabled. */
899 set_reentrant(1);
900
Victor Stinner15116802013-12-04 01:29:35 +0100901 gil_state = PyGILState_Ensure();
902 ptr2 = tracemalloc_realloc(ctx, ptr, new_size);
903 PyGILState_Release(gil_state);
Victor Stinner15116802013-12-04 01:29:35 +0100904
905 set_reentrant(0);
906 return ptr2;
907}
908#endif /* TRACE_RAW_MALLOC */
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100909
Victor Stinnere492ae52016-03-22 12:58:23 +0100910
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100911static int
Victor Stinner285cf0a2016-03-21 22:00:58 +0100912tracemalloc_clear_filename(_Py_hashtable_t *ht, _Py_hashtable_entry_t *entry,
913 void *user_data)
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100914{
Victor Stinner285cf0a2016-03-21 22:00:58 +0100915 PyObject *filename;
916
Victor Stinner5dacbd42016-03-23 09:52:13 +0100917 _Py_HASHTABLE_ENTRY_READ_KEY(ht, entry, filename);
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100918 Py_DECREF(filename);
919 return 0;
920}
921
Victor Stinnere492ae52016-03-22 12:58:23 +0100922
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100923static int
Victor Stinner285cf0a2016-03-21 22:00:58 +0100924traceback_free_traceback(_Py_hashtable_t *ht, _Py_hashtable_entry_t *entry,
925 void *user_data)
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100926{
Victor Stinner285cf0a2016-03-21 22:00:58 +0100927 traceback_t *traceback;
928
Victor Stinner5dacbd42016-03-23 09:52:13 +0100929 _Py_HASHTABLE_ENTRY_READ_KEY(ht, entry, traceback);
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100930 raw_free(traceback);
931 return 0;
932}
933
Victor Stinnere492ae52016-03-22 12:58:23 +0100934
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100935/* reentrant flag must be set to call this function and GIL must be held */
936static void
937tracemalloc_clear_traces(void)
938{
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100939 /* The GIL protects variables againt concurrent access */
940 assert(PyGILState_Check());
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100941
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100942 TABLES_LOCK();
943 _Py_hashtable_clear(tracemalloc_traces);
944 tracemalloc_traced_memory = 0;
Victor Stinner3c0481d2013-11-27 21:39:49 +0100945 tracemalloc_peak_traced_memory = 0;
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100946 TABLES_UNLOCK();
947
948 _Py_hashtable_foreach(tracemalloc_tracebacks, traceback_free_traceback, NULL);
949 _Py_hashtable_clear(tracemalloc_tracebacks);
950
951 _Py_hashtable_foreach(tracemalloc_filenames, tracemalloc_clear_filename, NULL);
952 _Py_hashtable_clear(tracemalloc_filenames);
953}
954
Victor Stinnere492ae52016-03-22 12:58:23 +0100955
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100956static int
957tracemalloc_init(void)
958{
959 if (tracemalloc_config.initialized == TRACEMALLOC_FINALIZED) {
960 PyErr_SetString(PyExc_RuntimeError,
961 "the tracemalloc module has been unloaded");
962 return -1;
963 }
964
Victor Stinnerf9a71152016-03-22 23:54:42 +0100965 if (tracemalloc_config.initialized == TRACEMALLOC_INITIALIZED)
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100966 return 0;
967
968 PyMem_GetAllocator(PYMEM_DOMAIN_RAW, &allocators.raw);
969
970#ifdef REENTRANT_THREADLOCAL
Masayuki Yamamoto731e1892017-10-06 19:41:34 +0900971 if (PyThread_tss_create(&tracemalloc_reentrant_key) != 0) {
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100972#ifdef MS_WINDOWS
973 PyErr_SetFromWindowsErr(0);
974#else
975 PyErr_SetFromErrno(PyExc_OSError);
976#endif
977 return -1;
978 }
979#endif
980
Antoine Pitroua6a4dc82017-09-07 18:56:24 +0200981#if defined(TRACE_RAW_MALLOC)
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100982 if (tables_lock == NULL) {
983 tables_lock = PyThread_allocate_lock();
984 if (tables_lock == NULL) {
985 PyErr_SetString(PyExc_RuntimeError, "cannot allocate lock");
986 return -1;
987 }
988 }
989#endif
990
Victor Stinner285cf0a2016-03-21 22:00:58 +0100991 tracemalloc_filenames = hashtable_new(sizeof(PyObject *), 0,
992 hashtable_hash_pyobject,
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100993 hashtable_compare_unicode);
994
Victor Stinner285cf0a2016-03-21 22:00:58 +0100995 tracemalloc_tracebacks = hashtable_new(sizeof(traceback_t *), 0,
996 hashtable_hash_traceback,
997 hashtable_compare_traceback);
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100998
Victor Stinnere492ae52016-03-22 12:58:23 +0100999 if (tracemalloc_config.use_domain) {
1000 tracemalloc_traces = hashtable_new(sizeof(pointer_t),
1001 sizeof(trace_t),
1002 hashtable_hash_pointer_t,
1003 hashtable_compare_pointer_t);
1004 }
1005 else {
Benjamin Petersonca470632016-09-06 13:47:26 -07001006 tracemalloc_traces = hashtable_new(sizeof(uintptr_t),
Victor Stinnere492ae52016-03-22 12:58:23 +01001007 sizeof(trace_t),
1008 _Py_hashtable_hash_ptr,
1009 _Py_hashtable_compare_direct);
1010 }
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001011
1012 if (tracemalloc_filenames == NULL || tracemalloc_tracebacks == NULL
Victor Stinner285cf0a2016-03-21 22:00:58 +01001013 || tracemalloc_traces == NULL) {
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001014 PyErr_NoMemory();
1015 return -1;
1016 }
1017
1018 unknown_filename = PyUnicode_FromString("<unknown>");
1019 if (unknown_filename == NULL)
1020 return -1;
1021 PyUnicode_InternInPlace(&unknown_filename);
1022
1023 tracemalloc_empty_traceback.nframe = 1;
1024 /* borrowed reference */
1025 tracemalloc_empty_traceback.frames[0].filename = unknown_filename;
1026 tracemalloc_empty_traceback.frames[0].lineno = 0;
1027 tracemalloc_empty_traceback.hash = traceback_hash(&tracemalloc_empty_traceback);
1028
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001029 tracemalloc_config.initialized = TRACEMALLOC_INITIALIZED;
1030 return 0;
1031}
1032
Victor Stinnere492ae52016-03-22 12:58:23 +01001033
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001034static void
1035tracemalloc_deinit(void)
1036{
Victor Stinnerf9a71152016-03-22 23:54:42 +01001037 if (tracemalloc_config.initialized != TRACEMALLOC_INITIALIZED)
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001038 return;
1039 tracemalloc_config.initialized = TRACEMALLOC_FINALIZED;
1040
1041 tracemalloc_stop();
1042
1043 /* destroy hash tables */
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001044 _Py_hashtable_destroy(tracemalloc_tracebacks);
1045 _Py_hashtable_destroy(tracemalloc_filenames);
Victor Stinner285cf0a2016-03-21 22:00:58 +01001046 _Py_hashtable_destroy(tracemalloc_traces);
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001047
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02001048#if defined(TRACE_RAW_MALLOC)
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001049 if (tables_lock != NULL) {
1050 PyThread_free_lock(tables_lock);
1051 tables_lock = NULL;
1052 }
1053#endif
1054
1055#ifdef REENTRANT_THREADLOCAL
Masayuki Yamamoto731e1892017-10-06 19:41:34 +09001056 PyThread_tss_delete(&tracemalloc_reentrant_key);
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001057#endif
1058
1059 Py_XDECREF(unknown_filename);
1060}
1061
Victor Stinnere492ae52016-03-22 12:58:23 +01001062
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001063static int
Victor Stinnerf28ce602013-11-27 22:27:13 +01001064tracemalloc_start(int max_nframe)
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001065{
Victor Stinnerd8f0d922014-06-02 21:57:10 +02001066 PyMemAllocatorEx alloc;
Victor Stinnerf28ce602013-11-27 22:27:13 +01001067 size_t size;
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001068
Victor Stinnera7368ac2017-11-15 18:11:45 -08001069 if (max_nframe < 1 || max_nframe > MAX_NFRAME) {
1070 PyErr_Format(PyExc_ValueError,
1071 "the number of frames must be in range [1; %i]",
1072 (int)MAX_NFRAME);
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001073 return -1;
Victor Stinnera7368ac2017-11-15 18:11:45 -08001074 }
1075
1076 if (tracemalloc_init() < 0) {
1077 return -1;
1078 }
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001079
1080 if (tracemalloc_config.tracing) {
1081 /* hook already installed: do nothing */
1082 return 0;
1083 }
1084
Victor Stinner52aee852014-08-16 15:44:02 +02001085 assert(1 <= max_nframe && max_nframe <= MAX_NFRAME);
Victor Stinnerf28ce602013-11-27 22:27:13 +01001086 tracemalloc_config.max_nframe = max_nframe;
1087
1088 /* allocate a buffer to store a new traceback */
1089 size = TRACEBACK_SIZE(max_nframe);
1090 assert(tracemalloc_traceback == NULL);
1091 tracemalloc_traceback = raw_malloc(size);
1092 if (tracemalloc_traceback == NULL) {
1093 PyErr_NoMemory();
1094 return -1;
1095 }
1096
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001097#ifdef TRACE_RAW_MALLOC
1098 alloc.malloc = tracemalloc_raw_malloc;
Victor Stinnerdb067af2014-05-02 22:31:14 +02001099 alloc.calloc = tracemalloc_raw_calloc;
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001100 alloc.realloc = tracemalloc_raw_realloc;
1101 alloc.free = tracemalloc_free;
1102
1103 alloc.ctx = &allocators.raw;
1104 PyMem_GetAllocator(PYMEM_DOMAIN_RAW, &allocators.raw);
1105 PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &alloc);
1106#endif
1107
1108 alloc.malloc = tracemalloc_malloc_gil;
Victor Stinnerdb067af2014-05-02 22:31:14 +02001109 alloc.calloc = tracemalloc_calloc_gil;
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001110 alloc.realloc = tracemalloc_realloc_gil;
1111 alloc.free = tracemalloc_free;
1112
1113 alloc.ctx = &allocators.mem;
1114 PyMem_GetAllocator(PYMEM_DOMAIN_MEM, &allocators.mem);
1115 PyMem_SetAllocator(PYMEM_DOMAIN_MEM, &alloc);
1116
1117 alloc.ctx = &allocators.obj;
1118 PyMem_GetAllocator(PYMEM_DOMAIN_OBJ, &allocators.obj);
1119 PyMem_SetAllocator(PYMEM_DOMAIN_OBJ, &alloc);
1120
1121 /* everything is ready: start tracing Python memory allocations */
1122 tracemalloc_config.tracing = 1;
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001123
1124 return 0;
1125}
1126
Victor Stinnere492ae52016-03-22 12:58:23 +01001127
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001128static void
1129tracemalloc_stop(void)
1130{
Victor Stinnerf9a71152016-03-22 23:54:42 +01001131 if (!tracemalloc_config.tracing)
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001132 return;
1133
1134 /* stop tracing Python memory allocations */
1135 tracemalloc_config.tracing = 0;
1136
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001137 /* unregister the hook on memory allocators */
1138#ifdef TRACE_RAW_MALLOC
1139 PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &allocators.raw);
1140#endif
1141 PyMem_SetAllocator(PYMEM_DOMAIN_MEM, &allocators.mem);
1142 PyMem_SetAllocator(PYMEM_DOMAIN_OBJ, &allocators.obj);
1143
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001144 tracemalloc_clear_traces();
Victor Stinner285cf0a2016-03-21 22:00:58 +01001145
1146 /* release memory */
Victor Stinnerf28ce602013-11-27 22:27:13 +01001147 raw_free(tracemalloc_traceback);
1148 tracemalloc_traceback = NULL;
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001149}
1150
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001151
Victor Stinnere492ae52016-03-22 12:58:23 +01001152
Serhiy Storchakab451f912017-02-04 12:18:38 +02001153/*[clinic input]
1154_tracemalloc.is_tracing
1155
1156Return True if the tracemalloc module is tracing Python memory allocations.
1157[clinic start generated code]*/
1158
1159static PyObject *
1160_tracemalloc_is_tracing_impl(PyObject *module)
Serhiy Storchaka97353842017-02-05 22:58:46 +02001161/*[clinic end generated code: output=2d763b42601cd3ef input=af104b0a00192f63]*/
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001162{
1163 return PyBool_FromLong(tracemalloc_config.tracing);
1164}
1165
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001166
Serhiy Storchakab451f912017-02-04 12:18:38 +02001167/*[clinic input]
1168_tracemalloc.clear_traces
Victor Stinnere492ae52016-03-22 12:58:23 +01001169
Serhiy Storchakab451f912017-02-04 12:18:38 +02001170Clear traces of memory blocks allocated by Python.
1171[clinic start generated code]*/
1172
1173static PyObject *
1174_tracemalloc_clear_traces_impl(PyObject *module)
1175/*[clinic end generated code: output=a86080ee41b84197 input=0dab5b6c785183a5]*/
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001176{
1177 if (!tracemalloc_config.tracing)
1178 Py_RETURN_NONE;
1179
1180 set_reentrant(1);
1181 tracemalloc_clear_traces();
1182 set_reentrant(0);
1183
1184 Py_RETURN_NONE;
1185}
1186
Victor Stinnere492ae52016-03-22 12:58:23 +01001187
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001188static PyObject*
1189frame_to_pyobject(frame_t *frame)
1190{
1191 PyObject *frame_obj, *lineno_obj;
1192
1193 frame_obj = PyTuple_New(2);
1194 if (frame_obj == NULL)
1195 return NULL;
1196
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001197 Py_INCREF(frame->filename);
1198 PyTuple_SET_ITEM(frame_obj, 0, frame->filename);
1199
Victor Stinner95283342016-03-15 21:57:02 +01001200 lineno_obj = PyLong_FromUnsignedLong(frame->lineno);
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001201 if (lineno_obj == NULL) {
1202 Py_DECREF(frame_obj);
1203 return NULL;
1204 }
1205 PyTuple_SET_ITEM(frame_obj, 1, lineno_obj);
1206
1207 return frame_obj;
1208}
1209
Victor Stinnere492ae52016-03-22 12:58:23 +01001210
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001211static PyObject*
1212traceback_to_pyobject(traceback_t *traceback, _Py_hashtable_t *intern_table)
1213{
1214 int i;
1215 PyObject *frames, *frame;
1216
1217 if (intern_table != NULL) {
1218 if (_Py_HASHTABLE_GET(intern_table, traceback, frames)) {
1219 Py_INCREF(frames);
1220 return frames;
1221 }
1222 }
1223
1224 frames = PyTuple_New(traceback->nframe);
1225 if (frames == NULL)
1226 return NULL;
1227
1228 for (i=0; i < traceback->nframe; i++) {
1229 frame = frame_to_pyobject(&traceback->frames[i]);
1230 if (frame == NULL) {
1231 Py_DECREF(frames);
1232 return NULL;
1233 }
1234 PyTuple_SET_ITEM(frames, i, frame);
1235 }
1236
1237 if (intern_table != NULL) {
1238 if (_Py_HASHTABLE_SET(intern_table, traceback, frames) < 0) {
1239 Py_DECREF(frames);
1240 PyErr_NoMemory();
1241 return NULL;
1242 }
1243 /* intern_table keeps a new reference to frames */
1244 Py_INCREF(frames);
1245 }
1246 return frames;
1247}
1248
Victor Stinnere492ae52016-03-22 12:58:23 +01001249
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001250static PyObject*
Victor Stinner5ea4c062017-06-20 17:46:36 +02001251trace_to_pyobject(unsigned int domain, trace_t *trace,
Victor Stinnere492ae52016-03-22 12:58:23 +01001252 _Py_hashtable_t *intern_tracebacks)
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001253{
1254 PyObject *trace_obj = NULL;
Victor Stinnere492ae52016-03-22 12:58:23 +01001255 PyObject *obj;
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001256
Victor Stinnere492ae52016-03-22 12:58:23 +01001257 trace_obj = PyTuple_New(3);
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001258 if (trace_obj == NULL)
1259 return NULL;
1260
Victor Stinnere492ae52016-03-22 12:58:23 +01001261 obj = PyLong_FromSize_t(domain);
1262 if (obj == NULL) {
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001263 Py_DECREF(trace_obj);
1264 return NULL;
1265 }
Victor Stinnere492ae52016-03-22 12:58:23 +01001266 PyTuple_SET_ITEM(trace_obj, 0, obj);
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001267
Victor Stinnere492ae52016-03-22 12:58:23 +01001268 obj = PyLong_FromSize_t(trace->size);
1269 if (obj == NULL) {
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001270 Py_DECREF(trace_obj);
1271 return NULL;
1272 }
Victor Stinnere492ae52016-03-22 12:58:23 +01001273 PyTuple_SET_ITEM(trace_obj, 1, obj);
1274
1275 obj = traceback_to_pyobject(trace->traceback, intern_tracebacks);
1276 if (obj == NULL) {
1277 Py_DECREF(trace_obj);
1278 return NULL;
1279 }
1280 PyTuple_SET_ITEM(trace_obj, 2, obj);
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001281
1282 return trace_obj;
1283}
1284
Victor Stinnere492ae52016-03-22 12:58:23 +01001285
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001286typedef struct {
1287 _Py_hashtable_t *traces;
1288 _Py_hashtable_t *tracebacks;
1289 PyObject *list;
1290} get_traces_t;
1291
1292static int
Victor Stinner285cf0a2016-03-21 22:00:58 +01001293tracemalloc_get_traces_fill(_Py_hashtable_t *traces, _Py_hashtable_entry_t *entry,
1294 void *user_data)
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001295{
1296 get_traces_t *get_traces = user_data;
Victor Stinner5ea4c062017-06-20 17:46:36 +02001297 unsigned int domain;
Victor Stinner5dacbd42016-03-23 09:52:13 +01001298 trace_t trace;
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001299 PyObject *tracemalloc_obj;
1300 int res;
1301
Victor Stinnere492ae52016-03-22 12:58:23 +01001302 if (tracemalloc_config.use_domain) {
1303 pointer_t key;
Victor Stinner5dacbd42016-03-23 09:52:13 +01001304 _Py_HASHTABLE_ENTRY_READ_KEY(traces, entry, key);
Victor Stinnere492ae52016-03-22 12:58:23 +01001305 domain = key.domain;
1306 }
1307 else {
1308 domain = DEFAULT_DOMAIN;
1309 }
Victor Stinner5dacbd42016-03-23 09:52:13 +01001310 _Py_HASHTABLE_ENTRY_READ_DATA(traces, entry, trace);
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001311
Victor Stinner5dacbd42016-03-23 09:52:13 +01001312 tracemalloc_obj = trace_to_pyobject(domain, &trace, get_traces->tracebacks);
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001313 if (tracemalloc_obj == NULL)
1314 return 1;
1315
1316 res = PyList_Append(get_traces->list, tracemalloc_obj);
1317 Py_DECREF(tracemalloc_obj);
1318 if (res < 0)
1319 return 1;
1320
1321 return 0;
1322}
1323
Victor Stinnere492ae52016-03-22 12:58:23 +01001324
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001325static int
Victor Stinner285cf0a2016-03-21 22:00:58 +01001326tracemalloc_pyobject_decref_cb(_Py_hashtable_t *tracebacks,
1327 _Py_hashtable_entry_t *entry,
1328 void *user_data)
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001329{
Victor Stinnerc9553872016-03-22 12:13:01 +01001330 PyObject *obj;
Victor Stinnere8c6b2f2016-03-23 09:25:01 +01001331 _Py_HASHTABLE_ENTRY_READ_DATA(tracebacks, entry, obj);
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001332 Py_DECREF(obj);
1333 return 0;
1334}
1335
Victor Stinnere492ae52016-03-22 12:58:23 +01001336
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001337
Serhiy Storchakab451f912017-02-04 12:18:38 +02001338/*[clinic input]
1339_tracemalloc._get_traces
1340
1341Get traces of all memory blocks allocated by Python.
1342
1343Return a list of (size: int, traceback: tuple) tuples.
1344traceback is a tuple of (filename: str, lineno: int) tuples.
1345
1346Return an empty list if the tracemalloc module is disabled.
1347[clinic start generated code]*/
1348
1349static PyObject *
1350_tracemalloc__get_traces_impl(PyObject *module)
1351/*[clinic end generated code: output=e9929876ced4b5cc input=6c7d2230b24255aa]*/
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001352{
1353 get_traces_t get_traces;
1354 int err;
1355
1356 get_traces.traces = NULL;
1357 get_traces.tracebacks = NULL;
1358 get_traces.list = PyList_New(0);
1359 if (get_traces.list == NULL)
1360 goto error;
1361
1362 if (!tracemalloc_config.tracing)
1363 return get_traces.list;
1364
Victor Stinnerde2f1322013-11-26 00:26:23 +01001365 /* the traceback hash table is used temporarily to intern traceback tuple
1366 of (filename, lineno) tuples */
Victor Stinnerc9553872016-03-22 12:13:01 +01001367 get_traces.tracebacks = hashtable_new(sizeof(traceback_t *),
1368 sizeof(PyObject *),
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001369 _Py_hashtable_hash_ptr,
1370 _Py_hashtable_compare_direct);
1371 if (get_traces.tracebacks == NULL) {
1372 PyErr_NoMemory();
1373 goto error;
1374 }
1375
1376 TABLES_LOCK();
1377 get_traces.traces = _Py_hashtable_copy(tracemalloc_traces);
1378 TABLES_UNLOCK();
1379
1380 if (get_traces.traces == NULL) {
1381 PyErr_NoMemory();
1382 goto error;
1383 }
1384
1385 set_reentrant(1);
1386 err = _Py_hashtable_foreach(get_traces.traces,
1387 tracemalloc_get_traces_fill, &get_traces);
1388 set_reentrant(0);
1389 if (err)
1390 goto error;
1391
1392 goto finally;
1393
1394error:
1395 Py_CLEAR(get_traces.list);
1396
1397finally:
1398 if (get_traces.tracebacks != NULL) {
1399 _Py_hashtable_foreach(get_traces.tracebacks,
Victor Stinner285cf0a2016-03-21 22:00:58 +01001400 tracemalloc_pyobject_decref_cb, NULL);
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001401 _Py_hashtable_destroy(get_traces.tracebacks);
1402 }
Victor Stinnerc9553872016-03-22 12:13:01 +01001403 if (get_traces.traces != NULL) {
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001404 _Py_hashtable_destroy(get_traces.traces);
Victor Stinnerc9553872016-03-22 12:13:01 +01001405 }
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001406
1407 return get_traces.list;
1408}
1409
Victor Stinnere492ae52016-03-22 12:58:23 +01001410
Victor Stinner0611c262016-03-15 22:22:13 +01001411static traceback_t*
Victor Stinner5ea4c062017-06-20 17:46:36 +02001412tracemalloc_get_traceback(unsigned int domain, uintptr_t ptr)
Victor Stinner0611c262016-03-15 22:22:13 +01001413{
1414 trace_t trace;
1415 int found;
1416
1417 if (!tracemalloc_config.tracing)
1418 return NULL;
1419
1420 TABLES_LOCK();
Victor Stinnere492ae52016-03-22 12:58:23 +01001421 if (tracemalloc_config.use_domain) {
Victor Stinner10b73e12016-03-22 13:39:05 +01001422 pointer_t key = {ptr, domain};
Victor Stinnere492ae52016-03-22 12:58:23 +01001423 found = _Py_HASHTABLE_GET(tracemalloc_traces, key, trace);
1424 }
1425 else {
1426 found = _Py_HASHTABLE_GET(tracemalloc_traces, ptr, trace);
1427 }
Victor Stinner0611c262016-03-15 22:22:13 +01001428 TABLES_UNLOCK();
1429
1430 if (!found)
1431 return NULL;
1432
1433 return trace.traceback;
1434}
1435
Victor Stinnere492ae52016-03-22 12:58:23 +01001436
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001437
Serhiy Storchakab451f912017-02-04 12:18:38 +02001438/*[clinic input]
1439_tracemalloc._get_object_traceback
1440
1441 obj: object
1442 /
1443
1444Get the traceback where the Python object obj was allocated.
1445
1446Return a tuple of (filename: str, lineno: int) tuples.
1447Return None if the tracemalloc module is disabled or did not
1448trace the allocation of the object.
1449[clinic start generated code]*/
1450
1451static PyObject *
1452_tracemalloc__get_object_traceback(PyObject *module, PyObject *obj)
1453/*[clinic end generated code: output=41ee0553a658b0aa input=29495f1b21c53212]*/
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001454{
1455 PyTypeObject *type;
1456 void *ptr;
Victor Stinner0611c262016-03-15 22:22:13 +01001457 traceback_t *traceback;
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001458
1459 type = Py_TYPE(obj);
1460 if (PyType_IS_GC(type))
1461 ptr = (void *)((char *)obj - sizeof(PyGC_Head));
1462 else
1463 ptr = (void *)obj;
1464
Benjamin Petersonca470632016-09-06 13:47:26 -07001465 traceback = tracemalloc_get_traceback(DEFAULT_DOMAIN, (uintptr_t)ptr);
Victor Stinner0611c262016-03-15 22:22:13 +01001466 if (traceback == NULL)
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001467 Py_RETURN_NONE;
1468
Victor Stinner0611c262016-03-15 22:22:13 +01001469 return traceback_to_pyobject(traceback, NULL);
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001470}
1471
Victor Stinnere492ae52016-03-22 12:58:23 +01001472
Victor Stinner0611c262016-03-15 22:22:13 +01001473#define PUTS(fd, str) _Py_write_noraise(fd, str, (int)strlen(str))
1474
1475static void
1476_PyMem_DumpFrame(int fd, frame_t * frame)
1477{
1478 PUTS(fd, " File \"");
1479 _Py_DumpASCII(fd, frame->filename);
1480 PUTS(fd, "\", line ");
1481 _Py_DumpDecimal(fd, frame->lineno);
1482 PUTS(fd, "\n");
1483}
1484
1485/* Dump the traceback where a memory block was allocated into file descriptor
1486 fd. The function may block on TABLES_LOCK() but it is unlikely. */
1487void
1488_PyMem_DumpTraceback(int fd, const void *ptr)
1489{
1490 traceback_t *traceback;
1491 int i;
1492
Benjamin Petersonca470632016-09-06 13:47:26 -07001493 traceback = tracemalloc_get_traceback(DEFAULT_DOMAIN, (uintptr_t)ptr);
Victor Stinner0611c262016-03-15 22:22:13 +01001494 if (traceback == NULL)
1495 return;
1496
1497 PUTS(fd, "Memory block allocated at (most recent call first):\n");
1498 for (i=0; i < traceback->nframe; i++) {
1499 _PyMem_DumpFrame(fd, &traceback->frames[i]);
1500 }
1501 PUTS(fd, "\n");
1502}
1503
1504#undef PUTS
1505
Victor Stinnere492ae52016-03-22 12:58:23 +01001506
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001507
Serhiy Storchakab451f912017-02-04 12:18:38 +02001508/*[clinic input]
1509_tracemalloc.start
1510
Victor Stinnera7368ac2017-11-15 18:11:45 -08001511 nframe: int = 1
Serhiy Storchakab451f912017-02-04 12:18:38 +02001512 /
1513
1514Start tracing Python memory allocations.
1515
1516Also set the maximum number of frames stored in the traceback of a
1517trace to nframe.
1518[clinic start generated code]*/
1519
1520static PyObject *
Victor Stinnera7368ac2017-11-15 18:11:45 -08001521_tracemalloc_start_impl(PyObject *module, int nframe)
1522/*[clinic end generated code: output=caae05c23c159d3c input=40d849b5b29d1933]*/
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001523{
Victor Stinnera7368ac2017-11-15 18:11:45 -08001524 if (tracemalloc_start(nframe) < 0) {
Victor Stinner3728d6c2013-11-23 12:37:20 +01001525 return NULL;
1526 }
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001527 Py_RETURN_NONE;
1528}
1529
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001530
Serhiy Storchakab451f912017-02-04 12:18:38 +02001531/*[clinic input]
1532_tracemalloc.stop
Victor Stinnere492ae52016-03-22 12:58:23 +01001533
Serhiy Storchakab451f912017-02-04 12:18:38 +02001534Stop tracing Python memory allocations.
1535
1536Also clear traces of memory blocks allocated by Python.
1537[clinic start generated code]*/
1538
1539static PyObject *
1540_tracemalloc_stop_impl(PyObject *module)
1541/*[clinic end generated code: output=c3c42ae03e3955cd input=7478f075e51dae18]*/
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001542{
1543 tracemalloc_stop();
1544 Py_RETURN_NONE;
1545}
1546
Victor Stinnere492ae52016-03-22 12:58:23 +01001547
Serhiy Storchakab451f912017-02-04 12:18:38 +02001548/*[clinic input]
1549_tracemalloc.get_traceback_limit
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001550
Serhiy Storchakab451f912017-02-04 12:18:38 +02001551Get the maximum number of frames stored in the traceback of a trace.
1552
1553By default, a trace of an allocated memory block only stores
1554the most recent frame: the limit is 1.
1555[clinic start generated code]*/
1556
1557static PyObject *
1558_tracemalloc_get_traceback_limit_impl(PyObject *module)
1559/*[clinic end generated code: output=d556d9306ba95567 input=da3cd977fc68ae3b]*/
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001560{
1561 return PyLong_FromLong(tracemalloc_config.max_nframe);
1562}
1563
Victor Stinnere492ae52016-03-22 12:58:23 +01001564
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001565
Serhiy Storchakab451f912017-02-04 12:18:38 +02001566/*[clinic input]
1567_tracemalloc.get_tracemalloc_memory
1568
1569Get the memory usage in bytes of the tracemalloc module.
1570
1571This memory is used internally to trace memory allocations.
1572[clinic start generated code]*/
1573
1574static PyObject *
1575_tracemalloc_get_tracemalloc_memory_impl(PyObject *module)
1576/*[clinic end generated code: output=e3f14e280a55f5aa input=5d919c0f4d5132ad]*/
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001577{
1578 size_t size;
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001579
1580 size = _Py_hashtable_size(tracemalloc_tracebacks);
1581 size += _Py_hashtable_size(tracemalloc_filenames);
1582
1583 TABLES_LOCK();
1584 size += _Py_hashtable_size(tracemalloc_traces);
1585 TABLES_UNLOCK();
1586
Serhiy Storchakab451f912017-02-04 12:18:38 +02001587 return PyLong_FromSize_t(size);
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001588}
1589
Victor Stinnere492ae52016-03-22 12:58:23 +01001590
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001591
Serhiy Storchakab451f912017-02-04 12:18:38 +02001592/*[clinic input]
1593_tracemalloc.get_traced_memory
1594
1595Get the current size and peak size of memory blocks traced by tracemalloc.
1596
1597Returns a tuple: (current: int, peak: int).
1598[clinic start generated code]*/
1599
1600static PyObject *
1601_tracemalloc_get_traced_memory_impl(PyObject *module)
1602/*[clinic end generated code: output=5b167189adb9e782 input=61ddb5478400ff66]*/
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001603{
Victor Stinner3c0481d2013-11-27 21:39:49 +01001604 Py_ssize_t size, peak_size;
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001605
1606 if (!tracemalloc_config.tracing)
1607 return Py_BuildValue("ii", 0, 0);
1608
1609 TABLES_LOCK();
1610 size = tracemalloc_traced_memory;
Victor Stinner3c0481d2013-11-27 21:39:49 +01001611 peak_size = tracemalloc_peak_traced_memory;
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001612 TABLES_UNLOCK();
1613
Serhiy Storchakab451f912017-02-04 12:18:38 +02001614 return Py_BuildValue("nn", size, peak_size);
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001615}
1616
Victor Stinnere492ae52016-03-22 12:58:23 +01001617
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001618static PyMethodDef module_methods[] = {
Serhiy Storchakab451f912017-02-04 12:18:38 +02001619 _TRACEMALLOC_IS_TRACING_METHODDEF
1620 _TRACEMALLOC_CLEAR_TRACES_METHODDEF
1621 _TRACEMALLOC__GET_TRACES_METHODDEF
1622 _TRACEMALLOC__GET_OBJECT_TRACEBACK_METHODDEF
1623 _TRACEMALLOC_START_METHODDEF
1624 _TRACEMALLOC_STOP_METHODDEF
1625 _TRACEMALLOC_GET_TRACEBACK_LIMIT_METHODDEF
1626 _TRACEMALLOC_GET_TRACEMALLOC_MEMORY_METHODDEF
1627 _TRACEMALLOC_GET_TRACED_MEMORY_METHODDEF
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001628 /* sentinel */
1629 {NULL, NULL}
1630};
1631
1632PyDoc_STRVAR(module_doc,
1633"Debug module to trace memory blocks allocated by Python.");
1634
1635static struct PyModuleDef module_def = {
1636 PyModuleDef_HEAD_INIT,
1637 "_tracemalloc",
1638 module_doc,
1639 0, /* non-negative size to be able to unload the module */
1640 module_methods,
1641 NULL,
1642};
1643
1644PyMODINIT_FUNC
1645PyInit__tracemalloc(void)
1646{
1647 PyObject *m;
1648 m = PyModule_Create(&module_def);
1649 if (m == NULL)
1650 return NULL;
1651
1652 if (tracemalloc_init() < 0)
1653 return NULL;
1654
1655 return m;
1656}
1657
Victor Stinnere492ae52016-03-22 12:58:23 +01001658
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001659int
Victor Stinnera7368ac2017-11-15 18:11:45 -08001660_PyTraceMalloc_Init(int nframe)
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001661{
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001662 assert(PyGILState_Check());
Victor Stinnera7368ac2017-11-15 18:11:45 -08001663 if (nframe == 0) {
1664 return 0;
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001665 }
Victor Stinnerf28ce602013-11-27 22:27:13 +01001666 return tracemalloc_start(nframe);
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001667}
1668
Victor Stinnere492ae52016-03-22 12:58:23 +01001669
Victor Stinnerbe0708f2013-12-01 10:03:26 +01001670void
1671_PyTraceMalloc_Fini(void)
1672{
Victor Stinnerbe0708f2013-12-01 10:03:26 +01001673 assert(PyGILState_Check());
Victor Stinnerbe0708f2013-12-01 10:03:26 +01001674 tracemalloc_deinit();
1675}
Victor Stinner10b73e12016-03-22 13:39:05 +01001676
1677int
Victor Stinner5ea4c062017-06-20 17:46:36 +02001678PyTraceMalloc_Track(unsigned int domain, uintptr_t ptr,
1679 size_t size)
Victor Stinner10b73e12016-03-22 13:39:05 +01001680{
1681 int res;
Victor Stinner10b73e12016-03-22 13:39:05 +01001682 PyGILState_STATE gil_state;
Victor Stinner10b73e12016-03-22 13:39:05 +01001683
1684 if (!tracemalloc_config.tracing) {
1685 /* tracemalloc is not tracing: do nothing */
1686 return -2;
1687 }
1688
Victor Stinner10b73e12016-03-22 13:39:05 +01001689 gil_state = PyGILState_Ensure();
Victor Stinner10b73e12016-03-22 13:39:05 +01001690
1691 TABLES_LOCK();
1692 res = tracemalloc_add_trace(domain, ptr, size);
1693 TABLES_UNLOCK();
1694
Victor Stinner10b73e12016-03-22 13:39:05 +01001695 PyGILState_Release(gil_state);
Victor Stinner10b73e12016-03-22 13:39:05 +01001696 return res;
1697}
1698
1699
1700int
Victor Stinner5ea4c062017-06-20 17:46:36 +02001701PyTraceMalloc_Untrack(unsigned int domain, uintptr_t ptr)
Victor Stinner10b73e12016-03-22 13:39:05 +01001702{
1703 if (!tracemalloc_config.tracing) {
1704 /* tracemalloc is not tracing: do nothing */
1705 return -2;
1706 }
1707
1708 TABLES_LOCK();
1709 tracemalloc_remove_trace(domain, ptr);
1710 TABLES_UNLOCK();
1711
1712 return 0;
1713}
1714
1715
1716PyObject*
Victor Stinner5ea4c062017-06-20 17:46:36 +02001717_PyTraceMalloc_GetTraceback(unsigned int domain, uintptr_t ptr)
Victor Stinner10b73e12016-03-22 13:39:05 +01001718{
1719 traceback_t *traceback;
1720
1721 traceback = tracemalloc_get_traceback(domain, ptr);
1722 if (traceback == NULL)
1723 Py_RETURN_NONE;
1724
1725 return traceback_to_pyobject(traceback, NULL);
1726}