@ -29,27 +29,6 @@ static struct {
PyMemAllocatorEx obj ;
} allocators ;
static struct {
/* Module initialized?
Variable protected by the GIL */
enum {
TRACEMALLOC_NOT_INITIALIZED ,
TRACEMALLOC_INITIALIZED ,
TRACEMALLOC_FINALIZED
} initialized ;
/* Is tracemalloc tracing memory allocations?
Variable protected by the GIL */
int tracing ;
/* limit of the number of frames in a traceback, 1 by default.
Variable protected by the GIL . */
int max_nframe ;
/* use domain in trace key?
Variable protected by the GIL . */
int use_domain ;
} tracemalloc_config = { TRACEMALLOC_NOT_INITIALIZED , 0 , 1 , 0 } ;
# if defined(TRACE_RAW_MALLOC)
/* This lock is needed because tracemalloc_free() is called without
@ -459,7 +438,7 @@ traceback_get_frames(traceback_t *traceback)
tracemalloc_get_frame ( pyframe , & traceback - > frames [ traceback - > nframe ] ) ;
assert ( traceback - > frames [ traceback - > nframe ] . filename ! = NULL ) ;
traceback - > nframe + + ;
if ( traceback - > nframe = = tracemalloc_config . max_nframe )
if ( traceback - > nframe = = _Py_ tracemalloc_config. max_nframe )
break ;
}
}
@ -540,7 +519,7 @@ tracemalloc_use_domain(void)
{
_Py_hashtable_t * new_traces = NULL ;
assert ( ! tracemalloc_config . use_domain ) ;
assert ( ! _Py_ tracemalloc_config. use_domain ) ;
new_traces = hashtable_new ( sizeof ( pointer_t ) ,
sizeof ( trace_t ) ,
@ -560,7 +539,7 @@ tracemalloc_use_domain(void)
_Py_hashtable_destroy ( tracemalloc_traces ) ;
tracemalloc_traces = new_traces ;
tracemalloc_config . use_domain = 1 ;
_Py_ tracemalloc_config. use_domain = 1 ;
return 0 ;
}
@ -572,9 +551,9 @@ tracemalloc_remove_trace(unsigned int domain, uintptr_t ptr)
trace_t trace ;
int removed ;
assert ( tracemalloc_config . tracing ) ;
assert ( _Py_ tracemalloc_config. tracing ) ;
if ( tracemalloc_config . use_domain ) {
if ( _Py_ tracemalloc_config. use_domain ) {
pointer_t key = { ptr , domain } ;
removed = _Py_HASHTABLE_POP ( tracemalloc_traces , key , trace ) ;
}
@ -603,14 +582,14 @@ tracemalloc_add_trace(unsigned int domain, uintptr_t ptr,
_Py_hashtable_entry_t * entry ;
int res ;
assert ( tracemalloc_config . tracing ) ;
assert ( _Py_ tracemalloc_config. tracing ) ;
traceback = traceback_new ( ) ;
if ( traceback = = NULL ) {
return - 1 ;
}
if ( ! tracemalloc_config . use_domain & & domain ! = DEFAULT_DOMAIN ) {
if ( ! _Py_ tracemalloc_config. use_domain & & domain ! = DEFAULT_DOMAIN ) {
/* first trace using a non-zero domain whereas traces use compact
( uintptr_t ) keys : switch to pointer_t keys . */
if ( tracemalloc_use_domain ( ) < 0 ) {
@ -618,7 +597,7 @@ tracemalloc_add_trace(unsigned int domain, uintptr_t ptr,
}
}
if ( tracemalloc_config . use_domain ) {
if ( _Py_ tracemalloc_config. use_domain ) {
entry = _Py_HASHTABLE_GET_ENTRY ( tracemalloc_traces , key ) ;
}
else {
@ -639,7 +618,7 @@ tracemalloc_add_trace(unsigned int domain, uintptr_t ptr,
trace . size = size ;
trace . traceback = traceback ;
if ( tracemalloc_config . use_domain ) {
if ( _Py_ tracemalloc_config. use_domain ) {
res = _Py_HASHTABLE_SET ( tracemalloc_traces , key , trace ) ;
}
else {
@ -956,13 +935,13 @@ tracemalloc_clear_traces(void)
static int
tracemalloc_init ( void )
{
if ( 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 ( tracemalloc_config . initialized = = TRACEMALLOC_INITIALIZED )
if ( _Py_ tracemalloc_config. initialized = = TRACEMALLOC_INITIALIZED )
return 0 ;
PyMem_GetAllocator ( PYMEM_DOMAIN_RAW , & allocators . raw ) ;
@ -996,7 +975,7 @@ tracemalloc_init(void)
hashtable_hash_traceback ,
hashtable_compare_traceback ) ;
if ( tracemalloc_config . use_domain ) {
if ( _Py_ tracemalloc_config. use_domain ) {
tracemalloc_traces = hashtable_new ( sizeof ( pointer_t ) ,
sizeof ( trace_t ) ,
hashtable_hash_pointer_t ,
@ -1026,7 +1005,7 @@ tracemalloc_init(void)
tracemalloc_empty_traceback . frames [ 0 ] . lineno = 0 ;
tracemalloc_empty_traceback . hash = traceback_hash ( & tracemalloc_empty_traceback ) ;
tracemalloc_config . initialized = TRACEMALLOC_INITIALIZED ;
_Py_ tracemalloc_config. initialized = TRACEMALLOC_INITIALIZED ;
return 0 ;
}
@ -1034,9 +1013,9 @@ tracemalloc_init(void)
static void
tracemalloc_deinit ( void )
{
if ( tracemalloc_config . initialized ! = TRACEMALLOC_INITIALIZED )
if ( _Py_ tracemalloc_config. initialized ! = TRACEMALLOC_INITIALIZED )
return ;
tracemalloc_config . initialized = TRACEMALLOC_FINALIZED ;
_Py_ tracemalloc_config. initialized = TRACEMALLOC_FINALIZED ;
tracemalloc_stop ( ) ;
@ -1077,13 +1056,13 @@ tracemalloc_start(int max_nframe)
return - 1 ;
}
if ( tracemalloc_config . tracing ) {
if ( _Py_ tracemalloc_config. tracing ) {
/* hook already installed: do nothing */
return 0 ;
}
assert ( 1 < = max_nframe & & max_nframe < = MAX_NFRAME ) ;
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 ) ;
@ -1119,7 +1098,7 @@ tracemalloc_start(int max_nframe)
PyMem_SetAllocator ( PYMEM_DOMAIN_OBJ , & alloc ) ;
/* everything is ready: start tracing Python memory allocations */
tracemalloc_config . tracing = 1 ;
_Py_ tracemalloc_config. tracing = 1 ;
return 0 ;
}
@ -1128,11 +1107,11 @@ tracemalloc_start(int max_nframe)
static void
tracemalloc_stop ( void )
{
if ( ! tracemalloc_config . tracing )
if ( ! _Py_ tracemalloc_config. tracing )
return ;
/* stop tracing Python memory allocations */
tracemalloc_config . tracing = 0 ;
_Py_ tracemalloc_config. tracing = 0 ;
/* unregister the hook on memory allocators */
# ifdef TRACE_RAW_MALLOC
@ -1160,7 +1139,7 @@ static PyObject *
_tracemalloc_is_tracing_impl ( PyObject * module )
/*[clinic end generated code: output=2d763b42601cd3ef input=af104b0a00192f63]*/
{
return PyBool_FromLong ( tracemalloc_config . tracing ) ;
return PyBool_FromLong ( _Py_ tracemalloc_config. tracing ) ;
}
@ -1174,7 +1153,7 @@ static PyObject *
_tracemalloc_clear_traces_impl ( PyObject * module )
/*[clinic end generated code: output=a86080ee41b84197 input=0dab5b6c785183a5]*/
{
if ( ! tracemalloc_config . tracing )
if ( ! _Py_ tracemalloc_config. tracing )
Py_RETURN_NONE ;
set_reentrant ( 1 ) ;
@ -1299,7 +1278,7 @@ tracemalloc_get_traces_fill(_Py_hashtable_t *traces, _Py_hashtable_entry_t *entr
PyObject * tracemalloc_obj ;
int res ;
if ( tracemalloc_config . use_domain ) {
if ( _Py_ tracemalloc_config. use_domain ) {
pointer_t key ;
_Py_HASHTABLE_ENTRY_READ_KEY ( traces , entry , key ) ;
domain = key . domain ;
@ -1359,7 +1338,7 @@ _tracemalloc__get_traces_impl(PyObject *module)
if ( get_traces . list = = NULL )
goto error ;
if ( ! tracemalloc_config . tracing )
if ( ! _Py_ tracemalloc_config. tracing )
return get_traces . list ;
/* the traceback hash table is used temporarily to intern traceback tuple
@ -1414,11 +1393,11 @@ tracemalloc_get_traceback(unsigned int domain, uintptr_t ptr)
trace_t trace ;
int found ;
if ( ! tracemalloc_config . tracing )
if ( ! _Py_ tracemalloc_config. tracing )
return NULL ;
TABLES_LOCK ( ) ;
if ( tracemalloc_config . use_domain ) {
if ( _Py_ tracemalloc_config. use_domain ) {
pointer_t key = { ptr , domain } ;
found = _Py_HASHTABLE_GET ( tracemalloc_traces , key , trace ) ;
}
@ -1558,7 +1537,7 @@ static PyObject *
_tracemalloc_get_traceback_limit_impl ( PyObject * module )
/*[clinic end generated code: output=d556d9306ba95567 input=da3cd977fc68ae3b]*/
{
return PyLong_FromLong ( tracemalloc_config . max_nframe ) ;
return PyLong_FromLong ( _Py_ tracemalloc_config. max_nframe ) ;
}
@ -1603,7 +1582,7 @@ _tracemalloc_get_traced_memory_impl(PyObject *module)
{
Py_ssize_t size , peak_size ;
if ( ! tracemalloc_config . tracing )
if ( ! _Py_ tracemalloc_config. tracing )
return Py_BuildValue ( " ii " , 0 , 0 ) ;
TABLES_LOCK ( ) ;
@ -1681,7 +1660,7 @@ PyTraceMalloc_Track(unsigned int domain, uintptr_t ptr,
int res ;
PyGILState_STATE gil_state ;
if ( ! tracemalloc_config . tracing ) {
if ( ! _Py_ tracemalloc_config. tracing ) {
/* tracemalloc is not tracing: do nothing */
return - 2 ;
}
@ -1700,7 +1679,7 @@ PyTraceMalloc_Track(unsigned int domain, uintptr_t ptr,
int
PyTraceMalloc_Untrack ( unsigned int domain , uintptr_t ptr )
{
if ( ! tracemalloc_config . tracing ) {
if ( ! _Py_ tracemalloc_config. tracing ) {
/* tracemalloc is not tracing: do nothing */
return - 2 ;
}
@ -1713,6 +1692,60 @@ 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 ;
}
_Py_hashtable_entry_t * entry ;
int res = - 1 ;
TABLES_LOCK ( ) ;
if ( _Py_tracemalloc_config . use_domain ) {
pointer_t key = { ptr , DEFAULT_DOMAIN } ;
entry = _Py_HASHTABLE_GET_ENTRY ( tracemalloc_traces , key ) ;
}
else {
entry = _Py_HASHTABLE_GET_ENTRY ( tracemalloc_traces , ptr ) ;
}
if ( entry ! = NULL ) {
/* update the traceback of the memory block */
traceback_t * traceback = traceback_new ( ) ;
if ( traceback ! = NULL ) {
trace_t trace ;
_Py_HASHTABLE_ENTRY_READ_DATA ( tracemalloc_traces , entry , trace ) ;
trace . traceback = traceback ;
_Py_HASHTABLE_ENTRY_WRITE_DATA ( tracemalloc_traces , entry , trace ) ;
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 )
{