blob: ec8bd960a7f7e02d9cf12cea11705bab212b3136 [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
7/* Trace memory blocks allocated by PyMem_RawMalloc() */
8#define TRACE_RAW_MALLOC
9
10/* Forward declaration */
11static void tracemalloc_stop(void);
Victor Stinnered3b0bc2013-11-23 12:27:24 +010012static void* raw_malloc(size_t size);
13static void raw_free(void *ptr);
14
15#ifdef Py_DEBUG
16# define TRACE_DEBUG
17#endif
18
Victor Stinnered3b0bc2013-11-23 12:27:24 +010019/* Protected by the GIL */
20static struct {
Victor Stinnerd8f0d922014-06-02 21:57:10 +020021 PyMemAllocatorEx mem;
22 PyMemAllocatorEx raw;
23 PyMemAllocatorEx obj;
Victor Stinnered3b0bc2013-11-23 12:27:24 +010024} allocators;
25
Victor Stinnered3b0bc2013-11-23 12:27:24 +010026static struct {
27 /* Module initialized?
28 Variable protected by the GIL */
29 enum {
30 TRACEMALLOC_NOT_INITIALIZED,
31 TRACEMALLOC_INITIALIZED,
32 TRACEMALLOC_FINALIZED
33 } initialized;
34
Victor Stinnered3b0bc2013-11-23 12:27:24 +010035 /* Is tracemalloc tracing memory allocations?
36 Variable protected by the GIL */
37 int tracing;
38
39 /* limit of the number of frames in a traceback, 1 by default.
40 Variable protected by the GIL. */
41 int max_nframe;
Victor Stinnere492ae52016-03-22 12:58:23 +010042
43 /* use domain in trace key?
44 Variable protected by the GIL. */
45 int use_domain;
Victor Stinner5e14a382016-03-23 22:03:55 +010046} tracemalloc_config = {TRACEMALLOC_NOT_INITIALIZED, 0, 1, 0};
Victor Stinnered3b0bc2013-11-23 12:27:24 +010047
48#if defined(TRACE_RAW_MALLOC) && defined(WITH_THREAD)
49/* This lock is needed because tracemalloc_free() is called without
50 the GIL held from PyMem_RawFree(). It cannot acquire the lock because it
51 would introduce a deadlock in PyThreadState_DeleteCurrent(). */
52static PyThread_type_lock tables_lock;
53# define TABLES_LOCK() PyThread_acquire_lock(tables_lock, 1)
54# define TABLES_UNLOCK() PyThread_release_lock(tables_lock)
55#else
56 /* variables are protected by the GIL */
57# define TABLES_LOCK()
58# define TABLES_UNLOCK()
59#endif
60
Victor Stinnere492ae52016-03-22 12:58:23 +010061
62#define DEFAULT_DOMAIN 0
63
Victor Stinnere492ae52016-03-22 12:58:23 +010064/* Pack the frame_t structure to reduce the memory footprint. */
65typedef struct
66#ifdef __GNUC__
67__attribute__((packed))
68#endif
69{
Benjamin Petersonca470632016-09-06 13:47:26 -070070 uintptr_t ptr;
Victor Stinner10b73e12016-03-22 13:39:05 +010071 _PyTraceMalloc_domain_t domain;
Victor Stinnere492ae52016-03-22 12:58:23 +010072} pointer_t;
73
Victor Stinnered3b0bc2013-11-23 12:27:24 +010074/* Pack the frame_t structure to reduce the memory footprint on 64-bit
Victor Stinnere492ae52016-03-22 12:58:23 +010075 architectures: 12 bytes instead of 16. */
Victor Stinnered3b0bc2013-11-23 12:27:24 +010076typedef struct
77#ifdef __GNUC__
78__attribute__((packed))
Victor Stinnerdd382ef2014-02-01 03:43:58 +010079#elif defined(_MSC_VER)
80_declspec(align(4))
Victor Stinnered3b0bc2013-11-23 12:27:24 +010081#endif
82{
Victor Stinner7105e9f2016-03-15 14:28:04 +010083 /* filename cannot be NULL: "<unknown>" is used if the Python frame
84 filename is NULL */
Victor Stinnered3b0bc2013-11-23 12:27:24 +010085 PyObject *filename;
Victor Stinner95283342016-03-15 21:57:02 +010086 unsigned int lineno;
Victor Stinnered3b0bc2013-11-23 12:27:24 +010087} frame_t;
88
Victor Stinnere492ae52016-03-22 12:58:23 +010089
Victor Stinnered3b0bc2013-11-23 12:27:24 +010090typedef struct {
91 Py_uhash_t hash;
92 int nframe;
93 frame_t frames[1];
94} traceback_t;
95
96#define TRACEBACK_SIZE(NFRAME) \
97 (sizeof(traceback_t) + sizeof(frame_t) * (NFRAME - 1))
Victor Stinnerf28ce602013-11-27 22:27:13 +010098
99#define MAX_NFRAME \
Victor Stinner52aee852014-08-16 15:44:02 +0200100 ((INT_MAX - (int)sizeof(traceback_t)) / (int)sizeof(frame_t) + 1)
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100101
Victor Stinnere492ae52016-03-22 12:58:23 +0100102
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100103static PyObject *unknown_filename = NULL;
104static traceback_t tracemalloc_empty_traceback;
105
Victor Stinner7a5be142013-11-26 01:06:02 +0100106/* Trace of a memory block */
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100107typedef struct {
Victor Stinner7a5be142013-11-26 01:06:02 +0100108 /* Size of the memory block in bytes */
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100109 size_t size;
Victor Stinner7a5be142013-11-26 01:06:02 +0100110
111 /* Traceback where the memory block was allocated */
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100112 traceback_t *traceback;
113} trace_t;
114
Victor Stinnere492ae52016-03-22 12:58:23 +0100115
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100116/* Size in bytes of currently traced memory.
117 Protected by TABLES_LOCK(). */
118static size_t tracemalloc_traced_memory = 0;
119
Victor Stinner3c0481d2013-11-27 21:39:49 +0100120/* Peak size in bytes of traced memory.
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100121 Protected by TABLES_LOCK(). */
Victor Stinner3c0481d2013-11-27 21:39:49 +0100122static size_t tracemalloc_peak_traced_memory = 0;
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100123
Serhiy Storchaka56a6d852014-12-01 18:28:43 +0200124/* Hash table used as a set to intern filenames:
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100125 PyObject* => PyObject*.
126 Protected by the GIL */
127static _Py_hashtable_t *tracemalloc_filenames = NULL;
128
Victor Stinnerf28ce602013-11-27 22:27:13 +0100129/* Buffer to store a new traceback in traceback_new().
130 Protected by the GIL. */
131static traceback_t *tracemalloc_traceback = NULL;
132
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100133/* Hash table used as a set to intern tracebacks:
134 traceback_t* => traceback_t*
135 Protected by the GIL */
136static _Py_hashtable_t *tracemalloc_tracebacks = NULL;
137
138/* pointer (void*) => trace (trace_t).
139 Protected by TABLES_LOCK(). */
140static _Py_hashtable_t *tracemalloc_traces = NULL;
141
Victor Stinnere492ae52016-03-22 12:58:23 +0100142
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100143#ifdef TRACE_DEBUG
144static void
145tracemalloc_error(const char *format, ...)
146{
147 va_list ap;
148 fprintf(stderr, "tracemalloc: ");
149 va_start(ap, format);
150 vfprintf(stderr, format, ap);
151 va_end(ap);
152 fprintf(stderr, "\n");
153 fflush(stderr);
154}
155#endif
156
Victor Stinnere492ae52016-03-22 12:58:23 +0100157
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100158#if defined(WITH_THREAD) && defined(TRACE_RAW_MALLOC)
159#define REENTRANT_THREADLOCAL
160
161/* If your OS does not provide native thread local storage, you can implement
162 it manually using a lock. Functions of thread.c cannot be used because
163 they use PyMem_RawMalloc() which leads to a reentrant call. */
164#if !(defined(_POSIX_THREADS) || defined(NT_THREADS))
165# error "need native thread local storage (TLS)"
166#endif
167
Victor Stinner4a066472016-03-22 17:45:09 +0100168static int tracemalloc_reentrant_key = -1;
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100169
170/* Any non-NULL pointer can be used */
171#define REENTRANT Py_True
172
173static int
174get_reentrant(void)
175{
Victor Stinner4a066472016-03-22 17:45:09 +0100176 void *ptr;
177
178 assert(tracemalloc_reentrant_key != -1);
179 ptr = PyThread_get_key_value(tracemalloc_reentrant_key);
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100180 if (ptr != NULL) {
181 assert(ptr == REENTRANT);
182 return 1;
183 }
184 else
185 return 0;
186}
187
188static void
189set_reentrant(int reentrant)
190{
Victor Stinner2ead3d22013-11-26 01:08:53 +0100191 assert(reentrant == 0 || reentrant == 1);
Victor Stinner4a066472016-03-22 17:45:09 +0100192 assert(tracemalloc_reentrant_key != -1);
193
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100194 if (reentrant) {
Victor Stinner0cfc0582016-03-22 17:40:07 +0100195 assert(!get_reentrant());
Victor Stinner590cebe2013-12-13 11:08:56 +0100196 PyThread_set_key_value(tracemalloc_reentrant_key, REENTRANT);
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100197 }
198 else {
Victor Stinner0cfc0582016-03-22 17:40:07 +0100199 assert(get_reentrant());
Victor Stinner590cebe2013-12-13 11:08:56 +0100200 PyThread_set_key_value(tracemalloc_reentrant_key, NULL);
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100201 }
202}
203
204#else
205
206/* WITH_THREAD not defined: Python compiled without threads,
207 or TRACE_RAW_MALLOC not defined: variable protected by the GIL */
208static int tracemalloc_reentrant = 0;
209
210static int
211get_reentrant(void)
212{
213 return tracemalloc_reentrant;
214}
215
216static void
217set_reentrant(int reentrant)
218{
Victor Stinnerd5871e62016-03-23 00:17:04 +0100219 assert(reentrant != tracemalloc_reentrant);
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100220 tracemalloc_reentrant = reentrant;
221}
222#endif
223
Victor Stinnere492ae52016-03-22 12:58:23 +0100224
Victor Stinner285cf0a2016-03-21 22:00:58 +0100225static Py_uhash_t
Victor Stinner5dacbd42016-03-23 09:52:13 +0100226hashtable_hash_pyobject(_Py_hashtable_t *ht, const void *pkey)
Victor Stinner51b846c2016-03-18 21:52:22 +0100227{
Victor Stinner285cf0a2016-03-21 22:00:58 +0100228 PyObject *obj;
229
Victor Stinner5dacbd42016-03-23 09:52:13 +0100230 _Py_HASHTABLE_READ_KEY(ht, pkey, obj);
Victor Stinner285cf0a2016-03-21 22:00:58 +0100231 return PyObject_Hash(obj);
232}
233
Victor Stinnere492ae52016-03-22 12:58:23 +0100234
Victor Stinner285cf0a2016-03-21 22:00:58 +0100235static int
Victor Stinner5dacbd42016-03-23 09:52:13 +0100236hashtable_compare_unicode(_Py_hashtable_t *ht, const void *pkey,
Victor Stinner285cf0a2016-03-21 22:00:58 +0100237 const _Py_hashtable_entry_t *entry)
238{
Victor Stinnere492ae52016-03-22 12:58:23 +0100239 PyObject *key1, *key2;
Victor Stinner285cf0a2016-03-21 22:00:58 +0100240
Victor Stinner5dacbd42016-03-23 09:52:13 +0100241 _Py_HASHTABLE_READ_KEY(ht, pkey, key1);
242 _Py_HASHTABLE_ENTRY_READ_KEY(ht, entry, key2);
Victor Stinner285cf0a2016-03-21 22:00:58 +0100243
Victor Stinnere492ae52016-03-22 12:58:23 +0100244 if (key1 != NULL && key2 != NULL)
245 return (PyUnicode_Compare(key1, key2) == 0);
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100246 else
Victor Stinnere492ae52016-03-22 12:58:23 +0100247 return key1 == key2;
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100248}
249
Victor Stinnere492ae52016-03-22 12:58:23 +0100250
251static Py_uhash_t
Victor Stinner5dacbd42016-03-23 09:52:13 +0100252hashtable_hash_pointer_t(_Py_hashtable_t *ht, const void *pkey)
Victor Stinnere492ae52016-03-22 12:58:23 +0100253{
254 pointer_t ptr;
255 Py_uhash_t hash;
256
Victor Stinner5dacbd42016-03-23 09:52:13 +0100257 _Py_HASHTABLE_READ_KEY(ht, pkey, ptr);
Victor Stinnere492ae52016-03-22 12:58:23 +0100258
259 hash = (Py_uhash_t)_Py_HashPointer((void*)ptr.ptr);
260 hash ^= ptr.domain;
261 return hash;
262}
263
264
doko@ubuntu.combc731502016-05-18 01:06:01 +0200265static int
Victor Stinner5dacbd42016-03-23 09:52:13 +0100266hashtable_compare_pointer_t(_Py_hashtable_t *ht, const void *pkey,
Victor Stinnere492ae52016-03-22 12:58:23 +0100267 const _Py_hashtable_entry_t *entry)
268{
269 pointer_t ptr1, ptr2;
270
Victor Stinner5dacbd42016-03-23 09:52:13 +0100271 _Py_HASHTABLE_READ_KEY(ht, pkey, ptr1);
272 _Py_HASHTABLE_ENTRY_READ_KEY(ht, entry, ptr2);
Victor Stinnere492ae52016-03-22 12:58:23 +0100273
274 /* compare pointer before domain, because pointer is more likely to be
275 different */
276 return (ptr1.ptr == ptr2.ptr && ptr1.domain == ptr2.domain);
277
278}
279
280
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100281static _Py_hashtable_t *
Victor Stinner285cf0a2016-03-21 22:00:58 +0100282hashtable_new(size_t key_size, size_t data_size,
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100283 _Py_hashtable_hash_func hash_func,
284 _Py_hashtable_compare_func compare_func)
285{
Victor Stinnerc9553872016-03-22 12:13:01 +0100286 _Py_hashtable_allocator_t hashtable_alloc = {malloc, free};
Victor Stinner285cf0a2016-03-21 22:00:58 +0100287 return _Py_hashtable_new_full(key_size, data_size, 0,
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100288 hash_func, compare_func,
Victor Stinnerc9553872016-03-22 12:13:01 +0100289 &hashtable_alloc);
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100290}
291
Victor Stinnere492ae52016-03-22 12:58:23 +0100292
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100293static void*
294raw_malloc(size_t size)
295{
296 return allocators.raw.malloc(allocators.raw.ctx, size);
297}
298
299static void
300raw_free(void *ptr)
301{
302 allocators.raw.free(allocators.raw.ctx, ptr);
303}
304
Victor Stinnere492ae52016-03-22 12:58:23 +0100305
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100306static Py_uhash_t
Victor Stinner5dacbd42016-03-23 09:52:13 +0100307hashtable_hash_traceback(_Py_hashtable_t *ht, const void *pkey)
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100308{
Victor Stinnerb32a7ed2016-03-21 23:05:08 +0100309 traceback_t *traceback;
Victor Stinner285cf0a2016-03-21 22:00:58 +0100310
Victor Stinner5dacbd42016-03-23 09:52:13 +0100311 _Py_HASHTABLE_READ_KEY(ht, pkey, traceback);
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100312 return traceback->hash;
313}
314
Victor Stinnere492ae52016-03-22 12:58:23 +0100315
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100316static int
Victor Stinner5dacbd42016-03-23 09:52:13 +0100317hashtable_compare_traceback(_Py_hashtable_t *ht, const void *pkey,
318 const _Py_hashtable_entry_t *entry)
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100319{
Victor Stinner285cf0a2016-03-21 22:00:58 +0100320 traceback_t *traceback1, *traceback2;
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100321 const frame_t *frame1, *frame2;
322 int i;
323
Victor Stinner5dacbd42016-03-23 09:52:13 +0100324 _Py_HASHTABLE_READ_KEY(ht, pkey, traceback1);
325 _Py_HASHTABLE_ENTRY_READ_KEY(ht, entry, traceback2);
Victor Stinner285cf0a2016-03-21 22:00:58 +0100326
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100327 if (traceback1->nframe != traceback2->nframe)
328 return 0;
329
330 for (i=0; i < traceback1->nframe; i++) {
331 frame1 = &traceback1->frames[i];
332 frame2 = &traceback2->frames[i];
333
334 if (frame1->lineno != frame2->lineno)
335 return 0;
336
337 if (frame1->filename != frame2->filename) {
338 assert(PyUnicode_Compare(frame1->filename, frame2->filename) != 0);
339 return 0;
340 }
341 }
342 return 1;
343}
344
Victor Stinnere492ae52016-03-22 12:58:23 +0100345
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100346static void
347tracemalloc_get_frame(PyFrameObject *pyframe, frame_t *frame)
348{
349 PyCodeObject *code;
350 PyObject *filename;
351 _Py_hashtable_entry_t *entry;
Victor Stinner95283342016-03-15 21:57:02 +0100352 int lineno;
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100353
354 frame->filename = unknown_filename;
Victor Stinner95283342016-03-15 21:57:02 +0100355 lineno = PyFrame_GetLineNumber(pyframe);
356 if (lineno < 0)
357 lineno = 0;
358 frame->lineno = (unsigned int)lineno;
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100359
360 code = pyframe->f_code;
361 if (code == NULL) {
362#ifdef TRACE_DEBUG
Victor Stinner4dc74202013-11-26 01:18:52 +0100363 tracemalloc_error("failed to get the code object of the frame");
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100364#endif
365 return;
366 }
367
368 if (code->co_filename == NULL) {
369#ifdef TRACE_DEBUG
370 tracemalloc_error("failed to get the filename of the code object");
371#endif
372 return;
373 }
374
375 filename = code->co_filename;
376 assert(filename != NULL);
377 if (filename == NULL)
378 return;
379
380 if (!PyUnicode_Check(filename)) {
381#ifdef TRACE_DEBUG
Martin Panter6245cb32016-04-15 02:14:19 +0000382 tracemalloc_error("filename is not a unicode string");
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100383#endif
384 return;
385 }
386 if (!PyUnicode_IS_READY(filename)) {
387 /* Don't make a Unicode string ready to avoid reentrant calls
388 to tracemalloc_malloc() or tracemalloc_realloc() */
389#ifdef TRACE_DEBUG
390 tracemalloc_error("filename is not a ready unicode string");
391#endif
392 return;
393 }
394
395 /* intern the filename */
Victor Stinner285cf0a2016-03-21 22:00:58 +0100396 entry = _Py_HASHTABLE_GET_ENTRY(tracemalloc_filenames, filename);
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100397 if (entry != NULL) {
Victor Stinner5dacbd42016-03-23 09:52:13 +0100398 _Py_HASHTABLE_ENTRY_READ_KEY(tracemalloc_filenames, entry, filename);
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100399 }
400 else {
401 /* tracemalloc_filenames is responsible to keep a reference
402 to the filename */
403 Py_INCREF(filename);
Victor Stinner285cf0a2016-03-21 22:00:58 +0100404 if (_Py_HASHTABLE_SET_NODATA(tracemalloc_filenames, filename) < 0) {
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100405 Py_DECREF(filename);
406#ifdef TRACE_DEBUG
407 tracemalloc_error("failed to intern the filename");
408#endif
409 return;
410 }
411 }
412
413 /* the tracemalloc_filenames table keeps a reference to the filename */
414 frame->filename = filename;
415}
416
Victor Stinnere492ae52016-03-22 12:58:23 +0100417
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100418static Py_uhash_t
419traceback_hash(traceback_t *traceback)
420{
421 /* code based on tuplehash() of Objects/tupleobject.c */
Victor Stinner4d8c29c2013-12-16 23:05:13 +0100422 Py_uhash_t x, y; /* Unsigned for defined overflow behavior. */
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100423 int len = traceback->nframe;
424 Py_uhash_t mult = _PyHASH_MULTIPLIER;
425 frame_t *frame;
426
427 x = 0x345678UL;
428 frame = traceback->frames;
429 while (--len >= 0) {
Victor Stinner4d8c29c2013-12-16 23:05:13 +0100430 y = (Py_uhash_t)PyObject_Hash(frame->filename);
431 y ^= (Py_uhash_t)frame->lineno;
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100432 frame++;
433
434 x = (x ^ y) * mult;
435 /* the cast might truncate len; that doesn't change hash stability */
Victor Stinner4d8c29c2013-12-16 23:05:13 +0100436 mult += (Py_uhash_t)(82520UL + len + len);
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100437 }
438 x += 97531UL;
439 return x;
440}
441
Victor Stinnere492ae52016-03-22 12:58:23 +0100442
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100443static void
444traceback_get_frames(traceback_t *traceback)
445{
446 PyThreadState *tstate;
447 PyFrameObject *pyframe;
448
449#ifdef WITH_THREAD
450 tstate = PyGILState_GetThisThreadState();
451#else
452 tstate = PyThreadState_Get();
453#endif
454 if (tstate == NULL) {
455#ifdef TRACE_DEBUG
456 tracemalloc_error("failed to get the current thread state");
457#endif
458 return;
459 }
460
461 for (pyframe = tstate->frame; pyframe != NULL; pyframe = pyframe->f_back) {
462 tracemalloc_get_frame(pyframe, &traceback->frames[traceback->nframe]);
463 assert(traceback->frames[traceback->nframe].filename != NULL);
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100464 traceback->nframe++;
465 if (traceback->nframe == tracemalloc_config.max_nframe)
466 break;
467 }
468}
469
Victor Stinnere492ae52016-03-22 12:58:23 +0100470
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100471static traceback_t *
472traceback_new(void)
473{
Victor Stinnerf28ce602013-11-27 22:27:13 +0100474 traceback_t *traceback;
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100475 _Py_hashtable_entry_t *entry;
476
477#ifdef WITH_THREAD
478 assert(PyGILState_Check());
479#endif
480
481 /* get frames */
Victor Stinnerf28ce602013-11-27 22:27:13 +0100482 traceback = tracemalloc_traceback;
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100483 traceback->nframe = 0;
484 traceback_get_frames(traceback);
485 if (traceback->nframe == 0)
486 return &tracemalloc_empty_traceback;
487 traceback->hash = traceback_hash(traceback);
488
489 /* intern the traceback */
Victor Stinner285cf0a2016-03-21 22:00:58 +0100490 entry = _Py_HASHTABLE_GET_ENTRY(tracemalloc_tracebacks, traceback);
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100491 if (entry != NULL) {
Victor Stinner5dacbd42016-03-23 09:52:13 +0100492 _Py_HASHTABLE_ENTRY_READ_KEY(tracemalloc_tracebacks, entry, traceback);
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100493 }
494 else {
495 traceback_t *copy;
496 size_t traceback_size;
497
498 traceback_size = TRACEBACK_SIZE(traceback->nframe);
499
500 copy = raw_malloc(traceback_size);
501 if (copy == NULL) {
502#ifdef TRACE_DEBUG
503 tracemalloc_error("failed to intern the traceback: malloc failed");
504#endif
505 return NULL;
506 }
507 memcpy(copy, traceback, traceback_size);
508
Victor Stinner285cf0a2016-03-21 22:00:58 +0100509 if (_Py_HASHTABLE_SET_NODATA(tracemalloc_tracebacks, copy) < 0) {
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100510 raw_free(copy);
511#ifdef TRACE_DEBUG
512 tracemalloc_error("failed to intern the traceback: putdata failed");
513#endif
514 return NULL;
515 }
516 traceback = copy;
517 }
518 return traceback;
519}
520
Victor Stinnere492ae52016-03-22 12:58:23 +0100521
Victor Stinner5e14a382016-03-23 22:03:55 +0100522static int
523tracemalloc_use_domain_cb(_Py_hashtable_t *old_traces,
524 _Py_hashtable_entry_t *entry, void *user_data)
525{
Benjamin Petersonca470632016-09-06 13:47:26 -0700526 uintptr_t ptr;
Victor Stinner5e14a382016-03-23 22:03:55 +0100527 pointer_t key;
528 _Py_hashtable_t *new_traces = (_Py_hashtable_t *)user_data;
529 const void *pdata = _Py_HASHTABLE_ENTRY_PDATA(old_traces, entry);
530
531 _Py_HASHTABLE_ENTRY_READ_KEY(old_traces, entry, ptr);
532 key.ptr = ptr;
533 key.domain = DEFAULT_DOMAIN;
534
535 return _Py_hashtable_set(new_traces,
536 sizeof(key), &key,
537 old_traces->data_size, pdata);
538}
539
540
Benjamin Petersonca470632016-09-06 13:47:26 -0700541/* Convert tracemalloc_traces from compact key (uintptr_t) to pointer_t key.
Victor Stinner5e14a382016-03-23 22:03:55 +0100542 * Return 0 on success, -1 on error. */
543static int
544tracemalloc_use_domain(void)
545{
546 _Py_hashtable_t *new_traces = NULL;
547
548 assert(!tracemalloc_config.use_domain);
549
550 new_traces = hashtable_new(sizeof(pointer_t),
551 sizeof(trace_t),
552 hashtable_hash_pointer_t,
553 hashtable_compare_pointer_t);
554 if (new_traces == NULL) {
555 return -1;
556 }
557
558 if (_Py_hashtable_foreach(tracemalloc_traces, tracemalloc_use_domain_cb,
559 new_traces) < 0)
560 {
561 _Py_hashtable_destroy(new_traces);
562 return -1;
563 }
564
565 _Py_hashtable_destroy(tracemalloc_traces);
566 tracemalloc_traces = new_traces;
567
568 tracemalloc_config.use_domain = 1;
569
570 return 0;
571}
572
573
Victor Stinnere492ae52016-03-22 12:58:23 +0100574static void
Benjamin Petersonca470632016-09-06 13:47:26 -0700575tracemalloc_remove_trace(_PyTraceMalloc_domain_t domain, uintptr_t ptr)
Victor Stinnere492ae52016-03-22 12:58:23 +0100576{
577 trace_t trace;
578 int removed;
579
Victor Stinner10b73e12016-03-22 13:39:05 +0100580 assert(tracemalloc_config.tracing);
581
Victor Stinnere492ae52016-03-22 12:58:23 +0100582 if (tracemalloc_config.use_domain) {
583 pointer_t key = {ptr, domain};
584 removed = _Py_HASHTABLE_POP(tracemalloc_traces, key, trace);
585 }
586 else {
587 removed = _Py_HASHTABLE_POP(tracemalloc_traces, ptr, trace);
588 }
589 if (!removed) {
590 return;
591 }
592
593 assert(tracemalloc_traced_memory >= trace.size);
594 tracemalloc_traced_memory -= trace.size;
595}
596
597#define REMOVE_TRACE(ptr) \
Benjamin Petersonca470632016-09-06 13:47:26 -0700598 tracemalloc_remove_trace(DEFAULT_DOMAIN, (uintptr_t)(ptr))
Victor Stinnere492ae52016-03-22 12:58:23 +0100599
600
Victor Stinner52968672013-11-24 11:37:15 +0100601static int
Benjamin Petersonca470632016-09-06 13:47:26 -0700602tracemalloc_add_trace(_PyTraceMalloc_domain_t domain, uintptr_t ptr,
Victor Stinner10b73e12016-03-22 13:39:05 +0100603 size_t size)
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100604{
Victor Stinnerca79ccd2016-03-23 09:38:54 +0100605 pointer_t key = {ptr, domain};
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100606 traceback_t *traceback;
607 trace_t trace;
Victor Stinnerca79ccd2016-03-23 09:38:54 +0100608 _Py_hashtable_entry_t* entry;
Victor Stinner52968672013-11-24 11:37:15 +0100609 int res;
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100610
Victor Stinner10b73e12016-03-22 13:39:05 +0100611 assert(tracemalloc_config.tracing);
612
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100613 traceback = traceback_new();
Victor Stinnere492ae52016-03-22 12:58:23 +0100614 if (traceback == NULL) {
Victor Stinner52968672013-11-24 11:37:15 +0100615 return -1;
Victor Stinnere492ae52016-03-22 12:58:23 +0100616 }
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100617
Victor Stinner5e14a382016-03-23 22:03:55 +0100618 if (!tracemalloc_config.use_domain && domain != DEFAULT_DOMAIN) {
619 /* first trace using a non-zero domain whereas traces use compact
Benjamin Petersonca470632016-09-06 13:47:26 -0700620 (uintptr_t) keys: switch to pointer_t keys. */
Victor Stinner5e14a382016-03-23 22:03:55 +0100621 if (tracemalloc_use_domain() < 0) {
622 return -1;
623 }
624 }
625
Victor Stinnere492ae52016-03-22 12:58:23 +0100626 if (tracemalloc_config.use_domain) {
Victor Stinnerca79ccd2016-03-23 09:38:54 +0100627 entry = _Py_HASHTABLE_GET_ENTRY(tracemalloc_traces, key);
Victor Stinnere492ae52016-03-22 12:58:23 +0100628 }
629 else {
Victor Stinnerca79ccd2016-03-23 09:38:54 +0100630 entry = _Py_HASHTABLE_GET_ENTRY(tracemalloc_traces, ptr);
Victor Stinnerd606ba72013-11-24 11:28:20 +0100631 }
Victor Stinner52968672013-11-24 11:37:15 +0100632
Victor Stinnerca79ccd2016-03-23 09:38:54 +0100633 if (entry != NULL) {
634 /* the memory block is already tracked */
635 _Py_HASHTABLE_ENTRY_READ_DATA(tracemalloc_traces, entry, trace);
636 assert(tracemalloc_traced_memory >= trace.size);
637 tracemalloc_traced_memory -= trace.size;
638
639 trace.size = size;
640 trace.traceback = traceback;
641 _Py_HASHTABLE_ENTRY_WRITE_DATA(tracemalloc_traces, entry, trace);
642 }
643 else {
644 trace.size = size;
645 trace.traceback = traceback;
646
647 if (tracemalloc_config.use_domain) {
648 res = _Py_HASHTABLE_SET(tracemalloc_traces, key, trace);
649 }
650 else {
651 res = _Py_HASHTABLE_SET(tracemalloc_traces, ptr, trace);
652 }
653 if (res != 0) {
654 return res;
655 }
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100656 }
Victor Stinnere492ae52016-03-22 12:58:23 +0100657
Benjamin Peterson2f8bfef2016-09-07 09:26:18 -0700658 assert(tracemalloc_traced_memory <= SIZE_MAX - size);
Victor Stinnere492ae52016-03-22 12:58:23 +0100659 tracemalloc_traced_memory += size;
660 if (tracemalloc_traced_memory > tracemalloc_peak_traced_memory)
661 tracemalloc_peak_traced_memory = tracemalloc_traced_memory;
662 return 0;
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100663}
664
Victor Stinnere492ae52016-03-22 12:58:23 +0100665#define ADD_TRACE(ptr, size) \
Benjamin Petersonca470632016-09-06 13:47:26 -0700666 tracemalloc_add_trace(DEFAULT_DOMAIN, (uintptr_t)(ptr), size)
Victor Stinnere492ae52016-03-22 12:58:23 +0100667
668
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100669static void*
Victor Stinnerdb067af2014-05-02 22:31:14 +0200670tracemalloc_alloc(int use_calloc, void *ctx, size_t nelem, size_t elsize)
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100671{
Victor Stinnerd8f0d922014-06-02 21:57:10 +0200672 PyMemAllocatorEx *alloc = (PyMemAllocatorEx *)ctx;
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100673 void *ptr;
674
Benjamin Peterson2f8bfef2016-09-07 09:26:18 -0700675 assert(elsize == 0 || nelem <= SIZE_MAX / elsize);
Victor Stinnerdb067af2014-05-02 22:31:14 +0200676
677 if (use_calloc)
678 ptr = alloc->calloc(alloc->ctx, nelem, elsize);
679 else
680 ptr = alloc->malloc(alloc->ctx, nelem * elsize);
Victor Stinner15116802013-12-04 01:29:35 +0100681 if (ptr == NULL)
682 return NULL;
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100683
Victor Stinner88c29872013-12-04 01:47:46 +0100684 TABLES_LOCK();
Victor Stinnere492ae52016-03-22 12:58:23 +0100685 if (ADD_TRACE(ptr, nelem * elsize) < 0) {
Victor Stinner15116802013-12-04 01:29:35 +0100686 /* Failed to allocate a trace for the new memory block */
Victor Stinner88c29872013-12-04 01:47:46 +0100687 TABLES_UNLOCK();
Victor Stinner15116802013-12-04 01:29:35 +0100688 alloc->free(alloc->ctx, ptr);
689 return NULL;
Victor Stinner52968672013-11-24 11:37:15 +0100690 }
Victor Stinner88c29872013-12-04 01:47:46 +0100691 TABLES_UNLOCK();
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100692 return ptr;
693}
694
Victor Stinnere492ae52016-03-22 12:58:23 +0100695
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100696static void*
Victor Stinner15116802013-12-04 01:29:35 +0100697tracemalloc_realloc(void *ctx, void *ptr, size_t new_size)
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100698{
Victor Stinnerd8f0d922014-06-02 21:57:10 +0200699 PyMemAllocatorEx *alloc = (PyMemAllocatorEx *)ctx;
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100700 void *ptr2;
701
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100702 ptr2 = alloc->realloc(alloc->ctx, ptr, new_size);
Victor Stinner15116802013-12-04 01:29:35 +0100703 if (ptr2 == NULL)
704 return NULL;
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100705
Victor Stinner15116802013-12-04 01:29:35 +0100706 if (ptr != NULL) {
707 /* an existing memory block has been resized */
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100708
Victor Stinner88c29872013-12-04 01:47:46 +0100709 TABLES_LOCK();
Victor Stinner42bcf372016-03-23 09:08:08 +0100710
711 /* tracemalloc_add_trace() updates the trace if there is already
712 a trace at address (domain, ptr2) */
713 if (ptr2 != ptr) {
714 REMOVE_TRACE(ptr);
715 }
Victor Stinner08facd22013-11-24 12:27:59 +0100716
Victor Stinnere492ae52016-03-22 12:58:23 +0100717 if (ADD_TRACE(ptr2, new_size) < 0) {
Victor Stinner15116802013-12-04 01:29:35 +0100718 /* Memory allocation failed. The error cannot be reported to
Raymond Hettinger15f44ab2016-08-30 10:47:49 -0700719 the caller, because realloc() may already have shrunk the
Victor Stinner15116802013-12-04 01:29:35 +0100720 memory block and so removed bytes.
721
Serhiy Storchaka6a7b3a72016-04-17 08:32:47 +0300722 This case is very unlikely: a hash entry has just been
Victor Stinner88c29872013-12-04 01:47:46 +0100723 released, so the hash table should have at least one free entry.
724
725 The GIL and the table lock ensures that only one thread is
726 allocating memory. */
727 assert(0 && "should never happen");
Victor Stinner52968672013-11-24 11:37:15 +0100728 }
Victor Stinner88c29872013-12-04 01:47:46 +0100729 TABLES_UNLOCK();
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100730 }
Victor Stinner15116802013-12-04 01:29:35 +0100731 else {
732 /* new allocation */
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100733
Victor Stinner88c29872013-12-04 01:47:46 +0100734 TABLES_LOCK();
Victor Stinnere492ae52016-03-22 12:58:23 +0100735 if (ADD_TRACE(ptr2, new_size) < 0) {
Victor Stinner15116802013-12-04 01:29:35 +0100736 /* Failed to allocate a trace for the new memory block */
Victor Stinner88c29872013-12-04 01:47:46 +0100737 TABLES_UNLOCK();
Victor Stinner15116802013-12-04 01:29:35 +0100738 alloc->free(alloc->ctx, ptr2);
739 return NULL;
740 }
Victor Stinner88c29872013-12-04 01:47:46 +0100741 TABLES_UNLOCK();
Victor Stinner15116802013-12-04 01:29:35 +0100742 }
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100743 return ptr2;
744}
745
Victor Stinnere492ae52016-03-22 12:58:23 +0100746
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100747static void
748tracemalloc_free(void *ctx, void *ptr)
749{
Victor Stinnerd8f0d922014-06-02 21:57:10 +0200750 PyMemAllocatorEx *alloc = (PyMemAllocatorEx *)ctx;
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100751
752 if (ptr == NULL)
753 return;
754
755 /* GIL cannot be locked in PyMem_RawFree() because it would introduce
756 a deadlock in PyThreadState_DeleteCurrent(). */
757
758 alloc->free(alloc->ctx, ptr);
Victor Stinner88c29872013-12-04 01:47:46 +0100759
760 TABLES_LOCK();
Victor Stinnere492ae52016-03-22 12:58:23 +0100761 REMOVE_TRACE(ptr);
Victor Stinner88c29872013-12-04 01:47:46 +0100762 TABLES_UNLOCK();
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100763}
764
Victor Stinnere492ae52016-03-22 12:58:23 +0100765
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100766static void*
Victor Stinnerdb067af2014-05-02 22:31:14 +0200767tracemalloc_alloc_gil(int use_calloc, void *ctx, size_t nelem, size_t elsize)
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100768{
Victor Stinner15116802013-12-04 01:29:35 +0100769 void *ptr;
770
771 if (get_reentrant()) {
Victor Stinnerd8f0d922014-06-02 21:57:10 +0200772 PyMemAllocatorEx *alloc = (PyMemAllocatorEx *)ctx;
Victor Stinnerdb067af2014-05-02 22:31:14 +0200773 if (use_calloc)
774 return alloc->calloc(alloc->ctx, nelem, elsize);
775 else
776 return alloc->malloc(alloc->ctx, nelem * elsize);
Victor Stinner15116802013-12-04 01:29:35 +0100777 }
778
779 /* Ignore reentrant call. PyObjet_Malloc() calls PyMem_Malloc() for
780 allocations larger than 512 bytes, don't trace the same memory
781 allocation twice. */
782 set_reentrant(1);
783
Victor Stinnerdb067af2014-05-02 22:31:14 +0200784 ptr = tracemalloc_alloc(use_calloc, ctx, nelem, elsize);
Victor Stinner15116802013-12-04 01:29:35 +0100785
786 set_reentrant(0);
787 return ptr;
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100788}
789
Victor Stinnere492ae52016-03-22 12:58:23 +0100790
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100791static void*
Victor Stinnerdb067af2014-05-02 22:31:14 +0200792tracemalloc_malloc_gil(void *ctx, size_t size)
793{
794 return tracemalloc_alloc_gil(0, ctx, 1, size);
795}
796
Victor Stinnere492ae52016-03-22 12:58:23 +0100797
Victor Stinnerdb067af2014-05-02 22:31:14 +0200798static void*
799tracemalloc_calloc_gil(void *ctx, size_t nelem, size_t elsize)
800{
801 return tracemalloc_alloc_gil(1, ctx, nelem, elsize);
802}
803
Victor Stinnere492ae52016-03-22 12:58:23 +0100804
Victor Stinnerdb067af2014-05-02 22:31:14 +0200805static void*
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100806tracemalloc_realloc_gil(void *ctx, void *ptr, size_t new_size)
807{
Victor Stinner15116802013-12-04 01:29:35 +0100808 void *ptr2;
809
810 if (get_reentrant()) {
811 /* Reentrant call to PyMem_Realloc() and PyMem_RawRealloc().
812 Example: PyMem_RawRealloc() is called internally by pymalloc
813 (_PyObject_Malloc() and _PyObject_Realloc()) to allocate a new
814 arena (new_arena()). */
Victor Stinnerd8f0d922014-06-02 21:57:10 +0200815 PyMemAllocatorEx *alloc = (PyMemAllocatorEx *)ctx;
Victor Stinner15116802013-12-04 01:29:35 +0100816
817 ptr2 = alloc->realloc(alloc->ctx, ptr, new_size);
Victor Stinner88c29872013-12-04 01:47:46 +0100818 if (ptr2 != NULL && ptr != NULL) {
819 TABLES_LOCK();
Victor Stinnere492ae52016-03-22 12:58:23 +0100820 REMOVE_TRACE(ptr);
Victor Stinner88c29872013-12-04 01:47:46 +0100821 TABLES_UNLOCK();
822 }
Victor Stinner15116802013-12-04 01:29:35 +0100823 return ptr2;
824 }
825
826 /* Ignore reentrant call. PyObjet_Realloc() calls PyMem_Realloc() for
827 allocations larger than 512 bytes. Don't trace the same memory
828 allocation twice. */
829 set_reentrant(1);
830
831 ptr2 = tracemalloc_realloc(ctx, ptr, new_size);
832
833 set_reentrant(0);
834 return ptr2;
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100835}
836
Victor Stinnere492ae52016-03-22 12:58:23 +0100837
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100838#ifdef TRACE_RAW_MALLOC
839static void*
Victor Stinnerdb067af2014-05-02 22:31:14 +0200840tracemalloc_raw_alloc(int use_calloc, void *ctx, size_t nelem, size_t elsize)
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100841{
Victor Stinner15116802013-12-04 01:29:35 +0100842#ifdef WITH_THREAD
843 PyGILState_STATE gil_state;
844#endif
845 void *ptr;
846
847 if (get_reentrant()) {
Victor Stinnerd8f0d922014-06-02 21:57:10 +0200848 PyMemAllocatorEx *alloc = (PyMemAllocatorEx *)ctx;
Victor Stinnerdb067af2014-05-02 22:31:14 +0200849 if (use_calloc)
850 return alloc->calloc(alloc->ctx, nelem, elsize);
851 else
852 return alloc->malloc(alloc->ctx, nelem * elsize);
Victor Stinner15116802013-12-04 01:29:35 +0100853 }
854
855 /* Ignore reentrant call. PyGILState_Ensure() may call PyMem_RawMalloc()
856 indirectly which would call PyGILState_Ensure() if reentrant are not
857 disabled. */
858 set_reentrant(1);
859
860#ifdef WITH_THREAD
861 gil_state = PyGILState_Ensure();
Victor Stinnerdb067af2014-05-02 22:31:14 +0200862 ptr = tracemalloc_alloc(use_calloc, ctx, nelem, elsize);
Victor Stinner15116802013-12-04 01:29:35 +0100863 PyGILState_Release(gil_state);
864#else
Victor Stinnerdb067af2014-05-02 22:31:14 +0200865 ptr = tracemalloc_alloc(use_calloc, ctx, nelem, elsize);
Victor Stinner15116802013-12-04 01:29:35 +0100866#endif
867
868 set_reentrant(0);
869 return ptr;
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100870}
871
Victor Stinnere492ae52016-03-22 12:58:23 +0100872
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100873static void*
Victor Stinnerdb067af2014-05-02 22:31:14 +0200874tracemalloc_raw_malloc(void *ctx, size_t size)
875{
876 return tracemalloc_raw_alloc(0, ctx, 1, size);
877}
878
Victor Stinnere492ae52016-03-22 12:58:23 +0100879
Victor Stinnerdb067af2014-05-02 22:31:14 +0200880static void*
881tracemalloc_raw_calloc(void *ctx, size_t nelem, size_t elsize)
882{
883 return tracemalloc_raw_alloc(1, ctx, nelem, elsize);
884}
885
Victor Stinnere492ae52016-03-22 12:58:23 +0100886
Victor Stinnerdb067af2014-05-02 22:31:14 +0200887static void*
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100888tracemalloc_raw_realloc(void *ctx, void *ptr, size_t new_size)
889{
Victor Stinner15116802013-12-04 01:29:35 +0100890#ifdef WITH_THREAD
891 PyGILState_STATE gil_state;
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100892#endif
Victor Stinner15116802013-12-04 01:29:35 +0100893 void *ptr2;
894
895 if (get_reentrant()) {
896 /* Reentrant call to PyMem_RawRealloc(). */
Victor Stinnerd8f0d922014-06-02 21:57:10 +0200897 PyMemAllocatorEx *alloc = (PyMemAllocatorEx *)ctx;
Victor Stinner15116802013-12-04 01:29:35 +0100898
899 ptr2 = alloc->realloc(alloc->ctx, ptr, new_size);
Victor Stinner15116802013-12-04 01:29:35 +0100900
Victor Stinner88c29872013-12-04 01:47:46 +0100901 if (ptr2 != NULL && ptr != NULL) {
902 TABLES_LOCK();
Victor Stinnere492ae52016-03-22 12:58:23 +0100903 REMOVE_TRACE(ptr);
Victor Stinner88c29872013-12-04 01:47:46 +0100904 TABLES_UNLOCK();
905 }
Victor Stinner15116802013-12-04 01:29:35 +0100906 return ptr2;
907 }
908
909 /* Ignore reentrant call. PyGILState_Ensure() may call PyMem_RawMalloc()
910 indirectly which would call PyGILState_Ensure() if reentrant calls are
911 not disabled. */
912 set_reentrant(1);
913
914#ifdef WITH_THREAD
915 gil_state = PyGILState_Ensure();
916 ptr2 = tracemalloc_realloc(ctx, ptr, new_size);
917 PyGILState_Release(gil_state);
918#else
919 ptr2 = tracemalloc_realloc(ctx, ptr, new_size);
920#endif
921
922 set_reentrant(0);
923 return ptr2;
924}
925#endif /* TRACE_RAW_MALLOC */
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100926
Victor Stinnere492ae52016-03-22 12:58:23 +0100927
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100928static int
Victor Stinner285cf0a2016-03-21 22:00:58 +0100929tracemalloc_clear_filename(_Py_hashtable_t *ht, _Py_hashtable_entry_t *entry,
930 void *user_data)
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100931{
Victor Stinner285cf0a2016-03-21 22:00:58 +0100932 PyObject *filename;
933
Victor Stinner5dacbd42016-03-23 09:52:13 +0100934 _Py_HASHTABLE_ENTRY_READ_KEY(ht, entry, filename);
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100935 Py_DECREF(filename);
936 return 0;
937}
938
Victor Stinnere492ae52016-03-22 12:58:23 +0100939
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100940static int
Victor Stinner285cf0a2016-03-21 22:00:58 +0100941traceback_free_traceback(_Py_hashtable_t *ht, _Py_hashtable_entry_t *entry,
942 void *user_data)
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100943{
Victor Stinner285cf0a2016-03-21 22:00:58 +0100944 traceback_t *traceback;
945
Victor Stinner5dacbd42016-03-23 09:52:13 +0100946 _Py_HASHTABLE_ENTRY_READ_KEY(ht, entry, traceback);
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100947 raw_free(traceback);
948 return 0;
949}
950
Victor Stinnere492ae52016-03-22 12:58:23 +0100951
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100952/* reentrant flag must be set to call this function and GIL must be held */
953static void
954tracemalloc_clear_traces(void)
955{
956#ifdef WITH_THREAD
957 /* The GIL protects variables againt concurrent access */
958 assert(PyGILState_Check());
959#endif
960
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100961 TABLES_LOCK();
962 _Py_hashtable_clear(tracemalloc_traces);
963 tracemalloc_traced_memory = 0;
Victor Stinner3c0481d2013-11-27 21:39:49 +0100964 tracemalloc_peak_traced_memory = 0;
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100965 TABLES_UNLOCK();
966
967 _Py_hashtable_foreach(tracemalloc_tracebacks, traceback_free_traceback, NULL);
968 _Py_hashtable_clear(tracemalloc_tracebacks);
969
970 _Py_hashtable_foreach(tracemalloc_filenames, tracemalloc_clear_filename, NULL);
971 _Py_hashtable_clear(tracemalloc_filenames);
972}
973
Victor Stinnere492ae52016-03-22 12:58:23 +0100974
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100975static int
976tracemalloc_init(void)
977{
978 if (tracemalloc_config.initialized == TRACEMALLOC_FINALIZED) {
979 PyErr_SetString(PyExc_RuntimeError,
980 "the tracemalloc module has been unloaded");
981 return -1;
982 }
983
Victor Stinnerf9a71152016-03-22 23:54:42 +0100984 if (tracemalloc_config.initialized == TRACEMALLOC_INITIALIZED)
Victor Stinnered3b0bc2013-11-23 12:27:24 +0100985 return 0;
986
987 PyMem_GetAllocator(PYMEM_DOMAIN_RAW, &allocators.raw);
988
989#ifdef REENTRANT_THREADLOCAL
990 tracemalloc_reentrant_key = PyThread_create_key();
991 if (tracemalloc_reentrant_key == -1) {
992#ifdef MS_WINDOWS
993 PyErr_SetFromWindowsErr(0);
994#else
995 PyErr_SetFromErrno(PyExc_OSError);
996#endif
997 return -1;
998 }
999#endif
1000
1001#if defined(WITH_THREAD) && defined(TRACE_RAW_MALLOC)
1002 if (tables_lock == NULL) {
1003 tables_lock = PyThread_allocate_lock();
1004 if (tables_lock == NULL) {
1005 PyErr_SetString(PyExc_RuntimeError, "cannot allocate lock");
1006 return -1;
1007 }
1008 }
1009#endif
1010
Victor Stinner285cf0a2016-03-21 22:00:58 +01001011 tracemalloc_filenames = hashtable_new(sizeof(PyObject *), 0,
1012 hashtable_hash_pyobject,
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001013 hashtable_compare_unicode);
1014
Victor Stinner285cf0a2016-03-21 22:00:58 +01001015 tracemalloc_tracebacks = hashtable_new(sizeof(traceback_t *), 0,
1016 hashtable_hash_traceback,
1017 hashtable_compare_traceback);
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001018
Victor Stinnere492ae52016-03-22 12:58:23 +01001019 if (tracemalloc_config.use_domain) {
1020 tracemalloc_traces = hashtable_new(sizeof(pointer_t),
1021 sizeof(trace_t),
1022 hashtable_hash_pointer_t,
1023 hashtable_compare_pointer_t);
1024 }
1025 else {
Benjamin Petersonca470632016-09-06 13:47:26 -07001026 tracemalloc_traces = hashtable_new(sizeof(uintptr_t),
Victor Stinnere492ae52016-03-22 12:58:23 +01001027 sizeof(trace_t),
1028 _Py_hashtable_hash_ptr,
1029 _Py_hashtable_compare_direct);
1030 }
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001031
1032 if (tracemalloc_filenames == NULL || tracemalloc_tracebacks == NULL
Victor Stinner285cf0a2016-03-21 22:00:58 +01001033 || tracemalloc_traces == NULL) {
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001034 PyErr_NoMemory();
1035 return -1;
1036 }
1037
1038 unknown_filename = PyUnicode_FromString("<unknown>");
1039 if (unknown_filename == NULL)
1040 return -1;
1041 PyUnicode_InternInPlace(&unknown_filename);
1042
1043 tracemalloc_empty_traceback.nframe = 1;
1044 /* borrowed reference */
1045 tracemalloc_empty_traceback.frames[0].filename = unknown_filename;
1046 tracemalloc_empty_traceback.frames[0].lineno = 0;
1047 tracemalloc_empty_traceback.hash = traceback_hash(&tracemalloc_empty_traceback);
1048
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001049 tracemalloc_config.initialized = TRACEMALLOC_INITIALIZED;
1050 return 0;
1051}
1052
Victor Stinnere492ae52016-03-22 12:58:23 +01001053
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001054static void
1055tracemalloc_deinit(void)
1056{
Victor Stinnerf9a71152016-03-22 23:54:42 +01001057 if (tracemalloc_config.initialized != TRACEMALLOC_INITIALIZED)
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001058 return;
1059 tracemalloc_config.initialized = TRACEMALLOC_FINALIZED;
1060
1061 tracemalloc_stop();
1062
1063 /* destroy hash tables */
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001064 _Py_hashtable_destroy(tracemalloc_tracebacks);
1065 _Py_hashtable_destroy(tracemalloc_filenames);
Victor Stinner285cf0a2016-03-21 22:00:58 +01001066 _Py_hashtable_destroy(tracemalloc_traces);
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001067
1068#if defined(WITH_THREAD) && defined(TRACE_RAW_MALLOC)
1069 if (tables_lock != NULL) {
1070 PyThread_free_lock(tables_lock);
1071 tables_lock = NULL;
1072 }
1073#endif
1074
1075#ifdef REENTRANT_THREADLOCAL
1076 PyThread_delete_key(tracemalloc_reentrant_key);
Victor Stinner4a066472016-03-22 17:45:09 +01001077 tracemalloc_reentrant_key = -1;
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001078#endif
1079
1080 Py_XDECREF(unknown_filename);
1081}
1082
Victor Stinnere492ae52016-03-22 12:58:23 +01001083
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001084static int
Victor Stinnerf28ce602013-11-27 22:27:13 +01001085tracemalloc_start(int max_nframe)
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001086{
Victor Stinnerd8f0d922014-06-02 21:57:10 +02001087 PyMemAllocatorEx alloc;
Victor Stinnerf28ce602013-11-27 22:27:13 +01001088 size_t size;
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001089
Victor Stinnerf9a71152016-03-22 23:54:42 +01001090 if (tracemalloc_init() < 0)
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001091 return -1;
1092
1093 if (tracemalloc_config.tracing) {
1094 /* hook already installed: do nothing */
1095 return 0;
1096 }
1097
Victor Stinner52aee852014-08-16 15:44:02 +02001098 assert(1 <= max_nframe && max_nframe <= MAX_NFRAME);
Victor Stinnerf28ce602013-11-27 22:27:13 +01001099 tracemalloc_config.max_nframe = max_nframe;
1100
1101 /* allocate a buffer to store a new traceback */
1102 size = TRACEBACK_SIZE(max_nframe);
1103 assert(tracemalloc_traceback == NULL);
1104 tracemalloc_traceback = raw_malloc(size);
1105 if (tracemalloc_traceback == NULL) {
1106 PyErr_NoMemory();
1107 return -1;
1108 }
1109
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001110#ifdef TRACE_RAW_MALLOC
1111 alloc.malloc = tracemalloc_raw_malloc;
Victor Stinnerdb067af2014-05-02 22:31:14 +02001112 alloc.calloc = tracemalloc_raw_calloc;
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001113 alloc.realloc = tracemalloc_raw_realloc;
1114 alloc.free = tracemalloc_free;
1115
1116 alloc.ctx = &allocators.raw;
1117 PyMem_GetAllocator(PYMEM_DOMAIN_RAW, &allocators.raw);
1118 PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &alloc);
1119#endif
1120
1121 alloc.malloc = tracemalloc_malloc_gil;
Victor Stinnerdb067af2014-05-02 22:31:14 +02001122 alloc.calloc = tracemalloc_calloc_gil;
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001123 alloc.realloc = tracemalloc_realloc_gil;
1124 alloc.free = tracemalloc_free;
1125
1126 alloc.ctx = &allocators.mem;
1127 PyMem_GetAllocator(PYMEM_DOMAIN_MEM, &allocators.mem);
1128 PyMem_SetAllocator(PYMEM_DOMAIN_MEM, &alloc);
1129
1130 alloc.ctx = &allocators.obj;
1131 PyMem_GetAllocator(PYMEM_DOMAIN_OBJ, &allocators.obj);
1132 PyMem_SetAllocator(PYMEM_DOMAIN_OBJ, &alloc);
1133
1134 /* everything is ready: start tracing Python memory allocations */
1135 tracemalloc_config.tracing = 1;
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001136
1137 return 0;
1138}
1139
Victor Stinnere492ae52016-03-22 12:58:23 +01001140
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001141static void
1142tracemalloc_stop(void)
1143{
Victor Stinnerf9a71152016-03-22 23:54:42 +01001144 if (!tracemalloc_config.tracing)
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001145 return;
1146
1147 /* stop tracing Python memory allocations */
1148 tracemalloc_config.tracing = 0;
1149
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001150 /* unregister the hook on memory allocators */
1151#ifdef TRACE_RAW_MALLOC
1152 PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &allocators.raw);
1153#endif
1154 PyMem_SetAllocator(PYMEM_DOMAIN_MEM, &allocators.mem);
1155 PyMem_SetAllocator(PYMEM_DOMAIN_OBJ, &allocators.obj);
1156
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001157 tracemalloc_clear_traces();
Victor Stinner285cf0a2016-03-21 22:00:58 +01001158
1159 /* release memory */
Victor Stinnerf28ce602013-11-27 22:27:13 +01001160 raw_free(tracemalloc_traceback);
1161 tracemalloc_traceback = NULL;
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001162}
1163
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001164PyDoc_STRVAR(tracemalloc_is_tracing_doc,
1165 "is_tracing()->bool\n"
1166 "\n"
1167 "True if the tracemalloc module is tracing Python memory allocations,\n"
1168 "False otherwise.");
1169
Victor Stinnere492ae52016-03-22 12:58:23 +01001170
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001171static PyObject*
1172py_tracemalloc_is_tracing(PyObject *self)
1173{
1174 return PyBool_FromLong(tracemalloc_config.tracing);
1175}
1176
1177PyDoc_STRVAR(tracemalloc_clear_traces_doc,
1178 "clear_traces()\n"
1179 "\n"
1180 "Clear traces of memory blocks allocated by Python.");
1181
Victor Stinnere492ae52016-03-22 12:58:23 +01001182
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001183static PyObject*
1184py_tracemalloc_clear_traces(PyObject *self)
1185{
1186 if (!tracemalloc_config.tracing)
1187 Py_RETURN_NONE;
1188
1189 set_reentrant(1);
1190 tracemalloc_clear_traces();
1191 set_reentrant(0);
1192
1193 Py_RETURN_NONE;
1194}
1195
Victor Stinnere492ae52016-03-22 12:58:23 +01001196
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001197static PyObject*
1198frame_to_pyobject(frame_t *frame)
1199{
1200 PyObject *frame_obj, *lineno_obj;
1201
1202 frame_obj = PyTuple_New(2);
1203 if (frame_obj == NULL)
1204 return NULL;
1205
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001206 Py_INCREF(frame->filename);
1207 PyTuple_SET_ITEM(frame_obj, 0, frame->filename);
1208
Victor Stinner95283342016-03-15 21:57:02 +01001209 lineno_obj = PyLong_FromUnsignedLong(frame->lineno);
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001210 if (lineno_obj == NULL) {
1211 Py_DECREF(frame_obj);
1212 return NULL;
1213 }
1214 PyTuple_SET_ITEM(frame_obj, 1, lineno_obj);
1215
1216 return frame_obj;
1217}
1218
Victor Stinnere492ae52016-03-22 12:58:23 +01001219
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001220static PyObject*
1221traceback_to_pyobject(traceback_t *traceback, _Py_hashtable_t *intern_table)
1222{
1223 int i;
1224 PyObject *frames, *frame;
1225
1226 if (intern_table != NULL) {
1227 if (_Py_HASHTABLE_GET(intern_table, traceback, frames)) {
1228 Py_INCREF(frames);
1229 return frames;
1230 }
1231 }
1232
1233 frames = PyTuple_New(traceback->nframe);
1234 if (frames == NULL)
1235 return NULL;
1236
1237 for (i=0; i < traceback->nframe; i++) {
1238 frame = frame_to_pyobject(&traceback->frames[i]);
1239 if (frame == NULL) {
1240 Py_DECREF(frames);
1241 return NULL;
1242 }
1243 PyTuple_SET_ITEM(frames, i, frame);
1244 }
1245
1246 if (intern_table != NULL) {
1247 if (_Py_HASHTABLE_SET(intern_table, traceback, frames) < 0) {
1248 Py_DECREF(frames);
1249 PyErr_NoMemory();
1250 return NULL;
1251 }
1252 /* intern_table keeps a new reference to frames */
1253 Py_INCREF(frames);
1254 }
1255 return frames;
1256}
1257
Victor Stinnere492ae52016-03-22 12:58:23 +01001258
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001259static PyObject*
Victor Stinner10b73e12016-03-22 13:39:05 +01001260trace_to_pyobject(_PyTraceMalloc_domain_t domain, trace_t *trace,
Victor Stinnere492ae52016-03-22 12:58:23 +01001261 _Py_hashtable_t *intern_tracebacks)
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001262{
1263 PyObject *trace_obj = NULL;
Victor Stinnere492ae52016-03-22 12:58:23 +01001264 PyObject *obj;
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001265
Victor Stinnere492ae52016-03-22 12:58:23 +01001266 trace_obj = PyTuple_New(3);
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001267 if (trace_obj == NULL)
1268 return NULL;
1269
Victor Stinnere492ae52016-03-22 12:58:23 +01001270 obj = PyLong_FromSize_t(domain);
1271 if (obj == NULL) {
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001272 Py_DECREF(trace_obj);
1273 return NULL;
1274 }
Victor Stinnere492ae52016-03-22 12:58:23 +01001275 PyTuple_SET_ITEM(trace_obj, 0, obj);
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001276
Victor Stinnere492ae52016-03-22 12:58:23 +01001277 obj = PyLong_FromSize_t(trace->size);
1278 if (obj == NULL) {
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001279 Py_DECREF(trace_obj);
1280 return NULL;
1281 }
Victor Stinnere492ae52016-03-22 12:58:23 +01001282 PyTuple_SET_ITEM(trace_obj, 1, obj);
1283
1284 obj = traceback_to_pyobject(trace->traceback, intern_tracebacks);
1285 if (obj == NULL) {
1286 Py_DECREF(trace_obj);
1287 return NULL;
1288 }
1289 PyTuple_SET_ITEM(trace_obj, 2, obj);
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001290
1291 return trace_obj;
1292}
1293
Victor Stinnere492ae52016-03-22 12:58:23 +01001294
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001295typedef struct {
1296 _Py_hashtable_t *traces;
1297 _Py_hashtable_t *tracebacks;
1298 PyObject *list;
1299} get_traces_t;
1300
1301static int
Victor Stinner285cf0a2016-03-21 22:00:58 +01001302tracemalloc_get_traces_fill(_Py_hashtable_t *traces, _Py_hashtable_entry_t *entry,
1303 void *user_data)
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001304{
1305 get_traces_t *get_traces = user_data;
Victor Stinner10b73e12016-03-22 13:39:05 +01001306 _PyTraceMalloc_domain_t domain;
Victor Stinner5dacbd42016-03-23 09:52:13 +01001307 trace_t trace;
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001308 PyObject *tracemalloc_obj;
1309 int res;
1310
Victor Stinnere492ae52016-03-22 12:58:23 +01001311 if (tracemalloc_config.use_domain) {
1312 pointer_t key;
Victor Stinner5dacbd42016-03-23 09:52:13 +01001313 _Py_HASHTABLE_ENTRY_READ_KEY(traces, entry, key);
Victor Stinnere492ae52016-03-22 12:58:23 +01001314 domain = key.domain;
1315 }
1316 else {
1317 domain = DEFAULT_DOMAIN;
1318 }
Victor Stinner5dacbd42016-03-23 09:52:13 +01001319 _Py_HASHTABLE_ENTRY_READ_DATA(traces, entry, trace);
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001320
Victor Stinner5dacbd42016-03-23 09:52:13 +01001321 tracemalloc_obj = trace_to_pyobject(domain, &trace, get_traces->tracebacks);
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001322 if (tracemalloc_obj == NULL)
1323 return 1;
1324
1325 res = PyList_Append(get_traces->list, tracemalloc_obj);
1326 Py_DECREF(tracemalloc_obj);
1327 if (res < 0)
1328 return 1;
1329
1330 return 0;
1331}
1332
Victor Stinnere492ae52016-03-22 12:58:23 +01001333
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001334static int
Victor Stinner285cf0a2016-03-21 22:00:58 +01001335tracemalloc_pyobject_decref_cb(_Py_hashtable_t *tracebacks,
1336 _Py_hashtable_entry_t *entry,
1337 void *user_data)
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001338{
Victor Stinnerc9553872016-03-22 12:13:01 +01001339 PyObject *obj;
Victor Stinnere8c6b2f2016-03-23 09:25:01 +01001340 _Py_HASHTABLE_ENTRY_READ_DATA(tracebacks, entry, obj);
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001341 Py_DECREF(obj);
1342 return 0;
1343}
1344
Victor Stinnere492ae52016-03-22 12:58:23 +01001345
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001346PyDoc_STRVAR(tracemalloc_get_traces_doc,
Victor Stinner4fbefdb2013-11-25 09:33:18 +01001347 "_get_traces() -> list\n"
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001348 "\n"
1349 "Get traces of all memory blocks allocated by Python.\n"
1350 "Return a list of (size: int, traceback: tuple) tuples.\n"
1351 "traceback is a tuple of (filename: str, lineno: int) tuples.\n"
1352 "\n"
1353 "Return an empty list if the tracemalloc module is disabled.");
1354
1355static PyObject*
1356py_tracemalloc_get_traces(PyObject *self, PyObject *obj)
1357{
1358 get_traces_t get_traces;
1359 int err;
1360
1361 get_traces.traces = NULL;
1362 get_traces.tracebacks = NULL;
1363 get_traces.list = PyList_New(0);
1364 if (get_traces.list == NULL)
1365 goto error;
1366
1367 if (!tracemalloc_config.tracing)
1368 return get_traces.list;
1369
Victor Stinnerde2f1322013-11-26 00:26:23 +01001370 /* the traceback hash table is used temporarily to intern traceback tuple
1371 of (filename, lineno) tuples */
Victor Stinnerc9553872016-03-22 12:13:01 +01001372 get_traces.tracebacks = hashtable_new(sizeof(traceback_t *),
1373 sizeof(PyObject *),
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001374 _Py_hashtable_hash_ptr,
1375 _Py_hashtable_compare_direct);
1376 if (get_traces.tracebacks == NULL) {
1377 PyErr_NoMemory();
1378 goto error;
1379 }
1380
1381 TABLES_LOCK();
1382 get_traces.traces = _Py_hashtable_copy(tracemalloc_traces);
1383 TABLES_UNLOCK();
1384
1385 if (get_traces.traces == NULL) {
1386 PyErr_NoMemory();
1387 goto error;
1388 }
1389
1390 set_reentrant(1);
1391 err = _Py_hashtable_foreach(get_traces.traces,
1392 tracemalloc_get_traces_fill, &get_traces);
1393 set_reentrant(0);
1394 if (err)
1395 goto error;
1396
1397 goto finally;
1398
1399error:
1400 Py_CLEAR(get_traces.list);
1401
1402finally:
1403 if (get_traces.tracebacks != NULL) {
1404 _Py_hashtable_foreach(get_traces.tracebacks,
Victor Stinner285cf0a2016-03-21 22:00:58 +01001405 tracemalloc_pyobject_decref_cb, NULL);
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001406 _Py_hashtable_destroy(get_traces.tracebacks);
1407 }
Victor Stinnerc9553872016-03-22 12:13:01 +01001408 if (get_traces.traces != NULL) {
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001409 _Py_hashtable_destroy(get_traces.traces);
Victor Stinnerc9553872016-03-22 12:13:01 +01001410 }
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001411
1412 return get_traces.list;
1413}
1414
Victor Stinnere492ae52016-03-22 12:58:23 +01001415
Victor Stinner0611c262016-03-15 22:22:13 +01001416static traceback_t*
Benjamin Petersonca470632016-09-06 13:47:26 -07001417tracemalloc_get_traceback(_PyTraceMalloc_domain_t domain, uintptr_t ptr)
Victor Stinner0611c262016-03-15 22:22:13 +01001418{
1419 trace_t trace;
1420 int found;
1421
1422 if (!tracemalloc_config.tracing)
1423 return NULL;
1424
1425 TABLES_LOCK();
Victor Stinnere492ae52016-03-22 12:58:23 +01001426 if (tracemalloc_config.use_domain) {
Victor Stinner10b73e12016-03-22 13:39:05 +01001427 pointer_t key = {ptr, domain};
Victor Stinnere492ae52016-03-22 12:58:23 +01001428 found = _Py_HASHTABLE_GET(tracemalloc_traces, key, trace);
1429 }
1430 else {
1431 found = _Py_HASHTABLE_GET(tracemalloc_traces, ptr, trace);
1432 }
Victor Stinner0611c262016-03-15 22:22:13 +01001433 TABLES_UNLOCK();
1434
1435 if (!found)
1436 return NULL;
1437
1438 return trace.traceback;
1439}
1440
Victor Stinnere492ae52016-03-22 12:58:23 +01001441
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001442PyDoc_STRVAR(tracemalloc_get_object_traceback_doc,
Victor Stinner4fbefdb2013-11-25 09:33:18 +01001443 "_get_object_traceback(obj)\n"
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001444 "\n"
1445 "Get the traceback where the Python object obj was allocated.\n"
1446 "Return a tuple of (filename: str, lineno: int) tuples.\n"
1447 "\n"
1448 "Return None if the tracemalloc module is disabled or did not\n"
1449 "trace the allocation of the object.");
1450
1451static PyObject*
1452py_tracemalloc_get_object_traceback(PyObject *self, PyObject *obj)
1453{
1454 PyTypeObject *type;
1455 void *ptr;
Victor Stinner0611c262016-03-15 22:22:13 +01001456 traceback_t *traceback;
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001457
1458 type = Py_TYPE(obj);
1459 if (PyType_IS_GC(type))
1460 ptr = (void *)((char *)obj - sizeof(PyGC_Head));
1461 else
1462 ptr = (void *)obj;
1463
Benjamin Petersonca470632016-09-06 13:47:26 -07001464 traceback = tracemalloc_get_traceback(DEFAULT_DOMAIN, (uintptr_t)ptr);
Victor Stinner0611c262016-03-15 22:22:13 +01001465 if (traceback == NULL)
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001466 Py_RETURN_NONE;
1467
Victor Stinner0611c262016-03-15 22:22:13 +01001468 return traceback_to_pyobject(traceback, NULL);
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001469}
1470
Victor Stinnere492ae52016-03-22 12:58:23 +01001471
Victor Stinner0611c262016-03-15 22:22:13 +01001472#define PUTS(fd, str) _Py_write_noraise(fd, str, (int)strlen(str))
1473
1474static void
1475_PyMem_DumpFrame(int fd, frame_t * frame)
1476{
1477 PUTS(fd, " File \"");
1478 _Py_DumpASCII(fd, frame->filename);
1479 PUTS(fd, "\", line ");
1480 _Py_DumpDecimal(fd, frame->lineno);
1481 PUTS(fd, "\n");
1482}
1483
1484/* Dump the traceback where a memory block was allocated into file descriptor
1485 fd. The function may block on TABLES_LOCK() but it is unlikely. */
1486void
1487_PyMem_DumpTraceback(int fd, const void *ptr)
1488{
1489 traceback_t *traceback;
1490 int i;
1491
Benjamin Petersonca470632016-09-06 13:47:26 -07001492 traceback = tracemalloc_get_traceback(DEFAULT_DOMAIN, (uintptr_t)ptr);
Victor Stinner0611c262016-03-15 22:22:13 +01001493 if (traceback == NULL)
1494 return;
1495
1496 PUTS(fd, "Memory block allocated at (most recent call first):\n");
1497 for (i=0; i < traceback->nframe; i++) {
1498 _PyMem_DumpFrame(fd, &traceback->frames[i]);
1499 }
1500 PUTS(fd, "\n");
1501}
1502
1503#undef PUTS
1504
Victor Stinnere492ae52016-03-22 12:58:23 +01001505
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001506PyDoc_STRVAR(tracemalloc_start_doc,
Victor Stinner3728d6c2013-11-23 12:37:20 +01001507 "start(nframe: int=1)\n"
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001508 "\n"
Victor Stinner3728d6c2013-11-23 12:37:20 +01001509 "Start tracing Python memory allocations. Set also the maximum number \n"
1510 "of frames stored in the traceback of a trace to nframe.");
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001511
1512static PyObject*
Victor Stinner3728d6c2013-11-23 12:37:20 +01001513py_tracemalloc_start(PyObject *self, PyObject *args)
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001514{
Victor Stinner3728d6c2013-11-23 12:37:20 +01001515 Py_ssize_t nframe = 1;
Victor Stinnerf28ce602013-11-27 22:27:13 +01001516 int nframe_int;
Victor Stinner3728d6c2013-11-23 12:37:20 +01001517
1518 if (!PyArg_ParseTuple(args, "|n:start", &nframe))
1519 return NULL;
1520
Victor Stinner52aee852014-08-16 15:44:02 +02001521 if (nframe < 1 || nframe > MAX_NFRAME) {
Victor Stinner3728d6c2013-11-23 12:37:20 +01001522 PyErr_Format(PyExc_ValueError,
1523 "the number of frames must be in range [1; %i]",
Victor Stinner52aee852014-08-16 15:44:02 +02001524 MAX_NFRAME);
Victor Stinner3728d6c2013-11-23 12:37:20 +01001525 return NULL;
1526 }
Victor Stinnerf28ce602013-11-27 22:27:13 +01001527 nframe_int = Py_SAFE_DOWNCAST(nframe, Py_ssize_t, int);
Victor Stinner3728d6c2013-11-23 12:37:20 +01001528
Victor Stinnerf9a71152016-03-22 23:54:42 +01001529 if (tracemalloc_start(nframe_int) < 0)
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001530 return NULL;
1531
1532 Py_RETURN_NONE;
1533}
1534
1535PyDoc_STRVAR(tracemalloc_stop_doc,
1536 "stop()\n"
1537 "\n"
1538 "Stop tracing Python memory allocations and clear traces\n"
1539 "of memory blocks allocated by Python.");
1540
Victor Stinnere492ae52016-03-22 12:58:23 +01001541
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001542static PyObject*
1543py_tracemalloc_stop(PyObject *self)
1544{
1545 tracemalloc_stop();
1546 Py_RETURN_NONE;
1547}
1548
Victor Stinnere492ae52016-03-22 12:58:23 +01001549
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001550PyDoc_STRVAR(tracemalloc_get_traceback_limit_doc,
1551 "get_traceback_limit() -> int\n"
1552 "\n"
1553 "Get the maximum number of frames stored in the traceback\n"
1554 "of a trace.\n"
1555 "\n"
1556 "By default, a trace of an allocated memory block only stores\n"
1557 "the most recent frame: the limit is 1.");
1558
1559static PyObject*
1560py_tracemalloc_get_traceback_limit(PyObject *self)
1561{
1562 return PyLong_FromLong(tracemalloc_config.max_nframe);
1563}
1564
Victor Stinnere492ae52016-03-22 12:58:23 +01001565
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001566PyDoc_STRVAR(tracemalloc_get_tracemalloc_memory_doc,
1567 "get_tracemalloc_memory() -> int\n"
1568 "\n"
1569 "Get the memory usage in bytes of the tracemalloc module\n"
1570 "used internally to trace memory allocations.");
1571
1572static PyObject*
1573tracemalloc_get_tracemalloc_memory(PyObject *self)
1574{
1575 size_t size;
1576 PyObject *size_obj;
1577
1578 size = _Py_hashtable_size(tracemalloc_tracebacks);
1579 size += _Py_hashtable_size(tracemalloc_filenames);
1580
1581 TABLES_LOCK();
1582 size += _Py_hashtable_size(tracemalloc_traces);
1583 TABLES_UNLOCK();
1584
1585 size_obj = PyLong_FromSize_t(size);
1586 return Py_BuildValue("N", size_obj);
1587}
1588
Victor Stinnere492ae52016-03-22 12:58:23 +01001589
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001590PyDoc_STRVAR(tracemalloc_get_traced_memory_doc,
Victor Stinner59463d82013-11-26 10:46:06 +01001591 "get_traced_memory() -> (int, int)\n"
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001592 "\n"
Victor Stinner3c0481d2013-11-27 21:39:49 +01001593 "Get the current size and peak size of memory blocks traced\n"
1594 "by the tracemalloc module as a tuple: (current: int, peak: int).");
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001595
1596static PyObject*
1597tracemalloc_get_traced_memory(PyObject *self)
1598{
Victor Stinner3c0481d2013-11-27 21:39:49 +01001599 Py_ssize_t size, peak_size;
1600 PyObject *size_obj, *peak_size_obj;
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001601
1602 if (!tracemalloc_config.tracing)
1603 return Py_BuildValue("ii", 0, 0);
1604
1605 TABLES_LOCK();
1606 size = tracemalloc_traced_memory;
Victor Stinner3c0481d2013-11-27 21:39:49 +01001607 peak_size = tracemalloc_peak_traced_memory;
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001608 TABLES_UNLOCK();
1609
1610 size_obj = PyLong_FromSize_t(size);
Victor Stinner3c0481d2013-11-27 21:39:49 +01001611 peak_size_obj = PyLong_FromSize_t(peak_size);
1612 return Py_BuildValue("NN", size_obj, peak_size_obj);
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001613}
1614
Victor Stinnere492ae52016-03-22 12:58:23 +01001615
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001616static PyMethodDef module_methods[] = {
1617 {"is_tracing", (PyCFunction)py_tracemalloc_is_tracing,
1618 METH_NOARGS, tracemalloc_is_tracing_doc},
1619 {"clear_traces", (PyCFunction)py_tracemalloc_clear_traces,
1620 METH_NOARGS, tracemalloc_clear_traces_doc},
1621 {"_get_traces", (PyCFunction)py_tracemalloc_get_traces,
1622 METH_NOARGS, tracemalloc_get_traces_doc},
1623 {"_get_object_traceback", (PyCFunction)py_tracemalloc_get_object_traceback,
1624 METH_O, tracemalloc_get_object_traceback_doc},
1625 {"start", (PyCFunction)py_tracemalloc_start,
Victor Stinner3728d6c2013-11-23 12:37:20 +01001626 METH_VARARGS, tracemalloc_start_doc},
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001627 {"stop", (PyCFunction)py_tracemalloc_stop,
1628 METH_NOARGS, tracemalloc_stop_doc},
1629 {"get_traceback_limit", (PyCFunction)py_tracemalloc_get_traceback_limit,
1630 METH_NOARGS, tracemalloc_get_traceback_limit_doc},
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001631 {"get_tracemalloc_memory", (PyCFunction)tracemalloc_get_tracemalloc_memory,
1632 METH_NOARGS, tracemalloc_get_tracemalloc_memory_doc},
1633 {"get_traced_memory", (PyCFunction)tracemalloc_get_traced_memory,
1634 METH_NOARGS, tracemalloc_get_traced_memory_doc},
1635
1636 /* sentinel */
1637 {NULL, NULL}
1638};
1639
1640PyDoc_STRVAR(module_doc,
1641"Debug module to trace memory blocks allocated by Python.");
1642
1643static struct PyModuleDef module_def = {
1644 PyModuleDef_HEAD_INIT,
1645 "_tracemalloc",
1646 module_doc,
1647 0, /* non-negative size to be able to unload the module */
1648 module_methods,
1649 NULL,
1650};
1651
1652PyMODINIT_FUNC
1653PyInit__tracemalloc(void)
1654{
1655 PyObject *m;
1656 m = PyModule_Create(&module_def);
1657 if (m == NULL)
1658 return NULL;
1659
1660 if (tracemalloc_init() < 0)
1661 return NULL;
1662
1663 return m;
1664}
1665
Victor Stinnere492ae52016-03-22 12:58:23 +01001666
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001667static int
1668parse_sys_xoptions(PyObject *value)
1669{
1670 PyObject *valuelong;
1671 long nframe;
1672
1673 if (value == Py_True)
1674 return 1;
1675
1676 assert(PyUnicode_Check(value));
1677 if (PyUnicode_GetLength(value) == 0)
1678 return -1;
1679
1680 valuelong = PyLong_FromUnicodeObject(value, 10);
1681 if (valuelong == NULL)
1682 return -1;
1683
1684 nframe = PyLong_AsLong(valuelong);
1685 Py_DECREF(valuelong);
1686 if (nframe == -1 && PyErr_Occurred())
1687 return -1;
1688
Victor Stinner52aee852014-08-16 15:44:02 +02001689 if (nframe < 1 || nframe > MAX_NFRAME)
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001690 return -1;
1691
1692 return Py_SAFE_DOWNCAST(nframe, long, int);
1693}
1694
Victor Stinnere492ae52016-03-22 12:58:23 +01001695
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001696int
1697_PyTraceMalloc_Init(void)
1698{
1699 char *p;
1700 int nframe;
1701
1702#ifdef WITH_THREAD
1703 assert(PyGILState_Check());
1704#endif
1705
1706 if ((p = Py_GETENV("PYTHONTRACEMALLOC")) && *p != '\0') {
1707 char *endptr = p;
Victor Stinnerf28ce602013-11-27 22:27:13 +01001708 long value;
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001709
Victor Stinner711e27c2013-12-16 23:06:19 +01001710 errno = 0;
Victor Stinnerf28ce602013-11-27 22:27:13 +01001711 value = strtol(p, &endptr, 10);
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001712 if (*endptr != '\0'
1713 || value < 1
Victor Stinner52aee852014-08-16 15:44:02 +02001714 || value > MAX_NFRAME
Victor Stinner711e27c2013-12-16 23:06:19 +01001715 || errno == ERANGE)
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001716 {
Victor Stinnerf28ce602013-11-27 22:27:13 +01001717 Py_FatalError("PYTHONTRACEMALLOC: invalid number of frames");
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001718 return -1;
1719 }
1720
1721 nframe = (int)value;
1722 }
1723 else {
1724 PyObject *xoptions, *key, *value;
1725
1726 xoptions = PySys_GetXOptions();
1727 if (xoptions == NULL)
1728 return -1;
1729
1730 key = PyUnicode_FromString("tracemalloc");
1731 if (key == NULL)
1732 return -1;
1733
1734 value = PyDict_GetItemWithError(xoptions, key);
1735 Py_DECREF(key);
1736 if (value == NULL) {
1737 if (PyErr_Occurred())
1738 return -1;
1739
1740 /* -X tracemalloc is not used */
1741 return 0;
1742 }
1743
1744 nframe = parse_sys_xoptions(value);
1745 Py_DECREF(value);
1746 if (nframe < 0) {
Victor Stinnerf28ce602013-11-27 22:27:13 +01001747 Py_FatalError("-X tracemalloc=NFRAME: invalid number of frames");
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001748 }
1749 }
1750
Victor Stinnerf28ce602013-11-27 22:27:13 +01001751 return tracemalloc_start(nframe);
Victor Stinnered3b0bc2013-11-23 12:27:24 +01001752}
1753
Victor Stinnere492ae52016-03-22 12:58:23 +01001754
Victor Stinnerbe0708f2013-12-01 10:03:26 +01001755void
1756_PyTraceMalloc_Fini(void)
1757{
1758#ifdef WITH_THREAD
1759 assert(PyGILState_Check());
1760#endif
1761 tracemalloc_deinit();
1762}
Victor Stinner10b73e12016-03-22 13:39:05 +01001763
1764int
Benjamin Petersonca470632016-09-06 13:47:26 -07001765_PyTraceMalloc_Track(_PyTraceMalloc_domain_t domain, uintptr_t ptr,
Victor Stinner10b73e12016-03-22 13:39:05 +01001766 size_t size)
1767{
1768 int res;
1769#ifdef WITH_THREAD
1770 PyGILState_STATE gil_state;
1771#endif
1772
1773 if (!tracemalloc_config.tracing) {
1774 /* tracemalloc is not tracing: do nothing */
1775 return -2;
1776 }
1777
1778#ifdef WITH_THREAD
1779 gil_state = PyGILState_Ensure();
1780#endif
1781
1782 TABLES_LOCK();
1783 res = tracemalloc_add_trace(domain, ptr, size);
1784 TABLES_UNLOCK();
1785
1786#ifdef WITH_THREAD
1787 PyGILState_Release(gil_state);
1788#endif
1789 return res;
1790}
1791
1792
1793int
Benjamin Petersonca470632016-09-06 13:47:26 -07001794_PyTraceMalloc_Untrack(_PyTraceMalloc_domain_t domain, uintptr_t ptr)
Victor Stinner10b73e12016-03-22 13:39:05 +01001795{
1796 if (!tracemalloc_config.tracing) {
1797 /* tracemalloc is not tracing: do nothing */
1798 return -2;
1799 }
1800
1801 TABLES_LOCK();
1802 tracemalloc_remove_trace(domain, ptr);
1803 TABLES_UNLOCK();
1804
1805 return 0;
1806}
1807
1808
1809PyObject*
Benjamin Petersonca470632016-09-06 13:47:26 -07001810_PyTraceMalloc_GetTraceback(_PyTraceMalloc_domain_t domain, uintptr_t ptr)
Victor Stinner10b73e12016-03-22 13:39:05 +01001811{
1812 traceback_t *traceback;
1813
1814 traceback = tracemalloc_get_traceback(domain, ptr);
1815 if (traceback == NULL)
1816 Py_RETURN_NONE;
1817
1818 return traceback_to_pyobject(traceback, NULL);
1819}