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 /Modules | |
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 'Modules')
-rw-r--r-- | Modules/_testcapimodule.c | 56 | ||||
-rw-r--r-- | Modules/_tracemalloc.c | 25 | ||||
-rw-r--r-- | Modules/faulthandler.c | 2 | ||||
-rw-r--r-- | Modules/posixmodule.c | 3 |
4 files changed, 65 insertions, 21 deletions
diff --git a/Modules/_testcapimodule.c b/Modules/_testcapimodule.c index 1a29621..b512c05 100644 --- a/Modules/_testcapimodule.c +++ b/Modules/_testcapimodule.c @@ -4306,6 +4306,61 @@ py_w_stopcode(PyObject *self, PyObject *args) #endif +static PyObject * +test_pythread_tss_key_state(PyObject *self, PyObject *args) +{ + Py_tss_t tss_key = Py_tss_NEEDS_INIT; + if (PyThread_tss_is_created(&tss_key)) { + return raiseTestError("test_pythread_tss_key_state", + "TSS key not in an uninitialized state at " + "creation time"); + } + if (PyThread_tss_create(&tss_key) != 0) { + PyErr_SetString(PyExc_RuntimeError, "PyThread_tss_create failed"); + return NULL; + } + if (!PyThread_tss_is_created(&tss_key)) { + return raiseTestError("test_pythread_tss_key_state", + "PyThread_tss_create succeeded, " + "but with TSS key in an uninitialized state"); + } + if (PyThread_tss_create(&tss_key) != 0) { + return raiseTestError("test_pythread_tss_key_state", + "PyThread_tss_create unsuccessful with " + "an already initialized key"); + } +#define CHECK_TSS_API(expr) \ + (void)(expr); \ + if (!PyThread_tss_is_created(&tss_key)) { \ + return raiseTestError("test_pythread_tss_key_state", \ + "TSS key initialization state was not " \ + "preserved after calling " #expr); } + CHECK_TSS_API(PyThread_tss_set(&tss_key, NULL)); + CHECK_TSS_API(PyThread_tss_get(&tss_key)); +#undef CHECK_TSS_API + PyThread_tss_delete(&tss_key); + if (PyThread_tss_is_created(&tss_key)) { + return raiseTestError("test_pythread_tss_key_state", + "PyThread_tss_delete called, but did not " + "set the key state to uninitialized"); + } + + Py_tss_t *ptr_key = PyThread_tss_alloc(); + if (ptr_key == NULL) { + PyErr_SetString(PyExc_RuntimeError, "PyThread_tss_alloc failed"); + return NULL; + } + if (PyThread_tss_is_created(ptr_key)) { + return raiseTestError("test_pythread_tss_key_state", + "TSS key not in an uninitialized state at " + "allocation time"); + } + PyThread_tss_free(ptr_key); + ptr_key = NULL; + Py_RETURN_NONE; +} + + static PyMethodDef TestMethods[] = { {"raise_exception", raise_exception, METH_VARARGS}, {"raise_memoryerror", (PyCFunction)raise_memoryerror, METH_NOARGS}, @@ -4518,6 +4573,7 @@ static PyMethodDef TestMethods[] = { #ifdef W_STOPCODE {"W_STOPCODE", py_w_stopcode, METH_VARARGS}, #endif + {"test_pythread_tss_key_state", test_pythread_tss_key_state, METH_VARARGS}, {NULL, NULL} /* sentinel */ }; diff --git a/Modules/_tracemalloc.c b/Modules/_tracemalloc.c index 386f2f1..af2a2fa 100644 --- a/Modules/_tracemalloc.c +++ b/Modules/_tracemalloc.c @@ -167,14 +167,7 @@ tracemalloc_error(const char *format, ...) #if defined(TRACE_RAW_MALLOC) #define REENTRANT_THREADLOCAL -/* If your OS does not provide native thread local storage, you can implement - it manually using a lock. Functions of thread.c cannot be used because - they use PyMem_RawMalloc() which leads to a reentrant call. */ -#if !(defined(_POSIX_THREADS) || defined(NT_THREADS)) -# error "need native thread local storage (TLS)" -#endif - -static int tracemalloc_reentrant_key = -1; +static Py_tss_t tracemalloc_reentrant_key = Py_tss_NEEDS_INIT; /* Any non-NULL pointer can be used */ #define REENTRANT Py_True @@ -184,8 +177,8 @@ get_reentrant(void) { void *ptr; - assert(tracemalloc_reentrant_key != -1); - ptr = PyThread_get_key_value(tracemalloc_reentrant_key); + assert(PyThread_tss_is_created(&tracemalloc_reentrant_key)); + ptr = PyThread_tss_get(&tracemalloc_reentrant_key); if (ptr != NULL) { assert(ptr == REENTRANT); return 1; @@ -198,15 +191,15 @@ static void set_reentrant(int reentrant) { assert(reentrant == 0 || reentrant == 1); - assert(tracemalloc_reentrant_key != -1); + assert(PyThread_tss_is_created(&tracemalloc_reentrant_key)); if (reentrant) { assert(!get_reentrant()); - PyThread_set_key_value(tracemalloc_reentrant_key, REENTRANT); + PyThread_tss_set(&tracemalloc_reentrant_key, REENTRANT); } else { assert(get_reentrant()); - PyThread_set_key_value(tracemalloc_reentrant_key, NULL); + PyThread_tss_set(&tracemalloc_reentrant_key, NULL); } } @@ -975,8 +968,7 @@ tracemalloc_init(void) PyMem_GetAllocator(PYMEM_DOMAIN_RAW, &allocators.raw); #ifdef REENTRANT_THREADLOCAL - tracemalloc_reentrant_key = PyThread_create_key(); - if (tracemalloc_reentrant_key == -1) { + if (PyThread_tss_create(&tracemalloc_reentrant_key) != 0) { #ifdef MS_WINDOWS PyErr_SetFromWindowsErr(0); #else @@ -1061,8 +1053,7 @@ tracemalloc_deinit(void) #endif #ifdef REENTRANT_THREADLOCAL - PyThread_delete_key(tracemalloc_reentrant_key); - tracemalloc_reentrant_key = -1; + PyThread_tss_delete(&tracemalloc_reentrant_key); #endif Py_XDECREF(unknown_filename); diff --git a/Modules/faulthandler.c b/Modules/faulthandler.c index 4f3d971..c2c2c53 100644 --- a/Modules/faulthandler.c +++ b/Modules/faulthandler.c @@ -232,7 +232,7 @@ faulthandler_dump_traceback(int fd, int all_threads, PyThreadState_Get() doesn't give the state of the thread that caused the fault if the thread released the GIL, and so this function cannot be - used. Read the thread local storage (TLS) instead: call + used. Read the thread specific storage (TSS) instead: call PyGILState_GetThisThreadState(). */ tstate = PyGILState_GetThisThreadState(); diff --git a/Modules/posixmodule.c b/Modules/posixmodule.c index 13ff916..5f30b20 100644 --- a/Modules/posixmodule.c +++ b/Modules/posixmodule.c @@ -454,9 +454,6 @@ PyOS_AfterFork_Parent(void) void PyOS_AfterFork_Child(void) { - /* PyThread_ReInitTLS() must be called early, to make sure that the TLS API - * can be called safely. */ - PyThread_ReInitTLS(); _PyGILState_Reinit(); PyEval_ReInitThreads(); _PyImport_ReInitLock(); |