bpo-40521: Make context free list per-interpreter (GH-20644)

Each interpreter now has its own context free list:

* Move context free list into PyInterpreterState.
* Add _Py_context_state structure.
* Add tstate parameter to _PyContext_ClearFreeList()
  and _PyContext_Fini().
* Pass tstate to clear_freelists().
This commit is contained in:
Victor Stinner 2020-06-05 02:56:37 +02:00 committed by GitHub
parent 78a02c2568
commit e005ead49b
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 34 additions and 28 deletions

View file

@ -10,8 +10,6 @@
#define CONTEXT_FREELIST_MAXLEN 255
static PyContext *ctx_freelist = NULL;
static int ctx_freelist_len = 0;
#include "clinic/context.c.h"
@ -334,11 +332,13 @@ class _contextvars.Context "PyContext *" "&PyContext_Type"
static inline PyContext *
_context_alloc(void)
{
PyInterpreterState *interp = _PyInterpreterState_GET();
struct _Py_context_state *state = &interp->context;
PyContext *ctx;
if (ctx_freelist_len) {
ctx_freelist_len--;
ctx = ctx_freelist;
ctx_freelist = (PyContext *)ctx->ctx_weakreflist;
if (state->numfree) {
state->numfree--;
ctx = state->freelist;
state->freelist = (PyContext *)ctx->ctx_weakreflist;
ctx->ctx_weakreflist = NULL;
_Py_NewReference((PyObject *)ctx);
}
@ -458,10 +458,12 @@ context_tp_dealloc(PyContext *self)
}
(void)context_tp_clear(self);
if (ctx_freelist_len < CONTEXT_FREELIST_MAXLEN) {
ctx_freelist_len++;
self->ctx_weakreflist = (PyObject *)ctx_freelist;
ctx_freelist = self;
PyInterpreterState *interp = _PyInterpreterState_GET();
struct _Py_context_state *state = &interp->context;
if (state->numfree < CONTEXT_FREELIST_MAXLEN) {
state->numfree++;
self->ctx_weakreflist = (PyObject *)state->freelist;
state->freelist = self;
}
else {
Py_TYPE(self)->tp_free(self);
@ -1271,11 +1273,12 @@ get_token_missing(void)
void
_PyContext_ClearFreeList(void)
_PyContext_ClearFreeList(PyThreadState *tstate)
{
for (; ctx_freelist_len; ctx_freelist_len--) {
PyContext *ctx = ctx_freelist;
ctx_freelist = (PyContext *)ctx->ctx_weakreflist;
struct _Py_context_state *state = &tstate->interp->context;
for (; state->numfree; state->numfree--) {
PyContext *ctx = state->freelist;
state->freelist = (PyContext *)ctx->ctx_weakreflist;
ctx->ctx_weakreflist = NULL;
PyObject_GC_Del(ctx);
}
@ -1283,10 +1286,10 @@ _PyContext_ClearFreeList(void)
void
_PyContext_Fini(void)
_PyContext_Fini(PyThreadState *tstate)
{
Py_CLEAR(_token_missing);
_PyContext_ClearFreeList();
_PyContext_ClearFreeList(tstate);
_PyHamt_Fini();
}