From e005ead49b1ee2b1507ceea94e6f89c28ecf1f81 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Fri, 5 Jun 2020 02:56:37 +0200 Subject: 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(). --- Python/context.c | 35 +++++++++++++++++++---------------- 1 file changed, 19 insertions(+), 16 deletions(-) (limited to 'Python/context.c') diff --git a/Python/context.c b/Python/context.c index bacc7010c4..3cf8db4c90 100644 --- a/Python/context.c +++ b/Python/context.c @@ -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(); } -- cgit v1.2.1