diff options
author | Sam Gross <colesbury@gmail.com> | 2024-02-20 18:04:37 (GMT) |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-02-20 18:04:37 (GMT) |
commit | e3ad6ca56f9b49db0694f432a870f907a8039f79 (patch) | |
tree | e04a42ed027f6595dec9efe051104d487cfb03a8 /Include | |
parent | d207c7cd5a8c0d3e5f6c5eb947243e4afcd718b0 (diff) | |
download | cpython-e3ad6ca56f9b49db0694f432a870f907a8039f79.zip cpython-e3ad6ca56f9b49db0694f432a870f907a8039f79.tar.gz cpython-e3ad6ca56f9b49db0694f432a870f907a8039f79.tar.bz2 |
gh-115103: Implement delayed free mechanism for free-threaded builds (#115367)
This adds `_PyMem_FreeDelayed()` and supporting functions. The
`_PyMem_FreeDelayed()` function frees memory with the same allocator as
`PyMem_Free()`, but after some delay to ensure that concurrent lock-free
readers have finished.
Diffstat (limited to 'Include')
-rw-r--r-- | Include/internal/pycore_interp.h | 1 | ||||
-rw-r--r-- | Include/internal/pycore_pymem.h | 19 | ||||
-rw-r--r-- | Include/internal/pycore_pymem_init.h | 5 | ||||
-rw-r--r-- | Include/internal/pycore_runtime_init.h | 1 | ||||
-rw-r--r-- | Include/internal/pycore_tstate.h | 1 |
5 files changed, 27 insertions, 0 deletions
diff --git a/Include/internal/pycore_interp.h b/Include/internal/pycore_interp.h index 06eba66..6a00aaf 100644 --- a/Include/internal/pycore_interp.h +++ b/Include/internal/pycore_interp.h @@ -231,6 +231,7 @@ struct _is { struct _Py_dict_state dict_state; struct _Py_exc_state exc_state; + struct _Py_mem_interp_free_queue mem_free_queue; struct ast_state ast; struct types_state types; diff --git a/Include/internal/pycore_pymem.h b/Include/internal/pycore_pymem.h index 1a72d07..1aea91a 100644 --- a/Include/internal/pycore_pymem.h +++ b/Include/internal/pycore_pymem.h @@ -1,6 +1,7 @@ #ifndef Py_INTERNAL_PYMEM_H #define Py_INTERNAL_PYMEM_H +#include "pycore_llist.h" // struct llist_node #include "pycore_lock.h" // PyMutex #ifdef __cplusplus @@ -48,6 +49,11 @@ struct _pymem_allocators { PyObjectArenaAllocator obj_arena; }; +struct _Py_mem_interp_free_queue { + int has_work; // true if the queue is not empty + PyMutex mutex; // protects the queue + struct llist_node head; // queue of _mem_work_chunk items +}; /* Set the memory allocator of the specified domain to the default. Save the old allocator into *old_alloc if it's non-NULL. @@ -110,6 +116,19 @@ extern int _PyMem_SetupAllocators(PyMemAllocatorName allocator); /* Is the debug allocator enabled? */ extern int _PyMem_DebugEnabled(void); +// Enqueue a pointer to be freed possibly after some delay. +extern void _PyMem_FreeDelayed(void *ptr); + +// Periodically process delayed free requests. +extern void _PyMem_ProcessDelayed(PyThreadState *tstate); + +// Abandon all thread-local delayed free requests and push them to the +// interpreter's queue. +extern void _PyMem_AbandonDelayed(PyThreadState *tstate); + +// On interpreter shutdown, frees all delayed free requests. +extern void _PyMem_FiniDelayed(PyInterpreterState *interp); + #ifdef __cplusplus } #endif diff --git a/Include/internal/pycore_pymem_init.h b/Include/internal/pycore_pymem_init.h index 96c49ed..c593edc 100644 --- a/Include/internal/pycore_pymem_init.h +++ b/Include/internal/pycore_pymem_init.h @@ -92,6 +92,11 @@ extern void _PyMem_ArenaFree(void *, void *, size_t); { NULL, _PyMem_ArenaAlloc, _PyMem_ArenaFree } +#define _Py_mem_free_queue_INIT(queue) \ + { \ + .head = LLIST_INIT(queue.head), \ + } + #ifdef __cplusplus } #endif diff --git a/Include/internal/pycore_runtime_init.h b/Include/internal/pycore_runtime_init.h index be81604..d093047 100644 --- a/Include/internal/pycore_runtime_init.h +++ b/Include/internal/pycore_runtime_init.h @@ -176,6 +176,7 @@ extern PyTypeObject _PyExc_MemoryError; }, \ .dtoa = _dtoa_state_INIT(&(INTERP)), \ .dict_state = _dict_state_INIT, \ + .mem_free_queue = _Py_mem_free_queue_INIT(INTERP.mem_free_queue), \ .func_state = { \ .next_version = 1, \ }, \ diff --git a/Include/internal/pycore_tstate.h b/Include/internal/pycore_tstate.h index d0f980e..e268e6f 100644 --- a/Include/internal/pycore_tstate.h +++ b/Include/internal/pycore_tstate.h @@ -29,6 +29,7 @@ typedef struct _PyThreadStateImpl { PyThreadState base; struct _qsbr_thread_state *qsbr; // only used by free-threaded build + struct llist_node mem_free_queue; // delayed free queue #ifdef Py_GIL_DISABLED struct _gc_thread_state gc; |