bpo-25658: Implement PEP 539 for Thread Specific Storage (TSS) API (G… · pythoncapi/cpython@731e189 · GitHub
Skip to content

Commit 731e189

Browse files
ma8mancoghlan
authored andcommitted
bpo-25658: Implement PEP 539 for Thread Specific Storage (TSS) API (pythonGH-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
1 parent b8ab9d3 commit 731e189

18 files changed

Lines changed: 651 additions & 108 deletions

Doc/c-api/init.rst

Lines changed: 157 additions & 0 deletions

Doc/whatsnew/3.7.rst

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,38 @@ built-in ``breakpoint()``.
127127
PEP written and implemented by Barry Warsaw
128128

129129

130+
.. _whatsnew37-pep539:
131+
132+
PEP 539: A New C-API for Thread-Local Storage in CPython
133+
--------------------------------------------------------
134+
135+
While Python provides a C API for thread-local storage support; the existing
136+
:ref:`Thread Local Storage (TLS) API <thread-local-storage-api>` has used
137+
:c:type:`int` to represent TLS keys across all platforms. This has not
138+
generally been a problem for officially-support platforms, but that is neither
139+
POSIX-compliant, nor portable in any practical sense.
140+
141+
:pep:`539` changes this by providing a new :ref:`Thread Specific Storage (TSS)
142+
API <thread-specific-storage-api>` to CPython which supersedes use of the
143+
existing TLS API within the CPython interpreter, while deprecating the existing
144+
API. The TSS API uses a new type :c:type:`Py_tss_t` instead of :c:type:`int`
145+
to represent TSS keys--an opaque type the definition of which may depend on
146+
the underlying TLS implementation. Therefore, this will allow to build CPython
147+
on platforms where the native TLS key is defined in a way that cannot be safely
148+
cast to :c:type:`int`.
149+
150+
Note that on platforms where the native TLS key is defined in a way that cannot
151+
be safely cast to :c:type:`int`, all functions of the existing TLS API will be
152+
no-op and immediately return failure. This indicates clearly that the old API
153+
is not supported on platforms where it cannot be used reliably, and that no
154+
effort will be made to add such support.
155+
156+
.. seealso::
157+
158+
:pep:`539` -- A New C-API for Thread-Local Storage in CPython
159+
PEP written by Erik M. Bray; implementation by Masayuki Yamamoto.
160+
161+
130162
Other Language Changes
131163
======================
132164

Include/internal/pystate.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ struct _gilstate_runtime_state {
2626
*/
2727
/* TODO: Given interp_main, it may be possible to kill this ref */
2828
PyInterpreterState *autoInterpreterState;
29-
int autoTLSkey;
29+
Py_tss_t autoTSSkey;
3030
};
3131

3232
/* hook for PyEval_GetFrame(), requested for Psyco */

Include/pythread.h

Lines changed: 63 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,8 @@ PyAPI_FUNC(unsigned long) PyThread_get_thread_ident(void);
2929
PyAPI_FUNC(PyThread_type_lock) PyThread_allocate_lock(void);
3030
PyAPI_FUNC(void) PyThread_free_lock(PyThread_type_lock);
3131
PyAPI_FUNC(int) PyThread_acquire_lock(PyThread_type_lock, int);
32-
#define WAIT_LOCK 1
33-
#define NOWAIT_LOCK 0
32+
#define WAIT_LOCK 1
33+
#define NOWAIT_LOCK 0
3434

3535
/* PY_TIMEOUT_T is the integral type used to specify timeouts when waiting
3636
on a lock (see PyThread_acquire_lock_timed() below).
@@ -77,15 +77,69 @@ PyAPI_FUNC(int) PyThread_set_stacksize(size_t);
7777
PyAPI_FUNC(PyObject*) PyThread_GetInfo(void);
7878
#endif
7979

80-
/* Thread Local Storage (TLS) API */
81-
PyAPI_FUNC(int) PyThread_create_key(void);
82-
PyAPI_FUNC(void) PyThread_delete_key(int);
83-
PyAPI_FUNC(int) PyThread_set_key_value(int, void *);
84-
PyAPI_FUNC(void *) PyThread_get_key_value(int);
85-
PyAPI_FUNC(void) PyThread_delete_key_value(int key);
80+
81+
/* Thread Local Storage (TLS) API
82+
TLS API is DEPRECATED. Use Thread Specific Storage (TSS) API.
83+
84+
The existing TLS API has used int to represent TLS keys across all
85+
platforms, but it is not POSIX-compliant. Therefore, the new TSS API uses
86+
opaque data type to represent TSS keys to be compatible (see PEP 539).
87+
*/
88+
PyAPI_FUNC(int) PyThread_create_key(void) Py_DEPRECATED(3.7);
89+
PyAPI_FUNC(void) PyThread_delete_key(int key) Py_DEPRECATED(3.7);
90+
PyAPI_FUNC(int) PyThread_set_key_value(int key, void *value) Py_DEPRECATED(3.7);
91+
PyAPI_FUNC(void *) PyThread_get_key_value(int key) Py_DEPRECATED(3.7);
92+
PyAPI_FUNC(void) PyThread_delete_key_value(int key) Py_DEPRECATED(3.7);
8693

8794
/* Cleanup after a fork */
88-
PyAPI_FUNC(void) PyThread_ReInitTLS(void);
95+
PyAPI_FUNC(void) PyThread_ReInitTLS(void) Py_DEPRECATED(3.7);
96+
97+
98+
#if !defined(Py_LIMITED_API) || Py_LIMITED_API+0 >= 0x03070000
99+
/* New in 3.7 */
100+
/* Thread Specific Storage (TSS) API */
101+
102+
typedef struct _Py_tss_t Py_tss_t; /* opaque */
103+
104+
#ifndef Py_LIMITED_API
105+
#if defined(_POSIX_THREADS)
106+
/* Darwin needs pthread.h to know type name the pthread_key_t. */
107+
# include <pthread.h>
108+
# define NATIVE_TSS_KEY_T pthread_key_t
109+
#elif defined(NT_THREADS)
110+
/* In Windows, native TSS key type is DWORD,
111+
but hardcode the unsigned long to avoid errors for include directive.
112+
*/
113+
# define NATIVE_TSS_KEY_T unsigned long
114+
#else
115+
# error "Require native threads. See https://bugs.python.org/issue31370"
116+
#endif
117+
118+
/* When Py_LIMITED_API is not defined, the type layout of Py_tss_t is
119+
exposed to allow static allocation in the API clients. Even in this case,
120+
you must handle TSS keys through API functions due to compatibility.
121+
*/
122+
struct _Py_tss_t {
123+
int _is_initialized;
124+
NATIVE_TSS_KEY_T _key;
125+
};
126+
127+
#undef NATIVE_TSS_KEY_T
128+
129+
/* When static allocation, you must initialize with Py_tss_NEEDS_INIT. */
130+
#define Py_tss_NEEDS_INIT {0}
131+
#endif /* !Py_LIMITED_API */
132+
133+
PyAPI_FUNC(Py_tss_t *) PyThread_tss_alloc(void);
134+
PyAPI_FUNC(void) PyThread_tss_free(Py_tss_t *key);
135+
136+
/* The parameter key must not be NULL. */
137+
PyAPI_FUNC(int) PyThread_tss_is_created(Py_tss_t *key);
138+
PyAPI_FUNC(int) PyThread_tss_create(Py_tss_t *key);
139+
PyAPI_FUNC(void) PyThread_tss_delete(Py_tss_t *key);
140+
PyAPI_FUNC(int) PyThread_tss_set(Py_tss_t *key, void *value);
141+
PyAPI_FUNC(void *) PyThread_tss_get(Py_tss_t *key);
142+
#endif /* New in 3.7 */
89143

90144
#ifdef __cplusplus
91145
}
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
Implement PEP 539 for Thread Specific Stroage (TSS) API: it is a new Thread
2+
Local Storage (TLS) API to CPython which would supersede use of the existing
3+
TLS API within the CPython interpreter, while deprecating the existing API.
4+
PEP written by Erik M. Bray, patch by Masayuki Yamamoto.

Modules/_testcapimodule.c

Lines changed: 56 additions & 0 deletions

0 commit comments

Comments
 (0)