mirror of
				https://github.com/python/cpython.git
				synced 2025-11-03 23:21:29 +00:00 
			
		
		
		
	gh-128679: Redesign tracemalloc locking (#128888)
* Use TABLES_LOCK() to protect 'tracemalloc_config.tracing'. * Hold TABLES_LOCK() longer while accessing tables. * tracemalloc_realloc() and tracemalloc_free() no longer remove the trace on reentrant call. * _PyTraceMalloc_Stop() unregisters _PyTraceMalloc_TraceRef(). * _PyTraceMalloc_GetTraces() sets the reentrant flag. * tracemalloc_clear_traces_unlocked() sets the reentrant flag.
This commit is contained in:
		
							parent
							
								
									080f444a58
								
							
						
					
					
						commit
						36c5e3bcc2
					
				
					 5 changed files with 302 additions and 364 deletions
				
			
		| 
						 | 
					@ -299,12 +299,6 @@ Py_ssize_t _Py_ExplicitMergeRefcount(PyObject *op, Py_ssize_t extra);
 | 
				
			||||||
extern int _PyType_CheckConsistency(PyTypeObject *type);
 | 
					extern int _PyType_CheckConsistency(PyTypeObject *type);
 | 
				
			||||||
extern int _PyDict_CheckConsistency(PyObject *mp, int check_content);
 | 
					extern int _PyDict_CheckConsistency(PyObject *mp, int check_content);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* Update the Python traceback of an object. This function must be called
 | 
					 | 
				
			||||||
   when a memory block is reused from a free list.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
   Internal function called by _Py_NewReference(). */
 | 
					 | 
				
			||||||
extern int _PyTraceMalloc_TraceRef(PyObject *op, PyRefTracerEvent event, void*);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// Fast inlined version of PyType_HasFeature()
 | 
					// Fast inlined version of PyType_HasFeature()
 | 
				
			||||||
static inline int
 | 
					static inline int
 | 
				
			||||||
_PyType_HasFeature(PyTypeObject *type, unsigned long feature) {
 | 
					_PyType_HasFeature(PyTypeObject *type, unsigned long feature) {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -25,7 +25,7 @@ struct _PyTraceMalloc_Config {
 | 
				
			||||||
    } initialized;
 | 
					    } initialized;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /* Is tracemalloc tracing memory allocations?
 | 
					    /* Is tracemalloc tracing memory allocations?
 | 
				
			||||||
       Variable protected by the GIL */
 | 
					       Variable protected by the TABLES_LOCK(). */
 | 
				
			||||||
    int tracing;
 | 
					    int tracing;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /* limit of the number of frames in a traceback, 1 by default.
 | 
					    /* limit of the number of frames in a traceback, 1 by default.
 | 
				
			||||||
| 
						 | 
					@ -85,14 +85,14 @@ struct _tracemalloc_runtime_state {
 | 
				
			||||||
    size_t peak_traced_memory;
 | 
					    size_t peak_traced_memory;
 | 
				
			||||||
    /* Hash table used as a set to intern filenames:
 | 
					    /* Hash table used as a set to intern filenames:
 | 
				
			||||||
       PyObject* => PyObject*.
 | 
					       PyObject* => PyObject*.
 | 
				
			||||||
       Protected by the GIL */
 | 
					       Protected by the TABLES_LOCK(). */
 | 
				
			||||||
    _Py_hashtable_t *filenames;
 | 
					    _Py_hashtable_t *filenames;
 | 
				
			||||||
    /* Buffer to store a new traceback in traceback_new().
 | 
					    /* Buffer to store a new traceback in traceback_new().
 | 
				
			||||||
       Protected by the GIL. */
 | 
					       Protected by the TABLES_LOCK(). */
 | 
				
			||||||
    struct tracemalloc_traceback *traceback;
 | 
					    struct tracemalloc_traceback *traceback;
 | 
				
			||||||
    /* Hash table used as a set to intern tracebacks:
 | 
					    /* Hash table used as a set to intern tracebacks:
 | 
				
			||||||
       traceback_t* => traceback_t*
 | 
					       traceback_t* => traceback_t*
 | 
				
			||||||
       Protected by the GIL */
 | 
					       Protected by the TABLES_LOCK(). */
 | 
				
			||||||
    _Py_hashtable_t *tracebacks;
 | 
					    _Py_hashtable_t *tracebacks;
 | 
				
			||||||
    /* pointer (void*) => trace (trace_t*).
 | 
					    /* pointer (void*) => trace (trace_t*).
 | 
				
			||||||
       Protected by TABLES_LOCK(). */
 | 
					       Protected by TABLES_LOCK(). */
 | 
				
			||||||
| 
						 | 
					@ -144,7 +144,7 @@ extern PyObject* _PyTraceMalloc_GetTraces(void);
 | 
				
			||||||
extern PyObject* _PyTraceMalloc_GetObjectTraceback(PyObject *obj);
 | 
					extern PyObject* _PyTraceMalloc_GetObjectTraceback(PyObject *obj);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* Initialize tracemalloc */
 | 
					/* Initialize tracemalloc */
 | 
				
			||||||
extern int _PyTraceMalloc_Init(void);
 | 
					extern PyStatus _PyTraceMalloc_Init(void);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* Start tracemalloc */
 | 
					/* Start tracemalloc */
 | 
				
			||||||
extern int _PyTraceMalloc_Start(int max_nframe);
 | 
					extern int _PyTraceMalloc_Start(int max_nframe);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -215,18 +215,14 @@ static struct PyModuleDef module_def = {
 | 
				
			||||||
PyMODINIT_FUNC
 | 
					PyMODINIT_FUNC
 | 
				
			||||||
PyInit__tracemalloc(void)
 | 
					PyInit__tracemalloc(void)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    PyObject *m;
 | 
					    PyObject *mod = PyModule_Create(&module_def);
 | 
				
			||||||
    m = PyModule_Create(&module_def);
 | 
					    if (mod == NULL) {
 | 
				
			||||||
    if (m == NULL)
 | 
					 | 
				
			||||||
        return NULL;
 | 
					        return NULL;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifdef Py_GIL_DISABLED
 | 
					#ifdef Py_GIL_DISABLED
 | 
				
			||||||
    PyUnstable_Module_SetGIL(m, Py_MOD_GIL_NOT_USED);
 | 
					    PyUnstable_Module_SetGIL(mod, Py_MOD_GIL_NOT_USED);
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (_PyTraceMalloc_Init() < 0) {
 | 
					    return mod;
 | 
				
			||||||
        Py_DECREF(m);
 | 
					 | 
				
			||||||
        return NULL;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    return m;
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -710,6 +710,11 @@ pycore_create_interpreter(_PyRuntimeState *runtime,
 | 
				
			||||||
        return _PyStatus_NO_MEMORY();
 | 
					        return _PyStatus_NO_MEMORY();
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    status = _PyTraceMalloc_Init();
 | 
				
			||||||
 | 
					    if (_PyStatus_EXCEPTION(status)) {
 | 
				
			||||||
 | 
					        return status;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    PyThreadState *tstate = _PyThreadState_New(interp,
 | 
					    PyThreadState *tstate = _PyThreadState_New(interp,
 | 
				
			||||||
                                               _PyThreadState_WHENCE_INIT);
 | 
					                                               _PyThreadState_WHENCE_INIT);
 | 
				
			||||||
    if (tstate == NULL) {
 | 
					    if (tstate == NULL) {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
										
											
												File diff suppressed because it is too large
												Load diff
											
										
									
								
							
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue