diff options
author | Masayuki Yamamoto <ma3yuki.8mamo10@gmail.com> | 2017-10-06 10:41:34 (GMT) |
---|---|---|
committer | Nick Coghlan <ncoghlan@gmail.com> | 2017-10-06 10:41:34 (GMT) |
commit | 731e18901484c75b60167a06a0ba0719a6d4827d (patch) | |
tree | fc9b8afc6eb8453729c130a146b838228ab103c6 /Python/pystate.c | |
parent | b8ab9d3fc816f85f4d6dbef12b7414e6dc10e4dd (diff) | |
download | cpython-731e18901484c75b60167a06a0ba0719a6d4827d.zip cpython-731e18901484c75b60167a06a0ba0719a6d4827d.tar.gz cpython-731e18901484c75b60167a06a0ba0719a6d4827d.tar.bz2 |
bpo-25658: Implement PEP 539 for Thread Specific Storage (TSS) API (GH-1362)
See PEP 539 for details.
Highlights of changes:
- Add Thread Specific Storage (TSS) API
- Document the Thread Local Storage (TLS) API as deprecated
- Update code that used TLS API to use TSS API
Diffstat (limited to 'Python/pystate.c')
-rw-r--r-- | Python/pystate.c | 71 |
1 files changed, 38 insertions, 33 deletions
diff --git a/Python/pystate.c b/Python/pystate.c index 53c1236..3feae34 100644 --- a/Python/pystate.c +++ b/Python/pystate.c @@ -46,7 +46,12 @@ _PyRuntimeState_Init(_PyRuntimeState *runtime) _PyEval_Initialize(&runtime->ceval); runtime->gilstate.check_enabled = 1; - runtime->gilstate.autoTLSkey = -1; + /* A TSS key must be initialized with Py_tss_NEEDS_INIT + in accordance with the specification. */ + { + Py_tss_t initial = Py_tss_NEEDS_INIT; + runtime->gilstate.autoTSSkey = initial; + } runtime->interpreters.mutex = PyThread_allocate_lock(); if (runtime->interpreters.mutex == NULL) @@ -485,9 +490,9 @@ PyThreadState_Delete(PyThreadState *tstate) if (tstate == GET_TSTATE()) Py_FatalError("PyThreadState_Delete: tstate is still current"); if (_PyRuntime.gilstate.autoInterpreterState && - PyThread_get_key_value(_PyRuntime.gilstate.autoTLSkey) == tstate) + PyThread_tss_get(&_PyRuntime.gilstate.autoTSSkey) == tstate) { - PyThread_delete_key_value(_PyRuntime.gilstate.autoTLSkey); + PyThread_tss_set(&_PyRuntime.gilstate.autoTSSkey, NULL); } tstate_delete_common(tstate); } @@ -502,9 +507,9 @@ PyThreadState_DeleteCurrent() "PyThreadState_DeleteCurrent: no current tstate"); tstate_delete_common(tstate); if (_PyRuntime.gilstate.autoInterpreterState && - PyThread_get_key_value(_PyRuntime.gilstate.autoTLSkey) == tstate) + PyThread_tss_get(&_PyRuntime.gilstate.autoTSSkey) == tstate) { - PyThread_delete_key_value(_PyRuntime.gilstate.autoTLSkey); + PyThread_tss_set(&_PyRuntime.gilstate.autoTSSkey, NULL); } SET_TSTATE(NULL); PyEval_ReleaseLock(); @@ -761,11 +766,11 @@ void _PyGILState_Init(PyInterpreterState *i, PyThreadState *t) { assert(i && t); /* must init with valid states */ - _PyRuntime.gilstate.autoTLSkey = PyThread_create_key(); - if (_PyRuntime.gilstate.autoTLSkey == -1) - Py_FatalError("Could not allocate TLS entry"); + if (PyThread_tss_create(&_PyRuntime.gilstate.autoTSSkey) != 0) { + Py_FatalError("Could not allocate TSS entry"); + } _PyRuntime.gilstate.autoInterpreterState = i; - assert(PyThread_get_key_value(_PyRuntime.gilstate.autoTLSkey) == NULL); + assert(PyThread_tss_get(&_PyRuntime.gilstate.autoTSSkey) == NULL); assert(t->gilstate_counter == 0); _PyGILState_NoteThreadState(t); @@ -780,14 +785,13 @@ _PyGILState_GetInterpreterStateUnsafe(void) void _PyGILState_Fini(void) { - PyThread_delete_key(_PyRuntime.gilstate.autoTLSkey); - _PyRuntime.gilstate.autoTLSkey = -1; + PyThread_tss_delete(&_PyRuntime.gilstate.autoTSSkey); _PyRuntime.gilstate.autoInterpreterState = NULL; } -/* Reset the TLS key - called by PyOS_AfterFork_Child(). +/* Reset the TSS key - called by PyOS_AfterFork_Child(). * This should not be necessary, but some - buggy - pthread implementations - * don't reset TLS upon fork(), see issue #10517. + * don't reset TSS upon fork(), see issue #10517. */ void _PyGILState_Reinit(void) @@ -796,15 +800,18 @@ _PyGILState_Reinit(void) if (_PyRuntime.interpreters.mutex == NULL) Py_FatalError("Can't initialize threads for interpreter"); PyThreadState *tstate = PyGILState_GetThisThreadState(); - PyThread_delete_key(_PyRuntime.gilstate.autoTLSkey); - if ((_PyRuntime.gilstate.autoTLSkey = PyThread_create_key()) == -1) - Py_FatalError("Could not allocate TLS entry"); + PyThread_tss_delete(&_PyRuntime.gilstate.autoTSSkey); + if (PyThread_tss_create(&_PyRuntime.gilstate.autoTSSkey) != 0) { + Py_FatalError("Could not allocate TSS entry"); + } /* If the thread had an associated auto thread state, reassociate it with * the new key. */ - if (tstate && PyThread_set_key_value(_PyRuntime.gilstate.autoTLSkey, - (void *)tstate) < 0) - Py_FatalError("Couldn't create autoTLSkey mapping"); + if (tstate && + PyThread_tss_set(&_PyRuntime.gilstate.autoTSSkey, (void *)tstate) != 0) + { + Py_FatalError("Couldn't create autoTSSkey mapping"); + } } /* When a thread state is created for a thread by some mechanism other than @@ -815,13 +822,13 @@ _PyGILState_Reinit(void) static void _PyGILState_NoteThreadState(PyThreadState* tstate) { - /* If autoTLSkey isn't initialized, this must be the very first + /* If autoTSSkey isn't initialized, this must be the very first threadstate created in Py_Initialize(). Don't do anything for now (we'll be back here when _PyGILState_Init is called). */ if (!_PyRuntime.gilstate.autoInterpreterState) return; - /* Stick the thread state for this thread in thread local storage. + /* Stick the thread state for this thread in thread specific storage. The only situation where you can legitimately have more than one thread state for an OS level thread is when there are multiple @@ -833,12 +840,11 @@ _PyGILState_NoteThreadState(PyThreadState* tstate) The first thread state created for that given OS level thread will "win", which seems reasonable behaviour. */ - if (PyThread_get_key_value(_PyRuntime.gilstate.autoTLSkey) == NULL) { - if ((PyThread_set_key_value(_PyRuntime.gilstate.autoTLSkey, - (void *)tstate) - ) < 0) + if (PyThread_tss_get(&_PyRuntime.gilstate.autoTSSkey) == NULL) { + if ((PyThread_tss_set(&_PyRuntime.gilstate.autoTSSkey, (void *)tstate) + ) != 0) { - Py_FatalError("Couldn't create autoTLSkey mapping"); + Py_FatalError("Couldn't create autoTSSkey mapping"); } } @@ -852,8 +858,7 @@ PyGILState_GetThisThreadState(void) { if (_PyRuntime.gilstate.autoInterpreterState == NULL) return NULL; - return (PyThreadState *)PyThread_get_key_value( - _PyRuntime.gilstate.autoTLSkey); + return (PyThreadState *)PyThread_tss_get(&_PyRuntime.gilstate.autoTSSkey); } int @@ -864,8 +869,9 @@ PyGILState_Check(void) if (!_PyGILState_check_enabled) return 1; - if (_PyRuntime.gilstate.autoTLSkey == -1) + if (!PyThread_tss_is_created(&_PyRuntime.gilstate.autoTSSkey)) { return 1; + } tstate = GET_TSTATE(); if (tstate == NULL) @@ -886,8 +892,7 @@ PyGILState_Ensure(void) */ /* Py_Initialize() hasn't been called! */ assert(_PyRuntime.gilstate.autoInterpreterState); - tcur = (PyThreadState *)PyThread_get_key_value( - _PyRuntime.gilstate.autoTLSkey); + tcur = (PyThreadState *)PyThread_tss_get(&_PyRuntime.gilstate.autoTSSkey); if (tcur == NULL) { /* At startup, Python has no concrete GIL. If PyGILState_Ensure() is called from a new thread for the first time, we need the create the @@ -919,8 +924,8 @@ PyGILState_Ensure(void) void PyGILState_Release(PyGILState_STATE oldstate) { - PyThreadState *tcur = (PyThreadState *)PyThread_get_key_value( - _PyRuntime.gilstate.autoTLSkey); + PyThreadState *tcur = (PyThreadState *)PyThread_tss_get( + &_PyRuntime.gilstate.autoTSSkey); if (tcur == NULL) Py_FatalError("auto-releasing thread-state, " "but no thread-state for this thread"); |