summaryrefslogtreecommitdiffstats
path: root/Python/getargs.c
diff options
context:
space:
mode:
Diffstat (limited to 'Python/getargs.c')
-rw-r--r--Python/getargs.c46
1 files changed, 17 insertions, 29 deletions
diff --git a/Python/getargs.c b/Python/getargs.c
index 5a12ca8..4f873e5 100644
--- a/Python/getargs.c
+++ b/Python/getargs.c
@@ -1877,8 +1877,9 @@ new_kwtuple(const char * const *keywords, int total, int pos)
}
static int
-_parser_init(struct _PyArg_Parser *parser)
+_parser_init(void *arg)
{
+ struct _PyArg_Parser *parser = (struct _PyArg_Parser *)arg;
const char * const *keywords = parser->keywords;
assert(keywords != NULL);
assert(parser->pos == 0 &&
@@ -1889,7 +1890,7 @@ _parser_init(struct _PyArg_Parser *parser)
int len, pos;
if (scan_keywords(keywords, &len, &pos) < 0) {
- return 0;
+ return -1;
}
const char *fname, *custommsg = NULL;
@@ -1898,7 +1899,7 @@ _parser_init(struct _PyArg_Parser *parser)
assert(parser->fname == NULL);
if (parse_format(parser->format, len, pos,
&fname, &custommsg, &min, &max) < 0) {
- return 0;
+ return -1;
}
}
else {
@@ -1911,7 +1912,7 @@ _parser_init(struct _PyArg_Parser *parser)
if (kwtuple == NULL) {
kwtuple = new_kwtuple(keywords, len, pos);
if (kwtuple == NULL) {
- return 0;
+ return -1;
}
owned = 1;
}
@@ -1925,40 +1926,27 @@ _parser_init(struct _PyArg_Parser *parser)
parser->min = min;
parser->max = max;
parser->kwtuple = kwtuple;
- parser->initialized = owned ? 1 : -1;
+ parser->is_kwtuple_owned = owned;
assert(parser->next == NULL);
- parser->next = _PyRuntime.getargs.static_parsers;
- _PyRuntime.getargs.static_parsers = parser;
- return 1;
+ parser->next = _Py_atomic_load_ptr(&_PyRuntime.getargs.static_parsers);
+ do {
+ // compare-exchange updates parser->next on failure
+ } while (_Py_atomic_compare_exchange_ptr(&_PyRuntime.getargs.static_parsers,
+ &parser->next, parser));
+ return 0;
}
static int
parser_init(struct _PyArg_Parser *parser)
{
- // volatile as it can be modified by other threads
- // and should not be optimized or reordered by compiler
- if (*((volatile int *)&parser->initialized)) {
- assert(parser->kwtuple != NULL);
- return 1;
- }
- PyThread_acquire_lock(_PyRuntime.getargs.mutex, WAIT_LOCK);
- // Check again if another thread initialized the parser
- // while we were waiting for the lock.
- if (*((volatile int *)&parser->initialized)) {
- assert(parser->kwtuple != NULL);
- PyThread_release_lock(_PyRuntime.getargs.mutex);
- return 1;
- }
- int ret = _parser_init(parser);
- PyThread_release_lock(_PyRuntime.getargs.mutex);
- return ret;
+ return _PyOnceFlag_CallOnce(&parser->once, &_parser_init, parser);
}
static void
parser_clear(struct _PyArg_Parser *parser)
{
- if (parser->initialized == 1) {
+ if (parser->is_kwtuple_owned) {
Py_CLEAR(parser->kwtuple);
}
}
@@ -2025,7 +2013,7 @@ vgetargskeywordsfast_impl(PyObject *const *args, Py_ssize_t nargs,
return 0;
}
- if (!parser_init(parser)) {
+ if (parser_init(parser) < 0) {
return 0;
}
@@ -2258,7 +2246,7 @@ _PyArg_UnpackKeywords(PyObject *const *args, Py_ssize_t nargs,
args = buf;
}
- if (!parser_init(parser)) {
+ if (parser_init(parser) < 0) {
return NULL;
}
@@ -2435,7 +2423,7 @@ _PyArg_UnpackKeywordsWithVararg(PyObject *const *args, Py_ssize_t nargs,
args = buf;
}
- if (!parser_init(parser)) {
+ if (parser_init(parser) < 0) {
return NULL;
}