Skip to content

Commit 1c9e493

Browse files
gh-106078: Move static objects related to CONTEXTVAR to the decimal module global state (#106395)
Co-authored-by: Erlend E. Aasland <[email protected]>
1 parent 48d5d32 commit 1c9e493

File tree

2 files changed

+32
-29
lines changed

2 files changed

+32
-29
lines changed

Modules/_decimal/_decimal.c

+32-28
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,8 @@
3939

4040
#include "docstrings.h"
4141

42+
struct PyDecContextObject;
43+
4244
typedef struct {
4345
PyTypeObject *PyDecContextManager_Type;
4446
PyTypeObject *PyDecContext_Type;
@@ -50,6 +52,15 @@ typedef struct {
5052
/* Top level Exception; inherits from ArithmeticError */
5153
PyObject *DecimalException;
5254

55+
#ifndef WITH_DECIMAL_CONTEXTVAR
56+
/* Key for thread state dictionary */
57+
PyObject *tls_context_key;
58+
/* Invariant: NULL or the most recently accessed thread local context */
59+
struct PyDecContextObject *cached_context;
60+
#else
61+
PyObject *current_context_var;
62+
#endif
63+
5364
/* Template for creating new thread contexts, calling Context() without
5465
* arguments and initializing the module_context on first access. */
5566
PyObject *default_context_template;
@@ -104,7 +115,7 @@ typedef struct {
104115
uint32_t *flags;
105116
} PyDecSignalDictObject;
106117

107-
typedef struct {
118+
typedef struct PyDecContextObject {
108119
PyObject_HEAD
109120
mpd_context_t ctx;
110121
PyObject *traps;
@@ -119,7 +130,6 @@ typedef struct {
119130
PyObject *global;
120131
} PyDecContextManagerObject;
121132

122-
123133
#undef MPD
124134
#undef CTX
125135
#define PyDec_CheckExact(st, v) Py_IS_TYPE(v, (st)->PyDec_Type)
@@ -145,16 +155,6 @@ incr_false(void)
145155
return Py_NewRef(Py_False);
146156
}
147157

148-
149-
#ifndef WITH_DECIMAL_CONTEXTVAR
150-
/* Key for thread state dictionary */
151-
static PyObject *tls_context_key = NULL;
152-
/* Invariant: NULL or the most recently accessed thread local context */
153-
static PyDecContextObject *cached_context = NULL;
154-
#else
155-
static PyObject *current_context_var = NULL;
156-
#endif
157-
158158
/* Error codes for functions that return signals or conditions */
159159
#define DEC_INVALID_SIGNALS (MPD_Max_status+1U)
160160
#define DEC_ERR_OCCURRED (DEC_INVALID_SIGNALS<<1)
@@ -1565,7 +1565,8 @@ current_context_from_dict(void)
15651565
return NULL;
15661566
}
15671567

1568-
PyObject *tl_context = PyDict_GetItemWithError(dict, tls_context_key);
1568+
PyObject *tl_context;
1569+
tl_context = PyDict_GetItemWithError(dict, modstate->tls_context_key);
15691570
if (tl_context != NULL) {
15701571
/* We already have a thread local context. */
15711572
CONTEXT_CHECK(modstate, tl_context);
@@ -1576,13 +1577,13 @@ current_context_from_dict(void)
15761577
}
15771578

15781579
/* Set up a new thread local context. */
1579-
tl_context = context_copy(state->default_context_template, NULL);
1580+
tl_context = context_copy(modstate->default_context_template, NULL);
15801581
if (tl_context == NULL) {
15811582
return NULL;
15821583
}
15831584
CTX(tl_context)->status = 0;
15841585

1585-
if (PyDict_SetItem(dict, tls_context_key, tl_context) < 0) {
1586+
if (PyDict_SetItem(dict, modstate->tls_context_key, tl_context) < 0) {
15861587
Py_DECREF(tl_context);
15871588
return NULL;
15881589
}
@@ -1591,8 +1592,8 @@ current_context_from_dict(void)
15911592

15921593
/* Cache the context of the current thread, assuming that it
15931594
* will be accessed several times before a thread switch. */
1594-
cached_context = (PyDecContextObject *)tl_context;
1595-
cached_context->tstate = tstate;
1595+
modstate->cached_context = (PyDecContextObject *)tl_context;
1596+
modstate->cached_context->tstate = tstate;
15961597

15971598
/* Borrowed reference with refcount==1 */
15981599
return tl_context;
@@ -1603,8 +1604,9 @@ static PyObject *
16031604
current_context(void)
16041605
{
16051606
PyThreadState *tstate = _PyThreadState_GET();
1606-
if (cached_context && cached_context->tstate == tstate) {
1607-
return (PyObject *)cached_context;
1607+
decimal_state *modstate = GLOBAL_STATE();
1608+
if (modstate->cached_context && modstate->cached_context->tstate == tstate) {
1609+
return (PyObject *)(modstate->cached_context);
16081610
}
16091611

16101612
return current_context_from_dict();
@@ -1662,8 +1664,8 @@ PyDec_SetCurrentContext(PyObject *self UNUSED, PyObject *v)
16621664
Py_INCREF(v);
16631665
}
16641666

1665-
cached_context = NULL;
1666-
if (PyDict_SetItem(dict, tls_context_key, v) < 0) {
1667+
state->cached_context = NULL;
1668+
if (PyDict_SetItem(dict, state->tls_context_key, v) < 0) {
16671669
Py_DECREF(v);
16681670
return NULL;
16691671
}
@@ -1682,7 +1684,7 @@ init_current_context(void)
16821684
}
16831685
CTX(tl_context)->status = 0;
16841686

1685-
PyObject *tok = PyContextVar_Set(current_context_var, tl_context);
1687+
PyObject *tok = PyContextVar_Set(state->current_context_var, tl_context);
16861688
if (tok == NULL) {
16871689
Py_DECREF(tl_context);
16881690
return NULL;
@@ -1696,7 +1698,8 @@ static inline PyObject *
16961698
current_context(void)
16971699
{
16981700
PyObject *tl_context;
1699-
if (PyContextVar_Get(current_context_var, NULL, &tl_context) < 0) {
1701+
decimal_state *state = GLOBAL_STATE();
1702+
if (PyContextVar_Get(state->current_context_var, NULL, &tl_context) < 0) {
17001703
return NULL;
17011704
}
17021705

@@ -1744,7 +1747,7 @@ PyDec_SetCurrentContext(PyObject *self UNUSED, PyObject *v)
17441747
Py_INCREF(v);
17451748
}
17461749

1747-
PyObject *tok = PyContextVar_Set(current_context_var, v);
1750+
PyObject *tok = PyContextVar_Set(state->current_context_var, v);
17481751
Py_DECREF(v);
17491752
if (tok == NULL) {
17501753
return NULL;
@@ -5987,10 +5990,11 @@ PyInit__decimal(void)
59875990
Py_NewRef(state->default_context_template)));
59885991

59895992
#ifndef WITH_DECIMAL_CONTEXTVAR
5990-
ASSIGN_PTR(tls_context_key, PyUnicode_FromString("___DECIMAL_CTX__"));
5993+
ASSIGN_PTR(state->tls_context_key,
5994+
PyUnicode_FromString("___DECIMAL_CTX__"));
59915995
CHECK_INT(PyModule_AddObject(m, "HAVE_CONTEXTVAR", Py_NewRef(Py_False)));
59925996
#else
5993-
ASSIGN_PTR(current_context_var, PyContextVar_New("decimal_context", NULL));
5997+
ASSIGN_PTR(state->current_context_var, PyContextVar_New("decimal_context", NULL));
59945998
CHECK_INT(PyModule_AddObject(m, "HAVE_CONTEXTVAR", Py_NewRef(Py_True)));
59955999
#endif
59966000
CHECK_INT(PyModule_AddObject(m, "HAVE_THREADS", Py_NewRef(Py_True)));
@@ -6049,9 +6053,9 @@ PyInit__decimal(void)
60496053
Py_CLEAR(state->DecimalTuple); /* GCOV_NOT_REACHED */
60506054
Py_CLEAR(state->default_context_template); /* GCOV_NOT_REACHED */
60516055
#ifndef WITH_DECIMAL_CONTEXTVAR
6052-
Py_CLEAR(tls_context_key); /* GCOV_NOT_REACHED */
6056+
Py_CLEAR(state->tls_context_key); /* GCOV_NOT_REACHED */
60536057
#else
6054-
Py_CLEAR(current_context_var); /* GCOV_NOT_REACHED */
6058+
Py_CLEAR(state->current_context_var); /* GCOV_NOT_REACHED */
60556059
#endif
60566060
Py_CLEAR(state->basic_context_template); /* GCOV_NOT_REACHED */
60576061
Py_CLEAR(state->extended_context_template); /* GCOV_NOT_REACHED */

Tools/c-analyzer/cpython/globals-to-fix.tsv

-1
Original file line numberDiff line numberDiff line change
@@ -422,7 +422,6 @@ Modules/_datetimemodule.c - us_per_day -
422422
Modules/_datetimemodule.c - us_per_week -
423423
Modules/_datetimemodule.c - seconds_per_day -
424424
Modules/_decimal/_decimal.c - global_state -
425-
Modules/_decimal/_decimal.c - current_context_var -
426425
Modules/_decimal/_decimal.c - round_map -
427426
Modules/_decimal/_decimal.c - Rational -
428427
Modules/_decimal/_decimal.c - SignalTuple -

0 commit comments

Comments
 (0)