aboutsummaryrefslogtreecommitdiffstats
path: root/erts/emulator/beam
diff options
context:
space:
mode:
Diffstat (limited to 'erts/emulator/beam')
-rw-r--r--erts/emulator/beam/beam_bif_load.c182
-rw-r--r--erts/emulator/beam/beam_bp.c16
-rw-r--r--erts/emulator/beam/beam_debug.c4
-rw-r--r--erts/emulator/beam/beam_emu.c4
-rw-r--r--erts/emulator/beam/beam_load.c24
-rw-r--r--erts/emulator/beam/break.c59
-rw-r--r--erts/emulator/beam/code_ix.h8
-rw-r--r--erts/emulator/beam/erl_nif.c2
-rw-r--r--erts/emulator/beam/export.c4
-rw-r--r--erts/emulator/beam/index.c15
-rw-r--r--erts/emulator/beam/index.h2
-rw-r--r--erts/emulator/beam/module.c109
-rw-r--r--erts/emulator/beam/module.h8
13 files changed, 294 insertions, 143 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