diff options
-rw-r--r-- | erts/emulator/beam/erl_bif_info.c | 8 | ||||
-rw-r--r-- | erts/emulator/beam/erl_db.c | 13 | ||||
-rw-r--r-- | erts/emulator/beam/erl_db.h | 1 | ||||
-rw-r--r-- | erts/emulator/beam/erl_db_catree.c | 14 | ||||
-rw-r--r-- | erts/emulator/beam/erl_db_catree.h | 1 | ||||
-rw-r--r-- | erts/emulator/beam/erl_db_util.h | 1 | ||||
-rw-r--r-- | lib/stdlib/test/ets_SUITE.erl | 20 |
7 files changed, 49 insertions, 9 deletions
diff --git a/erts/emulator/beam/erl_bif_info.c b/erts/emulator/beam/erl_bif_info.c index 7ff345a54b..c3d0ea40f6 100644 --- a/erts/emulator/beam/erl_bif_info.c +++ b/erts/emulator/beam/erl_bif_info.c @@ -4693,6 +4693,14 @@ BIF_RETTYPE erts_debug_set_internal_state_2(BIF_ALIST_2) BIF_RET(am_ok); } } + else if (ERTS_IS_ATOM_STR("ets_debug_random_split_join", BIF_ARG_1)) { + if (is_tuple(BIF_ARG_2)) { + Eterm* tpl = tuple_val(BIF_ARG_2); + + if (erts_ets_debug_random_split_join(tpl[1], tpl[2] == am_true)) + BIF_RET(am_ok); + } + } else if (ERTS_IS_ATOM_STR("mbuf", BIF_ARG_1)) { Uint sz = size_object(BIF_ARG_2); ErlHeapFragment* frag = new_message_buffer(sz); diff --git a/erts/emulator/beam/erl_db.c b/erts/emulator/beam/erl_db.c index c0f5c506f4..d24f30f126 100644 --- a/erts/emulator/beam/erl_db.c +++ b/erts/emulator/beam/erl_db.c @@ -4573,3 +4573,16 @@ int erts_ets_force_split(Eterm tid, int on) db_unlock(tb, LCK_WRITE); return 1; } + +int erts_ets_debug_random_split_join(Eterm tid, int on) +{ + DbTable* tb = tid2tab(tid); + if (!tb || !IS_CATREE_TABLE(tb->common.type)) + return 0; + + db_lock(tb, LCK_WRITE); + if (!(tb->common.status & DB_DELETE)) + db_catree_debug_random_split_join(&tb->catree, on); + db_unlock(tb, LCK_WRITE); + return 1; +} diff --git a/erts/emulator/beam/erl_db.h b/erts/emulator/beam/erl_db.h index b22f35a5ef..b3dc1b9ba3 100644 --- a/erts/emulator/beam/erl_db.h +++ b/erts/emulator/beam/erl_db.h @@ -131,6 +131,7 @@ extern erts_atomic_t erts_ets_misc_mem_size; Eterm erts_ets_colliding_names(Process*, Eterm name, Uint cnt); int erts_ets_force_split(Eterm tid, int on); +int erts_ets_debug_random_split_join(Eterm tid, int on); Uint erts_db_get_max_tabs(void); Eterm erts_db_make_tid(Process *c_p, DbTableCommon *tb); diff --git a/erts/emulator/beam/erl_db_catree.c b/erts/emulator/beam/erl_db_catree.c index 962fe4c4f8..e0d5e44f58 100644 --- a/erts/emulator/beam/erl_db_catree.c +++ b/erts/emulator/beam/erl_db_catree.c @@ -647,7 +647,8 @@ static int dbg_fastrand(void) static void dbg_provoke_random_splitjoin(DbTableCATree* tb, DbTableCATreeNode* base_node) { - if (tb->common.status & DB_CATREE_FORCE_SPLIT) + if (tb->common.status & DB_CATREE_FORCE_SPLIT || + !(tb->common.status & DB_CATREE_DEBUG_RANDOM_SPLIT_JOIN)) return; switch (dbg_fastrand() % 8) { @@ -1406,6 +1407,9 @@ int db_create_catree(Process *p, DbTable *tbl) tb->deletion = 0; tb->base_nodes_to_free_list = NULL; tb->nr_of_deleted_items = 0; +#ifdef DEBUG + tbl->common.status |= DB_CATREE_DEBUG_RANDOM_SPLIT_JOIN; +#endif erts_atomic_init_relb(&(tb->root), (erts_aint_t)root); return DB_ERROR_NONE; } @@ -2257,6 +2261,14 @@ void db_catree_force_split(DbTableCATree* tb, int on) tb->common.status &= ~DB_CATREE_FORCE_SPLIT; } +void db_catree_debug_random_split_join(DbTableCATree* tb, int on) +{ + if (on) + tb->common.status |= DB_CATREE_DEBUG_RANDOM_SPLIT_JOIN; + else + tb->common.status &= ~DB_CATREE_DEBUG_RANDOM_SPLIT_JOIN; +} + void db_calc_stats_catree(DbTableCATree* tb, DbCATreeStats* stats) { DbTableCATreeNode* stack[ERL_DB_CATREE_MAX_ROUTE_NODE_LAYER_HEIGHT]; diff --git a/erts/emulator/beam/erl_db_catree.h b/erts/emulator/beam/erl_db_catree.h index fde442eaf5..cf3498dabb 100644 --- a/erts/emulator/beam/erl_db_catree.h +++ b/erts/emulator/beam/erl_db_catree.h @@ -124,6 +124,7 @@ void erts_lcnt_enable_db_catree_lock_count(DbTableCATree *tb, int enable); #endif void db_catree_force_split(DbTableCATree*, int on); +void db_catree_debug_random_split_join(DbTableCATree*, int on); typedef struct { Uint route_nodes; diff --git a/erts/emulator/beam/erl_db_util.h b/erts/emulator/beam/erl_db_util.h index 97f2848679..02d4dd6c9a 100644 --- a/erts/emulator/beam/erl_db_util.h +++ b/erts/emulator/beam/erl_db_util.h @@ -326,6 +326,7 @@ typedef struct db_table_common { #define DB_BUSY (1 << 12) #define DB_CATREE_FORCE_SPLIT (1 << 31) /* erts_debug */ +#define DB_CATREE_DEBUG_RANDOM_SPLIT_JOIN (1 << 30) /* erts_debug */ #define IS_HASH_TABLE(Status) (!!((Status) & \ (DB_BAG | DB_SET | DB_DUPLICATE_BAG))) diff --git a/lib/stdlib/test/ets_SUITE.erl b/lib/stdlib/test/ets_SUITE.erl index 4640b2b228..dd49288417 100644 --- a/lib/stdlib/test/ets_SUITE.erl +++ b/lib/stdlib/test/ets_SUITE.erl @@ -4461,21 +4461,24 @@ add_loop(T, I) -> test_table_counter_concurrency(WhatToTest) -> + IntStatePrevOn = + erts_debug:set_internal_state(available_internal_state, true), ItemsToAdd = 1000000, SizeLoopSize = 1000, T = ets:new(k, [public, ordered_set, {write_concurrency, true}]), + erts_debug:set_internal_state(ets_debug_random_split_join, {T, false}), 0 = ets:info(T, size), P = self(), SpawnedSizeProcs = - [spawn(fun() -> - size_loop(T, SizeLoopSize, 0, WhatToTest), - P ! done - end) + [spawn_link(fun() -> + size_loop(T, SizeLoopSize, 0, WhatToTest), + P ! done + end) || _ <- lists:seq(1, 6)], - spawn(fun() -> - add_loop(T, ItemsToAdd), - P ! done_add - end), + spawn_link(fun() -> + add_loop(T, ItemsToAdd), + P ! done_add + end), [receive done -> ok; done_add -> ok @@ -4487,6 +4490,7 @@ test_table_counter_concurrency(WhatToTest) -> _ -> ok end, + erts_debug:set_internal_state(available_internal_state, IntStatePrevOn), ok. test_table_size_concurrency(Config) when is_list(Config) -> |