From e77e99b7a77e7c3cfa70b8145669f10feab40efe Mon Sep 17 00:00:00 2001 From: Damien George Date: Wed, 24 May 2023 10:50:30 +1000 Subject: [PATCH 1/2] py/map: Make map rehashing an atomic operation. Signed-off-by: Damien George --- py/map.c | 25 +++++++++++++++++++------ 1 file changed, 19 insertions(+), 6 deletions(-) diff --git a/py/map.c b/py/map.c index c18df5a9f333c..140a228fa0b23 100644 --- a/py/map.c +++ b/py/map.c @@ -32,6 +32,7 @@ #include "py/mpconfig.h" #include "py/misc.h" #include "py/runtime.h" +#include "py/mphal.h" #if MICROPY_DEBUG_VERBOSE // print debugging info #define DEBUG_PRINT (1) @@ -134,16 +135,28 @@ STATIC void mp_map_rehash(mp_map_t *map) { DEBUG_printf("mp_map_rehash(%p): " UINT_FMT " -> " UINT_FMT "\n", map, old_alloc, new_alloc); mp_map_elem_t *old_table = map->table; mp_map_elem_t *new_table = m_new0(mp_map_elem_t, new_alloc); - // If we reach this point, table resizing succeeded, now we can edit the old map. - map->alloc = new_alloc; - map->used = 0; - map->all_keys_are_qstrs = 1; - map->table = new_table; + + // If we reach this point then allocating the new table succeeded, so construct the new map. + mp_map_t new_map = { + .all_keys_are_qstrs = 1, + .is_fixed = 0, + .is_ordered = 0, + .used = 0, + .alloc = new_alloc, + .table = new_table, + }; for (size_t i = 0; i < old_alloc; i++) { if (old_table[i].key != MP_OBJ_NULL && old_table[i].key != MP_OBJ_SENTINEL) { - mp_map_lookup(map, old_table[i].key, MP_MAP_LOOKUP_ADD_IF_NOT_FOUND)->value = old_table[i].value; + mp_map_lookup(&new_map, old_table[i].key, MP_MAP_LOOKUP_ADD_IF_NOT_FOUND)->value = old_table[i].value; } } + + // Swap the old map for the new one. + mp_uint_t atomic_state = MICROPY_BEGIN_ATOMIC_SECTION(); + *map = new_map; + MICROPY_END_ATOMIC_SECTION(atomic_state); + + // Free the old table. m_del(mp_map_elem_t, old_table, old_alloc); } From d5a023bc2602b1cf857fb512c1b5216f986d5652 Mon Sep 17 00:00:00 2001 From: Damien George Date: Wed, 21 Feb 2024 10:55:51 +1100 Subject: [PATCH 2/2] tests/thread: Add a test to stress concurrent globals access. Signed-off-by: Damien George --- tests/thread/stress_globals.py | 79 ++++++++++++++++++++++++++++++++++ 1 file changed, 79 insertions(+) create mode 100644 tests/thread/stress_globals.py diff --git a/tests/thread/stress_globals.py b/tests/thread/stress_globals.py new file mode 100644 index 0000000000000..fe2f77b9ef908 --- /dev/null +++ b/tests/thread/stress_globals.py @@ -0,0 +1,79 @@ +import time, _thread + + +def thread_task(): + for _ in range(1000): + a00 + print("pass") + + +print("start") +a00 = None + +_thread.start_new_thread(thread_task, ()) + +# create lots of global variables +a01 = None +a02 = None +a03 = None +a04 = None +a05 = None +a06 = None +a07 = None +a10 = None +a11 = None +a12 = None +a13 = None +a14 = None +a15 = None +a16 = None +a17 = None +a18 = None +a19 = None +a20 = None +a21 = None +a22 = None +a23 = None +a24 = None +a25 = None +a26 = None +a27 = None +a28 = None +a29 = None +a30 = None +a31 = None +a32 = None +a33 = None +a34 = None +a35 = None +a36 = None +a37 = None +a38 = None +a39 = None +a40 = None +a41 = None +a42 = None +a43 = None +a44 = None +a45 = None +a46 = None +a47 = None +a48 = None +a49 = None +a50 = None +a51 = None +a52 = None +a53 = None +a54 = None +a55 = None +a56 = None +a57 = None +a58 = None +a59 = None +a60 = None +a61 = None +a62 = None +a63 = None + +# let the thread finish +time.sleep(0.1) pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy