diff options
author | Sverker Eriksson <sverker@erlang.org> | 2021-04-06 16:30:38 +0200 |
---|---|---|
committer | Sverker Eriksson <sverker@erlang.org> | 2021-04-06 16:30:38 +0200 |
commit | a849b19ecb71402601f72a72eaa34f918b882932 (patch) | |
tree | be96ac332f681e5b37481956c777c0de656c9235 | |
parent | 53d2a7d511081d961df9ff497494feef43ca9674 (diff) | |
parent | fb0c63315746fa503caaa949aba3aeb5c8286c08 (diff) | |
download | erlang-a849b19ecb71402601f72a72eaa34f918b882932.tar.gz |
Merge branch 'sverker/erts/persistent_term-get-0-race/OTP-17298' into maint
-rw-r--r-- | erts/emulator/beam/erl_bif_persistent.c | 8 | ||||
-rw-r--r-- | erts/emulator/test/persistent_term_SUITE.erl | 40 |
2 files changed, 46 insertions, 2 deletions
diff --git a/erts/emulator/beam/erl_bif_persistent.c b/erts/emulator/beam/erl_bif_persistent.c index 91cc03fe57..596604cdec 100644 --- a/erts/emulator/beam/erl_bif_persistent.c +++ b/erts/emulator/beam/erl_bif_persistent.c @@ -439,7 +439,7 @@ BIF_RETTYPE persistent_term_put_2(BIF_ALIST_2) BIF_RETTYPE persistent_term_get_0(BIF_ALIST_0) { - HashTable* hash_table = (HashTable *) erts_atomic_read_nob(&the_hash_table); + HashTable* hash_table; TrapData* trap_data; Eterm res = NIL; Eterm magic_ref; @@ -450,6 +450,8 @@ BIF_RETTYPE persistent_term_get_0(BIF_ALIST_0) ERTS_BIF_YIELD0(&bif_trap_export[BIF_persistent_term_get_0], BIF_P); } + hash_table = (HashTable *) erts_atomic_read_nob(&the_hash_table); + magic_ref = alloc_trap_data(BIF_P); mbp = erts_magic_ref2bin(magic_ref); trap_data = ERTS_MAGIC_BIN_DATA(mbp); @@ -673,7 +675,7 @@ BIF_RETTYPE erts_internal_erase_persistent_terms_0(BIF_ALIST_0) BIF_RETTYPE persistent_term_info_0(BIF_ALIST_0) { - HashTable* hash_table = (HashTable *) erts_atomic_read_nob(&the_hash_table); + HashTable* hash_table; TrapData* trap_data; Eterm res = NIL; Eterm magic_ref; @@ -684,6 +686,8 @@ BIF_RETTYPE persistent_term_info_0(BIF_ALIST_0) ERTS_BIF_YIELD0(&bif_trap_export[BIF_persistent_term_info_0], BIF_P); } + hash_table = (HashTable *) erts_atomic_read_nob(&the_hash_table); + magic_ref = alloc_trap_data(BIF_P); mbp = erts_magic_ref2bin(magic_ref); trap_data = ERTS_MAGIC_BIN_DATA(mbp); diff --git a/erts/emulator/test/persistent_term_SUITE.erl b/erts/emulator/test/persistent_term_SUITE.erl index f4511eb483..a988864c2d 100644 --- a/erts/emulator/test/persistent_term_SUITE.erl +++ b/erts/emulator/test/persistent_term_SUITE.erl @@ -22,8 +22,10 @@ -include_lib("common_test/include/ct.hrl"). -export([all/0,suite/0,init_per_suite/1,end_per_suite/1, + init_per_testcase/2, end_per_testcase/2, basic/1,purging/1,sharing/1,get_trapping/1, destruction/1, + get_all_race/1, info/1,info_trapping/1,killed_while_trapping/1, off_heap_values/1,keys/1,collisions/1, init_restart/1, put_erase_trapping/1, @@ -40,6 +42,7 @@ suite() -> all() -> [basic,purging,sharing,get_trapping,info,info_trapping, destruction, + get_all_race, killed_while_trapping,off_heap_values,keys,collisions, init_restart, put_erase_trapping, killed_while_trapping_put, killed_while_trapping_erase]. @@ -56,6 +59,15 @@ end_per_suite(Config) -> erts_debug:set_internal_state(available_internal_state, false), Config. +init_per_testcase(_, Config) -> + Config. + +end_per_testcase(_, _Config) -> + ok; +end_per_testcase(get_all_race, _Config) -> + get_all_race_cleanup(), + ok. + basic(_Config) -> Chk = chk(), N = 777, @@ -781,3 +793,31 @@ repeat(_Fun, 0) -> repeat(Fun, N) -> Fun(), repeat(Fun, N-1). + + +%% OTP-17298 +get_all_race(_Config) -> + N = 20 * erlang:system_info(schedulers_online), + persistent_term:put(get_all_race, N), + SPs = [spawn_link(fun() -> gar_setter(Seq) end) || Seq <- lists:seq(1, N)], + GPs = [spawn_link(fun gar_getter/0) || _ <- lists:seq(1, N)], + receive after 2000 -> ok end, + [begin unlink(Pid), exit(Pid,kill) end || Pid <- (SPs ++ GPs)], + ok. + +get_all_race_cleanup() -> + N = persistent_term:get(get_all_race, 0), + _ = persistent_term:erase(get_all_race), + [_ = persistent_term:erase(Seq) || Seq <- lists:seq(1, N)], + ok. + +gar_getter() -> + erts_debug:set_internal_state(reds_left, 1), + _ = persistent_term:get(), + gar_getter(). + +gar_setter(Key) -> + erts_debug:set_internal_state(reds_left, 1), + persistent_term:erase(Key), + persistent_term:put(Key, {complex, term}), + gar_setter(Key). |