From b022c5a175c528ebb66df129ddaa9f2d0b20a923 Mon Sep 17 00:00:00 2001 From: Rickard Green Date: Thu, 1 Sep 2016 14:24:55 +0200 Subject: Fix reclaim of literal areas --- erts/emulator/beam/beam_bif_load.c | 78 +++++++++++++++++++++++++++++--------- erts/emulator/beam/erl_alloc.types | 1 + erts/emulator/beam/global.h | 7 +++- 3 files changed, 66 insertions(+), 20 deletions(-) (limited to 'erts/emulator') diff --git a/erts/emulator/beam/beam_bif_load.c b/erts/emulator/beam/beam_bif_load.c index 2413ccdba9..9e4176752a 100644 --- a/erts/emulator/beam/beam_bif_load.c +++ b/erts/emulator/beam/beam_bif_load.c @@ -53,7 +53,10 @@ static struct { Process *erts_code_purger = NULL; -ErtsLiteralArea *erts_copy_literal_area = NULL; +erts_smp_atomic_t erts_copy_literal_area__; +#define ERTS_SET_COPY_LITERAL_AREA(LA) \ + erts_smp_atomic_set_nob(&erts_copy_literal_area__, \ + (erts_aint_t) (LA)) #ifdef ERTS_NEW_PURGE_STRATEGY Process *erts_literal_area_collector = NULL; @@ -105,6 +108,8 @@ erts_beam_bif_load_init(void) release_literal_areas.first = NULL; release_literal_areas.last = NULL; #endif + erts_smp_atomic_init_nob(&erts_copy_literal_area__, + (erts_aint_t) NULL); init_purge_state(); } @@ -849,7 +854,7 @@ erts_proc_copy_literal_area(Process *c_p, int *redsp, int fcalls, int gc_allowed Uint lit_bsize; ErlHeapFragment *hfrag; - la = erts_copy_literal_area; + la = ERTS_COPY_LITERAL_AREA(); if (!la) return am_ok; @@ -1438,16 +1443,33 @@ hfrag_literal_copy(Eterm **hpp, ErlOffHeap *ohp, #ifdef ERTS_NEW_PURGE_STRATEGY +#ifdef ERTS_SMP + ErtsThrPrgrLaterOp later_literal_area_switch; -#ifdef ERTS_SMP +typedef struct { + ErtsThrPrgrLaterOp lop; + ErtsLiteralArea *la; +} ErtsLaterReleasLiteralArea; + +static void +later_release_literal_area(void *vlrlap) +{ + ErtsLaterReleasLiteralArea *lrlap; + lrlap = (ErtsLaterReleasLiteralArea *) vlrlap; + erts_release_literal_area(lrlap->la); + erts_free(ERTS_ALC_T_RELEASE_LAREA, vlrlap); +} + static void -complete_literal_area_switch(void *unused) +complete_literal_area_switch(void *literal_area) { Process *p = erts_literal_area_collector; erts_smp_proc_lock(p, ERTS_PROC_LOCK_STATUS); erts_resume(p, ERTS_PROC_LOCK_STATUS); erts_smp_proc_unlock(p, ERTS_PROC_LOCK_STATUS); + if (literal_area) + erts_release_literal_area((ErtsLiteralArea *) literal_area); } #endif @@ -1458,6 +1480,7 @@ BIF_RETTYPE erts_internal_release_literal_area_switch_0(BIF_ALIST_0) #ifndef ERTS_NEW_PURGE_STRATEGY BIF_ERROR(BIF_P, EXC_NOTSUP); #else + ErtsLiteralArea *unused_la; ErtsLiteralAreaRef *la_ref; if (BIF_P != erts_literal_area_collector) @@ -1474,26 +1497,45 @@ BIF_RETTYPE erts_internal_release_literal_area_switch_0(BIF_ALIST_0) erts_smp_mtx_unlock(&release_literal_areas.mtx); - if (erts_copy_literal_area) - erts_release_literal_area(erts_copy_literal_area); + unused_la = ERTS_COPY_LITERAL_AREA(); if (!la_ref) { - erts_copy_literal_area = NULL; + ERTS_SET_COPY_LITERAL_AREA(NULL); + if (unused_la) { +#ifdef ERTS_SMP + ErtsLaterReleasLiteralArea *lrlap; + lrlap = erts_alloc(ERTS_ALC_T_RELEASE_LAREA, + sizeof(ErtsLaterReleasLiteralArea)); + lrlap->la = unused_la; + erts_schedule_thr_prgr_later_cleanup_op( + later_release_literal_area, + (void *) lrlap, + &lrlap->lop, + (sizeof(ErtsLaterReleasLiteralArea) + + sizeof(ErtsLiteralArea) + + ((unused_la->end + - &unused_la->start[0]) + - 1)*(sizeof(Eterm)))); +#else + erts_release_literal_area(unused_la); +#endif + } BIF_RET(am_false); } - erts_copy_literal_area = la_ref->literal_area; + ERTS_SET_COPY_LITERAL_AREA(la_ref->literal_area); erts_free(ERTS_ALC_T_LITERAL_REF, la_ref); -#ifndef ERTS_SMP - BIF_RET(am_true); -#else +#ifdef ERTS_SMP erts_schedule_thr_prgr_later_op(complete_literal_area_switch, - NULL, + unused_la, &later_literal_area_switch); erts_suspend(BIF_P, ERTS_PROC_LOCK_MAIN, NULL); ERTS_BIF_YIELD_RETURN(BIF_P, am_true); +#else + erts_release_literal_area(unused_la); + BIF_RET(am_true); #endif #endif /* ERTS_NEW_PURGE_STRATEGY */ @@ -1675,8 +1717,8 @@ BIF_RETTYPE erts_internal_purge_module_2(BIF_ALIST_2) end = (BeamInstr *)((char *)code + modp->old.code_length); erts_fun_purge_prepare(code, end); #if !defined(ERTS_NEW_PURGE_STRATEGY) - ASSERT(!erts_copy_literal_area); - erts_copy_literal_area = modp->old.code_hdr->literal_area; + ASSERT(!ERTS_COPY_LITERAL_AREA()); + ERTS_SET_COPY_LITERAL_AREA(modp->old.code_hdr->literal_area); #endif } erts_runlock_old_code(code_ix); @@ -1718,8 +1760,8 @@ BIF_RETTYPE erts_internal_purge_module_2(BIF_ALIST_2) erts_fun_purge_abort_prepare(purge_state.funs, purge_state.fe_ix); #if !defined(ERTS_NEW_PURGE_STRATEGY) - ASSERT(erts_copy_literal_area); - erts_copy_literal_area = NULL; + ASSERT(ERTS_COPY_LITERAL_AREA()); + ERTS_SET_COPY_LITERAL_AREA(NULL); #endif #ifndef ERTS_SMP erts_fun_purge_abort_finalize(purge_state.funs, purge_state.fe_ix); @@ -1831,8 +1873,8 @@ BIF_RETTYPE erts_internal_purge_module_2(BIF_ALIST_2) #if !defined(ERTS_NEW_PURGE_STRATEGY) - ASSERT(erts_copy_literal_area == literals); - erts_copy_literal_area = NULL; + ASSERT(ERTS_COPY_LITERAL_AREA() == literals); + ERTS_SET_COPY_LITERAL_AREA(NULL); erts_release_literal_area(literals); #else /* ERTS_NEW_PURGE_STRATEGY */ diff --git a/erts/emulator/beam/erl_alloc.types b/erts/emulator/beam/erl_alloc.types index 1b72a0cb59..d51086aa32 100644 --- a/erts/emulator/beam/erl_alloc.types +++ b/erts/emulator/beam/erl_alloc.types @@ -313,6 +313,7 @@ type RUNQ_BLNS LONG_LIVED SYSTEM run_queue_balancing type THR_PRGR_IDATA LONG_LIVED SYSTEM thr_prgr_internal_data type THR_PRGR_DATA LONG_LIVED SYSTEM thr_prgr_data type T_THR_PRGR_DATA SHORT_LIVED SYSTEM temp_thr_prgr_data +type RELEASE_LAREA SHORT_LIVED SYSTEM release_literal_area +endif # diff --git a/erts/emulator/beam/global.h b/erts/emulator/beam/global.h index 00dfc421d5..76e6be5443 100644 --- a/erts/emulator/beam/global.h +++ b/erts/emulator/beam/global.h @@ -1014,7 +1014,10 @@ typedef struct ErtsLiteralArea_ { #define ERTS_LITERAL_AREA_ALLOC_SIZE(N) \ (sizeof(ErtsLiteralArea) + sizeof(Eterm)*((N) - 1)) -extern ErtsLiteralArea *erts_copy_literal_area; +extern erts_smp_atomic_t erts_copy_literal_area__; +#define ERTS_COPY_LITERAL_AREA() \ + ((ErtsLiteralArea *) erts_smp_atomic_read_nob(&erts_copy_literal_area__)) + #ifdef ERTS_NEW_PURGE_STRATEGY extern Process *erts_literal_area_collector; #endif @@ -1102,7 +1105,7 @@ typedef struct { #define INITIALIZE_SHCOPY(info) \ do { \ - ErtsLiteralArea *larea__ = erts_copy_literal_area; \ + ErtsLiteralArea *larea__ = ERTS_COPY_LITERAL_AREA();\ info.queue_start = info.queue_default; \ info.bitstore_start = info.bitstore_default; \ info.shtable_start = info.shtable_default; \ -- cgit v1.2.3