summaryrefslogtreecommitdiffstats
path: root/Modules
diff options
context:
space:
mode:
authorMasayuki Yamamoto <ma3yuki.8mamo10@gmail.com>2017-10-06 10:41:34 (GMT)
committerNick Coghlan <ncoghlan@gmail.com>2017-10-06 10:41:34 (GMT)
commit731e18901484c75b60167a06a0ba0719a6d4827d (patch)
treefc9b8afc6eb8453729c130a146b838228ab103c6 /Modules
parentb8ab9d3fc816f85f4d6dbef12b7414e6dc10e4dd (diff)
downloadcpython-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.c56
-rw-r--r--Modules/_tracemalloc.c25
-rw-r--r--Modules/faulthandler.c2
-rw-r--r--Modules/posixmodule.c3
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();