From aac03c5e9ccf9f6066e291a7c87dd58c1181c227 Mon Sep 17 00:00:00 2001 From: Sverker Eriksson Date: Thu, 19 Jan 2012 12:10:20 +0100 Subject: erts: Multiple module tables using code_ix --- erts/emulator/beam/beam_bif_load.c | 182 +++++++++++++++++++++++-------------- erts/emulator/beam/beam_bp.c | 16 ++-- erts/emulator/beam/beam_debug.c | 4 +- erts/emulator/beam/beam_emu.c | 4 +- erts/emulator/beam/beam_load.c | 24 +++-- erts/emulator/beam/break.c | 59 ++++++------ erts/emulator/beam/code_ix.h | 8 +- erts/emulator/beam/erl_nif.c | 2 +- erts/emulator/beam/export.c | 4 - erts/emulator/beam/index.c | 15 +++ erts/emulator/beam/index.h | 2 + erts/emulator/beam/module.c | 109 +++++++++++++++++++--- erts/emulator/beam/module.h | 8 +- erts/emulator/hipe/hipe_bif0.c | 2 +- 14 files changed, 295 insertions(+), 144 deletions(-) diff --git a/erts/emulator/beam/beam_bif_load.c b/erts/emulator/beam/beam_bif_load.c index 346b64033b..458e4794bd 100644 --- a/erts/emulator/beam/beam_bif_load.c +++ b/erts/emulator/beam/beam_bif_load.c @@ -134,16 +134,22 @@ BIF_RETTYPE purge_module_1(BIF_ALIST_1) BIF_RETTYPE code_is_module_native_1(BIF_ALIST_1) { Module* modp; + Eterm res; + ErtsCodeIndex code_ix; if (is_not_atom(BIF_ARG_1)) { BIF_ERROR(BIF_P, BADARG); } - if ((modp = erts_get_module(BIF_ARG_1)) == NULL) { + code_ix = erts_active_code_ix(); + if ((modp = erts_get_module(BIF_ARG_1, code_ix)) == NULL) { return am_undefined; } - return ((modp->curr.code && is_native(modp->curr.code)) || + erts_rlock_old_code(code_ix); + res = ((modp->curr.code && is_native(modp->curr.code)) || (modp->old.code != 0 && is_native(modp->old.code))) ? am_true : am_false; + erts_runlock_old_code(code_ix); + return res; } BIF_RETTYPE code_make_stub_module_3(BIF_ALIST_3) @@ -164,18 +170,23 @@ BIF_RETTYPE code_make_stub_module_3(BIF_ALIST_3) BIF_RETTYPE check_old_code_1(BIF_ALIST_1) { + ErtsCodeIndex code_ix; Module* modp; + Eterm res = am_false; if (is_not_atom(BIF_ARG_1)) { BIF_ERROR(BIF_P, BADARG); } - modp = erts_get_module(BIF_ARG_1); - if (modp == NULL) { /* Doesn't exist. */ - BIF_RET(am_false); - } else if (modp->old.code == NULL) { /* No old code. */ - BIF_RET(am_false); + code_ix = erts_active_code_ix(); + modp = erts_get_module(BIF_ARG_1, code_ix); + if (modp != NULL) { + erts_rlock_old_code(code_ix); + if (modp->old.code != NULL) { + res = am_true; + } + erts_runlock_old_code(code_ix); } - BIF_RET(am_true); + BIF_RET(res); } Eterm @@ -189,13 +200,19 @@ check_process_code_2(BIF_ALIST_2) } if (is_internal_pid(BIF_ARG_1)) { Eterm res; + ErtsCodeIndex code_ix; if (internal_pid_index(BIF_ARG_1) >= erts_max_processes) goto error; - modp = erts_get_module(BIF_ARG_2); + code_ix = erts_active_code_ix(); + modp = erts_get_module(BIF_ARG_2, code_ix); if (modp == NULL) { /* Doesn't exist. */ return am_false; - } else if (modp->old.code == NULL) { /* No old code. */ - return am_false; + } else { + erts_rlock_old_code(code_ix); + if (modp->old.code == NULL) { /* No old code. */ + erts_runlock_old_code(code_ix); + return am_false; + } } #ifdef ERTS_SMP @@ -212,6 +229,7 @@ check_process_code_2(BIF_ALIST_2) BIF_ARG_1, BIF_ARG_2); } res = check_process_code(rp, modp); + erts_runlock_old_code(code_ix); #ifdef ERTS_SMP if (BIF_P != rp) { erts_resume(rp, ERTS_PROC_LOCK_MAIN); @@ -232,6 +250,7 @@ check_process_code_2(BIF_ALIST_2) BIF_RETTYPE delete_module_1(BIF_ALIST_1) { + ErtsCodeIndex code_ix; int res; if (is_not_atom(BIF_ARG_1)) @@ -240,8 +259,9 @@ BIF_RETTYPE delete_module_1(BIF_ALIST_1) erts_smp_proc_unlock(BIF_P, ERTS_PROC_LOCK_MAIN); erts_smp_thr_progress_block(); + code_ix = erts_active_code_ix(); { - Module *modp = erts_get_module(BIF_ARG_1); + Module *modp = erts_get_module(BIF_ARG_1, code_ix); if (!modp) { res = am_undefined; } @@ -272,16 +292,20 @@ BIF_RETTYPE delete_module_1(BIF_ALIST_1) BIF_RETTYPE module_loaded_1(BIF_ALIST_1) { Module* modp; + ErtsCodeIndex code_ix; + Eterm res = am_false; if (is_not_atom(BIF_ARG_1)) { BIF_ERROR(BIF_P, BADARG); } - if ((modp = erts_get_module(BIF_ARG_1)) == NULL || - modp->curr.code == NULL || - modp->curr.code[MI_ON_LOAD_FUNCTION_PTR] != 0) { - BIF_RET(am_false); + code_ix = erts_active_code_ix(); + if ((modp = erts_get_module(BIF_ARG_1, code_ix)) != NULL) { + if (modp->curr.code != NULL + && modp->curr.code[MI_ON_LOAD_FUNCTION_PTR] == 0) { + res = am_true; + } } - BIF_RET(am_true); + BIF_RET(res); } BIF_RETTYPE pre_loaded_0(BIF_ALIST_0) @@ -291,27 +315,28 @@ BIF_RETTYPE pre_loaded_0(BIF_ALIST_0) BIF_RETTYPE loaded_0(BIF_ALIST_0) { + ErtsCodeIndex code_ix = erts_active_code_ix(); + Module* modp; Eterm previous = NIL; Eterm* hp; int i; int j = 0; - - for (i = 0; i < module_code_size(); i++) { - if (module_code(i) != NULL && - ((module_code(i)->curr.code_length != 0) || - (module_code(i)->old.code_length != 0))) { + + for (i = 0; i < module_code_size(code_ix); i++) { + if ((modp = module_code(i, code_ix)) != NULL && + ((modp->curr.code_length != 0) || + (modp->old.code_length != 0))) { j++; } } if (j > 0) { hp = HAlloc(BIF_P, j*2); - for (i = 0; i < module_code_size(); i++) { - if (module_code(i) != NULL && - ((module_code(i)->curr.code_length != 0) || - (module_code(i)->old.code_length != 0))) { - previous = CONS(hp, make_atom(module_code(i)->module), - previous); + for (i = 0; i < module_code_size(code_ix); i++) { + if ((modp=module_code(i,code_ix)) != NULL && + ((modp->curr.code_length != 0) || + (modp->old.code_length != 0))) { + previous = CONS(hp, make_atom(modp->module), previous); hp += 2; } } @@ -321,25 +346,30 @@ BIF_RETTYPE loaded_0(BIF_ALIST_0) BIF_RETTYPE call_on_load_function_1(BIF_ALIST_1) { - Module* modp = erts_get_module(BIF_ARG_1); - Eterm on_load; + ErtsCodeIndex code_ix = erts_active_code_ix(); /*SVERK ?? on_load ?? */ + Module* modp = erts_get_module(BIF_ARG_1, code_ix); + Eterm on_load = 0; - if (!modp || modp->curr.code == 0) { - error: - BIF_ERROR(BIF_P, BADARG); + if (modp) { + if (modp->curr.code) { + on_load = modp->curr.code[MI_ON_LOAD_FUNCTION_PTR]; + } } - if ((on_load = modp->curr.code[MI_ON_LOAD_FUNCTION_PTR]) == 0) { - goto error; + if (on_load) { + BIF_TRAP_CODE_PTR_0(BIF_P, on_load); + } + else { + BIF_ERROR(BIF_P, BADARG); } - BIF_TRAP_CODE_PTR_0(BIF_P, on_load); } BIF_RETTYPE finish_after_on_load_2(BIF_ALIST_2) { ErtsCodeIndex code_ix; - Module* modp = erts_get_module(BIF_ARG_1); + Module* modp; Eterm on_load; code_ix = erts_active_code_ix(); + modp = erts_get_module(BIF_ARG_1, code_ix); if (!modp || modp->curr.code == 0) { error: @@ -439,6 +469,8 @@ check_process_code(Process* rp, Module* modp) #define INSIDE(a) (start <= (a) && (a) < end) + ERTS_SMP_LC_ASSERT(erts_is_old_code_rlocked()); + /* * Pick up limits for the module. */ @@ -645,50 +677,62 @@ any_heap_refs(Eterm* start, Eterm* end, char* mod_start, Uint mod_size) static int purge_module(int module) { + ErtsCodeIndex code_ix; BeamInstr* code; BeamInstr* end; Module* modp; + int ret; + + erts_lock_code_ix(); + code_ix = erts_active_code_ix(); /* * Correct module? */ - if ((modp = erts_get_module(make_atom(module))) == NULL) { - return -2; + if ((modp = erts_get_module(make_atom(module), code_ix)) == NULL) { + ret = -2; } + else { + erts_rwlock_old_code(code_ix); - /* - * Any code to purge? - */ - if (modp->old.code == 0) { - return -1; - } + /* + * Any code to purge? + */ + if (modp->old.code == 0) { + ret = -1; + } + else { + /* + * Unload any NIF library + */ + if (modp->old.nif != NULL) { + erts_unload_nif(modp->old.nif); + modp->old.nif = NULL; + } - /* - * Unload any NIF library - */ - if (modp->old.nif != NULL) { - erts_unload_nif(modp->old.nif); - modp->old.nif = NULL; + /* + * Remove the old code. + */ + ASSERT(erts_total_code_size >= modp->old.code_length); + erts_total_code_size -= modp->old.code_length; + code = modp->old.code; + end = (BeamInstr *)((char *)code + modp->old.code_length); + erts_cleanup_funs_on_purge(code, end); + beam_catches_delmod(modp->old.catches, code, modp->old.code_length, + code_ix); + decrement_refc(code); + erts_free(ERTS_ALC_T_CODE, (void *) code); + modp->old.code = NULL; + modp->old.code_length = 0; + modp->old.catches = BEAM_CATCHES_NIL; + remove_from_address_table(code); + ret = 0; + } + erts_rwunlock_old_code(code_ix); } - - /* - * Remove the old code. - */ - ASSERT(erts_total_code_size >= modp->old.code_length); - erts_total_code_size -= modp->old.code_length; - code = modp->old.code; - end = (BeamInstr *)((char *)code + modp->old.code_length); - erts_cleanup_funs_on_purge(code, end); - beam_catches_delmod(modp->old.catches, code, modp->old.code_length, - erts_active_code_ix()); - decrement_refc(code); - erts_free(ERTS_ALC_T_CODE, (void *) code); - modp->old.code = NULL; - modp->old.code_length = 0; - modp->old.catches = BEAM_CATCHES_NIL; - remove_from_address_table(code); - return 0; + erts_unlock_code_ix(); + return ret; } static void diff --git a/erts/emulator/beam/beam_bp.c b/erts/emulator/beam/beam_bp.c index 872907e232..30c458244b 100644 --- a/erts/emulator/beam/beam_bp.c +++ b/erts/emulator/beam/beam_bp.c @@ -478,7 +478,7 @@ erts_find_local_func(Eterm mfa[3]) { BeamInstr* code_ptr; Uint i,n; - if ((modp = erts_get_module(mfa[0])) == NULL) + if ((modp = erts_get_module(mfa[0], erts_active_code_ix())) == NULL) return NULL; if ((code_base = (BeamInstr **) modp->curr.code) == NULL) return NULL; @@ -850,12 +850,13 @@ static int set_break(Eterm mfa[3], int specified, { Module *modp; int num_processed = 0; + ErtsCodeIndex code_ix = erts_active_code_ix(); if (!specified) { /* Find and process all modules in the system... */ int current; - int last = module_code_size(); + int last = module_code_size(code_ix); for (current = 0; current < last; current++) { - modp = module_code(current); + modp = module_code(current, code_ix); ASSERT(modp != NULL); num_processed += set_module_break(modp, mfa, specified, @@ -864,7 +865,7 @@ static int set_break(Eterm mfa[3], int specified, } } else { /* Process a single module */ - if ((modp = erts_get_module(mfa[0])) != NULL) { + if ((modp = erts_get_module(mfa[0], code_ix)) != NULL) { num_processed += set_module_break(modp, mfa, specified, match_spec, break_op, count_op, @@ -1105,22 +1106,23 @@ static int set_function_break(Module *modp, BeamInstr *pc, int bif, static int clear_break(Eterm mfa[3], int specified, BeamInstr break_op) { + ErtsCodeIndex code_ix = erts_active_code_ix(); int num_processed = 0; Module *modp; if (!specified) { /* Iterate over all modules */ int current; - int last = module_code_size(); + int last = module_code_size(code_ix); for (current = 0; current < last; current++) { - modp = module_code(current); + modp = module_code(current, code_ix); ASSERT(modp != NULL); num_processed += clear_module_break(modp, mfa, specified, break_op); } } else { /* Process a single module */ - if ((modp = erts_get_module(mfa[0])) != NULL) { + if ((modp = erts_get_module(mfa[0], code_ix)) != NULL) { num_processed += clear_module_break(modp, mfa, specified, break_op); } diff --git a/erts/emulator/beam/beam_debug.c b/erts/emulator/beam/beam_debug.c index 608303cf4b..d9e9d0e348 100644 --- a/erts/emulator/beam/beam_debug.c +++ b/erts/emulator/beam/beam_debug.c @@ -226,13 +226,13 @@ erts_debug_disassemble_1(BIF_ALIST_1) goto error; } arity = signed_val(tp[3]); - modp = erts_get_module(mod); + code_ix = erts_active_code_ix(); + modp = erts_get_module(mod, code_ix); /* * Try the export entry first to allow disassembly of special functions * such as erts_debug:apply/4. Then search for it in the module. */ - code_ix = erts_active_code_ix(); if ((ep = erts_find_function(mod, name, arity, code_ix)) != NULL) { /* XXX: add "&& ep->address != ep->code+3" condition? * Consider a traced function. diff --git a/erts/emulator/beam/beam_emu.c b/erts/emulator/beam/beam_emu.c index 4bb4885cbb..d6189c6c65 100644 --- a/erts/emulator/beam/beam_emu.c +++ b/erts/emulator/beam/beam_emu.c @@ -6127,9 +6127,9 @@ call_fun(Process* p, /* Current process. */ * representation (the module has never been loaded), * or the module defining the fun has been unloaded. */ - module = fe->module; - if ((modp = erts_get_module(module)) != NULL && modp->curr.code != NULL) { + if ((modp = erts_get_module(module, code_ix)) != NULL + && modp->curr.code != NULL) { /* * There is a module loaded, but obviously the fun is not * defined in it. We must not call the error_handler diff --git a/erts/emulator/beam/beam_load.c b/erts/emulator/beam/beam_load.c index c35841af9d..fc3e395e91 100644 --- a/erts/emulator/beam/beam_load.c +++ b/erts/emulator/beam/beam_load.c @@ -5027,7 +5027,7 @@ erts_module_info_0(Process* p, Eterm module) return THE_NON_VALUE; } - if (erts_get_module(module) == NULL) { + if (erts_get_module(module, erts_active_code_ix()) == NULL) { return THE_NON_VALUE; } @@ -5091,7 +5091,7 @@ functions_in_module(Process* p, /* Process whose heap to use. */ return THE_NON_VALUE; } - modp = erts_get_module(mod); + modp = erts_get_module(mod, erts_active_code_ix()); if (modp == NULL) { return THE_NON_VALUE; } @@ -5145,7 +5145,7 @@ native_addresses(Process* p, Eterm mod) return THE_NON_VALUE; } - modp = erts_get_module(mod); + modp = erts_get_module(mod, erts_active_code_ix()); if (modp == NULL) { return THE_NON_VALUE; } @@ -5247,7 +5247,7 @@ attributes_for_module(Process* p, /* Process whose heap to use. */ return THE_NON_VALUE; } - modp = erts_get_module(mod); + modp = erts_get_module(mod, erts_active_code_ix()); if (modp == NULL) { return THE_NON_VALUE; } @@ -5287,7 +5287,7 @@ compilation_info_for_module(Process* p, /* Process whose heap to use. */ return THE_NON_VALUE; } - modp = erts_get_module(mod); + modp = erts_get_module(mod, erts_active_code_ix()); if (modp == NULL) { return THE_NON_VALUE; } @@ -6147,6 +6147,7 @@ void erts_start_loader_code_ix(void) { beam_catches_start_load(); export_start_load(); + module_start_load(); /*SVERK and more to come I guess... : */ @@ -6158,8 +6159,10 @@ void erts_commit_loader_code_ix(void) { beam_catches_end_load(1); export_end_load(1); + module_end_load(1); { - ErtsCodeIndex ix = erts_loader_code_ix(); + ErtsCodeIndex ix; + ix = erts_loader_code_ix(); erts_smp_atomic32_set_nob(&the_active_code_index, ix); ix = (ix + 1) % ERTS_NUM_CODE_IX; erts_smp_atomic32_set_nob(&the_loader_code_index, ix); @@ -6171,20 +6174,21 @@ void erts_abort_loader_code_ix(void) { beam_catches_end_load(0); export_end_load(0); + module_end_load(0); CIX_TRACE("abort"); } /*SVERK old_code lock should maybe be part of module.c */ -void erts_rwlock_old_code(void) +void erts_rwlock_old_code(ErtsCodeIndex code_ix) { } -void erts_rwunlock_old_code(void) +void erts_rwunlock_old_code(ErtsCodeIndex code_ix) { } -void erts_rlock_old_code(void) +void erts_rlock_old_code(ErtsCodeIndex code_ix) { } -void erts_runlock_old_code(void) +void erts_runlock_old_code(ErtsCodeIndex code_ix) { } diff --git a/erts/emulator/beam/break.c b/erts/emulator/beam/break.c index d769957210..39f91be7fc 100644 --- a/erts/emulator/beam/break.c +++ b/erts/emulator/beam/break.c @@ -377,17 +377,22 @@ loaded(int to, void *to_arg) int old = 0; int cur = 0; BeamInstr* code; + Module* modp; + ErtsCodeIndex code_ix; + + code_ix = erts_active_code_ix(); + erts_rlock_old_code(code_ix); /* * Calculate and print totals. */ - for (i = 0; i < module_code_size(); i++) { - if (module_code(i) != NULL && - ((module_code(i)->curr.code_length != 0) || - (module_code(i)->old.code_length != 0))) { - cur += module_code(i)->curr.code_length; - if (module_code(i)->old.code_length != 0) { - old += module_code(i)->old.code_length; + for (i = 0; i < module_code_size(code_ix); i++) { + if ((modp = module_code(i, code_ix)) != NULL && + ((modp->curr.code_length != 0) || + (modp->old.code_length != 0))) { + cur += modp->curr.code_length; + if (modp->old.code_length != 0) { + old += modp->old.code_length; } } } @@ -398,21 +403,22 @@ loaded(int to, void *to_arg) * Print one line per module. */ - for (i = 0; i < module_code_size(); i++) { + for (i = 0; i < module_code_size(code_ix); i++) { + modp = module_code(i, code_ix); if (!ERTS_IS_CRASH_DUMPING) { /* * Interactive dump; keep it brief. */ - if (module_code(i) != NULL && - ((module_code(i)->curr.code_length != 0) || - (module_code(i)->old.code_length != 0))) { - erts_print(to, to_arg, "%T", make_atom(module_code(i)->module)); - cur += module_code(i)->curr.code_length; - erts_print(to, to_arg, " %d", module_code(i)->curr.code_length ); - if (module_code(i)->old.code_length != 0) { + if (modp != NULL && + ((modp->curr.code_length != 0) || + (modp->old.code_length != 0))) { + erts_print(to, to_arg, "%T", make_atom(modp->module)); + cur += modp->curr.code_length; + erts_print(to, to_arg, " %d", modp->curr.code_length ); + if (modp->old.code_length != 0) { erts_print(to, to_arg, " (%d old)", - module_code(i)->old.code_length ); - old += module_code(i)->old.code_length; + modp->old.code_length ); + old += modp->old.code_length; } erts_print(to, to_arg, "\n"); } @@ -420,15 +426,15 @@ loaded(int to, void *to_arg) /* * To crash dump; make it parseable. */ - if (module_code(i) != NULL && - ((module_code(i)->curr.code_length != 0) || - (module_code(i)->old.code_length != 0))) { + if (modp != NULL && + ((modp->curr.code_length != 0) || + (modp->old.code_length != 0))) { erts_print(to, to_arg, "=mod:"); - erts_print(to, to_arg, "%T", make_atom(module_code(i)->module)); + erts_print(to, to_arg, "%T", make_atom(modp->module)); erts_print(to, to_arg, "\n"); erts_print(to, to_arg, "Current size: %d\n", - module_code(i)->curr.code_length); - code = module_code(i)->curr.code; + modp->curr.code_length); + code = modp->curr.code; if (code != NULL && code[MI_ATTR_PTR]) { erts_print(to, to_arg, "Current attributes: "); dump_attributes(to, to_arg, (byte *) code[MI_ATTR_PTR], @@ -440,9 +446,9 @@ loaded(int to, void *to_arg) code[MI_COMPILE_SIZE]); } - if (module_code(i)->old.code_length != 0) { - erts_print(to, to_arg, "Old size: %d\n", module_code(i)->old.code_length); - code = module_code(i)->old.code; + if (modp->old.code_length != 0) { + erts_print(to, to_arg, "Old size: %d\n", modp->old.code_length); + code = modp->old.code; if (code[MI_ATTR_PTR]) { erts_print(to, to_arg, "Old attributes: "); dump_attributes(to, to_arg, (byte *) code[MI_ATTR_PTR], @@ -457,6 +463,7 @@ loaded(int to, void *to_arg) } } } + erts_runlock_old_code(code_ix); } diff --git a/erts/emulator/beam/code_ix.h b/erts/emulator/beam/code_ix.h index 6b81102269..585ddd3f20 100644 --- a/erts/emulator/beam/code_ix.h +++ b/erts/emulator/beam/code_ix.h @@ -52,10 +52,10 @@ void erts_start_loader_code_ix(void); void erts_commit_loader_code_ix(void); void erts_abort_loader_code_ix(void); -void erts_rwlock_old_code(void); -void erts_rwunlock_old_code(void); -void erts_rlock_old_code(void); -void erts_runlock_old_code(void); +void erts_rwlock_old_code(ErtsCodeIndex); +void erts_rwunlock_old_code(ErtsCodeIndex); +void erts_rlock_old_code(ErtsCodeIndex); +void erts_runlock_old_code(ErtsCodeIndex); #ifdef ERTS_ENABLE_LOCK_CHECK int erts_is_old_code_rlocked(void); diff --git a/erts/emulator/beam/erl_nif.c b/erts/emulator/beam/erl_nif.c index f6082c09f2..8e8b58a7ad 100644 --- a/erts/emulator/beam/erl_nif.c +++ b/erts/emulator/beam/erl_nif.c @@ -1534,7 +1534,7 @@ BIF_RETTYPE load_nif_2(BIF_ALIST_2) ASSERT(caller != NULL); mod_atom = caller[0]; ASSERT(is_atom(mod_atom)); - mod=erts_get_module(mod_atom); + mod=erts_get_module(mod_atom, erts_active_code_ix()); ASSERT(mod != NULL); if (!in_area(caller, mod->curr.code, mod->curr.code_length)) { diff --git a/erts/emulator/beam/export.c b/erts/emulator/beam/export.c index 51d0116110..e5d9da187a 100644 --- a/erts/emulator/beam/export.c +++ b/erts/emulator/beam/export.c @@ -254,10 +254,6 @@ erts_find_function(Eterm m, Eterm f, unsigned int a, ErtsCodeIndex code_ix) struct export_templ templ; struct export_entry* ee; - if (ERTS_IS_ATOM_STR("gen_event",m) && ERTS_IS_ATOM_STR("add_handler",f)) { - sverk_break(); - } - ee = hash_get(&export_tables[code_ix].htable, init_template(&templ, m, f, a)); if (ee == NULL || (ee->ep->addressv[code_ix] == ee->ep->code+3 && ee->ep->code[3] != (BeamInstr) em_call_traced_function)) { diff --git a/erts/emulator/beam/index.c b/erts/emulator/beam/index.c index a4a3007f93..7cd45440f4 100644 --- a/erts/emulator/beam/index.c +++ b/erts/emulator/beam/index.c @@ -135,3 +135,18 @@ void erts_index_merge(Hash* src, IndexTable* dst) } } } + +void index_erase_latest_from(IndexTable* t, Uint from_ix) +{ + if(from_ix < (Uint)t->entries) { + int ix; + for (ix = from_ix; ix < t->entries; ix++) { + IndexSlot* obj = t->seg_table[ix>>INDEX_PAGE_SHIFT][ix&INDEX_PAGE_MASK]; + hash_erase(&t->htable, obj); + } + t->entries = from_ix; + } + else { + ASSERT(from_ix == t->entries); + } +} diff --git a/erts/emulator/beam/index.h b/erts/emulator/beam/index.h index 4eb9b1f992..67b250590b 100644 --- a/erts/emulator/beam/index.h +++ b/erts/emulator/beam/index.h @@ -58,6 +58,8 @@ int index_get(IndexTable*, void*); int index_put(IndexTable*, void*); void erts_index_merge(Hash*, IndexTable*); +void index_erase_latest_from(IndexTable*, Uint ix); + ERTS_GLB_INLINE IndexSlot* erts_index_lookup(IndexTable*, Uint); #if ERTS_GLB_INLINE_INCL_FUNC_DEF diff --git a/erts/emulator/beam/module.c b/erts/emulator/beam/module.c index 39baabdf54..1c629cd614 100644 --- a/erts/emulator/beam/module.c +++ b/erts/emulator/beam/module.c @@ -26,10 +26,16 @@ #include "global.h" #include "module.h" +#ifdef DEBUG +# define IF_DEBUG(x) x +#else +# define IF_DEBUG(x) +#endif + #define MODULE_SIZE 50 #define MODULE_LIMIT (64*1024) -static IndexTable module_table; +static IndexTable module_tables[ERTS_NUM_CODE_IX]; /* * SMP note: We don't need to look accesses to the module table because @@ -40,7 +46,7 @@ static IndexTable module_table; void module_info(int to, void *to_arg) { - index_info(to, to_arg, &module_table); + index_info(to, to_arg, &module_tables[erts_active_code_ix()]); } @@ -71,33 +77,44 @@ static Module* module_alloc(Module* tmpl) return obj; } +static void module_free(Module* mod) +{ + erts_free(ERTS_ALC_T_MODULE, mod); +} void init_module_table(void) { HashFunctions f; + int i; f.hash = (H_FUN) module_hash; f.cmp = (HCMP_FUN) module_cmp; f.alloc = (HALLOC_FUN) module_alloc; - f.free = 0; + f.free = (HFREE_FUN) module_free; - erts_index_init(ERTS_ALC_T_MODULE_TABLE, &module_table, "module_code", - MODULE_SIZE, MODULE_LIMIT, f); + for (i = 0; i < ERTS_NUM_CODE_IX; i++) { + erts_index_init(ERTS_ALC_T_MODULE_TABLE, &module_tables[i], "module_code", + MODULE_SIZE, MODULE_LIMIT, f); + } } Module* -erts_get_module(Eterm mod) +erts_get_module(Eterm mod, ErtsCodeIndex code_ix) { Module e; int index; + IndexTable* mod_tab; ASSERT(is_atom(mod)); + + mod_tab = &module_tables[code_ix]; + e.module = atom_val(mod); - index = index_get(&module_table, (void*) &e); + index = index_get(mod_tab, (void*) &e); if (index == -1) { return NULL; } else { - return (Module*) erts_index_lookup(&module_table, index); + return (Module*) erts_index_lookup(mod_tab, index); } } @@ -106,26 +123,88 @@ erts_put_module(Eterm mod) { Module e; int index; + IndexTable* mod_tab; ASSERT(is_atom(mod)); ERTS_SMP_LC_ASSERT(erts_initialized == 0 || erts_smp_thr_progress_is_blocking()); + + mod_tab = &module_tables[erts_loader_code_ix()]; e.module = atom_val(mod); - index = index_put(&module_table, (void*) &e); - return (Module*) erts_index_lookup(&module_table, index); + index = index_put(mod_tab, (void*) &e); + return (Module*) erts_index_lookup(mod_tab, index); } -Module *module_code(int i) +Module *module_code(int i, ErtsCodeIndex code_ix) { - return (Module*) erts_index_lookup(&module_table, i); + return (Module*) erts_index_lookup(&module_tables[code_ix], i); } -int module_code_size(void) +int module_code_size(ErtsCodeIndex code_ix) { - return module_table.entries; + return module_tables[code_ix].entries; } int module_table_sz(void) { - return index_table_sz(&module_table); + return index_table_sz(&module_tables[erts_active_code_ix()]); +} + +#ifdef DEBUG +static ErtsCodeIndex dbg_load_code_ix = 0; +#endif + +static int entries_at_start_load = 0; + +void module_start_load(void) +{ + IndexTable* src = &module_tables[erts_active_code_ix()]; + IndexTable* dst = &module_tables[erts_loader_code_ix()]; + Module* src_mod; + Module* dst_mod; + int i; + + ASSERT(dbg_load_code_ix == -1); + ASSERT(dst->entries <= src->entries); + + /* + * Make sure our existing modules are up-to-date + */ + for (i = 0; i < dst->entries; i++) { + src_mod = (Module*) erts_index_lookup(src, i); + dst_mod = (Module*) erts_index_lookup(dst, i); + ASSERT(src_mod->module == dst_mod->module); + + dst_mod->curr = src_mod->curr; + dst_mod->old = src_mod->old; + } + + /* + * Copy all new modules from active table + */ + for (i = dst->entries; i < src->entries; i++) { + src_mod = (Module*) erts_index_lookup(src, i); + dst_mod = (Module*) erts_index_lookup(dst, index_put(dst, src_mod)); + ASSERT(dst_mod != src_mod); + + dst_mod->curr = src_mod->curr; + dst_mod->old = src_mod->old; + } + entries_at_start_load = dst->entries; + + IF_DEBUG(dbg_load_code_ix = erts_loader_code_ix()); +} + +void module_end_load(int commit) +{ + ASSERT(dbg_load_code_ix == erts_loader_code_ix()); + + if (!commit) { /* abort */ + IndexTable* tab = &module_tables[erts_loader_code_ix()]; + + ASSERT(entries_at_start_load <= tab->entries); + index_erase_latest_from(tab, entries_at_start_load); + } + + IF_DEBUG(dbg_load_code_ix = -1); } diff --git a/erts/emulator/beam/module.h b/erts/emulator/beam/module.h index 4a2c92c0f7..8a87ae4952 100644 --- a/erts/emulator/beam/module.h +++ b/erts/emulator/beam/module.h @@ -39,14 +39,16 @@ typedef struct erl_module { struct erl_module_instance old; } Module; -Module* erts_get_module(Eterm mod); +Module* erts_get_module(Eterm mod, ErtsCodeIndex code_ix); Module* erts_put_module(Eterm mod); void init_module_table(void); +void module_start_load(void); +void module_end_load(int commit); void module_info(int, void *); -Module *module_code(int); -int module_code_size(void); +Module *module_code(int, ErtsCodeIndex); +int module_code_size(ErtsCodeIndex); int module_table_sz(void); #endif diff --git a/erts/emulator/hipe/hipe_bif0.c b/erts/emulator/hipe/hipe_bif0.c index 4afc2030e7..cb599bd682 100644 --- a/erts/emulator/hipe/hipe_bif0.c +++ b/erts/emulator/hipe/hipe_bif0.c @@ -609,7 +609,7 @@ static Uint *hipe_find_emu_address(Eterm mod, Eterm name, unsigned int arity) Uint *code_base; int i, n; - modp = erts_get_module(mod); + modp = erts_get_module(mod, erts_active_code_ix()); /*SVERK ?? */ if (modp == NULL || (code_base = modp->curr.code) == NULL) return NULL; n = code_base[MI_NUM_FUNCTIONS]; -- cgit v1.2.3