Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit c5d3b2c

Browse filesBrowse files
Add _PyThreadState_SwapNoGIL().
1 parent ca1f78e commit c5d3b2c
Copy full SHA for c5d3b2c

File tree

4 files changed

+53
-21
lines changed
Filter options

4 files changed

+53
-21
lines changed

‎Include/internal/pycore_ceval.h

Copy file name to clipboardExpand all lines: Include/internal/pycore_ceval.h
+1Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,7 @@ extern void _PyEval_FiniGIL(PyInterpreterState *interp);
102102

103103
extern void _PyEval_AcquireLock(PyThreadState *tstate);
104104
extern void _PyEval_ReleaseLock(PyThreadState *tstate);
105+
extern PyThreadState * _PyThreadState_SwapNoGIL(PyThreadState *);
105106

106107
extern void _PyEval_DeactivateOpCache(void);
107108

‎Python/ceval_gil.c

Copy file name to clipboardExpand all lines: Python/ceval_gil.c
+6-8Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -631,7 +631,7 @@ PyEval_AcquireThread(PyThreadState *tstate)
631631

632632
take_gil(tstate);
633633

634-
if (_PyThreadState_Swap(tstate->interp->runtime, tstate) != NULL) {
634+
if (_PyThreadState_SwapNoGIL(tstate) != NULL) {
635635
Py_FatalError("non-NULL old thread state");
636636
}
637637
}
@@ -641,8 +641,7 @@ PyEval_ReleaseThread(PyThreadState *tstate)
641641
{
642642
assert(is_tstate_valid(tstate));
643643

644-
_PyRuntimeState *runtime = tstate->interp->runtime;
645-
PyThreadState *new_tstate = _PyThreadState_Swap(runtime, NULL);
644+
PyThreadState *new_tstate = _PyThreadState_SwapNoGIL(NULL);
646645
if (new_tstate != tstate) {
647646
Py_FatalError("wrong thread state");
648647
}
@@ -690,8 +689,7 @@ _PyEval_SignalAsyncExc(PyInterpreterState *interp)
690689
PyThreadState *
691690
PyEval_SaveThread(void)
692691
{
693-
_PyRuntimeState *runtime = &_PyRuntime;
694-
PyThreadState *tstate = _PyThreadState_Swap(runtime, NULL);
692+
PyThreadState *tstate = _PyThreadState_SwapNoGIL(NULL);
695693
_Py_EnsureTstateNotNULL(tstate);
696694

697695
struct _ceval_state *ceval = &tstate->interp->ceval;
@@ -707,7 +705,7 @@ PyEval_RestoreThread(PyThreadState *tstate)
707705

708706
take_gil(tstate);
709707

710-
_PyThreadState_Swap(tstate->interp->runtime, tstate);
708+
_PyThreadState_SwapNoGIL(tstate);
711709
}
712710

713711

@@ -1011,7 +1009,7 @@ _Py_HandlePending(PyThreadState *tstate)
10111009
/* GIL drop request */
10121010
if (_Py_atomic_load_relaxed_int32(&interp_ceval_state->gil_drop_request)) {
10131011
/* Give another thread a chance */
1014-
if (_PyThreadState_Swap(runtime, NULL) != tstate) {
1012+
if (_PyThreadState_SwapNoGIL(NULL) != tstate) {
10151013
Py_FatalError("tstate mix-up");
10161014
}
10171015
drop_gil(interp_ceval_state, tstate);
@@ -1020,7 +1018,7 @@ _Py_HandlePending(PyThreadState *tstate)
10201018

10211019
take_gil(tstate);
10221020

1023-
if (_PyThreadState_Swap(runtime, tstate) != NULL) {
1021+
if (_PyThreadState_SwapNoGIL(tstate) != NULL) {
10241022
Py_FatalError("orphan tstate");
10251023
}
10261024
}

‎Python/pylifecycle.c

Copy file name to clipboardExpand all lines: Python/pylifecycle.c
+14-3Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -591,6 +591,7 @@ init_interp_create_gil(PyThreadState *tstate, int own_gil)
591591

592592
/* finalize_interp_delete() comment explains why _PyEval_FiniGIL() is
593593
only called here. */
594+
// XXX This is broken with a per-interpreter GIL.
594595
_PyEval_FiniGIL(tstate->interp);
595596

596597
/* Auto-thread-state API */
@@ -645,7 +646,8 @@ pycore_create_interpreter(_PyRuntimeState *runtime,
645646
return _PyStatus_ERR("can't make first thread");
646647
}
647648
_PyThreadState_Bind(tstate);
648-
(void) PyThreadState_Swap(tstate);
649+
// XXX For now we do this before the GIL is created.
650+
(void) _PyThreadState_SwapNoGIL(tstate);
649651

650652
status = init_interp_create_gil(tstate, config.own_gil);
651653
if (_PyStatus_EXCEPTION(status)) {
@@ -2025,11 +2027,14 @@ new_interpreter(PyThreadState **tstate_p, const PyInterpreterConfig *config)
20252027
}
20262028
_PyThreadState_Bind(tstate);
20272029

2028-
PyThreadState *save_tstate = PyThreadState_Swap(tstate);
2030+
// XXX For now we do this before the GIL is created.
2031+
PyThreadState *save_tstate = _PyThreadState_SwapNoGIL(tstate);
2032+
int has_gil = 0;
20292033

20302034
/* Copy the current interpreter config into the new interpreter */
20312035
const PyConfig *src_config;
20322036
if (save_tstate != NULL) {
2037+
_PyEval_ReleaseLock(save_tstate);
20332038
src_config = _PyInterpreterState_GetConfig(save_tstate->interp);
20342039
}
20352040
else
@@ -2053,6 +2058,7 @@ new_interpreter(PyThreadState **tstate_p, const PyInterpreterConfig *config)
20532058
if (_PyStatus_EXCEPTION(status)) {
20542059
goto error;
20552060
}
2061+
has_gil = 1;
20562062

20572063
status = pycore_interp_init(tstate);
20582064
if (_PyStatus_EXCEPTION(status)) {
@@ -2072,7 +2078,12 @@ new_interpreter(PyThreadState **tstate_p, const PyInterpreterConfig *config)
20722078

20732079
/* Oops, it didn't work. Undo it all. */
20742080
PyErr_PrintEx(0);
2075-
PyThreadState_Swap(save_tstate);
2081+
if (has_gil) {
2082+
PyThreadState_Swap(save_tstate);
2083+
}
2084+
else {
2085+
_PyThreadState_SwapNoGIL(save_tstate);
2086+
}
20762087
PyThreadState_Clear(tstate);
20772088
PyThreadState_Delete(tstate);
20782089
PyInterpreterState_Delete(interp);

‎Python/pystate.c

Copy file name to clipboardExpand all lines: Python/pystate.c
+32-10Lines changed: 32 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1863,17 +1863,11 @@ PyThreadState_Get(void)
18631863
}
18641864

18651865

1866-
PyThreadState *
1867-
_PyThreadState_Swap(_PyRuntimeState *runtime, PyThreadState *newts)
1866+
static void
1867+
_swap_thread_states(_PyRuntimeState *runtime,
1868+
PyThreadState *oldts, PyThreadState *newts)
18681869
{
1869-
#if defined(Py_DEBUG)
1870-
/* This can be called from PyEval_RestoreThread(). Similar
1871-
to it, we need to ensure errno doesn't change.
1872-
*/
1873-
int err = errno;
1874-
#endif
1875-
PyThreadState *oldts = current_fast_get(runtime);
1876-
1870+
// XXX Do this only if oldts != NULL?
18771871
current_fast_clear(runtime);
18781872

18791873
if (oldts != NULL) {
@@ -1887,13 +1881,41 @@ _PyThreadState_Swap(_PyRuntimeState *runtime, PyThreadState *newts)
18871881
current_fast_set(runtime, newts);
18881882
tstate_activate(newts);
18891883
}
1884+
}
1885+
1886+
PyThreadState *
1887+
_PyThreadState_SwapNoGIL(PyThreadState *newts)
1888+
{
1889+
#if defined(Py_DEBUG)
1890+
/* This can be called from PyEval_RestoreThread(). Similar
1891+
to it, we need to ensure errno doesn't change.
1892+
*/
1893+
int err = errno;
1894+
#endif
1895+
1896+
PyThreadState *oldts = current_fast_get(&_PyRuntime);
1897+
_swap_thread_states(&_PyRuntime, oldts, newts);
18901898

18911899
#if defined(Py_DEBUG)
18921900
errno = err;
18931901
#endif
18941902
return oldts;
18951903
}
18961904

1905+
PyThreadState *
1906+
_PyThreadState_Swap(_PyRuntimeState *runtime, PyThreadState *newts)
1907+
{
1908+
PyThreadState *oldts = current_fast_get(runtime);
1909+
if (oldts != NULL) {
1910+
_PyEval_ReleaseLock(oldts);
1911+
}
1912+
_swap_thread_states(runtime, oldts, newts);
1913+
if (newts != NULL) {
1914+
_PyEval_AcquireLock(newts);
1915+
}
1916+
return oldts;
1917+
}
1918+
18971919
PyThreadState *
18981920
PyThreadState_Swap(PyThreadState *newts)
18991921
{

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.