diff options
author | Sverker Eriksson <[email protected]> | 2018-10-11 23:34:49 +0200 |
---|---|---|
committer | Sverker Eriksson <[email protected]> | 2018-10-23 12:36:28 +0200 |
commit | 129e61564807c0ad43faf9d0c36260c793501920 (patch) | |
tree | 26822017b645e14403c5e7989d9a4d536217e063 /erts/emulator | |
parent | 375a1f5c29fd2d3b537e117149e78b0ac61e263f (diff) | |
download | otp-129e61564807c0ad43faf9d0c36260c793501920.tar.gz otp-129e61564807c0ad43faf9d0c36260c793501920.tar.bz2 otp-129e61564807c0ad43faf9d0c36260c793501920.zip |
erts: Add erts_debug feature 'ets_force_split'
to easier generate a routing tree for test
without having to spend cpu to provoke actual repeated lock conflicts.
Diffstat (limited to 'erts/emulator')
-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 | 25 | ||||
-rw-r--r-- | erts/emulator/beam/erl_db_catree.h | 2 | ||||
-rw-r--r-- | erts/emulator/beam/erl_db_util.h | 2 |
6 files changed, 49 insertions, 2 deletions
diff --git a/erts/emulator/beam/erl_bif_info.c b/erts/emulator/beam/erl_bif_info.c index 2a8e7e8858..3b0f0d33fa 100644 --- a/erts/emulator/beam/erl_bif_info.c +++ b/erts/emulator/beam/erl_bif_info.c @@ -4669,6 +4669,14 @@ BIF_RETTYPE erts_debug_set_internal_state_2(BIF_ALIST_2) BIF_RET(am_notsup); #endif } + else if (ERTS_IS_ATOM_STR("ets_force_split", BIF_ARG_1)) { + if (is_tuple(BIF_ARG_2)) { + Eterm* tpl = tuple_val(BIF_ARG_2); + + if (erts_ets_force_split(tpl[1], tpl[2] == am_true)) + BIF_RET(am_ok); + } + } } BIF_ERROR(BIF_P, BADARG); diff --git a/erts/emulator/beam/erl_db.c b/erts/emulator/beam/erl_db.c index 337efa94bd..df6f42edd3 100644 --- a/erts/emulator/beam/erl_db.c +++ b/erts/emulator/beam/erl_db.c @@ -4465,3 +4465,16 @@ void erts_lcnt_update_db_locks(int enable) { #ifdef ETS_DBG_FORCE_TRAP erts_aint_t erts_ets_dbg_force_trap = 0; #endif + +int erts_ets_force_split(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_force_split(&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 7a915ccea2..5955d42aae 100644 --- a/erts/emulator/beam/erl_db.h +++ b/erts/emulator/beam/erl_db.h @@ -130,6 +130,7 @@ extern Export ets_select_continue_exp; 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); 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 f467230ced..975e19a878 100644 --- a/erts/emulator/beam/erl_db_catree.c +++ b/erts/emulator/beam/erl_db_catree.c @@ -885,7 +885,8 @@ static DbTableCATreeNode *create_base_node(DbTableCATree *tb, "erl_db_catree_base_node", lc_key, ERTS_LOCK_FLAGS_CATEGORY_DB); - p->u.base.lock_statistics = 0; + p->u.base.lock_statistics = ((tb->common.status & DB_CATREE_FORCE_SPLIT) + ? INT_MAX : 0); p->u.base.is_valid = 1; return p; } @@ -1205,7 +1206,8 @@ static void split_catree(DbTableCATree *tb, DbTableCATreeNode* ERTS_RESTRICT new_route; if (less_than_two_elements(base->u.base.root)) { - base->u.base.lock_statistics = 0; + if (!(tb->common.status & DB_CATREE_FORCE_SPLIT)) + base->u.base.lock_statistics = 0; wunlock_base_node(&base->u.base); return; } else { @@ -2118,6 +2120,25 @@ void erts_lcnt_enable_db_catree_lock_count(DbTableCATree *tb, int enable) } #endif /* ERTS_ENABLE_LOCK_COUNT */ +void db_catree_force_split(DbTableCATree* tb, int on) +{ + CATreeRootIterator iter; + TreeDbTerm** root; + + init_root_iterator(tb, &iter, 1); + root = catree_find_first_root(&iter); + do { + iter.locked_bnode->lock_statistics = (on ? INT_MAX : 0); + root = catree_find_next_root(&iter); + } while (root); + ASSERT(!iter.locked_bnode); + + if (on) + tb->common.status |= DB_CATREE_FORCE_SPLIT; + else + tb->common.status &= ~DB_CATREE_FORCE_SPLIT; +} + 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 e3d574589c..feb6f27980 100644 --- a/erts/emulator/beam/erl_db_catree.h +++ b/erts/emulator/beam/erl_db_catree.h @@ -120,6 +120,8 @@ TreeDbTerm** catree_find_last_root(CATreeRootIterator*); void erts_lcnt_enable_db_catree_lock_count(DbTableCATree *tb, int enable); #endif +void db_catree_force_split(DbTableCATree*, int on); + typedef struct { Uint route_nodes; Uint base_nodes; diff --git a/erts/emulator/beam/erl_db_util.h b/erts/emulator/beam/erl_db_util.h index be74bc795c..dcffaf9718 100644 --- a/erts/emulator/beam/erl_db_util.h +++ b/erts/emulator/beam/erl_db_util.h @@ -290,6 +290,8 @@ typedef struct db_table_common { #define DB_NAMED_TABLE (1 << 11) #define DB_BUSY (1 << 12) +#define DB_CATREE_FORCE_SPLIT (1 << 31) /* erts_debug */ + #define IS_HASH_TABLE(Status) (!!((Status) & \ (DB_BAG | DB_SET | DB_DUPLICATE_BAG))) #define IS_TREE_TABLE(Status) (!!((Status) & \ |