diff options
author | Rickard Green <[email protected]> | 2010-09-10 09:55:48 +0200 |
---|---|---|
committer | Rickard Green <[email protected]> | 2010-09-10 09:55:48 +0200 |
commit | 358eaf9d14a0102eaca5bb482d03d4fc37639724 (patch) | |
tree | 472b11b92a6c75f72cd6d626558444363097da1d /erts/lib_src | |
parent | a4c1adcdbb8bcf6be85b22232ea3093cf2299b83 (diff) | |
parent | 775365a86f69bd4a9f8db44b7017662854415540 (diff) | |
download | otp-358eaf9d14a0102eaca5bb482d03d4fc37639724.tar.gz otp-358eaf9d14a0102eaca5bb482d03d4fc37639724.tar.bz2 otp-358eaf9d14a0102eaca5bb482d03d4fc37639724.zip |
Merge branch 'rickard/rwmtx-spin/OTP-8819' into dev
* rickard/rwmtx-spin/OTP-8819:
Fix deadlock in reader optimized rwlock implementation
Remove unused variables
Increase spincount with many schedulers
Re-enable spin wait on ethreads rwlocks
Diffstat (limited to 'erts/lib_src')
-rw-r--r-- | erts/lib_src/common/ethr_mutex.c | 80 |
1 files changed, 43 insertions, 37 deletions
diff --git a/erts/lib_src/common/ethr_mutex.c b/erts/lib_src/common/ethr_mutex.c index aac0d44a32..78323b62a3 100644 --- a/erts/lib_src/common/ethr_mutex.c +++ b/erts/lib_src/common/ethr_mutex.c @@ -35,7 +35,7 @@ #define ETHR_SPIN_WITH_WAITERS 1 -#define ETHR_MTX_MAX_FLGS_SPIN 1000 +#define ETHR_MTX_MAX_FLGS_SPIN 10 #ifdef ETHR_USE_OWN_RWMTX_IMPL__ static int default_rwmtx_main_spincount; @@ -90,7 +90,7 @@ ethr_mutex_lib_init(int cpu_conf) no_spin = cpu_conf == 1; #ifdef ETHR_USE_OWN_MTX_IMPL__ - default_mtx_main_spincount = ETHR_MTX_DEFAULT_MAIN_SPINCOUNT; + default_mtx_main_spincount = ETHR_MTX_DEFAULT_MAIN_SPINCOUNT_BASE; default_mtx_aux_spincount = ETHR_MTX_DEFAULT_AUX_SPINCOUNT; default_cnd_main_spincount = ETHR_CND_DEFAULT_MAIN_SPINCOUNT; default_cnd_aux_spincount = ETHR_CND_DEFAULT_AUX_SPINCOUNT; @@ -98,7 +98,7 @@ ethr_mutex_lib_init(int cpu_conf) #ifdef ETHR_USE_OWN_RWMTX_IMPL__ - default_rwmtx_main_spincount = ETHR_RWMTX_DEFAULT_MAIN_SPINCOUNT; + default_rwmtx_main_spincount = ETHR_RWMTX_DEFAULT_MAIN_SPINCOUNT_BASE; default_rwmtx_aux_spincount = ETHR_RWMTX_DEFAULT_AUX_SPINCOUNT; #else @@ -146,7 +146,21 @@ static int main_threads_array_size = 0; int ethr_mutex_lib_late_init(int no_reader_groups, int no_main_threads) { + +#ifdef ETHR_USE_OWN_MTX_IMPL__ + default_mtx_main_spincount += (no_main_threads + * ETHR_MTX_DEFAULT_MAIN_SPINCOUNT_INC); + if (default_mtx_main_spincount > ETHR_MTX_DEFAULT_MAIN_SPINCOUNT_MAX) + default_mtx_main_spincount = ETHR_MTX_DEFAULT_MAIN_SPINCOUNT_MAX; +#endif + #ifdef ETHR_USE_OWN_RWMTX_IMPL__ + + default_rwmtx_main_spincount += (no_main_threads + * ETHR_RWMTX_DEFAULT_MAIN_SPINCOUNT_INC); + if (default_rwmtx_main_spincount > ETHR_RWMTX_DEFAULT_MAIN_SPINCOUNT_MAX) + default_rwmtx_main_spincount = ETHR_RWMTX_DEFAULT_MAIN_SPINCOUNT_MAX; + reader_groups_array_size = (no_reader_groups <= 1 ? 1 : no_reader_groups + 1); @@ -593,24 +607,31 @@ initial_spincount(struct ethr_mutex_base_ *mtxb) static ETHR_INLINE int update_spincount(struct ethr_mutex_base_ *mtxb, ethr_ts_event *tse, - int *start_scnt, + int *scnt_state, int *scnt) { - int sscnt = *start_scnt; - if (sscnt < 0) { - *scnt = ((tse->iflgs & ETHR_TS_EV_MAIN_THR) - ? mtxb->main_scnt - : mtxb->aux_scnt); - *scnt -= ETHR_MTX_MAX_FLGS_SPIN; + int state = *scnt_state; + if (state <= 0) { + /* Here state is max spincount to do on event negated */ + *scnt = -state; } else { + /* Here state is initial spincount made on flags */ *scnt = ((tse->iflgs & ETHR_TS_EV_MAIN_THR) ? mtxb->main_scnt : mtxb->aux_scnt); - *scnt -= sscnt; - if (*scnt > 0 && sscnt < ETHR_MTX_MAX_FLGS_SPIN) { - *scnt = ETHR_MTX_MAX_FLGS_SPIN - sscnt; - *start_scnt = -1; + if (*scnt <= state) + *scnt = 0; + else { + if (*scnt <= ETHR_MTX_MAX_FLGS_SPIN) + *scnt_state = 0; /* No spin on event */ + else { + /* Spin on event after... */ + *scnt_state = -1*(*scnt - ETHR_MTX_MAX_FLGS_SPIN); + /* ... we have spun on flags */ + *scnt = ETHR_MTX_MAX_FLGS_SPIN; + } + *scnt -= state; return 0; } } @@ -619,8 +640,7 @@ update_spincount(struct ethr_mutex_base_ *mtxb, int check_readers_array(ethr_rwmutex *rwmtx, int start_rix, - int length, - int pre_check); + int length); static ETHR_INLINE void write_lock_wait(struct ethr_mutex_base_ *mtxb, @@ -666,8 +686,7 @@ write_lock_wait(struct ethr_mutex_base_ *mtxb, } res = check_readers_array(rwmtx, freq_read_start_ix, - freq_read_size, - 1); + freq_read_size); scnt--; if (res == 0) { act = ethr_atomic_read(&mtxb->flgs); @@ -708,7 +727,6 @@ write_lock_wait(struct ethr_mutex_base_ *mtxb, act = ethr_atomic_read(&mtxb->flgs); scnt--; } - ETHR_ASSERT(scnt >= 0); exp = act; @@ -985,7 +1003,6 @@ enqueue_mtx(ethr_mutex *mtx, ethr_ts_event *tse_start, ethr_ts_event *tse_end) int ethr_cond_init_opt(ethr_cond *cnd, ethr_cond_opt *opt) { - int res; #if ETHR_XCHK if (!cnd) { ETHR_ASSERT(0); @@ -1085,7 +1102,6 @@ ethr_cond_signal(ethr_cond *cnd) void ethr_cond_broadcast(ethr_cond *cnd) { - int res; int got_all; ethr_ts_event *tse; ETHR_ASSERT(!ethr_not_inited__); @@ -1153,7 +1169,6 @@ ethr_cond_wait(ethr_cond *cnd, ethr_mutex *mtx) { int woken; int scnt; - int res; void *udata = NULL; ethr_ts_event *tse; @@ -1466,17 +1481,11 @@ multiple_w_waiters(ethr_rwmutex *rwmtx) int check_readers_array(ethr_rwmutex *rwmtx, int start_rix, - int length, - int pre_check) + int length) { int ix = start_rix; -#ifndef ETHR_READ_MEMORY_BARRIER_IS_FULL - if (pre_check) - ETHR_READ_MEMORY_BARRIER; - else -#endif - ETHR_MEMORY_BARRIER; + ETHR_MEMORY_BARRIER; do { long act = rwmutex_freqread_rdrs_read(rwmtx, ix); @@ -1559,7 +1568,7 @@ rwmutex_try_complete_runlock(ethr_rwmutex *rwmtx, ethr_leave_ts_event(tse_tmp); if (check_before_try) { - res = check_readers_array(rwmtx, six, length, 1); + res = check_readers_array(rwmtx, six, length); if (res == EBUSY) return try_write_lock ? EBUSY : 0; } @@ -1597,7 +1606,7 @@ rwmutex_try_complete_runlock(ethr_rwmutex *rwmtx, } } - res = check_readers_array(rwmtx, six, length, 0); + res = check_readers_array(rwmtx, six, length); if (res == EBUSY) { act = ethr_atomic_dec_read(&rwmtx->mtxb.flgs); if (act & ETHR_RWMTX_R_MASK__) @@ -1691,7 +1700,7 @@ rwmutex_normal_rlock_wait(ethr_rwmutex *rwmtx, #endif while (act & (ETHR_RWMTX_W_FLG__|ETHR_RWMTX_W_WAIT_FLG__)) { - if (scnt == 0) { + if (scnt >= 0) { tse = ethr_get_ts_event(); if (update_spincount(&rwmtx->mtxb, tse, &start_scnt, &scnt)) { event_wait(&rwmtx->mtxb, tse, scnt, @@ -1708,7 +1717,6 @@ rwmutex_normal_rlock_wait(ethr_rwmutex *rwmtx, scnt--; } exp = act; - ETHR_ASSERT(scnt >= 0); #ifdef ETHR_RLOCK_WITH_INC_DEC act = ethr_atomic_inc_read(&rwmtx->mtxb.flgs); @@ -1749,7 +1757,7 @@ rwmutex_freqread_rlock_wait(ethr_rwmutex *rwmtx, act = ethr_atomic_read(&rwmtx->mtxb.flgs); while (act & ~(ETHR_RWMTX_R_FLG__|ETHR_RWMTX_R_WAIT_FLG__)) { - if (scnt == 0) { + if (scnt >= 0) { if (update_spincount(&rwmtx->mtxb, tse, &start_scnt, &scnt)) { event_wait(&rwmtx->mtxb, tse, scnt, ETHR_RWMTX_R_WAIT_FLG__, 1, 1); @@ -1765,8 +1773,6 @@ rwmutex_freqread_rlock_wait(ethr_rwmutex *rwmtx, scnt--; } - ETHR_ASSERT(scnt >= 0); - rwmutex_freqread_rdrs_inc(rwmtx, tse); ETHR_MEMORY_BARRIER; |