diff options
author | shadchin <shadchin@yandex-team.ru> | 2022-02-10 16:44:30 +0300 |
---|---|---|
committer | Daniil Cherednik <dcherednik@yandex-team.ru> | 2022-02-10 16:44:30 +0300 |
commit | 2598ef1d0aee359b4b6d5fdd1758916d5907d04f (patch) | |
tree | 012bb94d777798f1f56ac1cec429509766d05181 /contrib/tools/python3/src/Modules/_tracemalloc.c | |
parent | 6751af0b0c1b952fede40b19b71da8025b5d8bcf (diff) | |
download | ydb-2598ef1d0aee359b4b6d5fdd1758916d5907d04f.tar.gz |
Restoring authorship annotation for <shadchin@yandex-team.ru>. Commit 1 of 2.
Diffstat (limited to 'contrib/tools/python3/src/Modules/_tracemalloc.c')
-rw-r--r-- | contrib/tools/python3/src/Modules/_tracemalloc.c | 908 |
1 files changed, 454 insertions, 454 deletions
diff --git a/contrib/tools/python3/src/Modules/_tracemalloc.c b/contrib/tools/python3/src/Modules/_tracemalloc.c index 4c8f3c4cd8..fe11262674 100644 --- a/contrib/tools/python3/src/Modules/_tracemalloc.c +++ b/contrib/tools/python3/src/Modules/_tracemalloc.c @@ -1,9 +1,9 @@ #include "Python.h" -#include "pycore_gc.h" // PyGC_Head -#include "pycore_pymem.h" // _Py_tracemalloc_config -#include "pycore_traceback.h" -#include "pycore_hashtable.h" -#include "frameobject.h" // PyFrame_GetBack() +#include "pycore_gc.h" // PyGC_Head +#include "pycore_pymem.h" // _Py_tracemalloc_config +#include "pycore_traceback.h" +#include "pycore_hashtable.h" +#include "frameobject.h" // PyFrame_GetBack() #include "clinic/_tracemalloc.c.h" /*[clinic input] @@ -23,9 +23,9 @@ static void raw_free(void *ptr); # define TRACE_DEBUG #endif -#define TO_PTR(key) ((const void *)(uintptr_t)(key)) -#define FROM_PTR(key) ((uintptr_t)(key)) - +#define TO_PTR(key) ((const void *)(uintptr_t)(key)) +#define FROM_PTR(key) ((uintptr_t)(key)) + /* Protected by the GIL */ static struct { PyMemAllocatorEx mem; @@ -37,7 +37,7 @@ static struct { #if defined(TRACE_RAW_MALLOC) /* This lock is needed because tracemalloc_free() is called without the GIL held from PyMem_RawFree(). It cannot acquire the lock because it - would introduce a deadlock in _PyThreadState_DeleteCurrent(). */ + would introduce a deadlock in _PyThreadState_DeleteCurrent(). */ static PyThread_type_lock tables_lock; # define TABLES_LOCK() PyThread_acquire_lock(tables_lock, 1) # define TABLES_UNLOCK() PyThread_release_lock(tables_lock) @@ -71,20 +71,20 @@ __attribute__((packed)) typedef struct { Py_uhash_t hash; - /* Number of frames stored */ - uint16_t nframe; - /* Total number of frames the traceback had */ - uint16_t total_nframe; + /* Number of frames stored */ + uint16_t nframe; + /* Total number of frames the traceback had */ + uint16_t total_nframe; frame_t frames[1]; } traceback_t; #define TRACEBACK_SIZE(NFRAME) \ (sizeof(traceback_t) + sizeof(frame_t) * (NFRAME - 1)) -/* The maximum number of frames is either: - - The maximum number of frames we can store in `traceback_t.nframe` - - The maximum memory size_t we can allocate */ -static const unsigned long MAX_NFRAME = Py_MIN(UINT16_MAX, ((SIZE_MAX - sizeof(traceback_t)) / sizeof(frame_t) + 1)); +/* The maximum number of frames is either: + - The maximum number of frames we can store in `traceback_t.nframe` + - The maximum memory size_t we can allocate */ +static const unsigned long MAX_NFRAME = Py_MIN(UINT16_MAX, ((SIZE_MAX - sizeof(traceback_t)) / sizeof(frame_t) + 1)); static PyObject *unknown_filename = NULL; @@ -122,15 +122,15 @@ static traceback_t *tracemalloc_traceback = NULL; Protected by the GIL */ static _Py_hashtable_t *tracemalloc_tracebacks = NULL; -/* pointer (void*) => trace (trace_t*). +/* pointer (void*) => trace (trace_t*). Protected by TABLES_LOCK(). */ static _Py_hashtable_t *tracemalloc_traces = NULL; -/* domain (unsigned int) => traces (_Py_hashtable_t). - Protected by TABLES_LOCK(). */ -static _Py_hashtable_t *tracemalloc_domains = NULL; - +/* domain (unsigned int) => traces (_Py_hashtable_t). + Protected by TABLES_LOCK(). */ +static _Py_hashtable_t *tracemalloc_domains = NULL; + #ifdef TRACE_DEBUG static void tracemalloc_error(const char *format, ...) @@ -206,44 +206,44 @@ set_reentrant(int reentrant) static Py_uhash_t -hashtable_hash_pyobject(const void *key) +hashtable_hash_pyobject(const void *key) { - PyObject *obj = (PyObject *)key; + PyObject *obj = (PyObject *)key; return PyObject_Hash(obj); } static int -hashtable_compare_unicode(const void *key1, const void *key2) +hashtable_compare_unicode(const void *key1, const void *key2) { - PyObject *obj1 = (PyObject *)key1; - PyObject *obj2 = (PyObject *)key2; - if (obj1 != NULL && obj2 != NULL) { - return (PyUnicode_Compare(obj1, obj2) == 0); - } - else { - return obj1 == obj2; - } + PyObject *obj1 = (PyObject *)key1; + PyObject *obj2 = (PyObject *)key2; + if (obj1 != NULL && obj2 != NULL) { + return (PyUnicode_Compare(obj1, obj2) == 0); + } + else { + return obj1 == obj2; + } } static Py_uhash_t -hashtable_hash_uint(const void *key_raw) +hashtable_hash_uint(const void *key_raw) { - unsigned int key = (unsigned int)FROM_PTR(key_raw); - return (Py_uhash_t)key; + unsigned int key = (unsigned int)FROM_PTR(key_raw); + return (Py_uhash_t)key; } static _Py_hashtable_t * -hashtable_new(_Py_hashtable_hash_func hash_func, - _Py_hashtable_compare_func compare_func, - _Py_hashtable_destroy_func key_destroy_func, - _Py_hashtable_destroy_func value_destroy_func) +hashtable_new(_Py_hashtable_hash_func hash_func, + _Py_hashtable_compare_func compare_func, + _Py_hashtable_destroy_func key_destroy_func, + _Py_hashtable_destroy_func value_destroy_func) { _Py_hashtable_allocator_t hashtable_alloc = {malloc, free}; - return _Py_hashtable_new_full(hash_func, compare_func, - key_destroy_func, value_destroy_func, + return _Py_hashtable_new_full(hash_func, compare_func, + key_destroy_func, value_destroy_func, &hashtable_alloc); } @@ -262,33 +262,33 @@ raw_free(void *ptr) static Py_uhash_t -hashtable_hash_traceback(const void *key) +hashtable_hash_traceback(const void *key) { - const traceback_t *traceback = (const traceback_t *)key; + const traceback_t *traceback = (const traceback_t *)key; return traceback->hash; } static int -hashtable_compare_traceback(const void *key1, const void *key2) +hashtable_compare_traceback(const void *key1, const void *key2) { - const traceback_t *traceback1 = (const traceback_t *)key1; - const traceback_t *traceback2 = (const traceback_t *)key2; + const traceback_t *traceback1 = (const traceback_t *)key1; + const traceback_t *traceback2 = (const traceback_t *)key2; - if (traceback1->nframe != traceback2->nframe) { - return 0; - } - if (traceback1->total_nframe != traceback2->total_nframe) { + if (traceback1->nframe != traceback2->nframe) { return 0; - } + } + if (traceback1->total_nframe != traceback2->total_nframe) { + return 0; + } - for (int i=0; i < traceback1->nframe; i++) { - const frame_t *frame1 = &traceback1->frames[i]; - const frame_t *frame2 = &traceback2->frames[i]; + for (int i=0; i < traceback1->nframe; i++) { + const frame_t *frame1 = &traceback1->frames[i]; + const frame_t *frame2 = &traceback2->frames[i]; - if (frame1->lineno != frame2->lineno) { + if (frame1->lineno != frame2->lineno) { return 0; - } + } if (frame1->filename != frame2->filename) { assert(PyUnicode_Compare(frame1->filename, frame2->filename) != 0); return 0; @@ -302,17 +302,17 @@ static void tracemalloc_get_frame(PyFrameObject *pyframe, frame_t *frame) { frame->filename = unknown_filename; - int lineno = PyFrame_GetLineNumber(pyframe); - if (lineno < 0) { + int lineno = PyFrame_GetLineNumber(pyframe); + if (lineno < 0) { lineno = 0; - } + } frame->lineno = (unsigned int)lineno; - PyCodeObject *code = PyFrame_GetCode(pyframe); - PyObject *filename = code->co_filename; - Py_DECREF(code); + PyCodeObject *code = PyFrame_GetCode(pyframe); + PyObject *filename = code->co_filename; + Py_DECREF(code); - if (filename == NULL) { + if (filename == NULL) { #ifdef TRACE_DEBUG tracemalloc_error("failed to get the filename of the code object"); #endif @@ -335,16 +335,16 @@ tracemalloc_get_frame(PyFrameObject *pyframe, frame_t *frame) } /* intern the filename */ - _Py_hashtable_entry_t *entry; - entry = _Py_hashtable_get_entry(tracemalloc_filenames, filename); + _Py_hashtable_entry_t *entry; + entry = _Py_hashtable_get_entry(tracemalloc_filenames, filename); if (entry != NULL) { - filename = (PyObject *)entry->key; + filename = (PyObject *)entry->key; } else { /* tracemalloc_filenames is responsible to keep a reference to the filename */ Py_INCREF(filename); - if (_Py_hashtable_set(tracemalloc_filenames, filename, NULL) < 0) { + if (_Py_hashtable_set(tracemalloc_filenames, filename, NULL) < 0) { Py_DECREF(filename); #ifdef TRACE_DEBUG tracemalloc_error("failed to intern the filename"); @@ -378,7 +378,7 @@ traceback_hash(traceback_t *traceback) /* the cast might truncate len; that doesn't change hash stability */ mult += (Py_uhash_t)(82520UL + len + len); } - x ^= traceback->total_nframe; + x ^= traceback->total_nframe; x += 97531UL; return x; } @@ -387,7 +387,7 @@ traceback_hash(traceback_t *traceback) static void traceback_get_frames(traceback_t *traceback) { - PyThreadState *tstate = PyGILState_GetThisThreadState(); + PyThreadState *tstate = PyGILState_GetThisThreadState(); if (tstate == NULL) { #ifdef TRACE_DEBUG tracemalloc_error("failed to get the current thread state"); @@ -395,20 +395,20 @@ traceback_get_frames(traceback_t *traceback) return; } - PyFrameObject *pyframe = PyThreadState_GetFrame(tstate); - for (; pyframe != NULL;) { - if (traceback->nframe < _Py_tracemalloc_config.max_nframe) { - tracemalloc_get_frame(pyframe, &traceback->frames[traceback->nframe]); - assert(traceback->frames[traceback->nframe].filename != NULL); - traceback->nframe++; - } - if (traceback->total_nframe < UINT16_MAX) { - traceback->total_nframe++; - } - - PyFrameObject *back = PyFrame_GetBack(pyframe); - Py_DECREF(pyframe); - pyframe = back; + PyFrameObject *pyframe = PyThreadState_GetFrame(tstate); + for (; pyframe != NULL;) { + if (traceback->nframe < _Py_tracemalloc_config.max_nframe) { + tracemalloc_get_frame(pyframe, &traceback->frames[traceback->nframe]); + assert(traceback->frames[traceback->nframe].filename != NULL); + traceback->nframe++; + } + if (traceback->total_nframe < UINT16_MAX) { + traceback->total_nframe++; + } + + PyFrameObject *back = PyFrame_GetBack(pyframe); + Py_DECREF(pyframe); + pyframe = back; } } @@ -424,16 +424,16 @@ traceback_new(void) /* get frames */ traceback = tracemalloc_traceback; traceback->nframe = 0; - traceback->total_nframe = 0; + traceback->total_nframe = 0; traceback_get_frames(traceback); if (traceback->nframe == 0) return &tracemalloc_empty_traceback; traceback->hash = traceback_hash(traceback); /* intern the traceback */ - entry = _Py_hashtable_get_entry(tracemalloc_tracebacks, traceback); + entry = _Py_hashtable_get_entry(tracemalloc_tracebacks, traceback); if (entry != NULL) { - traceback = (traceback_t *)entry->key; + traceback = (traceback_t *)entry->key; } else { traceback_t *copy; @@ -450,7 +450,7 @@ traceback_new(void) } memcpy(copy, traceback, traceback_size); - if (_Py_hashtable_set(tracemalloc_tracebacks, copy, NULL) < 0) { + if (_Py_hashtable_set(tracemalloc_tracebacks, copy, NULL) < 0) { raw_free(copy); #ifdef TRACE_DEBUG tracemalloc_error("failed to intern the traceback: putdata failed"); @@ -463,33 +463,33 @@ traceback_new(void) } -static _Py_hashtable_t* -tracemalloc_create_traces_table(void) +static _Py_hashtable_t* +tracemalloc_create_traces_table(void) { - return hashtable_new(_Py_hashtable_hash_ptr, - _Py_hashtable_compare_direct, - NULL, raw_free); -} + return hashtable_new(_Py_hashtable_hash_ptr, + _Py_hashtable_compare_direct, + NULL, raw_free); +} -static _Py_hashtable_t* -tracemalloc_create_domains_table(void) -{ - return hashtable_new(hashtable_hash_uint, - _Py_hashtable_compare_direct, - NULL, - (_Py_hashtable_destroy_func)_Py_hashtable_destroy); +static _Py_hashtable_t* +tracemalloc_create_domains_table(void) +{ + return hashtable_new(hashtable_hash_uint, + _Py_hashtable_compare_direct, + NULL, + (_Py_hashtable_destroy_func)_Py_hashtable_destroy); } -static _Py_hashtable_t* -tracemalloc_get_traces_table(unsigned int domain) +static _Py_hashtable_t* +tracemalloc_get_traces_table(unsigned int domain) { - if (domain == DEFAULT_DOMAIN) { - return tracemalloc_traces; + if (domain == DEFAULT_DOMAIN) { + return tracemalloc_traces; } - else { - return _Py_hashtable_get(tracemalloc_domains, TO_PTR(domain)); + else { + return _Py_hashtable_get(tracemalloc_domains, TO_PTR(domain)); } } @@ -497,20 +497,20 @@ tracemalloc_get_traces_table(unsigned int domain) static void tracemalloc_remove_trace(unsigned int domain, uintptr_t ptr) { - assert(_Py_tracemalloc_config.tracing); + assert(_Py_tracemalloc_config.tracing); - _Py_hashtable_t *traces = tracemalloc_get_traces_table(domain); - if (!traces) { - return; + _Py_hashtable_t *traces = tracemalloc_get_traces_table(domain); + if (!traces) { + return; } - - trace_t *trace = _Py_hashtable_steal(traces, TO_PTR(ptr)); - if (!trace) { + + trace_t *trace = _Py_hashtable_steal(traces, TO_PTR(ptr)); + if (!trace) { return; } - assert(tracemalloc_traced_memory >= trace->size); - tracemalloc_traced_memory -= trace->size; - raw_free(trace); + assert(tracemalloc_traced_memory >= trace->size); + tracemalloc_traced_memory -= trace->size; + raw_free(trace); } #define REMOVE_TRACE(ptr) \ @@ -521,55 +521,55 @@ static int tracemalloc_add_trace(unsigned int domain, uintptr_t ptr, size_t size) { - assert(_Py_tracemalloc_config.tracing); + assert(_Py_tracemalloc_config.tracing); - traceback_t *traceback = traceback_new(); + traceback_t *traceback = traceback_new(); if (traceback == NULL) { return -1; } - _Py_hashtable_t *traces = tracemalloc_get_traces_table(domain); - if (traces == NULL) { - traces = tracemalloc_create_traces_table(); - if (traces == NULL) { + _Py_hashtable_t *traces = tracemalloc_get_traces_table(domain); + if (traces == NULL) { + traces = tracemalloc_create_traces_table(); + if (traces == NULL) { return -1; } - if (_Py_hashtable_set(tracemalloc_domains, TO_PTR(domain), traces) < 0) { - _Py_hashtable_destroy(traces); - return -1; - } + if (_Py_hashtable_set(tracemalloc_domains, TO_PTR(domain), traces) < 0) { + _Py_hashtable_destroy(traces); + return -1; + } } - trace_t *trace = _Py_hashtable_get(traces, TO_PTR(ptr)); - if (trace != NULL) { + trace_t *trace = _Py_hashtable_get(traces, TO_PTR(ptr)); + if (trace != NULL) { /* the memory block is already tracked */ - assert(tracemalloc_traced_memory >= trace->size); - tracemalloc_traced_memory -= trace->size; + assert(tracemalloc_traced_memory >= trace->size); + tracemalloc_traced_memory -= trace->size; - trace->size = size; - trace->traceback = traceback; + trace->size = size; + trace->traceback = traceback; } else { - trace = raw_malloc(sizeof(trace_t)); - if (trace == NULL) { - return -1; - } - trace->size = size; - trace->traceback = traceback; - - int res = _Py_hashtable_set(traces, TO_PTR(ptr), trace); + trace = raw_malloc(sizeof(trace_t)); + if (trace == NULL) { + return -1; + } + trace->size = size; + trace->traceback = traceback; + + int res = _Py_hashtable_set(traces, TO_PTR(ptr), trace); if (res != 0) { - raw_free(trace); + raw_free(trace); return res; } } assert(tracemalloc_traced_memory <= SIZE_MAX - size); tracemalloc_traced_memory += size; - if (tracemalloc_traced_memory > tracemalloc_peak_traced_memory) { + if (tracemalloc_traced_memory > tracemalloc_peak_traced_memory) { tracemalloc_peak_traced_memory = tracemalloc_traced_memory; - } + } return 0; } @@ -620,7 +620,7 @@ tracemalloc_realloc(void *ctx, void *ptr, size_t new_size) TABLES_LOCK(); /* tracemalloc_add_trace() updates the trace if there is already - a trace at address ptr2 */ + a trace at address ptr2 */ if (ptr2 != ptr) { REMOVE_TRACE(ptr); } @@ -635,7 +635,7 @@ tracemalloc_realloc(void *ctx, void *ptr, size_t new_size) The GIL and the table lock ensures that only one thread is allocating memory. */ - Py_FatalError("tracemalloc_realloc() failed to allocate a trace"); + Py_FatalError("tracemalloc_realloc() failed to allocate a trace"); } TABLES_UNLOCK(); } @@ -664,7 +664,7 @@ tracemalloc_free(void *ctx, void *ptr) return; /* GIL cannot be locked in PyMem_RawFree() because it would introduce - a deadlock in _PyThreadState_DeleteCurrent(). */ + a deadlock in _PyThreadState_DeleteCurrent(). */ alloc->free(alloc->ctx, ptr); @@ -824,10 +824,10 @@ tracemalloc_raw_realloc(void *ctx, void *ptr, size_t new_size) #endif /* TRACE_RAW_MALLOC */ -static void -tracemalloc_clear_filename(void *value) +static void +tracemalloc_clear_filename(void *value) { - PyObject *filename = (PyObject *)value; + PyObject *filename = (PyObject *)value; Py_DECREF(filename); } @@ -836,12 +836,12 @@ tracemalloc_clear_filename(void *value) static void tracemalloc_clear_traces(void) { - /* The GIL protects variables against concurrent access */ + /* The GIL protects variables against concurrent access */ assert(PyGILState_Check()); TABLES_LOCK(); _Py_hashtable_clear(tracemalloc_traces); - _Py_hashtable_clear(tracemalloc_domains); + _Py_hashtable_clear(tracemalloc_domains); tracemalloc_traced_memory = 0; tracemalloc_peak_traced_memory = 0; TABLES_UNLOCK(); @@ -855,13 +855,13 @@ tracemalloc_clear_traces(void) static int tracemalloc_init(void) { - if (_Py_tracemalloc_config.initialized == TRACEMALLOC_FINALIZED) { + if (_Py_tracemalloc_config.initialized == TRACEMALLOC_FINALIZED) { PyErr_SetString(PyExc_RuntimeError, "the tracemalloc module has been unloaded"); return -1; } - if (_Py_tracemalloc_config.initialized == TRACEMALLOC_INITIALIZED) + if (_Py_tracemalloc_config.initialized == TRACEMALLOC_INITIALIZED) return 0; PyMem_GetAllocator(PYMEM_DOMAIN_RAW, &allocators.raw); @@ -887,19 +887,19 @@ tracemalloc_init(void) } #endif - tracemalloc_filenames = hashtable_new(hashtable_hash_pyobject, - hashtable_compare_unicode, - tracemalloc_clear_filename, NULL); + tracemalloc_filenames = hashtable_new(hashtable_hash_pyobject, + hashtable_compare_unicode, + tracemalloc_clear_filename, NULL); - tracemalloc_tracebacks = hashtable_new(hashtable_hash_traceback, - hashtable_compare_traceback, - NULL, raw_free); + tracemalloc_tracebacks = hashtable_new(hashtable_hash_traceback, + hashtable_compare_traceback, + NULL, raw_free); - tracemalloc_traces = tracemalloc_create_traces_table(); - tracemalloc_domains = tracemalloc_create_domains_table(); + tracemalloc_traces = tracemalloc_create_traces_table(); + tracemalloc_domains = tracemalloc_create_domains_table(); if (tracemalloc_filenames == NULL || tracemalloc_tracebacks == NULL - || tracemalloc_traces == NULL || tracemalloc_domains == NULL) { + || tracemalloc_traces == NULL || tracemalloc_domains == NULL) { PyErr_NoMemory(); return -1; } @@ -910,13 +910,13 @@ tracemalloc_init(void) PyUnicode_InternInPlace(&unknown_filename); tracemalloc_empty_traceback.nframe = 1; - tracemalloc_empty_traceback.total_nframe = 1; + tracemalloc_empty_traceback.total_nframe = 1; /* borrowed reference */ tracemalloc_empty_traceback.frames[0].filename = unknown_filename; tracemalloc_empty_traceback.frames[0].lineno = 0; tracemalloc_empty_traceback.hash = traceback_hash(&tracemalloc_empty_traceback); - _Py_tracemalloc_config.initialized = TRACEMALLOC_INITIALIZED; + _Py_tracemalloc_config.initialized = TRACEMALLOC_INITIALIZED; return 0; } @@ -924,15 +924,15 @@ tracemalloc_init(void) static void tracemalloc_deinit(void) { - if (_Py_tracemalloc_config.initialized != TRACEMALLOC_INITIALIZED) + if (_Py_tracemalloc_config.initialized != TRACEMALLOC_INITIALIZED) return; - _Py_tracemalloc_config.initialized = TRACEMALLOC_FINALIZED; + _Py_tracemalloc_config.initialized = TRACEMALLOC_FINALIZED; tracemalloc_stop(); /* destroy hash tables */ - _Py_hashtable_destroy(tracemalloc_domains); - _Py_hashtable_destroy(tracemalloc_traces); + _Py_hashtable_destroy(tracemalloc_domains); + _Py_hashtable_destroy(tracemalloc_traces); _Py_hashtable_destroy(tracemalloc_tracebacks); _Py_hashtable_destroy(tracemalloc_filenames); @@ -957,10 +957,10 @@ tracemalloc_start(int max_nframe) PyMemAllocatorEx alloc; size_t size; - if (max_nframe < 1 || (unsigned long) max_nframe > MAX_NFRAME) { + if (max_nframe < 1 || (unsigned long) max_nframe > MAX_NFRAME) { PyErr_Format(PyExc_ValueError, - "the number of frames must be in range [1; %lu]", - MAX_NFRAME); + "the number of frames must be in range [1; %lu]", + MAX_NFRAME); return -1; } @@ -968,12 +968,12 @@ tracemalloc_start(int max_nframe) return -1; } - if (_Py_tracemalloc_config.tracing) { + if (_Py_tracemalloc_config.tracing) { /* hook already installed: do nothing */ return 0; } - _Py_tracemalloc_config.max_nframe = max_nframe; + _Py_tracemalloc_config.max_nframe = max_nframe; /* allocate a buffer to store a new traceback */ size = TRACEBACK_SIZE(max_nframe); @@ -1009,7 +1009,7 @@ tracemalloc_start(int max_nframe) PyMem_SetAllocator(PYMEM_DOMAIN_OBJ, &alloc); /* everything is ready: start tracing Python memory allocations */ - _Py_tracemalloc_config.tracing = 1; + _Py_tracemalloc_config.tracing = 1; return 0; } @@ -1018,11 +1018,11 @@ tracemalloc_start(int max_nframe) static void tracemalloc_stop(void) { - if (!_Py_tracemalloc_config.tracing) + if (!_Py_tracemalloc_config.tracing) return; /* stop tracing Python memory allocations */ - _Py_tracemalloc_config.tracing = 0; + _Py_tracemalloc_config.tracing = 0; /* unregister the hook on memory allocators */ #ifdef TRACE_RAW_MALLOC @@ -1050,7 +1050,7 @@ static PyObject * _tracemalloc_is_tracing_impl(PyObject *module) /*[clinic end generated code: output=2d763b42601cd3ef input=af104b0a00192f63]*/ { - return PyBool_FromLong(_Py_tracemalloc_config.tracing); + return PyBool_FromLong(_Py_tracemalloc_config.tracing); } @@ -1064,7 +1064,7 @@ static PyObject * _tracemalloc_clear_traces_impl(PyObject *module) /*[clinic end generated code: output=a86080ee41b84197 input=0dab5b6c785183a5]*/ { - if (!_Py_tracemalloc_config.tracing) + if (!_Py_tracemalloc_config.tracing) Py_RETURN_NONE; set_reentrant(1); @@ -1101,11 +1101,11 @@ frame_to_pyobject(frame_t *frame) static PyObject* traceback_to_pyobject(traceback_t *traceback, _Py_hashtable_t *intern_table) { - PyObject *frames; + PyObject *frames; if (intern_table != NULL) { - frames = _Py_hashtable_get(intern_table, (const void *)traceback); - if (frames) { + frames = _Py_hashtable_get(intern_table, (const void *)traceback); + if (frames) { Py_INCREF(frames); return frames; } @@ -1115,8 +1115,8 @@ traceback_to_pyobject(traceback_t *traceback, _Py_hashtable_t *intern_table) if (frames == NULL) return NULL; - for (int i=0; i < traceback->nframe; i++) { - PyObject *frame = frame_to_pyobject(&traceback->frames[i]); + for (int i=0; i < traceback->nframe; i++) { + PyObject *frame = frame_to_pyobject(&traceback->frames[i]); if (frame == NULL) { Py_DECREF(frames); return NULL; @@ -1125,7 +1125,7 @@ traceback_to_pyobject(traceback_t *traceback, _Py_hashtable_t *intern_table) } if (intern_table != NULL) { - if (_Py_hashtable_set(intern_table, traceback, frames) < 0) { + if (_Py_hashtable_set(intern_table, traceback, frames) < 0) { Py_DECREF(frames); PyErr_NoMemory(); return NULL; @@ -1138,13 +1138,13 @@ traceback_to_pyobject(traceback_t *traceback, _Py_hashtable_t *intern_table) static PyObject* -trace_to_pyobject(unsigned int domain, const trace_t *trace, +trace_to_pyobject(unsigned int domain, const trace_t *trace, _Py_hashtable_t *intern_tracebacks) { PyObject *trace_obj = NULL; PyObject *obj; - trace_obj = PyTuple_New(4); + trace_obj = PyTuple_New(4); if (trace_obj == NULL) return NULL; @@ -1169,151 +1169,151 @@ trace_to_pyobject(unsigned int domain, const trace_t *trace, } PyTuple_SET_ITEM(trace_obj, 2, obj); - obj = PyLong_FromUnsignedLong(trace->traceback->total_nframe); - if (obj == NULL) { - Py_DECREF(trace_obj); - return NULL; - } - PyTuple_SET_ITEM(trace_obj, 3, obj); - + obj = PyLong_FromUnsignedLong(trace->traceback->total_nframe); + if (obj == NULL) { + Py_DECREF(trace_obj); + return NULL; + } + PyTuple_SET_ITEM(trace_obj, 3, obj); + return trace_obj; } typedef struct { _Py_hashtable_t *traces; - _Py_hashtable_t *domains; + _Py_hashtable_t *domains; _Py_hashtable_t *tracebacks; PyObject *list; - unsigned int domain; + unsigned int domain; } get_traces_t; - + static int -tracemalloc_copy_trace(_Py_hashtable_t *traces, - const void *key, const void *value, - void *user_data) -{ - _Py_hashtable_t *traces2 = (_Py_hashtable_t *)user_data; - - trace_t *trace = (trace_t *)value; - - trace_t *trace2 = raw_malloc(sizeof(trace_t)); - if (trace2 == NULL) { - return -1; - } - *trace2 = *trace; - if (_Py_hashtable_set(traces2, key, trace2) < 0) { - raw_free(trace2); - return -1; - } - return 0; -} - - -static _Py_hashtable_t* -tracemalloc_copy_traces(_Py_hashtable_t *traces) -{ - _Py_hashtable_t *traces2 = tracemalloc_create_traces_table(); - if (traces2 == NULL) { - return NULL; - } - - int err = _Py_hashtable_foreach(traces, - tracemalloc_copy_trace, - traces2); - if (err) { - _Py_hashtable_destroy(traces2); - return NULL; - } - return traces2; -} - - -static int -tracemalloc_copy_domain(_Py_hashtable_t *domains, - const void *key, const void *value, - void *user_data) -{ - _Py_hashtable_t *domains2 = (_Py_hashtable_t *)user_data; - - unsigned int domain = (unsigned int)FROM_PTR(key); - _Py_hashtable_t *traces = (_Py_hashtable_t *)value; - - _Py_hashtable_t *traces2 = tracemalloc_copy_traces(traces); - if (_Py_hashtable_set(domains2, TO_PTR(domain), traces2) < 0) { - _Py_hashtable_destroy(traces2); - return -1; - } - return 0; -} - - -static _Py_hashtable_t* -tracemalloc_copy_domains(_Py_hashtable_t *domains) -{ - _Py_hashtable_t *domains2 = tracemalloc_create_domains_table(); - if (domains2 == NULL) { - return NULL; - } - - int err = _Py_hashtable_foreach(domains, - tracemalloc_copy_domain, - domains2); - if (err) { - _Py_hashtable_destroy(domains2); - return NULL; - } - return domains2; -} - - -static int -tracemalloc_get_traces_fill(_Py_hashtable_t *traces, - const void *key, const void *value, - void *user_data) -{ - get_traces_t *get_traces = user_data; - - const trace_t *trace = (const trace_t *)value; - - PyObject *tuple = trace_to_pyobject(get_traces->domain, trace, - get_traces->tracebacks); - if (tuple == NULL) { +tracemalloc_copy_trace(_Py_hashtable_t *traces, + const void *key, const void *value, + void *user_data) +{ + _Py_hashtable_t *traces2 = (_Py_hashtable_t *)user_data; + + trace_t *trace = (trace_t *)value; + + trace_t *trace2 = raw_malloc(sizeof(trace_t)); + if (trace2 == NULL) { + return -1; + } + *trace2 = *trace; + if (_Py_hashtable_set(traces2, key, trace2) < 0) { + raw_free(trace2); + return -1; + } + return 0; +} + + +static _Py_hashtable_t* +tracemalloc_copy_traces(_Py_hashtable_t *traces) +{ + _Py_hashtable_t *traces2 = tracemalloc_create_traces_table(); + if (traces2 == NULL) { + return NULL; + } + + int err = _Py_hashtable_foreach(traces, + tracemalloc_copy_trace, + traces2); + if (err) { + _Py_hashtable_destroy(traces2); + return NULL; + } + return traces2; +} + + +static int +tracemalloc_copy_domain(_Py_hashtable_t *domains, + const void *key, const void *value, + void *user_data) +{ + _Py_hashtable_t *domains2 = (_Py_hashtable_t *)user_data; + + unsigned int domain = (unsigned int)FROM_PTR(key); + _Py_hashtable_t *traces = (_Py_hashtable_t *)value; + + _Py_hashtable_t *traces2 = tracemalloc_copy_traces(traces); + if (_Py_hashtable_set(domains2, TO_PTR(domain), traces2) < 0) { + _Py_hashtable_destroy(traces2); + return -1; + } + return 0; +} + + +static _Py_hashtable_t* +tracemalloc_copy_domains(_Py_hashtable_t *domains) +{ + _Py_hashtable_t *domains2 = tracemalloc_create_domains_table(); + if (domains2 == NULL) { + return NULL; + } + + int err = _Py_hashtable_foreach(domains, + tracemalloc_copy_domain, + domains2); + if (err) { + _Py_hashtable_destroy(domains2); + return NULL; + } + return domains2; +} + + +static int +tracemalloc_get_traces_fill(_Py_hashtable_t *traces, + const void *key, const void *value, + void *user_data) +{ + get_traces_t *get_traces = user_data; + + const trace_t *trace = (const trace_t *)value; + + PyObject *tuple = trace_to_pyobject(get_traces->domain, trace, + get_traces->tracebacks); + if (tuple == NULL) { return 1; - } + } - int res = PyList_Append(get_traces->list, tuple); - Py_DECREF(tuple); - if (res < 0) { + int res = PyList_Append(get_traces->list, tuple); + Py_DECREF(tuple); + if (res < 0) { return 1; - } + } return 0; } static int -tracemalloc_get_traces_domain(_Py_hashtable_t *domains, - const void *key, const void *value, - void *user_data) -{ - get_traces_t *get_traces = user_data; - - unsigned int domain = (unsigned int)FROM_PTR(key); - _Py_hashtable_t *traces = (_Py_hashtable_t *)value; - - get_traces->domain = domain; - return _Py_hashtable_foreach(traces, - tracemalloc_get_traces_fill, - get_traces); -} - - -static void -tracemalloc_pyobject_decref(void *value) -{ - PyObject *obj = (PyObject *)value; +tracemalloc_get_traces_domain(_Py_hashtable_t *domains, + const void *key, const void *value, + void *user_data) +{ + get_traces_t *get_traces = user_data; + + unsigned int domain = (unsigned int)FROM_PTR(key); + _Py_hashtable_t *traces = (_Py_hashtable_t *)value; + + get_traces->domain = domain; + return _Py_hashtable_foreach(traces, + tracemalloc_get_traces_fill, + get_traces); +} + + +static void +tracemalloc_pyobject_decref(void *value) +{ + PyObject *obj = (PyObject *)value; Py_DECREF(obj); } @@ -1335,65 +1335,65 @@ _tracemalloc__get_traces_impl(PyObject *module) /*[clinic end generated code: output=e9929876ced4b5cc input=6c7d2230b24255aa]*/ { get_traces_t get_traces; - get_traces.domain = DEFAULT_DOMAIN; + get_traces.domain = DEFAULT_DOMAIN; get_traces.traces = NULL; - get_traces.domains = NULL; + get_traces.domains = NULL; get_traces.tracebacks = NULL; get_traces.list = PyList_New(0); if (get_traces.list == NULL) goto error; - if (!_Py_tracemalloc_config.tracing) + if (!_Py_tracemalloc_config.tracing) return get_traces.list; /* the traceback hash table is used temporarily to intern traceback tuple of (filename, lineno) tuples */ - get_traces.tracebacks = hashtable_new(_Py_hashtable_hash_ptr, - _Py_hashtable_compare_direct, - NULL, tracemalloc_pyobject_decref); + get_traces.tracebacks = hashtable_new(_Py_hashtable_hash_ptr, + _Py_hashtable_compare_direct, + NULL, tracemalloc_pyobject_decref); if (get_traces.tracebacks == NULL) { - goto no_memory; + goto no_memory; } - // Copy all traces so tracemalloc_get_traces_fill() doesn't have to disable - // temporarily tracemalloc which would impact other threads and so would - // miss allocations while get_traces() is called. + // Copy all traces so tracemalloc_get_traces_fill() doesn't have to disable + // temporarily tracemalloc which would impact other threads and so would + // miss allocations while get_traces() is called. TABLES_LOCK(); - get_traces.traces = tracemalloc_copy_traces(tracemalloc_traces); + get_traces.traces = tracemalloc_copy_traces(tracemalloc_traces); TABLES_UNLOCK(); if (get_traces.traces == NULL) { - goto no_memory; - } - - TABLES_LOCK(); - get_traces.domains = tracemalloc_copy_domains(tracemalloc_domains); - TABLES_UNLOCK(); - - if (get_traces.domains == NULL) { - goto no_memory; - } - - // Convert traces to a list of tuples + goto no_memory; + } + + TABLES_LOCK(); + get_traces.domains = tracemalloc_copy_domains(tracemalloc_domains); + TABLES_UNLOCK(); + + if (get_traces.domains == NULL) { + goto no_memory; + } + + // Convert traces to a list of tuples set_reentrant(1); - int err = _Py_hashtable_foreach(get_traces.traces, - tracemalloc_get_traces_fill, - &get_traces); - if (!err) { - err = _Py_hashtable_foreach(get_traces.domains, - tracemalloc_get_traces_domain, - &get_traces); - } + int err = _Py_hashtable_foreach(get_traces.traces, + tracemalloc_get_traces_fill, + &get_traces); + if (!err) { + err = _Py_hashtable_foreach(get_traces.domains, + tracemalloc_get_traces_domain, + &get_traces); + } set_reentrant(0); - if (err) { + if (err) { goto error; - } + } goto finally; -no_memory: - PyErr_NoMemory(); - +no_memory: + PyErr_NoMemory(); + error: Py_CLEAR(get_traces.list); @@ -1404,9 +1404,9 @@ finally: if (get_traces.traces != NULL) { _Py_hashtable_destroy(get_traces.traces); } - if (get_traces.domains != NULL) { - _Py_hashtable_destroy(get_traces.domains); - } + if (get_traces.domains != NULL) { + _Py_hashtable_destroy(get_traces.domains); + } return get_traces.list; } @@ -1416,25 +1416,25 @@ static traceback_t* tracemalloc_get_traceback(unsigned int domain, uintptr_t ptr) { - if (!_Py_tracemalloc_config.tracing) + if (!_Py_tracemalloc_config.tracing) return NULL; - trace_t *trace; + trace_t *trace; TABLES_LOCK(); - _Py_hashtable_t *traces = tracemalloc_get_traces_table(domain); - if (traces) { - trace = _Py_hashtable_get(traces, TO_PTR(ptr)); + _Py_hashtable_t *traces = tracemalloc_get_traces_table(domain); + if (traces) { + trace = _Py_hashtable_get(traces, TO_PTR(ptr)); } else { - trace = NULL; + trace = NULL; } TABLES_UNLOCK(); - if (!trace) { + if (!trace) { return NULL; - } + } - return trace->traceback; + return trace->traceback; } @@ -1461,12 +1461,12 @@ _tracemalloc__get_object_traceback(PyObject *module, PyObject *obj) traceback_t *traceback; type = Py_TYPE(obj); - if (PyType_IS_GC(type)) { + if (PyType_IS_GC(type)) { ptr = (void *)((char *)obj - sizeof(PyGC_Head)); - } - else { + } + else { ptr = (void *)obj; - } + } traceback = tracemalloc_get_traceback(DEFAULT_DOMAIN, (uintptr_t)ptr); if (traceback == NULL) @@ -1496,7 +1496,7 @@ _PyMem_DumpTraceback(int fd, const void *ptr) traceback_t *traceback; int i; - if (!_Py_tracemalloc_config.tracing) { + if (!_Py_tracemalloc_config.tracing) { PUTS(fd, "Enable tracemalloc to get the memory block " "allocation traceback\n\n"); return; @@ -1570,22 +1570,22 @@ static PyObject * _tracemalloc_get_traceback_limit_impl(PyObject *module) /*[clinic end generated code: output=d556d9306ba95567 input=da3cd977fc68ae3b]*/ { - return PyLong_FromLong(_Py_tracemalloc_config.max_nframe); + return PyLong_FromLong(_Py_tracemalloc_config.max_nframe); } -static int -tracemalloc_get_tracemalloc_memory_cb(_Py_hashtable_t *domains, - const void *key, const void *value, - void *user_data) -{ - const _Py_hashtable_t *traces = value; - size_t *size = (size_t*)user_data; - *size += _Py_hashtable_size(traces); - return 0; -} - +static int +tracemalloc_get_tracemalloc_memory_cb(_Py_hashtable_t *domains, + const void *key, const void *value, + void *user_data) +{ + const _Py_hashtable_t *traces = value; + size_t *size = (size_t*)user_data; + *size += _Py_hashtable_size(traces); + return 0; +} + /*[clinic input] _tracemalloc.get_tracemalloc_memory @@ -1605,8 +1605,8 @@ _tracemalloc_get_tracemalloc_memory_impl(PyObject *module) TABLES_LOCK(); size += _Py_hashtable_size(tracemalloc_traces); - _Py_hashtable_foreach(tracemalloc_domains, - tracemalloc_get_tracemalloc_memory_cb, &size); + _Py_hashtable_foreach(tracemalloc_domains, + tracemalloc_get_tracemalloc_memory_cb, &size); TABLES_UNLOCK(); return PyLong_FromSize_t(size); @@ -1628,7 +1628,7 @@ _tracemalloc_get_traced_memory_impl(PyObject *module) { Py_ssize_t size, peak_size; - if (!_Py_tracemalloc_config.tracing) + if (!_Py_tracemalloc_config.tracing) return Py_BuildValue("ii", 0, 0); TABLES_LOCK(); @@ -1639,31 +1639,31 @@ _tracemalloc_get_traced_memory_impl(PyObject *module) return Py_BuildValue("nn", size, peak_size); } -/*[clinic input] -_tracemalloc.reset_peak - -Set the peak size of memory blocks traced by tracemalloc to the current size. - -Do nothing if the tracemalloc module is not tracing memory allocations. - -[clinic start generated code]*/ - -static PyObject * -_tracemalloc_reset_peak_impl(PyObject *module) -/*[clinic end generated code: output=140c2870f691dbb2 input=18afd0635066e9ce]*/ -{ - if (!_Py_tracemalloc_config.tracing) { - Py_RETURN_NONE; - } - - TABLES_LOCK(); - tracemalloc_peak_traced_memory = tracemalloc_traced_memory; - TABLES_UNLOCK(); - - Py_RETURN_NONE; -} - - +/*[clinic input] +_tracemalloc.reset_peak + +Set the peak size of memory blocks traced by tracemalloc to the current size. + +Do nothing if the tracemalloc module is not tracing memory allocations. + +[clinic start generated code]*/ + +static PyObject * +_tracemalloc_reset_peak_impl(PyObject *module) +/*[clinic end generated code: output=140c2870f691dbb2 input=18afd0635066e9ce]*/ +{ + if (!_Py_tracemalloc_config.tracing) { + Py_RETURN_NONE; + } + + TABLES_LOCK(); + tracemalloc_peak_traced_memory = tracemalloc_traced_memory; + TABLES_UNLOCK(); + + Py_RETURN_NONE; +} + + static PyMethodDef module_methods[] = { _TRACEMALLOC_IS_TRACING_METHODDEF _TRACEMALLOC_CLEAR_TRACES_METHODDEF @@ -1674,7 +1674,7 @@ static PyMethodDef module_methods[] = { _TRACEMALLOC_GET_TRACEBACK_LIMIT_METHODDEF _TRACEMALLOC_GET_TRACEMALLOC_MEMORY_METHODDEF _TRACEMALLOC_GET_TRACED_MEMORY_METHODDEF - _TRACEMALLOC_RESET_PEAK_METHODDEF + _TRACEMALLOC_RESET_PEAK_METHODDEF /* sentinel */ {NULL, NULL} }; @@ -1699,10 +1699,10 @@ PyInit__tracemalloc(void) if (m == NULL) return NULL; - if (tracemalloc_init() < 0) { - Py_DECREF(m); + if (tracemalloc_init() < 0) { + Py_DECREF(m); return NULL; - } + } return m; } @@ -1733,7 +1733,7 @@ PyTraceMalloc_Track(unsigned int domain, uintptr_t ptr, int res; PyGILState_STATE gil_state; - if (!_Py_tracemalloc_config.tracing) { + if (!_Py_tracemalloc_config.tracing) { /* tracemalloc is not tracing: do nothing */ return -2; } @@ -1752,7 +1752,7 @@ PyTraceMalloc_Track(unsigned int domain, uintptr_t ptr, int PyTraceMalloc_Untrack(unsigned int domain, uintptr_t ptr) { - if (!_Py_tracemalloc_config.tracing) { + if (!_Py_tracemalloc_config.tracing) { /* tracemalloc is not tracing: do nothing */ return -2; } @@ -1765,49 +1765,49 @@ PyTraceMalloc_Untrack(unsigned int domain, uintptr_t ptr) } -/* If the object memory block is already traced, update its trace - with the current Python traceback. - - Do nothing if tracemalloc is not tracing memory allocations - or if the object memory block is not already traced. */ -int -_PyTraceMalloc_NewReference(PyObject *op) -{ - assert(PyGILState_Check()); - - if (!_Py_tracemalloc_config.tracing) { - /* tracemalloc is not tracing: do nothing */ - return -1; - } - - uintptr_t ptr; - PyTypeObject *type = Py_TYPE(op); - if (PyType_IS_GC(type)) { - ptr = (uintptr_t)((char *)op - sizeof(PyGC_Head)); - } - else { - ptr = (uintptr_t)op; - } - - int res = -1; - - TABLES_LOCK(); - trace_t *trace = _Py_hashtable_get(tracemalloc_traces, TO_PTR(ptr)); - if (trace != NULL) { - /* update the traceback of the memory block */ - traceback_t *traceback = traceback_new(); - if (traceback != NULL) { - trace->traceback = traceback; - res = 0; - } - } - /* else: cannot track the object, its memory block size is unknown */ - TABLES_UNLOCK(); - - return res; -} - - +/* If the object memory block is already traced, update its trace + with the current Python traceback. + + Do nothing if tracemalloc is not tracing memory allocations + or if the object memory block is not already traced. */ +int +_PyTraceMalloc_NewReference(PyObject *op) +{ + assert(PyGILState_Check()); + + if (!_Py_tracemalloc_config.tracing) { + /* tracemalloc is not tracing: do nothing */ + return -1; + } + + uintptr_t ptr; + PyTypeObject *type = Py_TYPE(op); + if (PyType_IS_GC(type)) { + ptr = (uintptr_t)((char *)op - sizeof(PyGC_Head)); + } + else { + ptr = (uintptr_t)op; + } + + int res = -1; + + TABLES_LOCK(); + trace_t *trace = _Py_hashtable_get(tracemalloc_traces, TO_PTR(ptr)); + if (trace != NULL) { + /* update the traceback of the memory block */ + traceback_t *traceback = traceback_new(); + if (traceback != NULL) { + trace->traceback = traceback; + res = 0; + } + } + /* else: cannot track the object, its memory block size is unknown */ + TABLES_UNLOCK(); + + return res; +} + + PyObject* _PyTraceMalloc_GetTraceback(unsigned int domain, uintptr_t ptr) { |