aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSverker Eriksson <[email protected]>2018-05-07 18:15:56 +0200
committerSverker Eriksson <[email protected]>2018-05-08 14:38:43 +0200
commitc500b0acdad588fa4c3d0cba15a9c61dc30a3190 (patch)
tree736c3b415c96ab57aed37d555d84049ad15b6c59
parent0657a616adc74bf71342053539c807031fa9d162 (diff)
downloadotp-c500b0acdad588fa4c3d0cba15a9c61dc30a3190.tar.gz
otp-c500b0acdad588fa4c3d0cba15a9c61dc30a3190.tar.bz2
otp-c500b0acdad588fa4c3d0cba15a9c61dc30a3190.zip
erts: Make ets:delete_all_objects yield on fixed table
-rw-r--r--erts/emulator/beam/erl_db_hash.c43
-rw-r--r--erts/emulator/beam/erl_db_hash.h3
2 files changed, 34 insertions, 12 deletions
diff --git a/erts/emulator/beam/erl_db_hash.c b/erts/emulator/beam/erl_db_hash.c
index d55e110e10..6bb5034971 100644
--- a/erts/emulator/beam/erl_db_hash.c
+++ b/erts/emulator/beam/erl_db_hash.c
@@ -2321,28 +2321,50 @@ void db_initialize_hash(void)
static SWord db_mark_all_deleted_hash(DbTable *tbl, SWord reds)
{
+ const int LOOPS_PER_REDUCTION = 8;
DbTableHash *tb = &tbl->hash;
FixedDeletion* fixdel;
+ SWord loops = reds * LOOPS_PER_REDUCTION;
int i;
ERTS_LC_ASSERT(IS_TAB_WLOCKED(tb));
- fixdel = erts_db_alloc(ERTS_ALC_T_DB_FIX_DEL,
- (DbTable *) tb,
- sizeof(FixedDeletion));
- ERTS_ETS_MISC_MEM_ADD(sizeof(FixedDeletion));
- fixdel->slot = NACTIVE(tb) - 1;
- fixdel->all = 1;
- link_fixdel(tb, fixdel, 0);
+ fixdel = (FixedDeletion*) erts_atomic_read_nob(&tb->fixdel);
+ if (fixdel && fixdel->trap) {
+ /* Continue after trap */
+ ASSERT(fixdel->all);
+ ASSERT(fixdel->slot < NACTIVE(tb));
+ i = fixdel->slot;
+ }
+ else {
+ /* First call */
+ fixdel = erts_db_alloc(ERTS_ALC_T_DB_FIX_DEL,
+ (DbTable *) tb,
+ sizeof(FixedDeletion));
+ ERTS_ETS_MISC_MEM_ADD(sizeof(FixedDeletion));
+ link_fixdel(tb, fixdel, 0);
+ i = 0;
+ }
- for (i = 0; i < NACTIVE(tb); i++) {
+ do {
HashDbTerm* b;
for (b = BUCKET(tb,i); b; b = b->next)
b->pseudo_deleted = 1;
- --reds;
+ } while (++i < NACTIVE(tb) && --loops > 0);
+
+ if (i < NACTIVE(tb)) {
+ /* Yield */
+ fixdel->slot = i;
+ fixdel->all = 0;
+ fixdel->trap = 1;
+ return -1;
}
+
+ fixdel->slot = NACTIVE(tb) - 1;
+ fixdel->all = 1;
+ fixdel->trap = 0;
erts_atomic_set_nob(&tb->common.nitems, 0);
- return reds < 0 ? 0 : reds; /* ToDo: Yield! */
+ return loops < 0 ? 0 : loops / LOOPS_PER_REDUCTION;
}
@@ -3145,7 +3167,6 @@ db_finalize_dbterm_hash(int cret, DbUpdateHandle* handle)
static SWord db_delete_all_objects_hash(Process* p, DbTable* tbl, SWord reds)
{
if (IS_FIXED(tbl)) {
- /* ToDo: Yield! */
reds = db_mark_all_deleted_hash(tbl, reds);
} else {
reds = db_free_table_continue_hash(tbl, reds);
diff --git a/erts/emulator/beam/erl_db_hash.h b/erts/emulator/beam/erl_db_hash.h
index d48343378d..08e5b13db1 100644
--- a/erts/emulator/beam/erl_db_hash.h
+++ b/erts/emulator/beam/erl_db_hash.h
@@ -24,8 +24,9 @@
#include "erl_db_util.h" /* DbTerm & DbTableCommon */
typedef struct fixed_deletion {
- UWord slot : sizeof(UWord)*8 - 1;
+ UWord slot : sizeof(UWord)*8 - 2;
UWord all : 1;
+ UWord trap : 1;
struct fixed_deletion *next;
} FixedDeletion;