forked from python/cpython
-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
pythongh-115103: Implement delayed memory reclamation (QSBR)
- Loading branch information
Showing
13 changed files
with
485 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -1095,3 +1095,35 @@ which is distributed under the MIT license:: | |
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION | ||
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION | ||
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | ||
|
||
|
||
Global Unbounded Sequences (GUS) | ||
-------------------------------- | ||
|
||
The file :file:`Python/qsbr.c` is adapted from FreeBSD's "Global Unbounded | ||
Sequences" safe memory reclamation scheme in | ||
`subr_smr.c <https://github.com/freebsd/freebsd-src/blob/main/sys/kern/subr_smr.c>`_. | ||
The file is distributed under the 2-Clause BSD License:: | ||
|
||
Copyright (c) 2019,2020 Jeffrey Roberson <[email protected]> | ||
|
||
Redistribution and use in source and binary forms, with or without | ||
modification, are permitted provided that the following conditions | ||
are met: | ||
1. Redistributions of source code must retain the above copyright | ||
notice unmodified, this list of conditions, and the following | ||
disclaimer. | ||
2. Redistributions in binary form must reproduce the above copyright | ||
notice, this list of conditions and the following disclaimer in the | ||
documentation and/or other materials provided with the distribution. | ||
|
||
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR | ||
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES | ||
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. | ||
IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, | ||
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT | ||
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | ||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | ||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF | ||
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,117 @@ | ||
#ifndef Py_INTERNAL_QSBR_H | ||
#define Py_INTERNAL_QSBR_H | ||
|
||
#include <stdbool.h> | ||
#include <stdint.h> | ||
#include "pycore_lock.h" // PyMutex | ||
|
||
#ifdef __cplusplus | ||
extern "C" { | ||
#endif | ||
|
||
#ifndef Py_BUILD_CORE | ||
# error "this header requires Py_BUILD_CORE define" | ||
#endif | ||
|
||
struct _qsbr_shared; | ||
struct _PyThreadStateImpl; // forward declare to avoid circular dependency | ||
|
||
// Per-thread state | ||
struct _qsbr_thread_state { | ||
// Last observed write sequence (or 0 if detached) | ||
uint64_t seq; | ||
|
||
// Shared (per-interpreter) QSBR state | ||
struct _qsbr_shared *shared; | ||
|
||
// Thread state (or NULL) | ||
PyThreadState *tstate; | ||
|
||
// Used to defer advancing write sequence a fixed number of times | ||
int deferrals; | ||
|
||
// Is this thread state allocated? | ||
bool allocated; | ||
struct _qsbr_thread_state *freelist_next; | ||
}; | ||
|
||
// Padding to avoid false sharing | ||
struct _qsbr_pad { | ||
struct _qsbr_thread_state qsbr; | ||
char __padding[64 - sizeof(struct _qsbr_thread_state)]; | ||
}; | ||
|
||
// Per-interpreter state | ||
struct _qsbr_shared { | ||
// Always odd, incremented by two | ||
uint64_t wr_seq; | ||
|
||
// Minimum observed read sequence | ||
uint64_t rd_seq; | ||
|
||
// Array of QSBR thread states. | ||
struct _qsbr_pad *array; | ||
Py_ssize_t size; | ||
|
||
// Freelist of unused _qsbr_thread_states (protected by mutex) | ||
PyMutex mutex; | ||
struct _qsbr_thread_state *freelist; | ||
}; | ||
|
||
static inline uint64_t | ||
_Py_qsbr_shared_current(struct _qsbr_shared *shared) | ||
{ | ||
return _Py_atomic_load_uint64(&shared->wr_seq); // at least acquire | ||
} | ||
|
||
static inline void | ||
_Py_qsbr_quiescent_state(struct _qsbr_thread_state *qsbr) | ||
{ | ||
uint64_t seq = _Py_qsbr_shared_current(qsbr->shared); | ||
_Py_atomic_store_uint64_relaxed(&qsbr->seq, seq); // probably release | ||
} | ||
|
||
// Advance the write sequence and return the new goal. | ||
extern uint64_t | ||
_Py_qsbr_advance(struct _qsbr_shared *shared); | ||
|
||
// Batches requests to advance the write sequence. This advances the write | ||
// sequence every N calls. Returns the new goal. | ||
extern uint64_t | ||
_Py_qsbr_deferred_advance(struct _qsbr_thread_state *qsbr); | ||
|
||
// Have the read sequences advanced to the given goal? | ||
extern bool | ||
_Py_qsbr_poll(struct _qsbr_thread_state *qsbr, uint64_t goal); | ||
|
||
// Called when thread attaches to interpreter | ||
extern void | ||
_Py_qsbr_attach(struct _qsbr_thread_state *qsbr); | ||
|
||
// Called when thread detaches from interpreter | ||
extern void | ||
_Py_qsbr_detach(struct _qsbr_thread_state *qsbr); | ||
|
||
// Reserves (allocates) a QSBR state and returns its index | ||
extern Py_ssize_t | ||
_Py_qsbr_reserve(PyInterpreterState *interp); | ||
|
||
// Associates a PyThreadState with the QSBR state at the given index | ||
extern void | ||
_Py_qsbr_register(struct _PyThreadStateImpl *tstate, | ||
PyInterpreterState *interp, Py_ssize_t index); | ||
|
||
// Disassociates a PyThreadState from the QSBR state and frees the QSBR state. | ||
extern void | ||
_Py_qsbr_unregister(struct _PyThreadStateImpl *tstate); | ||
|
||
extern void | ||
_Py_qsbr_fini(PyInterpreterState *interp); | ||
|
||
extern void | ||
_Py_qsbr_after_fork(struct _qsbr_shared *shared, struct _qsbr_thread_state *qsbr); | ||
|
||
#ifdef __cplusplus | ||
} | ||
#endif | ||
#endif /* !Py_INTERNAL_QSBR_H */ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.