summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Include/internal/pycore_pymem.h22
-rw-r--r--Include/internal/pycore_runtime.h5
-rw-r--r--Include/internal/pycore_runtime_init.h4
-rw-r--r--Include/internal/pycore_tracemalloc.h121
-rw-r--r--Makefile.pre.in1
-rw-r--r--Modules/_tracemalloc.c82
-rw-r--r--PCbuild/pythoncore.vcxproj1
-rw-r--r--PCbuild/pythoncore.vcxproj.filters3
-rw-r--r--Tools/c-analyzer/cpython/globals-to-fix.tsv11
9 files changed, 143 insertions, 107 deletions
diff --git a/Include/internal/pycore_pymem.h b/Include/internal/pycore_pymem.h
index 5749af7..4cc953d 100644
--- a/Include/internal/pycore_pymem.h
+++ b/Include/internal/pycore_pymem.h
@@ -90,28 +90,6 @@ PyAPI_FUNC(int) _PyMem_GetAllocatorName(
PYMEM_ALLOCATOR_NOT_SET does nothing. */
PyAPI_FUNC(int) _PyMem_SetupAllocators(PyMemAllocatorName allocator);
-struct _PyTraceMalloc_Config {
- /* 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;
-};
-
-#define _PyTraceMalloc_Config_INIT \
- {.initialized = TRACEMALLOC_NOT_INITIALIZED, \
- .tracing = 0, \
- .max_nframe = 1}
#ifdef __cplusplus
}
diff --git a/Include/internal/pycore_runtime.h b/Include/internal/pycore_runtime.h
index fe2de5f..99ec6fc 100644
--- a/Include/internal/pycore_runtime.h
+++ b/Include/internal/pycore_runtime.h
@@ -23,6 +23,7 @@ extern "C" {
#include "pycore_pythread.h" // struct _pythread_runtime_state
#include "pycore_obmalloc.h" // struct obmalloc_state
#include "pycore_time.h" // struct _time_runtime_state
+#include "pycore_tracemalloc.h" // struct _tracemalloc_runtime_state
#include "pycore_unicodeobject.h" // struct _Py_unicode_runtime_ids
struct _getargs_runtime_state {
@@ -137,11 +138,9 @@ typedef struct pyruntimestate {
struct _ceval_runtime_state ceval;
struct _gilstate_runtime_state gilstate;
struct _getargs_runtime_state getargs;
- struct {
- struct _PyTraceMalloc_Config config;
- } tracemalloc;
struct _dtoa_runtime_state dtoa;
struct _fileutils_state fileutils;
+ struct _tracemalloc_runtime_state tracemalloc;
PyPreConfig preconfig;
diff --git a/Include/internal/pycore_runtime_init.h b/Include/internal/pycore_runtime_init.h
index b569e58..029357d 100644
--- a/Include/internal/pycore_runtime_init.h
+++ b/Include/internal/pycore_runtime_init.h
@@ -50,13 +50,11 @@ extern "C" {
in accordance with the specification. */ \
.autoTSSkey = Py_tss_NEEDS_INIT, \
}, \
- .tracemalloc = { \
- .config = _PyTraceMalloc_Config_INIT, \
- }, \
.dtoa = _dtoa_runtime_state_INIT(runtime), \
.fileutils = { \
.force_ascii = -1, \
}, \
+ .tracemalloc = _tracemalloc_runtime_state_INIT, \
.float_state = { \
.float_format = _py_float_format_unknown, \
.double_format = _py_float_format_unknown, \
diff --git a/Include/internal/pycore_tracemalloc.h b/Include/internal/pycore_tracemalloc.h
new file mode 100644
index 0000000..08d7d10
--- /dev/null
+++ b/Include/internal/pycore_tracemalloc.h
@@ -0,0 +1,121 @@
+#ifndef Py_INTERNAL_TRACEMALLOC_H
+#define Py_INTERNAL_TRACEMALLOC_H
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef Py_BUILD_CORE
+# error "this header requires Py_BUILD_CORE define"
+#endif
+
+#include "pycore_hashtable.h" // _Py_hashtable_t
+
+
+/* Trace memory blocks allocated by PyMem_RawMalloc() */
+#define TRACE_RAW_MALLOC
+
+
+struct _PyTraceMalloc_Config {
+ /* 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;
+};
+
+
+/* Pack the frame_t structure to reduce the memory footprint on 64-bit
+ architectures: 12 bytes instead of 16. */
+struct
+#ifdef __GNUC__
+__attribute__((packed))
+#elif defined(_MSC_VER)
+#pragma pack(push, 4)
+#endif
+tracemalloc_frame {
+ /* filename cannot be NULL: "<unknown>" is used if the Python frame
+ filename is NULL */
+ PyObject *filename;
+ unsigned int lineno;
+};
+#ifdef _MSC_VER
+#pragma pack(pop)
+#endif
+
+struct tracemalloc_traceback {
+ Py_uhash_t hash;
+ /* Number of frames stored */
+ uint16_t nframe;
+ /* Total number of frames the traceback had */
+ uint16_t total_nframe;
+ struct tracemalloc_frame frames[1];
+};
+
+
+struct _tracemalloc_runtime_state {
+ struct _PyTraceMalloc_Config config;
+
+ /* Protected by the GIL */
+ struct {
+ PyMemAllocatorEx mem;
+ PyMemAllocatorEx raw;
+ PyMemAllocatorEx obj;
+ } allocators;
+
+#if defined(TRACE_RAW_MALLOC)
+ PyThread_type_lock tables_lock;
+#endif
+ /* Size in bytes of currently traced memory.
+ Protected by TABLES_LOCK(). */
+ size_t traced_memory;
+ /* Peak size in bytes of traced memory.
+ Protected by TABLES_LOCK(). */
+ size_t peak_traced_memory;
+ /* Hash table used as a set to intern filenames:
+ PyObject* => PyObject*.
+ Protected by the GIL */
+ _Py_hashtable_t *filenames;
+ /* Buffer to store a new traceback in traceback_new().
+ Protected by the GIL. */
+ struct tracemalloc_traceback *traceback;
+ /* Hash table used as a set to intern tracebacks:
+ traceback_t* => traceback_t*
+ Protected by the GIL */
+ _Py_hashtable_t *tracebacks;
+ /* pointer (void*) => trace (trace_t*).
+ Protected by TABLES_LOCK(). */
+ _Py_hashtable_t *traces;
+ /* domain (unsigned int) => traces (_Py_hashtable_t).
+ Protected by TABLES_LOCK(). */
+ _Py_hashtable_t *domains;
+
+ struct tracemalloc_traceback empty_traceback;
+
+ Py_tss_t reentrant_key;
+};
+
+#define _tracemalloc_runtime_state_INIT \
+ { \
+ .config = { \
+ .initialized = TRACEMALLOC_NOT_INITIALIZED, \
+ .tracing = 0, \
+ .max_nframe = 1, \
+ }, \
+ .reentrant_key = Py_tss_NEEDS_INIT, \
+ }
+
+
+#ifdef __cplusplus
+}
+#endif
+#endif // !Py_INTERNAL_TRACEMALLOC_H
diff --git a/Makefile.pre.in b/Makefile.pre.in
index 815df69..9577f9d 100644
--- a/Makefile.pre.in
+++ b/Makefile.pre.in
@@ -1678,6 +1678,7 @@ PYTHON_HEADERS= \
$(srcdir)/Include/internal/pycore_time.h \
$(srcdir)/Include/internal/pycore_token.h \
$(srcdir)/Include/internal/pycore_traceback.h \
+ $(srcdir)/Include/internal/pycore_tracemalloc.h \
$(srcdir)/Include/internal/pycore_tuple.h \
$(srcdir)/Include/internal/pycore_typeobject.h \
$(srcdir)/Include/internal/pycore_ucnhash.h \
diff --git a/Modules/_tracemalloc.c b/Modules/_tracemalloc.c
index 0d70f0c..ac16626 100644
--- a/Modules/_tracemalloc.c
+++ b/Modules/_tracemalloc.c
@@ -20,9 +20,6 @@ module _tracemalloc
_Py_DECLARE_STR(anon_unknown, "<unknown>");
-/* Trace memory blocks allocated by PyMem_RawMalloc() */
-#define TRACE_RAW_MALLOC
-
/* Forward declaration */
static void tracemalloc_stop(void);
static void* raw_malloc(size_t size);
@@ -35,19 +32,14 @@ static void raw_free(void *ptr);
#define TO_PTR(key) ((const void *)(uintptr_t)(key))
#define FROM_PTR(key) ((uintptr_t)(key))
-/* Protected by the GIL */
-static struct {
- PyMemAllocatorEx mem;
- PyMemAllocatorEx raw;
- PyMemAllocatorEx obj;
-} allocators;
+#define allocators _PyRuntime.tracemalloc.allocators
#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(). */
-static PyThread_type_lock tables_lock;
+# define tables_lock _PyRuntime.tracemalloc.tables_lock
# define TABLES_LOCK() PyThread_acquire_lock(tables_lock, 1)
# define TABLES_UNLOCK() PyThread_release_lock(tables_lock)
#else
@@ -59,33 +51,8 @@ static PyThread_type_lock tables_lock;
#define DEFAULT_DOMAIN 0
-/* Pack the frame_t structure to reduce the memory footprint on 64-bit
- architectures: 12 bytes instead of 16. */
-typedef struct
-#ifdef __GNUC__
-__attribute__((packed))
-#elif defined(_MSC_VER)
-#pragma pack(push, 4)
-#endif
-{
- /* filename cannot be NULL: "<unknown>" is used if the Python frame
- filename is NULL */
- PyObject *filename;
- unsigned int lineno;
-} frame_t;
-#ifdef _MSC_VER
-#pragma pack(pop)
-#endif
-
-
-typedef struct {
- Py_uhash_t hash;
- /* Number of frames stored */
- uint16_t nframe;
- /* Total number of frames the traceback had */
- uint16_t total_nframe;
- frame_t frames[1];
-} traceback_t;
+typedef struct tracemalloc_frame frame_t;
+typedef struct tracemalloc_traceback traceback_t;
#define TRACEBACK_SIZE(NFRAME) \
(sizeof(traceback_t) + sizeof(frame_t) * (NFRAME - 1))
@@ -96,7 +63,8 @@ typedef struct {
static const unsigned long MAX_NFRAME = Py_MIN(UINT16_MAX, ((SIZE_MAX - sizeof(traceback_t)) / sizeof(frame_t) + 1));
-static traceback_t tracemalloc_empty_traceback;
+#define tracemalloc_empty_traceback _PyRuntime.tracemalloc.empty_traceback
+
/* Trace of a memory block */
typedef struct {
@@ -108,35 +76,13 @@ typedef struct {
} trace_t;
-/* Size in bytes of currently traced memory.
- Protected by TABLES_LOCK(). */
-static size_t tracemalloc_traced_memory = 0;
-
-/* Peak size in bytes of traced memory.
- Protected by TABLES_LOCK(). */
-static size_t tracemalloc_peak_traced_memory = 0;
-
-/* Hash table used as a set to intern filenames:
- PyObject* => PyObject*.
- Protected by the GIL */
-static _Py_hashtable_t *tracemalloc_filenames = NULL;
-
-/* Buffer to store a new traceback in traceback_new().
- Protected by the GIL. */
-static traceback_t *tracemalloc_traceback = NULL;
-
-/* Hash table used as a set to intern tracebacks:
- traceback_t* => traceback_t*
- Protected by the GIL */
-static _Py_hashtable_t *tracemalloc_tracebacks = NULL;
-
-/* 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;
+#define tracemalloc_traced_memory _PyRuntime.tracemalloc.traced_memory
+#define tracemalloc_peak_traced_memory _PyRuntime.tracemalloc.peak_traced_memory
+#define tracemalloc_filenames _PyRuntime.tracemalloc.filenames
+#define tracemalloc_traceback _PyRuntime.tracemalloc.traceback
+#define tracemalloc_tracebacks _PyRuntime.tracemalloc.tracebacks
+#define tracemalloc_traces _PyRuntime.tracemalloc.traces
+#define tracemalloc_domains _PyRuntime.tracemalloc.domains
#ifdef TRACE_DEBUG
@@ -157,7 +103,7 @@ tracemalloc_error(const char *format, ...)
#if defined(TRACE_RAW_MALLOC)
#define REENTRANT_THREADLOCAL
-static Py_tss_t tracemalloc_reentrant_key = Py_tss_NEEDS_INIT;
+#define tracemalloc_reentrant_key _PyRuntime.tracemalloc.reentrant_key
/* Any non-NULL pointer can be used */
#define REENTRANT Py_True
diff --git a/PCbuild/pythoncore.vcxproj b/PCbuild/pythoncore.vcxproj
index 35fbff3..25572d6 100644
--- a/PCbuild/pythoncore.vcxproj
+++ b/PCbuild/pythoncore.vcxproj
@@ -259,6 +259,7 @@
<ClInclude Include="..\Include\internal\pycore_time.h" />
<ClInclude Include="..\Include\internal\pycore_token.h" />
<ClInclude Include="..\Include\internal\pycore_traceback.h" />
+ <ClInclude Include="..\Include\internal\pycore_tracemalloc.h" />
<ClInclude Include="..\Include\internal\pycore_tuple.h" />
<ClInclude Include="..\Include\internal\pycore_typeobject.h" />
<ClInclude Include="..\Include\internal\pycore_ucnhash.h" />
diff --git a/PCbuild/pythoncore.vcxproj.filters b/PCbuild/pythoncore.vcxproj.filters
index 19cb5cf..d45b50c 100644
--- a/PCbuild/pythoncore.vcxproj.filters
+++ b/PCbuild/pythoncore.vcxproj.filters
@@ -678,6 +678,9 @@
<ClInclude Include="..\Include\internal\pycore_traceback.h">
<Filter>Include\internal</Filter>
</ClInclude>
+ <ClInclude Include="..\Include\internal\pycore_tracemalloc.h">
+ <Filter>Include\internal</Filter>
+ </ClInclude>
<ClInclude Include="..\Include\internal\pycore_tuple.h">
<Filter>Include\internal</Filter>
</ClInclude>
diff --git a/Tools/c-analyzer/cpython/globals-to-fix.tsv b/Tools/c-analyzer/cpython/globals-to-fix.tsv
index 94e9831..5dcd396 100644
--- a/Tools/c-analyzer/cpython/globals-to-fix.tsv
+++ b/Tools/c-analyzer/cpython/globals-to-fix.tsv
@@ -377,17 +377,6 @@ Modules/faulthandler.c - old_stack -
##-----------------------
## state
-Modules/_tracemalloc.c - allocators -
-Modules/_tracemalloc.c - tables_lock -
-Modules/_tracemalloc.c - tracemalloc_empty_traceback -
-Modules/_tracemalloc.c - tracemalloc_traced_memory -
-Modules/_tracemalloc.c - tracemalloc_peak_traced_memory -
-Modules/_tracemalloc.c - tracemalloc_filenames -
-Modules/_tracemalloc.c - tracemalloc_traceback -
-Modules/_tracemalloc.c - tracemalloc_tracebacks -
-Modules/_tracemalloc.c - tracemalloc_traces -
-Modules/_tracemalloc.c - tracemalloc_domains -
-Modules/_tracemalloc.c - tracemalloc_reentrant_key -
Modules/faulthandler.c faulthandler_dump_traceback reentrant -
Modules/signalmodule.c - is_tripped -
Modules/signalmodule.c - signal_global_state -