Home | History | Annotate | Download | only in Modules
      1 #include "Python.h"
      2 #include "hashtable.h"
      3 #include "frameobject.h"
      4 #include "pythread.h"
      5 #include "osdefs.h"
      6 
      7 #include "clinic/_tracemalloc.c.h"
      8 /*[clinic input]
      9 module _tracemalloc
     10 [clinic start generated code]*/
     11 /*[clinic end generated code: output=da39a3ee5e6b4b0d input=708a98302fc46e5f]*/
     12 
     13 /* Trace memory blocks allocated by PyMem_RawMalloc() */
     14 #define TRACE_RAW_MALLOC
     15 
     16 /* Forward declaration */
     17 static void tracemalloc_stop(void);
     18 static void* raw_malloc(size_t size);
     19 static void raw_free(void *ptr);
     20 
     21 #ifdef Py_DEBUG
     22 #  define TRACE_DEBUG
     23 #endif
     24 
     25 /* Protected by the GIL */
     26 static struct {
     27     PyMemAllocatorEx mem;
     28     PyMemAllocatorEx raw;
     29     PyMemAllocatorEx obj;
     30 } allocators;
     31 
     32 static 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 
     41     /* 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;
     48 
     49     /* use domain in trace key?
     50        Variable protected by the GIL. */
     51     int use_domain;
     52 } tracemalloc_config = {TRACEMALLOC_NOT_INITIALIZED, 0, 1, 0};
     53 
     54 #if defined(TRACE_RAW_MALLOC)
     55 /* 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(). */
     58 static 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 
     67 
     68 #define DEFAULT_DOMAIN 0
     69 
     70 /* Pack the frame_t structure to reduce the memory footprint. */
     71 typedef struct
     72 #ifdef __GNUC__
     73 __attribute__((packed))
     74 #endif
     75 {
     76     uintptr_t ptr;
     77     unsigned int domain;
     78 } pointer_t;
     79 
     80 /* Pack the frame_t structure to reduce the memory footprint on 64-bit
     81    architectures: 12 bytes instead of 16. */
     82 typedef struct
     83 #ifdef __GNUC__
     84 __attribute__((packed))
     85 #elif defined(_MSC_VER)
     86 #pragma pack(push, 4)
     87 #endif
     88 {
     89     /* filename cannot be NULL: "<unknown>" is used if the Python frame
     90        filename is NULL */
     91     PyObject *filename;
     92     unsigned int lineno;
     93 } frame_t;
     94 #ifdef _MSC_VER
     95 #pragma pack(pop)
     96 #endif
     97 
     98 
     99 typedef 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))
    107 
    108 #define MAX_NFRAME \
    109         ((INT_MAX - (int)sizeof(traceback_t)) / (int)sizeof(frame_t) + 1)
    110 
    111 
    112 static PyObject *unknown_filename = NULL;
    113 static traceback_t tracemalloc_empty_traceback;
    114 
    115 /* Trace of a memory block */
    116 typedef struct {
    117     /* Size of the memory block in bytes */
    118     size_t size;
    119 
    120     /* Traceback where the memory block was allocated */
    121     traceback_t *traceback;
    122 } trace_t;
    123 
    124 
    125 /* Size in bytes of currently traced memory.
    126    Protected by TABLES_LOCK(). */
    127 static size_t tracemalloc_traced_memory = 0;
    128 
    129 /* Peak size in bytes of traced memory.
    130    Protected by TABLES_LOCK(). */
    131 static size_t tracemalloc_peak_traced_memory = 0;
    132 
    133 /* Hash table used as a set to intern filenames:
    134    PyObject* => PyObject*.
    135    Protected by the GIL */
    136 static _Py_hashtable_t *tracemalloc_filenames = NULL;
    137 
    138 /* Buffer to store a new traceback in traceback_new().
    139    Protected by the GIL. */
    140 static traceback_t *tracemalloc_traceback = NULL;
    141 
    142 /* Hash table used as a set to intern tracebacks:
    143    traceback_t* => traceback_t*
    144    Protected by the GIL */
    145 static _Py_hashtable_t *tracemalloc_tracebacks = NULL;
    146 
    147 /* pointer (void*) => trace (trace_t).
    148    Protected by TABLES_LOCK(). */
    149 static _Py_hashtable_t *tracemalloc_traces = NULL;
    150 
    151 
    152 #ifdef TRACE_DEBUG
    153 static void
    154 tracemalloc_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 
    166 
    167 #if defined(TRACE_RAW_MALLOC)
    168 #define REENTRANT_THREADLOCAL
    169 
    170 static Py_tss_t tracemalloc_reentrant_key = Py_tss_NEEDS_INIT;
    171 
    172 /* Any non-NULL pointer can be used */
    173 #define REENTRANT Py_True
    174 
    175 static int
    176 get_reentrant(void)
    177 {
    178     void *ptr;
    179 
    180     assert(PyThread_tss_is_created(&tracemalloc_reentrant_key));
    181     ptr = PyThread_tss_get(&tracemalloc_reentrant_key);
    182     if (ptr != NULL) {
    183         assert(ptr == REENTRANT);
    184         return 1;
    185     }
    186     else
    187         return 0;
    188 }
    189 
    190 static void
    191 set_reentrant(int reentrant)
    192 {
    193     assert(reentrant == 0 || reentrant == 1);
    194     assert(PyThread_tss_is_created(&tracemalloc_reentrant_key));
    195 
    196     if (reentrant) {
    197         assert(!get_reentrant());
    198         PyThread_tss_set(&tracemalloc_reentrant_key, REENTRANT);
    199     }
    200     else {
    201         assert(get_reentrant());
    202         PyThread_tss_set(&tracemalloc_reentrant_key, NULL);
    203     }
    204 }
    205 
    206 #else
    207 
    208 /* TRACE_RAW_MALLOC not defined: variable protected by the GIL */
    209 static int tracemalloc_reentrant = 0;
    210 
    211 static int
    212 get_reentrant(void)
    213 {
    214     return tracemalloc_reentrant;
    215 }
    216 
    217 static void
    218 set_reentrant(int reentrant)
    219 {
    220     assert(reentrant != tracemalloc_reentrant);
    221     tracemalloc_reentrant = reentrant;
    222 }
    223 #endif
    224 
    225 
    226 static Py_uhash_t
    227 hashtable_hash_pyobject(_Py_hashtable_t *ht, const void *pkey)
    228 {
    229     PyObject *obj;
    230 
    231     _Py_HASHTABLE_READ_KEY(ht, pkey, obj);
    232     return PyObject_Hash(obj);
    233 }
    234 
    235 
    236 static int
    237 hashtable_compare_unicode(_Py_hashtable_t *ht, const void *pkey,
    238                           const _Py_hashtable_entry_t *entry)
    239 {
    240     PyObject *key1, *key2;
    241 
    242     _Py_HASHTABLE_READ_KEY(ht, pkey, key1);
    243     _Py_HASHTABLE_ENTRY_READ_KEY(ht, entry, key2);
    244 
    245     if (key1 != NULL && key2 != NULL)
    246         return (PyUnicode_Compare(key1, key2) == 0);
    247     else
    248         return key1 == key2;
    249 }
    250 
    251 
    252 static Py_uhash_t
    253 hashtable_hash_pointer_t(_Py_hashtable_t *ht, const void *pkey)
    254 {
    255     pointer_t ptr;
    256     Py_uhash_t hash;
    257 
    258     _Py_HASHTABLE_READ_KEY(ht, pkey, ptr);
    259 
    260     hash = (Py_uhash_t)_Py_HashPointer((void*)ptr.ptr);
    261     hash ^= ptr.domain;
    262     return hash;
    263 }
    264 
    265 
    266 static int
    267 hashtable_compare_pointer_t(_Py_hashtable_t *ht, const void *pkey,
    268                             const _Py_hashtable_entry_t *entry)
    269 {
    270     pointer_t ptr1, ptr2;
    271 
    272     _Py_HASHTABLE_READ_KEY(ht, pkey, ptr1);
    273     _Py_HASHTABLE_ENTRY_READ_KEY(ht, entry, ptr2);
    274 
    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 
    282 static _Py_hashtable_t *
    283 hashtable_new(size_t key_size, size_t data_size,
    284               _Py_hashtable_hash_func hash_func,
    285               _Py_hashtable_compare_func compare_func)
    286 {
    287     _Py_hashtable_allocator_t hashtable_alloc = {malloc, free};
    288     return _Py_hashtable_new_full(key_size, data_size, 0,
    289                                   hash_func, compare_func,
    290                                   &hashtable_alloc);
    291 }
    292 
    293 
    294 static void*
    295 raw_malloc(size_t size)
    296 {
    297     return allocators.raw.malloc(allocators.raw.ctx, size);
    298 }
    299 
    300 static void
    301 raw_free(void *ptr)
    302 {
    303     allocators.raw.free(allocators.raw.ctx, ptr);
    304 }
    305 
    306 
    307 static Py_uhash_t
    308 hashtable_hash_traceback(_Py_hashtable_t *ht, const void *pkey)
    309 {
    310     traceback_t *traceback;
    311 
    312     _Py_HASHTABLE_READ_KEY(ht, pkey, traceback);
    313     return traceback->hash;
    314 }
    315 
    316 
    317 static int
    318 hashtable_compare_traceback(_Py_hashtable_t *ht, const void *pkey,
    319                             const _Py_hashtable_entry_t *entry)
    320 {
    321     traceback_t *traceback1, *traceback2;
    322     const frame_t *frame1, *frame2;
    323     int i;
    324 
    325     _Py_HASHTABLE_READ_KEY(ht, pkey, traceback1);
    326     _Py_HASHTABLE_ENTRY_READ_KEY(ht, entry, traceback2);
    327 
    328     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 
    346 
    347 static void
    348 tracemalloc_get_frame(PyFrameObject *pyframe, frame_t *frame)
    349 {
    350     PyCodeObject *code;
    351     PyObject *filename;
    352     _Py_hashtable_entry_t *entry;
    353     int lineno;
    354 
    355     frame->filename = unknown_filename;
    356     lineno = PyFrame_GetLineNumber(pyframe);
    357     if (lineno < 0)
    358         lineno = 0;
    359     frame->lineno = (unsigned int)lineno;
    360 
    361     code = pyframe->f_code;
    362     if (code == NULL) {
    363 #ifdef TRACE_DEBUG
    364         tracemalloc_error("failed to get the code object of the frame");
    365 #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
    383         tracemalloc_error("filename is not a unicode string");
    384 #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 */
    397     entry = _Py_HASHTABLE_GET_ENTRY(tracemalloc_filenames, filename);
    398     if (entry != NULL) {
    399         _Py_HASHTABLE_ENTRY_READ_KEY(tracemalloc_filenames, entry, filename);
    400     }
    401     else {
    402         /* tracemalloc_filenames is responsible to keep a reference
    403            to the filename */
    404         Py_INCREF(filename);
    405         if (_Py_HASHTABLE_SET_NODATA(tracemalloc_filenames, filename) < 0) {
    406             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 
    418 
    419 static Py_uhash_t
    420 traceback_hash(traceback_t *traceback)
    421 {
    422     /* code based on tuplehash() of Objects/tupleobject.c */
    423     Py_uhash_t x, y;  /* Unsigned for defined overflow behavior. */
    424     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) {
    431         y = (Py_uhash_t)PyObject_Hash(frame->filename);
    432         y ^= (Py_uhash_t)frame->lineno;
    433         frame++;
    434 
    435         x = (x ^ y) * mult;
    436         /* the cast might truncate len; that doesn't change hash stability */
    437         mult += (Py_uhash_t)(82520UL + len + len);
    438     }
    439     x += 97531UL;
    440     return x;
    441 }
    442 
    443 
    444 static void
    445 traceback_get_frames(traceback_t *traceback)
    446 {
    447     PyThreadState *tstate;
    448     PyFrameObject *pyframe;
    449 
    450     tstate = PyGILState_GetThisThreadState();
    451     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);
    461         traceback->nframe++;
    462         if (traceback->nframe == tracemalloc_config.max_nframe)
    463             break;
    464     }
    465 }
    466 
    467 
    468 static traceback_t *
    469 traceback_new(void)
    470 {
    471     traceback_t *traceback;
    472     _Py_hashtable_entry_t *entry;
    473 
    474     assert(PyGILState_Check());
    475 
    476     /* get frames */
    477     traceback = tracemalloc_traceback;
    478     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 */
    485     entry = _Py_HASHTABLE_GET_ENTRY(tracemalloc_tracebacks, traceback);
    486     if (entry != NULL) {
    487         _Py_HASHTABLE_ENTRY_READ_KEY(tracemalloc_tracebacks, entry, traceback);
    488     }
    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 
    504         if (_Py_HASHTABLE_SET_NODATA(tracemalloc_tracebacks, copy) < 0) {
    505             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 
    516 
    517 static int
    518 tracemalloc_use_domain_cb(_Py_hashtable_t *old_traces,
    519                            _Py_hashtable_entry_t *entry, void *user_data)
    520 {
    521     uintptr_t ptr;
    522     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 
    536 /* Convert tracemalloc_traces from compact key (uintptr_t) to pointer_t key.
    537  * Return 0 on success, -1 on error. */
    538 static int
    539 tracemalloc_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 
    569 static void
    570 tracemalloc_remove_trace(unsigned int domain, uintptr_t ptr)
    571 {
    572     trace_t trace;
    573     int removed;
    574 
    575     assert(tracemalloc_config.tracing);
    576 
    577     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) \
    593             tracemalloc_remove_trace(DEFAULT_DOMAIN, (uintptr_t)(ptr))
    594 
    595 
    596 static int
    597 tracemalloc_add_trace(unsigned int domain, uintptr_t ptr,
    598                       size_t size)
    599 {
    600     pointer_t key = {ptr, domain};
    601     traceback_t *traceback;
    602     trace_t trace;
    603     _Py_hashtable_entry_t* entry;
    604     int res;
    605 
    606     assert(tracemalloc_config.tracing);
    607 
    608     traceback = traceback_new();
    609     if (traceback == NULL) {
    610         return -1;
    611     }
    612 
    613     if (!tracemalloc_config.use_domain && domain != DEFAULT_DOMAIN) {
    614         /* first trace using a non-zero domain whereas traces use compact
    615            (uintptr_t) keys: switch to pointer_t keys. */
    616         if (tracemalloc_use_domain() < 0) {
    617             return -1;
    618         }
    619     }
    620 
    621     if (tracemalloc_config.use_domain) {
    622         entry = _Py_HASHTABLE_GET_ENTRY(tracemalloc_traces, key);
    623     }
    624     else {
    625         entry = _Py_HASHTABLE_GET_ENTRY(tracemalloc_traces, ptr);
    626     }
    627 
    628     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         }
    651     }
    652 
    653     assert(tracemalloc_traced_memory <= SIZE_MAX - size);
    654     tracemalloc_traced_memory += size;
    655     if (tracemalloc_traced_memory > tracemalloc_peak_traced_memory)
    656         tracemalloc_peak_traced_memory = tracemalloc_traced_memory;
    657     return 0;
    658 }
    659 
    660 #define ADD_TRACE(ptr, size) \
    661             tracemalloc_add_trace(DEFAULT_DOMAIN, (uintptr_t)(ptr), size)
    662 
    663 
    664 static void*
    665 tracemalloc_alloc(int use_calloc, void *ctx, size_t nelem, size_t elsize)
    666 {
    667     PyMemAllocatorEx *alloc = (PyMemAllocatorEx *)ctx;
    668     void *ptr;
    669 
    670     assert(elsize == 0 || nelem <= SIZE_MAX / elsize);
    671 
    672     if (use_calloc)
    673         ptr = alloc->calloc(alloc->ctx, nelem, elsize);
    674     else
    675         ptr = alloc->malloc(alloc->ctx, nelem * elsize);
    676     if (ptr == NULL)
    677         return NULL;
    678 
    679     TABLES_LOCK();
    680     if (ADD_TRACE(ptr, nelem * elsize) < 0) {
    681         /* Failed to allocate a trace for the new memory block */
    682         TABLES_UNLOCK();
    683         alloc->free(alloc->ctx, ptr);
    684         return NULL;
    685     }
    686     TABLES_UNLOCK();
    687     return ptr;
    688 }
    689 
    690 
    691 static void*
    692 tracemalloc_realloc(void *ctx, void *ptr, size_t new_size)
    693 {
    694     PyMemAllocatorEx *alloc = (PyMemAllocatorEx *)ctx;
    695     void *ptr2;
    696 
    697     ptr2 = alloc->realloc(alloc->ctx, ptr, new_size);
    698     if (ptr2 == NULL)
    699         return NULL;
    700 
    701     if (ptr != NULL) {
    702         /* an existing memory block has been resized */
    703 
    704         TABLES_LOCK();
    705 
    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         }
    711 
    712         if (ADD_TRACE(ptr2, new_size) < 0) {
    713             /* Memory allocation failed. The error cannot be reported to
    714                the caller, because realloc() may already have shrunk the
    715                memory block and so removed bytes.
    716 
    717                This case is very unlikely: a hash entry has just been
    718                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. */
    722             Py_UNREACHABLE();
    723         }
    724         TABLES_UNLOCK();
    725     }
    726     else {
    727         /* new allocation */
    728 
    729         TABLES_LOCK();
    730         if (ADD_TRACE(ptr2, new_size) < 0) {
    731             /* Failed to allocate a trace for the new memory block */
    732             TABLES_UNLOCK();
    733             alloc->free(alloc->ctx, ptr2);
    734             return NULL;
    735         }
    736         TABLES_UNLOCK();
    737     }
    738     return ptr2;
    739 }
    740 
    741 
    742 static void
    743 tracemalloc_free(void *ctx, void *ptr)
    744 {
    745     PyMemAllocatorEx *alloc = (PyMemAllocatorEx *)ctx;
    746 
    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);
    754 
    755     TABLES_LOCK();
    756     REMOVE_TRACE(ptr);
    757     TABLES_UNLOCK();
    758 }
    759 
    760 
    761 static void*
    762 tracemalloc_alloc_gil(int use_calloc, void *ctx, size_t nelem, size_t elsize)
    763 {
    764     void *ptr;
    765 
    766     if (get_reentrant()) {
    767         PyMemAllocatorEx *alloc = (PyMemAllocatorEx *)ctx;
    768         if (use_calloc)
    769             return alloc->calloc(alloc->ctx, nelem, elsize);
    770         else
    771             return alloc->malloc(alloc->ctx, nelem * elsize);
    772     }
    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 
    779     ptr = tracemalloc_alloc(use_calloc, ctx, nelem, elsize);
    780 
    781     set_reentrant(0);
    782     return ptr;
    783 }
    784 
    785 
    786 static void*
    787 tracemalloc_malloc_gil(void *ctx, size_t size)
    788 {
    789     return tracemalloc_alloc_gil(0, ctx, 1, size);
    790 }
    791 
    792 
    793 static void*
    794 tracemalloc_calloc_gil(void *ctx, size_t nelem, size_t elsize)
    795 {
    796     return tracemalloc_alloc_gil(1, ctx, nelem, elsize);
    797 }
    798 
    799 
    800 static void*
    801 tracemalloc_realloc_gil(void *ctx, void *ptr, size_t new_size)
    802 {
    803     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()). */
    810         PyMemAllocatorEx *alloc = (PyMemAllocatorEx *)ctx;
    811 
    812         ptr2 = alloc->realloc(alloc->ctx, ptr, new_size);
    813         if (ptr2 != NULL && ptr != NULL) {
    814             TABLES_LOCK();
    815             REMOVE_TRACE(ptr);
    816             TABLES_UNLOCK();
    817         }
    818         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;
    830 }
    831 
    832 
    833 #ifdef TRACE_RAW_MALLOC
    834 static void*
    835 tracemalloc_raw_alloc(int use_calloc, void *ctx, size_t nelem, size_t elsize)
    836 {
    837     PyGILState_STATE gil_state;
    838     void *ptr;
    839 
    840     if (get_reentrant()) {
    841         PyMemAllocatorEx *alloc = (PyMemAllocatorEx *)ctx;
    842         if (use_calloc)
    843             return alloc->calloc(alloc->ctx, nelem, elsize);
    844         else
    845             return alloc->malloc(alloc->ctx, nelem * elsize);
    846     }
    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 
    853     gil_state = PyGILState_Ensure();
    854     ptr = tracemalloc_alloc(use_calloc, ctx, nelem, elsize);
    855     PyGILState_Release(gil_state);
    856 
    857     set_reentrant(0);
    858     return ptr;
    859 }
    860 
    861 
    862 static void*
    863 tracemalloc_raw_malloc(void *ctx, size_t size)
    864 {
    865     return tracemalloc_raw_alloc(0, ctx, 1, size);
    866 }
    867 
    868 
    869 static void*
    870 tracemalloc_raw_calloc(void *ctx, size_t nelem, size_t elsize)
    871 {
    872     return tracemalloc_raw_alloc(1, ctx, nelem, elsize);
    873 }
    874 
    875 
    876 static void*
    877 tracemalloc_raw_realloc(void *ctx, void *ptr, size_t new_size)
    878 {
    879     PyGILState_STATE gil_state;
    880     void *ptr2;
    881 
    882     if (get_reentrant()) {
    883         /* Reentrant call to PyMem_RawRealloc(). */
    884         PyMemAllocatorEx *alloc = (PyMemAllocatorEx *)ctx;
    885 
    886         ptr2 = alloc->realloc(alloc->ctx, ptr, new_size);
    887 
    888         if (ptr2 != NULL && ptr != NULL) {
    889             TABLES_LOCK();
    890             REMOVE_TRACE(ptr);
    891             TABLES_UNLOCK();
    892         }
    893         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 
    901     gil_state = PyGILState_Ensure();
    902     ptr2 = tracemalloc_realloc(ctx, ptr, new_size);
    903     PyGILState_Release(gil_state);
    904 
    905     set_reentrant(0);
    906     return ptr2;
    907 }
    908 #endif   /* TRACE_RAW_MALLOC */
    909 
    910 
    911 static int
    912 tracemalloc_clear_filename(_Py_hashtable_t *ht, _Py_hashtable_entry_t *entry,
    913                            void *user_data)
    914 {
    915     PyObject *filename;
    916 
    917     _Py_HASHTABLE_ENTRY_READ_KEY(ht, entry, filename);
    918     Py_DECREF(filename);
    919     return 0;
    920 }
    921 
    922 
    923 static int
    924 traceback_free_traceback(_Py_hashtable_t *ht, _Py_hashtable_entry_t *entry,
    925                          void *user_data)
    926 {
    927     traceback_t *traceback;
    928 
    929     _Py_HASHTABLE_ENTRY_READ_KEY(ht, entry, traceback);
    930     raw_free(traceback);
    931     return 0;
    932 }
    933 
    934 
    935 /* reentrant flag must be set to call this function and GIL must be held */
    936 static void
    937 tracemalloc_clear_traces(void)
    938 {
    939     /* The GIL protects variables againt concurrent access */
    940     assert(PyGILState_Check());
    941 
    942     TABLES_LOCK();
    943     _Py_hashtable_clear(tracemalloc_traces);
    944     tracemalloc_traced_memory = 0;
    945     tracemalloc_peak_traced_memory = 0;
    946     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 
    955 
    956 static int
    957 tracemalloc_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 
    965     if (tracemalloc_config.initialized == TRACEMALLOC_INITIALIZED)
    966         return 0;
    967 
    968     PyMem_GetAllocator(PYMEM_DOMAIN_RAW, &allocators.raw);
    969 
    970 #ifdef REENTRANT_THREADLOCAL
    971     if (PyThread_tss_create(&tracemalloc_reentrant_key) != 0) {
    972 #ifdef MS_WINDOWS
    973         PyErr_SetFromWindowsErr(0);
    974 #else
    975         PyErr_SetFromErrno(PyExc_OSError);
    976 #endif
    977         return -1;
    978     }
    979 #endif
    980 
    981 #if defined(TRACE_RAW_MALLOC)
    982     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 
    991     tracemalloc_filenames = hashtable_new(sizeof(PyObject *), 0,
    992                                           hashtable_hash_pyobject,
    993                                           hashtable_compare_unicode);
    994 
    995     tracemalloc_tracebacks = hashtable_new(sizeof(traceback_t *), 0,
    996                                            hashtable_hash_traceback,
    997                                            hashtable_compare_traceback);
    998 
    999     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 {
   1006         tracemalloc_traces = hashtable_new(sizeof(uintptr_t),
   1007                                            sizeof(trace_t),
   1008                                            _Py_hashtable_hash_ptr,
   1009                                            _Py_hashtable_compare_direct);
   1010     }
   1011 
   1012     if (tracemalloc_filenames == NULL || tracemalloc_tracebacks == NULL
   1013        || tracemalloc_traces == NULL) {
   1014         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 
   1029     tracemalloc_config.initialized = TRACEMALLOC_INITIALIZED;
   1030     return 0;
   1031 }
   1032 
   1033 
   1034 static void
   1035 tracemalloc_deinit(void)
   1036 {
   1037     if (tracemalloc_config.initialized != TRACEMALLOC_INITIALIZED)
   1038         return;
   1039     tracemalloc_config.initialized = TRACEMALLOC_FINALIZED;
   1040 
   1041     tracemalloc_stop();
   1042 
   1043     /* destroy hash tables */
   1044     _Py_hashtable_destroy(tracemalloc_tracebacks);
   1045     _Py_hashtable_destroy(tracemalloc_filenames);
   1046     _Py_hashtable_destroy(tracemalloc_traces);
   1047 
   1048 #if defined(TRACE_RAW_MALLOC)
   1049     if (tables_lock != NULL) {
   1050         PyThread_free_lock(tables_lock);
   1051         tables_lock = NULL;
   1052     }
   1053 #endif
   1054 
   1055 #ifdef REENTRANT_THREADLOCAL
   1056     PyThread_tss_delete(&tracemalloc_reentrant_key);
   1057 #endif
   1058 
   1059     Py_XDECREF(unknown_filename);
   1060 }
   1061 
   1062 
   1063 static int
   1064 tracemalloc_start(int max_nframe)
   1065 {
   1066     PyMemAllocatorEx alloc;
   1067     size_t size;
   1068 
   1069     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);
   1073         return -1;
   1074     }
   1075 
   1076     if (tracemalloc_init() < 0) {
   1077         return -1;
   1078     }
   1079 
   1080     if (tracemalloc_config.tracing) {
   1081         /* hook already installed: do nothing */
   1082         return 0;
   1083     }
   1084 
   1085     assert(1 <= max_nframe && max_nframe <= MAX_NFRAME);
   1086     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 
   1097 #ifdef TRACE_RAW_MALLOC
   1098     alloc.malloc = tracemalloc_raw_malloc;
   1099     alloc.calloc = tracemalloc_raw_calloc;
   1100     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;
   1109     alloc.calloc = tracemalloc_calloc_gil;
   1110     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;
   1123 
   1124     return 0;
   1125 }
   1126 
   1127 
   1128 static void
   1129 tracemalloc_stop(void)
   1130 {
   1131     if (!tracemalloc_config.tracing)
   1132         return;
   1133 
   1134     /* stop tracing Python memory allocations */
   1135     tracemalloc_config.tracing = 0;
   1136 
   1137     /* 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 
   1144     tracemalloc_clear_traces();
   1145 
   1146     /* release memory */
   1147     raw_free(tracemalloc_traceback);
   1148     tracemalloc_traceback = NULL;
   1149 }
   1150 
   1151 
   1152 
   1153 /*[clinic input]
   1154 _tracemalloc.is_tracing
   1155 
   1156 Return True if the tracemalloc module is tracing Python memory allocations.
   1157 [clinic start generated code]*/
   1158 
   1159 static PyObject *
   1160 _tracemalloc_is_tracing_impl(PyObject *module)
   1161 /*[clinic end generated code: output=2d763b42601cd3ef input=af104b0a00192f63]*/
   1162 {
   1163     return PyBool_FromLong(tracemalloc_config.tracing);
   1164 }
   1165 
   1166 
   1167 /*[clinic input]
   1168 _tracemalloc.clear_traces
   1169 
   1170 Clear traces of memory blocks allocated by Python.
   1171 [clinic start generated code]*/
   1172 
   1173 static PyObject *
   1174 _tracemalloc_clear_traces_impl(PyObject *module)
   1175 /*[clinic end generated code: output=a86080ee41b84197 input=0dab5b6c785183a5]*/
   1176 {
   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 
   1187 
   1188 static PyObject*
   1189 frame_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 
   1197     Py_INCREF(frame->filename);
   1198     PyTuple_SET_ITEM(frame_obj, 0, frame->filename);
   1199 
   1200     lineno_obj = PyLong_FromUnsignedLong(frame->lineno);
   1201     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 
   1210 
   1211 static PyObject*
   1212 traceback_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 
   1249 
   1250 static PyObject*
   1251 trace_to_pyobject(unsigned int domain, trace_t *trace,
   1252                   _Py_hashtable_t *intern_tracebacks)
   1253 {
   1254     PyObject *trace_obj = NULL;
   1255     PyObject *obj;
   1256 
   1257     trace_obj = PyTuple_New(3);
   1258     if (trace_obj == NULL)
   1259         return NULL;
   1260 
   1261     obj = PyLong_FromSize_t(domain);
   1262     if (obj == NULL) {
   1263         Py_DECREF(trace_obj);
   1264         return NULL;
   1265     }
   1266     PyTuple_SET_ITEM(trace_obj, 0, obj);
   1267 
   1268     obj = PyLong_FromSize_t(trace->size);
   1269     if (obj == NULL) {
   1270         Py_DECREF(trace_obj);
   1271         return NULL;
   1272     }
   1273     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);
   1281 
   1282     return trace_obj;
   1283 }
   1284 
   1285 
   1286 typedef struct {
   1287     _Py_hashtable_t *traces;
   1288     _Py_hashtable_t *tracebacks;
   1289     PyObject *list;
   1290 } get_traces_t;
   1291 
   1292 static int
   1293 tracemalloc_get_traces_fill(_Py_hashtable_t *traces, _Py_hashtable_entry_t *entry,
   1294                             void *user_data)
   1295 {
   1296     get_traces_t *get_traces = user_data;
   1297     unsigned int domain;
   1298     trace_t trace;
   1299     PyObject *tracemalloc_obj;
   1300     int res;
   1301 
   1302     if (tracemalloc_config.use_domain) {
   1303         pointer_t key;
   1304         _Py_HASHTABLE_ENTRY_READ_KEY(traces, entry, key);
   1305         domain = key.domain;
   1306     }
   1307     else {
   1308         domain = DEFAULT_DOMAIN;
   1309     }
   1310     _Py_HASHTABLE_ENTRY_READ_DATA(traces, entry, trace);
   1311 
   1312     tracemalloc_obj = trace_to_pyobject(domain, &trace, get_traces->tracebacks);
   1313     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 
   1324 
   1325 static int
   1326 tracemalloc_pyobject_decref_cb(_Py_hashtable_t *tracebacks,
   1327                                _Py_hashtable_entry_t *entry,
   1328                                void *user_data)
   1329 {
   1330     PyObject *obj;
   1331     _Py_HASHTABLE_ENTRY_READ_DATA(tracebacks, entry, obj);
   1332     Py_DECREF(obj);
   1333     return 0;
   1334 }
   1335 
   1336 
   1337 
   1338 /*[clinic input]
   1339 _tracemalloc._get_traces
   1340 
   1341 Get traces of all memory blocks allocated by Python.
   1342 
   1343 Return a list of (size: int, traceback: tuple) tuples.
   1344 traceback is a tuple of (filename: str, lineno: int) tuples.
   1345 
   1346 Return an empty list if the tracemalloc module is disabled.
   1347 [clinic start generated code]*/
   1348 
   1349 static PyObject *
   1350 _tracemalloc__get_traces_impl(PyObject *module)
   1351 /*[clinic end generated code: output=e9929876ced4b5cc input=6c7d2230b24255aa]*/
   1352 {
   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 
   1365     /* the traceback hash table is used temporarily to intern traceback tuple
   1366        of (filename, lineno) tuples */
   1367     get_traces.tracebacks = hashtable_new(sizeof(traceback_t *),
   1368                                           sizeof(PyObject *),
   1369                                           _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 
   1394 error:
   1395     Py_CLEAR(get_traces.list);
   1396 
   1397 finally:
   1398     if (get_traces.tracebacks != NULL) {
   1399         _Py_hashtable_foreach(get_traces.tracebacks,
   1400                               tracemalloc_pyobject_decref_cb, NULL);
   1401         _Py_hashtable_destroy(get_traces.tracebacks);
   1402     }
   1403     if (get_traces.traces != NULL) {
   1404         _Py_hashtable_destroy(get_traces.traces);
   1405     }
   1406 
   1407     return get_traces.list;
   1408 }
   1409 
   1410 
   1411 static traceback_t*
   1412 tracemalloc_get_traceback(unsigned int domain, uintptr_t ptr)
   1413 {
   1414     trace_t trace;
   1415     int found;
   1416 
   1417     if (!tracemalloc_config.tracing)
   1418         return NULL;
   1419 
   1420     TABLES_LOCK();
   1421     if (tracemalloc_config.use_domain) {
   1422         pointer_t key = {ptr, domain};
   1423         found = _Py_HASHTABLE_GET(tracemalloc_traces, key, trace);
   1424     }
   1425     else {
   1426         found = _Py_HASHTABLE_GET(tracemalloc_traces, ptr, trace);
   1427     }
   1428     TABLES_UNLOCK();
   1429 
   1430     if (!found)
   1431         return NULL;
   1432 
   1433     return trace.traceback;
   1434 }
   1435 
   1436 
   1437 
   1438 /*[clinic input]
   1439 _tracemalloc._get_object_traceback
   1440 
   1441     obj: object
   1442     /
   1443 
   1444 Get the traceback where the Python object obj was allocated.
   1445 
   1446 Return a tuple of (filename: str, lineno: int) tuples.
   1447 Return None if the tracemalloc module is disabled or did not
   1448 trace the allocation of the object.
   1449 [clinic start generated code]*/
   1450 
   1451 static PyObject *
   1452 _tracemalloc__get_object_traceback(PyObject *module, PyObject *obj)
   1453 /*[clinic end generated code: output=41ee0553a658b0aa input=29495f1b21c53212]*/
   1454 {
   1455     PyTypeObject *type;
   1456     void *ptr;
   1457     traceback_t *traceback;
   1458 
   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 
   1465     traceback = tracemalloc_get_traceback(DEFAULT_DOMAIN, (uintptr_t)ptr);
   1466     if (traceback == NULL)
   1467         Py_RETURN_NONE;
   1468 
   1469     return traceback_to_pyobject(traceback, NULL);
   1470 }
   1471 
   1472 
   1473 #define PUTS(fd, str) _Py_write_noraise(fd, str, (int)strlen(str))
   1474 
   1475 static 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. */
   1487 void
   1488 _PyMem_DumpTraceback(int fd, const void *ptr)
   1489 {
   1490     traceback_t *traceback;
   1491     int i;
   1492 
   1493     if (!tracemalloc_config.tracing) {
   1494         PUTS(fd, "Enable tracemalloc to get the memory block "
   1495                  "allocation traceback\n\n");
   1496         return;
   1497     }
   1498 
   1499     traceback = tracemalloc_get_traceback(DEFAULT_DOMAIN, (uintptr_t)ptr);
   1500     if (traceback == NULL)
   1501         return;
   1502 
   1503     PUTS(fd, "Memory block allocated at (most recent call first):\n");
   1504     for (i=0; i < traceback->nframe; i++) {
   1505         _PyMem_DumpFrame(fd, &traceback->frames[i]);
   1506     }
   1507     PUTS(fd, "\n");
   1508 }
   1509 
   1510 #undef PUTS
   1511 
   1512 
   1513 
   1514 /*[clinic input]
   1515 _tracemalloc.start
   1516 
   1517     nframe: int = 1
   1518     /
   1519 
   1520 Start tracing Python memory allocations.
   1521 
   1522 Also set the maximum number of frames stored in the traceback of a
   1523 trace to nframe.
   1524 [clinic start generated code]*/
   1525 
   1526 static PyObject *
   1527 _tracemalloc_start_impl(PyObject *module, int nframe)
   1528 /*[clinic end generated code: output=caae05c23c159d3c input=40d849b5b29d1933]*/
   1529 {
   1530     if (tracemalloc_start(nframe) < 0) {
   1531         return NULL;
   1532     }
   1533     Py_RETURN_NONE;
   1534 }
   1535 
   1536 
   1537 /*[clinic input]
   1538 _tracemalloc.stop
   1539 
   1540 Stop tracing Python memory allocations.
   1541 
   1542 Also clear traces of memory blocks allocated by Python.
   1543 [clinic start generated code]*/
   1544 
   1545 static PyObject *
   1546 _tracemalloc_stop_impl(PyObject *module)
   1547 /*[clinic end generated code: output=c3c42ae03e3955cd input=7478f075e51dae18]*/
   1548 {
   1549     tracemalloc_stop();
   1550     Py_RETURN_NONE;
   1551 }
   1552 
   1553 
   1554 /*[clinic input]
   1555 _tracemalloc.get_traceback_limit
   1556 
   1557 Get the maximum number of frames stored in the traceback of a trace.
   1558 
   1559 By default, a trace of an allocated memory block only stores
   1560 the most recent frame: the limit is 1.
   1561 [clinic start generated code]*/
   1562 
   1563 static PyObject *
   1564 _tracemalloc_get_traceback_limit_impl(PyObject *module)
   1565 /*[clinic end generated code: output=d556d9306ba95567 input=da3cd977fc68ae3b]*/
   1566 {
   1567     return PyLong_FromLong(tracemalloc_config.max_nframe);
   1568 }
   1569 
   1570 
   1571 
   1572 /*[clinic input]
   1573 _tracemalloc.get_tracemalloc_memory
   1574 
   1575 Get the memory usage in bytes of the tracemalloc module.
   1576 
   1577 This memory is used internally to trace memory allocations.
   1578 [clinic start generated code]*/
   1579 
   1580 static PyObject *
   1581 _tracemalloc_get_tracemalloc_memory_impl(PyObject *module)
   1582 /*[clinic end generated code: output=e3f14e280a55f5aa input=5d919c0f4d5132ad]*/
   1583 {
   1584     size_t size;
   1585 
   1586     size = _Py_hashtable_size(tracemalloc_tracebacks);
   1587     size += _Py_hashtable_size(tracemalloc_filenames);
   1588 
   1589     TABLES_LOCK();
   1590     size += _Py_hashtable_size(tracemalloc_traces);
   1591     TABLES_UNLOCK();
   1592 
   1593     return PyLong_FromSize_t(size);
   1594 }
   1595 
   1596 
   1597 
   1598 /*[clinic input]
   1599 _tracemalloc.get_traced_memory
   1600 
   1601 Get the current size and peak size of memory blocks traced by tracemalloc.
   1602 
   1603 Returns a tuple: (current: int, peak: int).
   1604 [clinic start generated code]*/
   1605 
   1606 static PyObject *
   1607 _tracemalloc_get_traced_memory_impl(PyObject *module)
   1608 /*[clinic end generated code: output=5b167189adb9e782 input=61ddb5478400ff66]*/
   1609 {
   1610     Py_ssize_t size, peak_size;
   1611 
   1612     if (!tracemalloc_config.tracing)
   1613         return Py_BuildValue("ii", 0, 0);
   1614 
   1615     TABLES_LOCK();
   1616     size = tracemalloc_traced_memory;
   1617     peak_size = tracemalloc_peak_traced_memory;
   1618     TABLES_UNLOCK();
   1619 
   1620     return Py_BuildValue("nn", size, peak_size);
   1621 }
   1622 
   1623 
   1624 static PyMethodDef module_methods[] = {
   1625     _TRACEMALLOC_IS_TRACING_METHODDEF
   1626     _TRACEMALLOC_CLEAR_TRACES_METHODDEF
   1627     _TRACEMALLOC__GET_TRACES_METHODDEF
   1628     _TRACEMALLOC__GET_OBJECT_TRACEBACK_METHODDEF
   1629     _TRACEMALLOC_START_METHODDEF
   1630     _TRACEMALLOC_STOP_METHODDEF
   1631     _TRACEMALLOC_GET_TRACEBACK_LIMIT_METHODDEF
   1632     _TRACEMALLOC_GET_TRACEMALLOC_MEMORY_METHODDEF
   1633     _TRACEMALLOC_GET_TRACED_MEMORY_METHODDEF
   1634     /* sentinel */
   1635     {NULL, NULL}
   1636 };
   1637 
   1638 PyDoc_STRVAR(module_doc,
   1639 "Debug module to trace memory blocks allocated by Python.");
   1640 
   1641 static struct PyModuleDef module_def = {
   1642     PyModuleDef_HEAD_INIT,
   1643     "_tracemalloc",
   1644     module_doc,
   1645     0, /* non-negative size to be able to unload the module */
   1646     module_methods,
   1647     NULL,
   1648 };
   1649 
   1650 PyMODINIT_FUNC
   1651 PyInit__tracemalloc(void)
   1652 {
   1653     PyObject *m;
   1654     m = PyModule_Create(&module_def);
   1655     if (m == NULL)
   1656         return NULL;
   1657 
   1658     if (tracemalloc_init() < 0)
   1659         return NULL;
   1660 
   1661     return m;
   1662 }
   1663 
   1664 
   1665 int
   1666 _PyTraceMalloc_Init(int nframe)
   1667 {
   1668     assert(PyGILState_Check());
   1669     if (nframe == 0) {
   1670         return 0;
   1671     }
   1672     return tracemalloc_start(nframe);
   1673 }
   1674 
   1675 
   1676 void
   1677 _PyTraceMalloc_Fini(void)
   1678 {
   1679     assert(PyGILState_Check());
   1680     tracemalloc_deinit();
   1681 }
   1682 
   1683 int
   1684 PyTraceMalloc_Track(unsigned int domain, uintptr_t ptr,
   1685                     size_t size)
   1686 {
   1687     int res;
   1688     PyGILState_STATE gil_state;
   1689 
   1690     if (!tracemalloc_config.tracing) {
   1691         /* tracemalloc is not tracing: do nothing */
   1692         return -2;
   1693     }
   1694 
   1695     gil_state = PyGILState_Ensure();
   1696 
   1697     TABLES_LOCK();
   1698     res = tracemalloc_add_trace(domain, ptr, size);
   1699     TABLES_UNLOCK();
   1700 
   1701     PyGILState_Release(gil_state);
   1702     return res;
   1703 }
   1704 
   1705 
   1706 int
   1707 PyTraceMalloc_Untrack(unsigned int domain, uintptr_t ptr)
   1708 {
   1709     if (!tracemalloc_config.tracing) {
   1710         /* tracemalloc is not tracing: do nothing */
   1711         return -2;
   1712     }
   1713 
   1714     TABLES_LOCK();
   1715     tracemalloc_remove_trace(domain, ptr);
   1716     TABLES_UNLOCK();
   1717 
   1718     return 0;
   1719 }
   1720 
   1721 
   1722 PyObject*
   1723 _PyTraceMalloc_GetTraceback(unsigned int domain, uintptr_t ptr)
   1724 {
   1725     traceback_t *traceback;
   1726 
   1727     traceback = tracemalloc_get_traceback(domain, ptr);
   1728     if (traceback == NULL)
   1729         Py_RETURN_NONE;
   1730 
   1731     return traceback_to_pyobject(traceback, NULL);
   1732 }
   1733