Skip to content

Commit 7c7e2b2

Browse files
committed
Use a thread-local variable to store a pointer to the interpreter-state.
1 parent fa26245 commit 7c7e2b2

26 files changed

+118
-76
lines changed

Include/internal/pycore_long.h

+5-4
Original file line numberDiff line numberDiff line change
@@ -26,13 +26,14 @@ static inline PyObject* __PyLong_GetSmallInt_internal(int value)
2626

2727
// Return a borrowed reference to the zero singleton.
2828
// The function cannot return NULL.
29-
static inline PyObject* _PyLong_GetZero(void)
30-
{ return __PyLong_GetSmallInt_internal(0); }
29+
PyAPI_FUNC(PyObject*) _PyLong_GetZero(void);
3130

3231
// Return a borrowed reference to the one singleton.
3332
// The function cannot return NULL.
34-
static inline PyObject* _PyLong_GetOne(void)
35-
{ return __PyLong_GetSmallInt_internal(1); }
33+
PyAPI_FUNC(PyObject*) _PyLong_GetOne(void);
34+
35+
#define PY_ZERO() ((PyObject *)_PyInterpreterState_GET()->small_ints[_PY_NSMALLNEGINTS])
36+
#define PY_ONE() ((PyObject *)_PyInterpreterState_GET()->small_ints[_PY_NSMALLNEGINTS+1])
3637

3738
PyObject *_PyLong_Add(PyLongObject *left, PyLongObject *right);
3839
PyObject *_PyLong_Multiply(PyLongObject *left, PyLongObject *right);

Include/internal/pycore_pystate.h

+15-14
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ extern "C" {
88
# error "this header requires Py_BUILD_CORE define"
99
#endif
1010

11+
#include "pycore_tls.h" /* PyRuntimeState */
1112
#include "pycore_runtime.h" /* PyRuntimeState */
1213

1314

@@ -20,15 +21,8 @@ _Py_IsMainThread(void)
2021
return (thread == _PyRuntime.main_thread);
2122
}
2223

23-
24-
static inline int
25-
_Py_IsMainInterpreter(PyInterpreterState *interp)
26-
{
27-
/* Use directly _PyRuntime rather than tstate->interp->runtime, since
28-
this function is used in performance critical code path (ceval) */
29-
return (interp == _PyRuntime.interpreters.main);
30-
}
31-
24+
extern int
25+
_Py_IsMainInterpreter(PyInterpreterState *interp);
3226

3327
static inline const PyConfig *
3428
_Py_GetMainConfig(void)
@@ -40,6 +34,9 @@ _Py_GetMainConfig(void)
4034
return _PyInterpreterState_GetConfig(interp);
4135
}
4236

37+
#ifdef _Py_THREAD_LOCAL
38+
extern _Py_THREAD_LOCAL PyInterpreterState *_py_current_interpreter;
39+
#endif
4340

4441
/* Only handle signals on the main thread of the main interpreter. */
4542
static inline int
@@ -107,7 +104,6 @@ _Py_EnsureFuncTstateNotNULL(const char *func, PyThreadState *tstate)
107104
#define _Py_EnsureTstateNotNULL(tstate) \
108105
_Py_EnsureFuncTstateNotNULL(__func__, tstate)
109106

110-
111107
/* Get the current interpreter state.
112108
113109
The macro is unsafe: it does not check for error and it can return NULL.
@@ -116,14 +112,19 @@ _Py_EnsureFuncTstateNotNULL(const char *func, PyThreadState *tstate)
116112
117113
See also _PyInterpreterState_Get()
118114
and _PyGILState_GetInterpreterStateUnsafe(). */
115+
#ifdef _Py_THREAD_LOCAL
116+
#define _PyInterpreterState_GET() _py_current_interpreter
117+
#else
119118
static inline PyInterpreterState* _PyInterpreterState_GET(void) {
120119
PyThreadState *tstate = _PyThreadState_GET();
121-
#ifdef Py_DEBUG
122120
_Py_EnsureTstateNotNULL(tstate);
123-
#endif
124-
return tstate->interp;
121+
PyInterpreterState *interp = tstate->interp;
122+
if (interp == NULL) {
123+
Py_FatalError("no current interpreter");
124+
}
125+
return interp;
125126
}
126-
127+
#endif
127128

128129
// PyThreadState functions
129130

Include/internal/pycore_tls.h

+18
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
2+
#ifndef Py_CORE_TLS_H
3+
#define Py_CORE_TLS_H
4+
5+
#ifndef Py_BUILD_CORE
6+
# error "this header requires Py_BUILD_CORE to be defined"
7+
#endif
8+
9+
#ifndef _Py_THREAD_LOCAL
10+
#if defined(__GNUC__)
11+
#define _Py_THREAD_LOCAL __thread
12+
#endif
13+
#if defined(_MSC_VER)
14+
#define _Py_THREAD_LOCAL __declspec(thread)
15+
#endif
16+
#endif
17+
18+
#endif /* Py_CORE_TLS_H */

Makefile.pre.in

+1
Original file line numberDiff line numberDiff line change
@@ -1273,6 +1273,7 @@ PYTHON_HEADERS= \
12731273
$(srcdir)/Include/internal/pycore_structseq.h \
12741274
$(srcdir)/Include/internal/pycore_symtable.h \
12751275
$(srcdir)/Include/internal/pycore_sysmodule.h \
1276+
$(srcdir)/Include/internal/pycore_tls.h \
12761277
$(srcdir)/Include/internal/pycore_traceback.h \
12771278
$(srcdir)/Include/internal/pycore_tuple.h \
12781279
$(srcdir)/Include/internal/pycore_ucnhash.h \

Modules/_functoolsmodule.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -703,7 +703,7 @@ functools_reduce(PyObject *self, PyObject *args)
703703
// bpo-42536: The GC may have untracked this args tuple. Since we're
704704
// recycling it, make sure it's tracked again:
705705
if (!_PyObject_GC_IS_TRACKED(args)) {
706-
_PyObject_GC_TRACK(args);
706+
PyObject_GC_Track(args);
707707
}
708708
}
709709
}

Modules/_io/_iomodule.c

+4-4
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
#define PY_SSIZE_T_CLEAN
1111
#include "Python.h"
1212
#include "_iomodule.h"
13-
#include "pycore_pystate.h" // _PyInterpreterState_GET()
13+
#include "pycore_pystate.h" // PyInterpreterState_Get()
1414

1515
#ifdef HAVE_SYS_TYPES_H
1616
#include <sys/types.h>
@@ -91,7 +91,7 @@ PyDoc_STRVAR(module_doc,
9191
" I/O classes. open() uses the file's blksize (as obtained by os.stat) if\n"
9292
" possible.\n"
9393
);
94-
94+
9595

9696
/*
9797
* The main open() function
@@ -509,7 +509,7 @@ _io_text_encoding_impl(PyObject *module, PyObject *encoding, int stacklevel)
509509
/*[clinic end generated code: output=91b2cfea6934cc0c input=bf70231213e2a7b4]*/
510510
{
511511
if (encoding == NULL || encoding == Py_None) {
512-
PyInterpreterState *interp = _PyInterpreterState_GET();
512+
PyInterpreterState *interp = PyInterpreterState_Get();
513513
if (_PyInterpreterState_GetConfig(interp)->warn_default_encoding) {
514514
if (PyErr_WarnEx(PyExc_EncodingWarning,
515515
"'encoding' argument not specified", stacklevel)) {
@@ -542,7 +542,7 @@ _io_open_code_impl(PyObject *module, PyObject *path)
542542
{
543543
return PyFile_OpenCodeObject(path);
544544
}
545-
545+
546546
/*
547547
* Private helpers for the io module.
548548
*/

Modules/_io/textio.c

+3-3
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
#include "pycore_long.h" // _PyLong_GetZero()
1313
#include "pycore_fileutils.h" // _Py_GetLocaleEncoding()
1414
#include "pycore_object.h"
15-
#include "pycore_pystate.h" // _PyInterpreterState_GET()
15+
#include "pycore_pystate.h" // PyInterpreterState_Get()
1616
#include "structmember.h" // PyMemberDef
1717
#include "_iomodule.h"
1818

@@ -996,7 +996,7 @@ io_check_errors(PyObject *errors)
996996
{
997997
assert(errors != NULL && errors != Py_None);
998998

999-
PyInterpreterState *interp = _PyInterpreterState_GET();
999+
PyInterpreterState *interp = PyInterpreterState_Get();
10001000
#ifndef Py_DEBUG
10011001
/* In release mode, only check in development mode (-X dev) */
10021002
if (!_PyInterpreterState_GetConfig(interp)->dev_mode) {
@@ -1086,7 +1086,7 @@ _io_TextIOWrapper___init___impl(textio *self, PyObject *buffer,
10861086
self->detached = 0;
10871087

10881088
if (encoding == NULL) {
1089-
PyInterpreterState *interp = _PyInterpreterState_GET();
1089+
PyInterpreterState *interp = PyInterpreterState_Get();
10901090
if (_PyInterpreterState_GetConfig(interp)->warn_default_encoding) {
10911091
if (PyErr_WarnEx(PyExc_EncodingWarning,
10921092
"'encoding' argument not specified", 1)) {

Modules/_threadmodule.c

+4-4
Original file line numberDiff line numberDiff line change
@@ -850,7 +850,7 @@ local_clear(localobject *self)
850850
Py_CLEAR(self->wr_callback);
851851
/* Remove all strong references to dummies from the thread states */
852852
if (self->key) {
853-
PyInterpreterState *interp = _PyInterpreterState_GET();
853+
PyInterpreterState *interp = PyInterpreterState_Get();
854854
PyThreadState *tstate = PyInterpreterState_ThreadHead(interp);
855855
for(; tstate; tstate = PyThreadState_Next(tstate)) {
856856
if (tstate->dict == NULL) {
@@ -1139,7 +1139,7 @@ thread_PyThread_start_new_thread(PyObject *self, PyObject *fargs)
11391139
return NULL;
11401140
}
11411141

1142-
PyInterpreterState *interp = _PyInterpreterState_GET();
1142+
PyInterpreterState *interp = PyInterpreterState_Get();
11431143
if (interp->config._isolated_interpreter) {
11441144
PyErr_SetString(PyExc_RuntimeError,
11451145
"thread is not supported for isolated subinterpreters");
@@ -1150,7 +1150,7 @@ thread_PyThread_start_new_thread(PyObject *self, PyObject *fargs)
11501150
if (boot == NULL) {
11511151
return PyErr_NoMemory();
11521152
}
1153-
boot->interp = _PyInterpreterState_GET();
1153+
boot->interp = PyInterpreterState_Get();
11541154
boot->tstate = _PyThreadState_Prealloc(boot->interp);
11551155
if (boot->tstate == NULL) {
11561156
PyMem_Free(boot);
@@ -1278,7 +1278,7 @@ particular thread within a system.");
12781278
static PyObject *
12791279
thread__count(PyObject *self, PyObject *Py_UNUSED(ignored))
12801280
{
1281-
PyInterpreterState *interp = _PyInterpreterState_GET();
1281+
PyInterpreterState *interp = PyInterpreterState_Get();
12821282
return PyLong_FromLong(interp->num_threads);
12831283
}
12841284

Modules/atexitmodule.c

+2-2
Original file line numberDiff line numberDiff line change
@@ -9,15 +9,15 @@
99
#include "Python.h"
1010
#include "pycore_initconfig.h" // _PyStatus_NO_MEMORY
1111
#include "pycore_interp.h" // PyInterpreterState.atexit
12-
#include "pycore_pystate.h" // _PyInterpreterState_GET
12+
#include "pycore_pystate.h" // PyInterpreterState_Get
1313

1414
/* ===================================================================== */
1515
/* Callback machinery. */
1616

1717
static inline struct atexit_state*
1818
get_atexit_state(void)
1919
{
20-
PyInterpreterState *interp = _PyInterpreterState_GET();
20+
PyInterpreterState *interp = PyInterpreterState_Get();
2121
return &interp->atexit;
2222
}
2323

Modules/gcmodule.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -131,7 +131,7 @@ gc_decref(PyGC_Head *g)
131131
static GCState *
132132
get_gc_state(void)
133133
{
134-
PyInterpreterState *interp = _PyInterpreterState_GET();
134+
PyInterpreterState *interp = PyInterpreterState_Get();
135135
return &interp->gc;
136136
}
137137

Modules/main.c

+2-2
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
#include "pycore_interp.h" // _PyInterpreterState.sysdict
77
#include "pycore_pathconfig.h" // _PyPathConfig_ComputeSysPath0()
88
#include "pycore_pylifecycle.h" // _Py_PreInitializeFromPyArgv()
9-
#include "pycore_pystate.h" // _PyInterpreterState_GET()
9+
#include "pycore_pystate.h" // PyInterpreterState_Get()
1010

1111
/* Includes for exit_sigint() */
1212
#include <stdio.h> // perror()
@@ -534,7 +534,7 @@ pymain_repl(PyConfig *config, int *exitcode)
534534
static void
535535
pymain_run_python(int *exitcode)
536536
{
537-
PyInterpreterState *interp = _PyInterpreterState_GET();
537+
PyInterpreterState *interp = PyInterpreterState_Get();
538538
/* pymain_run_stdin() modify the config */
539539
PyConfig *config = (PyConfig*)_PyInterpreterState_GetConfig(interp);
540540

Modules/posixmodule.c

+8-8
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@
2727
#include "pycore_ceval.h" // _PyEval_ReInitThreads()
2828
#include "pycore_import.h" // _PyImport_ReInitLock()
2929
#include "pycore_initconfig.h" // _PyStatus_EXCEPTION()
30-
#include "pycore_pystate.h" // _PyInterpreterState_GET()
30+
#include "pycore_pystate.h" // PyInterpreterState_Get()
3131

3232
#include "structmember.h" // PyMemberDef
3333
#ifndef MS_WINDOWS
@@ -575,7 +575,7 @@ run_at_forkers(PyObject *lst, int reverse)
575575
void
576576
PyOS_BeforeFork(void)
577577
{
578-
run_at_forkers(_PyInterpreterState_GET()->before_forkers, 1);
578+
run_at_forkers(PyInterpreterState_Get()->before_forkers, 1);
579579

580580
_PyImport_AcquireLock();
581581
}
@@ -586,7 +586,7 @@ PyOS_AfterFork_Parent(void)
586586
if (_PyImport_ReleaseLock() <= 0)
587587
Py_FatalError("failed releasing import lock after fork");
588588

589-
run_at_forkers(_PyInterpreterState_GET()->after_forkers_parent, 0);
589+
run_at_forkers(PyInterpreterState_Get()->after_forkers_parent, 0);
590590
}
591591

592592
void
@@ -6650,7 +6650,7 @@ os_register_at_fork_impl(PyObject *module, PyObject *before,
66506650
check_null_or_callable(after_in_parent, "after_in_parent")) {
66516651
return NULL;
66526652
}
6653-
interp = _PyInterpreterState_GET();
6653+
interp = PyInterpreterState_Get();
66546654

66556655
if (register_at_forker(&interp->before_forkers, before)) {
66566656
return NULL;
@@ -6680,8 +6680,8 @@ os_fork1_impl(PyObject *module)
66806680
/*[clinic end generated code: output=0de8e67ce2a310bc input=12db02167893926e]*/
66816681
{
66826682
pid_t pid;
6683-
6684-
if (_PyInterpreterState_GET() != PyInterpreterState_Main()) {
6683+
PyInterpreterState *interp = PyInterpreterState_Get();
6684+
if (_Py_IsMainInterpreter(interp)) {
66856685
PyErr_SetString(PyExc_RuntimeError, "fork not supported for subinterpreters");
66866686
return NULL;
66876687
}
@@ -6715,7 +6715,7 @@ os_fork_impl(PyObject *module)
67156715
/*[clinic end generated code: output=3626c81f98985d49 input=13c956413110eeaa]*/
67166716
{
67176717
pid_t pid;
6718-
PyInterpreterState *interp = _PyInterpreterState_GET();
6718+
PyInterpreterState *interp = PyInterpreterState_Get();
67196719
if (interp->config._isolated_interpreter) {
67206720
PyErr_SetString(PyExc_RuntimeError,
67216721
"fork not supported for isolated subinterpreters");
@@ -7333,7 +7333,7 @@ os_forkpty_impl(PyObject *module)
73337333
int master_fd = -1;
73347334
pid_t pid;
73357335

7336-
if (_PyInterpreterState_GET() != PyInterpreterState_Main()) {
7336+
if (PyInterpreterState_Get() != PyInterpreterState_Main()) {
73377337
PyErr_SetString(PyExc_RuntimeError, "fork not supported for subinterpreters");
73387338
return NULL;
73397339
}

Modules/signalmodule.c

+3-4
Original file line numberDiff line numberDiff line change
@@ -1655,8 +1655,8 @@ signal_module_exec(PyObject *m)
16551655
}
16561656
#endif
16571657

1658-
PyThreadState *tstate = _PyThreadState_GET();
1659-
if (_Py_IsMainInterpreter(tstate->interp)) {
1658+
PyInterpreterState *interp = PyInterpreterState_Get();
1659+
if (_Py_IsMainInterpreter(interp)) {
16601660
if (signal_get_set_handlers(state, d) < 0) {
16611661
return -1;
16621662
}
@@ -2032,8 +2032,7 @@ _PySignal_AfterFork(void)
20322032
int
20332033
_PyOS_IsMainThread(void)
20342034
{
2035-
PyInterpreterState *interp = _PyInterpreterState_GET();
2036-
return _Py_ThreadCanHandleSignals(interp);
2035+
return _Py_ThreadCanHandleSignals(PyInterpreterState_Get());
20372036
}
20382037

20392038
#ifdef MS_WINDOWS

Objects/complexobject.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -907,7 +907,7 @@ complex_new_impl(PyTypeObject *type, PyObject *r, PyObject *i)
907907
int ci_is_complex = 0;
908908

909909
if (r == NULL) {
910-
r = _PyLong_GetZero();
910+
r = PY_ZERO();
911911
}
912912

913913
/* Special-case for a single argument when type(arg) is complex. */

Objects/floatobject.c

+3-4
Original file line numberDiff line numberDiff line change
@@ -29,11 +29,10 @@ class float "PyObject *" "&PyFloat_Type"
2929

3030

3131
#if PyFloat_MAXFREELIST > 0
32-
static struct _Py_float_state *
32+
static inline struct _Py_float_state *
3333
get_float_state(void)
3434
{
35-
PyInterpreterState *interp = _PyInterpreterState_GET();
36-
return &interp->float_state;
35+
return &_PyInterpreterState_GET()->float_state;
3736
}
3837
#endif
3938

@@ -1630,7 +1629,7 @@ float_new_impl(PyTypeObject *type, PyObject *x)
16301629
{
16311630
if (type != &PyFloat_Type) {
16321631
if (x == NULL) {
1633-
x = _PyLong_GetZero();
1632+
x = PY_ZERO();
16341633
}
16351634
return float_subtype_new(type, x); /* Wimp out */
16361635
}

Objects/frameobject.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ static PyMemberDef frame_memberlist[] = {
2020
};
2121

2222
#if PyFrame_MAXFREELIST > 0
23-
static struct _Py_frame_state *
23+
static inline struct _Py_frame_state *
2424
get_frame_state(void)
2525
{
2626
PyInterpreterState *interp = _PyInterpreterState_GET();

0 commit comments

Comments
 (0)