diff options
author | Erlang/OTP <[email protected]> | 2016-07-14 11:22:31 +0200 |
---|---|---|
committer | Erlang/OTP <[email protected]> | 2016-07-14 11:22:31 +0200 |
commit | c7d729da231c40a656725f2e9bb84c40a6bddc7d (patch) | |
tree | da2003f9e74c8c9fb7bc8f595144cf7805e0bb76 /erts | |
parent | 23bb0ba4db2351c2b89e8fb80371fad74d58d544 (diff) | |
parent | 30cb490ed08d358d584a90aac4819c85ddf6fcce (diff) | |
download | otp-c7d729da231c40a656725f2e9bb84c40a6bddc7d.tar.gz otp-c7d729da231c40a656725f2e9bb84c40a6bddc7d.tar.bz2 otp-c7d729da231c40a656725f2e9bb84c40a6bddc7d.zip |
Merge branch 'sverker/update_counter-deadlock/ERL-188/OTP-13731' into maint-19
* sverker/update_counter-deadlock/ERL-188/OTP-13731:
erts: Add test ets_SUITE:update_counter_table_growth
erts: Fix deadlock in ets:update_counter/4
erts: Optimize db_finalize_dbterm_hash
Diffstat (limited to 'erts')
-rw-r--r-- | erts/emulator/beam/erl_db_hash.c | 42 | ||||
-rw-r--r-- | erts/emulator/beam/erl_db_util.h | 1 |
2 files changed, 25 insertions, 18 deletions
diff --git a/erts/emulator/beam/erl_db_hash.c b/erts/emulator/beam/erl_db_hash.c index 74979f984a..12ae086b31 100644 --- a/erts/emulator/beam/erl_db_hash.c +++ b/erts/emulator/beam/erl_db_hash.c @@ -2866,15 +2866,7 @@ db_lookup_dbterm_hash(Process *p, DbTable *tbl, Eterm key, Eterm obj, q->hvalue = hval; q->next = NULL; *bp = b = q; - - { - int nitems = erts_smp_atomic_inc_read_nob(&tb->common.nitems); - int nactive = NACTIVE(tb); - - if (nitems > nactive * (CHAIN_LEN + 1) && !IS_FIXED(tb)) { - grow(tb, nactive); - } - } + flags |= DB_INC_TRY_GROW; } else { HashDbTerm *q, *next = b->next; @@ -2910,6 +2902,7 @@ db_finalize_dbterm_hash(int cret, DbUpdateHandle* handle) HashDbTerm **bp = (HashDbTerm **) handle->bp; HashDbTerm *b = *bp; erts_smp_rwmtx_t* lck = (erts_smp_rwmtx_t*) handle->lck; + HashDbTerm* free_me = NULL; ERTS_SMP_LC_ASSERT(IS_HASH_WLOCKED(tb, lck)); /* locked by db_lookup_dbterm_hash */ @@ -2921,21 +2914,34 @@ db_finalize_dbterm_hash(int cret, DbUpdateHandle* handle) b->hvalue = INVALID_HASH; } else { *bp = b->next; - free_term(tb, b); + free_me = b; } WUNLOCK_HASH(lck); erts_smp_atomic_dec_nob(&tb->common.nitems); try_shrink(tb); - } else if (handle->flags & DB_MUST_RESIZE) { - db_finalize_resize(handle, offsetof(HashDbTerm,dbterm)); - WUNLOCK_HASH(lck); - - free_term(tb, b); - } - else { - WUNLOCK_HASH(lck); + } else { + if (handle->flags & DB_MUST_RESIZE) { + db_finalize_resize(handle, offsetof(HashDbTerm,dbterm)); + free_me = b; + } + if (handle->flags & DB_INC_TRY_GROW) { + int nactive; + int nitems = erts_smp_atomic_inc_read_nob(&tb->common.nitems); + WUNLOCK_HASH(lck); + nactive = NACTIVE(tb); + + if (nitems > nactive * (CHAIN_LEN + 1) && !IS_FIXED(tb)) { + grow(tb, nactive); + } + } else { + WUNLOCK_HASH(lck); + } } + + if (free_me) + free_term(tb, free_me); + #ifdef DEBUG handle->dbterm = 0; #endif diff --git a/erts/emulator/beam/erl_db_util.h b/erts/emulator/beam/erl_db_util.h index 60f7067d70..4acedbfed0 100644 --- a/erts/emulator/beam/erl_db_util.h +++ b/erts/emulator/beam/erl_db_util.h @@ -79,6 +79,7 @@ typedef union db_table DbTable; #define DB_MUST_RESIZE 1 #define DB_NEW_OBJECT 2 +#define DB_INC_TRY_GROW 4 /* Info about a database entry while it's being updated * (by update_counter or update_element) |