aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--erts/emulator/beam/beam_bif_load.c33
-rw-r--r--erts/emulator/beam/beam_debug.c5
-rw-r--r--erts/emulator/beam/beam_emu.c17
-rw-r--r--erts/emulator/beam/beam_load.c15
-rw-r--r--erts/emulator/beam/bif.c3
-rw-r--r--erts/emulator/beam/code_ix.h65
-rw-r--r--erts/emulator/beam/erl_alloc.c4
-rw-r--r--erts/emulator/beam/erl_bif_trace.c10
-rw-r--r--erts/emulator/beam/erl_init.c3
-rw-r--r--erts/emulator/beam/export.c176
-rw-r--r--erts/emulator/beam/export.h13
-rw-r--r--erts/emulator/beam/external.c2
-rw-r--r--erts/emulator/beam/global.h50
-rw-r--r--erts/emulator/hipe/hipe_bif0.c2
14 files changed, 271 insertions, 127 deletions
diff --git a/erts/emulator/beam/beam_bif_load.c b/erts/emulator/beam/beam_bif_load.c
index a8ef198be5..4858859c2d 100644
--- a/erts/emulator/beam/beam_bif_load.c
+++ b/erts/emulator/beam/beam_bif_load.c
@@ -35,7 +35,7 @@
#include "erl_nif.h"
#include "erl_thr_progress.h"
-static void set_default_trace_pattern(Eterm module);
+static void set_default_trace_pattern(Eterm module, ErtsCodeIndex);
static Eterm check_process_code(Process* rp, Module* modp);
static void delete_code(Process *c_p, ErtsProcLocks c_p_locks, Module* modp);
static void delete_export_references(Eterm module);
@@ -90,10 +90,15 @@ load_module_2(BIF_ALIST_2)
reason = erts_finish_loading(stp, BIF_P, 0, &BIF_ARG_1);
if (reason != NIL) {
- erts_abort_loader_code_ix();
+ if (reason == am_on_load) {
+ erts_commit_loader_code_ix();
+ }
+ else {
+ erts_abort_loader_code_ix();
+ }
res = TUPLE2(hp, am_error, reason);
} else {
- set_default_trace_pattern(BIF_ARG_1);
+ set_default_trace_pattern(BIF_ARG_1, erts_loader_code_ix());
erts_commit_loader_code_ix();
res = TUPLE2(hp, am_module, BIF_ARG_1);
}
@@ -114,7 +119,7 @@ BIF_RETTYPE purge_module_1(BIF_ALIST_1)
erts_smp_proc_unlock(BIF_P, ERTS_PROC_LOCK_MAIN);
erts_smp_thr_progress_block();
- erts_export_consolidate();
+ erts_export_consolidate(erts_active_code_ix());
purge_res = purge_module(atom_val(BIF_ARG_1));
erts_smp_thr_progress_unblock();
@@ -148,7 +153,7 @@ BIF_RETTYPE code_make_stub_module_3(BIF_ALIST_3)
erts_smp_proc_unlock(BIF_P, ERTS_PROC_LOCK_MAIN);
erts_smp_thr_progress_block();
- erts_export_consolidate();
+ erts_export_consolidate(erts_active_code_ix());
res = erts_make_stub_module(BIF_P, BIF_ARG_1, BIF_ARG_2, BIF_ARG_3);
erts_smp_thr_progress_unblock();
@@ -331,8 +336,10 @@ BIF_RETTYPE call_on_load_function_1(BIF_ALIST_1)
BIF_RETTYPE finish_after_on_load_2(BIF_ALIST_2)
{
+ ErtsCodeIndex code_ix;
Module* modp = erts_get_module(BIF_ARG_1);
Eterm on_load;
+ code_ix = erts_active_code_ix();
if (!modp || modp->curr.code == 0) {
error:
@@ -354,8 +361,8 @@ BIF_RETTYPE finish_after_on_load_2(BIF_ALIST_2)
/*
* The on_load function succeded. Fix up export entries.
*/
- for (i = 0; i < export_list_size(); i++) {
- Export *ep = export_list(i);
+ for (i = 0; i < export_list_size(code_ix); i++) {
+ Export *ep = export_list(i,code_ix);
if (ep != NULL &&
ep->code[0] == BIF_ARG_1 &&
ep->code[4] != 0) {
@@ -364,7 +371,7 @@ BIF_RETTYPE finish_after_on_load_2(BIF_ALIST_2)
}
}
modp->curr.code[MI_ON_LOAD_FUNCTION_PTR] = 0;
- set_default_trace_pattern(BIF_ARG_1);
+ set_default_trace_pattern(BIF_ARG_1, erts_active_code_ix ());
} else if (BIF_ARG_2 == am_false) {
BeamInstr* code;
BeamInstr* end;
@@ -392,7 +399,7 @@ BIF_RETTYPE finish_after_on_load_2(BIF_ALIST_2)
}
static void
-set_default_trace_pattern(Eterm module)
+set_default_trace_pattern(Eterm module, ErtsCodeIndex code_ix)
{
int trace_pattern_is_on;
Binary *match_spec;
@@ -412,7 +419,8 @@ set_default_trace_pattern(Eterm module)
match_spec,
meta_match_spec,
1, trace_pattern_flags,
- meta_tracer_pid);
+ meta_tracer_pid,
+ code_ix);
}
}
@@ -763,12 +771,13 @@ delete_code(Process *c_p, ErtsProcLocks c_p_locks, Module* modp)
static void
delete_export_references(Eterm module)
{
+ ErtsCodeIndex code_ix = erts_loader_code_ix();
int i;
ASSERT(is_atom(module));
- for (i = 0; i < export_list_size(); i++) {
- Export *ep = export_list(i);
+ for (i = 0; i < export_list_size(code_ix); i++) {
+ Export *ep = export_list(i, code_ix);
if (ep != NULL && (ep->code[0] == module)) {
if (ep->address == ep->code+3 &&
(ep->code[3] == (BeamInstr) em_apply_bif)) {
diff --git a/erts/emulator/beam/beam_debug.c b/erts/emulator/beam/beam_debug.c
index 4bef59dd66..ff47b26e13 100644
--- a/erts/emulator/beam/beam_debug.c
+++ b/erts/emulator/beam/beam_debug.c
@@ -207,6 +207,7 @@ erts_debug_disassemble_1(BIF_ALIST_1)
BIF_RET(am_false);
}
} else if (is_tuple(addr)) {
+ ErtsCodeIndex code_ix;
Module* modp;
Eterm mod;
Eterm name;
@@ -231,8 +232,8 @@ erts_debug_disassemble_1(BIF_ALIST_1)
* Try the export entry first to allow disassembly of special functions
* such as erts_debug:apply/4. Then search for it in the module.
*/
-
- if ((ep = erts_find_function(mod, name, arity)) != NULL) {
+ 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.
* Its ep will have ep->address == ep->code+3.
diff --git a/erts/emulator/beam/beam_emu.c b/erts/emulator/beam/beam_emu.c
index 97eb4f1edc..177dd397f1 100644
--- a/erts/emulator/beam/beam_emu.c
+++ b/erts/emulator/beam/beam_emu.c
@@ -5742,7 +5742,8 @@ call_error_handler(Process* p, BeamInstr* fi, Eterm* reg, Eterm func)
/*
* Search for the error_handler module.
*/
- ep = erts_find_function(erts_proc_get_error_handler(p), func, 3);
+ ep = erts_find_function(erts_proc_get_error_handler(p), func, 3,
+ erts_active_code_ix());
if (ep == NULL) { /* No error handler */
p->current = fi;
p->freason = EXC_UNDEF;
@@ -5786,7 +5787,7 @@ apply_setup_error_handler(Process* p, Eterm module, Eterm function, Uint arity,
* there is no error handler module.
*/
- if ((ep = erts_find_export_entry(erts_proc_get_error_handler(p),
+ if ((ep = erts_active_export_entry(erts_proc_get_error_handler(p),
am_undefined_function, 3)) == NULL) {
return NULL;
} else {
@@ -5893,7 +5894,7 @@ apply(Process* p, Eterm module, Eterm function, Eterm args, Eterm* reg)
* Note: All BIFs have export entries; thus, no special case is needed.
*/
- if ((ep = erts_find_export_entry(module, function, arity)) == NULL) {
+ if ((ep = erts_active_export_entry(module, function, arity)) == NULL) {
if ((ep = apply_setup_error_handler(p, module, function, arity, reg)) == NULL) goto error;
} else if (ERTS_PROC_GET_SAVED_CALLS_BUF(p)) {
save_calls(p, ep);
@@ -5941,7 +5942,7 @@ fixed_apply(Process* p, Eterm* reg, Uint arity)
* Note: All BIFs have export entries; thus, no special case is needed.
*/
- if ((ep = erts_find_export_entry(module, function, arity)) == NULL) {
+ if ((ep = erts_active_export_entry(module, function, arity)) == NULL) {
if ((ep = apply_setup_error_handler(p, module, function, arity, reg)) == NULL)
goto error;
} else if (ERTS_PROC_GET_SAVED_CALLS_BUF(p)) {
@@ -6118,7 +6119,7 @@ call_fun(Process* p, /* Current process. */
Export* ep;
Module* modp;
Eterm module;
-
+ ErtsCodeIndex code_ix = erts_active_code_ix();
/*
* No arity. There is no module loaded that defines the fun,
@@ -6143,7 +6144,7 @@ call_fun(Process* p, /* Current process. */
*/
ep = erts_find_function(erts_proc_get_error_handler(p),
- am_undefined_lambda, 3);
+ am_undefined_lambda, 3, code_ix);
if (ep == NULL) { /* No error handler */
p->current = NULL;
p->freason = EXC_UNDEF;
@@ -6215,8 +6216,8 @@ call_fun(Process* p, /* Current process. */
erts_send_warning_to_logger(p->group_leader, dsbufp);
}
- if ((ep = erts_find_export_entry(module, function, arity)) == NULL) {
- ep = erts_find_export_entry(erts_proc_get_error_handler(p),
+ if ((ep = erts_active_export_entry(module, function, arity)) == NULL) {
+ ep = erts_active_export_entry(erts_proc_get_error_handler(p),
am_undefined_function, 3);
if (ep == NULL) {
p->freason = EXC_UNDEF;
diff --git a/erts/emulator/beam/beam_load.c b/erts/emulator/beam/beam_load.c
index f7c8395cb6..7768438dd0 100644
--- a/erts/emulator/beam/beam_load.c
+++ b/erts/emulator/beam/beam_load.c
@@ -812,7 +812,7 @@ erts_finish_loading(LoaderState* stp, Process* c_p,
* exported and imported functions. This can't fail.
*/
- erts_export_consolidate();
+ erts_export_consolidate(erts_loader_code_ix());
CHKBLK(ERTS_ALC_T_CODE,stp->code);
final_touch(stp);
@@ -1294,7 +1294,7 @@ load_import_table(LoaderState* stp)
* If the export entry refers to a BIF, get the pointer to
* the BIF function.
*/
- if ((e = erts_find_export_entry(mod, func, arity)) != NULL) {
+ if ((e = erts_active_export_entry(mod, func, arity)) != NULL) { /*SVERK does it matter which one we use? */
if (e->code[3] == (BeamInstr) em_apply_bif) {
stp->import[i].bf = (BifFunction) e->code[4];
if (func == am_load_nif && mod == am_erlang && arity == 2) {
@@ -1386,7 +1386,7 @@ read_export_table(LoaderState* stp)
static int
is_bif(Eterm mod, Eterm func, unsigned arity)
{
- Export* e = erts_find_export_entry(mod, func, arity);
+ Export* e = erts_active_export_entry(mod, func, arity);
if (e == NULL) {
return 0;
}
@@ -5190,13 +5190,15 @@ exported_from_module(Process* p, /* Process whose heap to use. */
Eterm* hp = NULL;
Eterm* hend = NULL;
Eterm result = NIL;
+ ErtsCodeIndex code_ix;
if (is_not_atom(mod)) {
return THE_NON_VALUE;
}
- for (i = 0; i < export_list_size(); i++) {
- Export* ep = export_list(i);
+ code_ix = erts_active_code_ix();
+ for (i = 0; i < export_list_size(code_ix); i++) {
+ Export* ep = export_list(i,code_ix);
if (ep->code[0] == mod) {
Eterm tuple;
@@ -6144,6 +6146,7 @@ void erts_unlock_code_ix(void)
void erts_start_loader_code_ix(void)
{
beam_catches_start_load();
+ export_start_load();
/*SVERK and more to come I guess...
:
*/
@@ -6154,6 +6157,7 @@ void erts_start_loader_code_ix(void)
void erts_commit_loader_code_ix(void)
{
beam_catches_end_load(1);
+ export_end_load(1);
{
ErtsCodeIndex ix = erts_loader_code_ix();
erts_smp_atomic32_set_nob(&the_active_code_index, ix);
@@ -6166,6 +6170,7 @@ void erts_commit_loader_code_ix(void)
void erts_abort_loader_code_ix(void)
{
beam_catches_end_load(0);
+ export_end_load(0);
CIX_TRACE("abort");
}
diff --git a/erts/emulator/beam/bif.c b/erts/emulator/beam/bif.c
index 9512aa1558..cb99c1381c 100644
--- a/erts/emulator/beam/bif.c
+++ b/erts/emulator/beam/bif.c
@@ -3709,7 +3709,8 @@ BIF_RETTYPE function_exported_3(BIF_ALIST_3)
is_not_small(BIF_ARG_3)) {
BIF_ERROR(BIF_P, BADARG);
}
- if (erts_find_function(BIF_ARG_1, BIF_ARG_2, signed_val(BIF_ARG_3)) == NULL) {
+ if (erts_find_function(BIF_ARG_1, BIF_ARG_2, signed_val(BIF_ARG_3),
+ erts_active_code_ix()) == NULL) {
BIF_RET(am_false);
}
BIF_RET(am_true);
diff --git a/erts/emulator/beam/code_ix.h b/erts/emulator/beam/code_ix.h
new file mode 100644
index 0000000000..6b81102269
--- /dev/null
+++ b/erts/emulator/beam/code_ix.h
@@ -0,0 +1,65 @@
+/*
+ * %CopyrightBegin%
+ *
+ * Copyright Ericsson AB 2012-2012. All Rights Reserved.
+ *
+ * The contents of this file are subject to the Erlang Public License,
+ * Version 1.1, (the "License"); you may not use this file except in
+ * compliance with the License. You should have received a copy of the
+ * Erlang Public License along with this software. If not, it can be
+ * retrieved online at http://www.erlang.org/.
+ *
+ * Software distributed under the License is distributed on an "AS IS"
+ * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+ * the License for the specific language governing rights and limitations
+ * under the License.
+ *
+ * %CopyrightEnd%
+ */
+#ifndef __CODE_IX_H__
+#define __CODE_IX_H__
+
+
+#define ERTS_NUM_CODE_IX 3
+typedef unsigned ErtsCodeIndex;
+
+void erts_code_ix_init(void);
+ErtsCodeIndex erts_active_code_ix(void);
+ErtsCodeIndex erts_loader_code_ix(void);
+
+/* Lock code_ix (enqueue and suspend until we get it)
+*/
+void erts_lock_code_ix(void);
+
+/*SVERK
+ erts_lock_code_ix();
+ wait for thread progress
+ (we don't want any retarded threads with pointers to inactive Module)
+ Copy active -> loader
+ rlock old_code while copying Modules
+ Update loader
+ wait for thread progress
+ (we need a membarrier for everybody to "see" the new code)
+ Set loader as new active
+ erts_unlock_code_ix();
+}*/
+
+
+/* Unlock code_ix (resume first waiter)
+*/
+void erts_unlock_code_ix(void);
+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);
+
+#ifdef ERTS_ENABLE_LOCK_CHECK
+int erts_is_old_code_rlocked(void);
+int erts_is_code_ix_locked(void);
+#endif
+
+#endif /* !__CODE_IX_H__ */
diff --git a/erts/emulator/beam/erl_alloc.c b/erts/emulator/beam/erl_alloc.c
index df27186680..07a2539367 100644
--- a/erts/emulator/beam/erl_alloc.c
+++ b/erts/emulator/beam/erl_alloc.c
@@ -2185,7 +2185,7 @@ erts_memory(int *print_to_p, void *print_to_arg, void *proc, Eterm earg)
if (want.code) {
size.code = module_table_sz();
size.code += export_table_sz();
- size.code += export_list_size() * sizeof(Export);
+ size.code += export_list_size(erts_active_code_ix()) * sizeof(Export);
size.code += erts_fun_table_sz();
size.code += allocated_modules*sizeof(Range);
size.code += erts_total_code_size;
@@ -2335,7 +2335,7 @@ erts_allocated_areas(int *print_to_p, void *print_to_arg, void *proc)
values[i].arity = 2;
values[i].name = "export_list";
- values[i].ui[0] = export_list_size() * sizeof(Export);
+ values[i].ui[0] = export_list_size(erts_active_code_ix ()) * sizeof(Export);
i++;
values[i].arity = 2;
diff --git a/erts/emulator/beam/erl_bif_trace.c b/erts/emulator/beam/erl_bif_trace.c
index b0a58c80ea..7db764280a 100644
--- a/erts/emulator/beam/erl_bif_trace.c
+++ b/erts/emulator/beam/erl_bif_trace.c
@@ -333,7 +333,8 @@ trace_pattern(Process* p, Eterm MFA, Eterm Pattern, Eterm flaglist)
matches = erts_set_trace_pattern(mfa, specified,
match_prog_set, match_prog_set,
- on, flags, meta_tracer_pid);
+ on, flags, meta_tracer_pid,
+ erts_active_code_ix());
MatchSetUnref(match_prog_set);
done:
@@ -1331,7 +1332,8 @@ int
erts_set_trace_pattern(Eterm* mfa, int specified,
Binary* match_prog_set, Binary *meta_match_prog_set,
int on, struct trace_pattern_flags flags,
- Eterm meta_tracer_pid)
+ Eterm meta_tracer_pid,
+ ErtsCodeIndex code_ix)
{
int matches = 0;
int i;
@@ -1340,8 +1342,8 @@ erts_set_trace_pattern(Eterm* mfa, int specified,
* First work on normal functions (not real BIFs).
*/
- for (i = 0; i < export_list_size(); i++) {
- Export* ep = export_list(i);
+ for (i = 0; i < export_list_size(code_ix); i++) {
+ Export* ep = export_list(i, code_ix);
int j;
if (ExportIsBuiltIn(ep)) {
diff --git a/erts/emulator/beam/erl_init.c b/erts/emulator/beam/erl_init.c
index 8d382057dc..54b3c19616 100644
--- a/erts/emulator/beam/erl_init.c
+++ b/erts/emulator/beam/erl_init.c
@@ -353,7 +353,8 @@ erl_first_process_otp(char* modname, void* code, unsigned size, int argc, char**
Eterm env;
start_mod = am_atom_put(modname, sys_strlen(modname));
- if (erts_find_function(start_mod, am_start, 2) == NULL) {
+ if (erts_find_function(start_mod, am_start, 2,
+ erts_active_code_ix()) == NULL) {
erl_exit(5, "No function %s:start/2\n", modname);
}
diff --git a/erts/emulator/beam/export.c b/erts/emulator/beam/export.c
index 82636526bf..6a71b09472 100644
--- a/erts/emulator/beam/export.c
+++ b/erts/emulator/beam/export.c
@@ -32,7 +32,13 @@
#define EXPORT_HASH(m,f,a) ((m)*(f)+(a))
-static IndexTable export_table; /* Not locked. */
+#ifdef DEBUG
+# define IF_DEBUG(x) x
+#else
+# define IF_DEBUG(x)
+#endif
+
+static IndexTable export_tables[ERTS_NUM_CODE_IX]; /* Active not locked */
static Hash secondary_export_table; /* Locked. */
#include "erl_smp.h"
@@ -58,9 +64,19 @@ struct export_entry
struct export_blob
{
Export exp;
+ unsigned top_ix; /*SVERK atomic? */
+ struct export_entry entryv[ERTS_NUM_CODE_IX];
+};
+
+/* Helper struct only used as template
+*/
+struct export_templ
+{
struct export_entry entry;
+ Export exp;
};
+
void
export_info(int to, void *to_arg)
{
@@ -69,7 +85,7 @@ export_info(int to, void *to_arg)
if (lock)
export_read_lock();
#endif
- index_info(to, to_arg, &export_table);
+ index_info(to, to_arg, &export_tables[erts_active_code_ix()]);
hash_info(to, to_arg, &secondary_export_table);
#ifdef ERTS_SMP
if (lock)
@@ -104,20 +120,24 @@ export_alloc(struct export_entry* tmpl_e)
struct export_blob* blob =
(struct export_blob*) erts_alloc(ERTS_ALC_T_EXPORT, sizeof(*blob));
Export* obj = &blob->exp;
-
+ int i;
+
obj->fake_op_func_info_for_hipe[0] = 0;
obj->fake_op_func_info_for_hipe[1] = 0;
obj->code[0] = tmpl->code[0];
obj->code[1] = tmpl->code[1];
obj->code[2] = tmpl->code[2];
- blob->entry.slot.index = -1;
obj->address = obj->code+3;
obj->code[3] = (BeamInstr) em_call_error_handler;
obj->code[4] = 0;
obj->match_prog_set = NULL;
- blob->entry.ep = &blob->exp;
- return &blob->entry;
+ for (i=0; i<ERTS_NUM_CODE_IX; i++) {
+ blob->entryv[i].slot.index = -1;
+ blob->entryv[i].ep = &blob->exp;
+ }
+ blob->top_ix = 0;
+ return &blob->entryv[blob->top_ix];
}
/*SVERK
@@ -133,6 +153,7 @@ init_export_table(void)
{
HashFunctions f;
erts_smp_rwmtx_opt_t rwmtx_opt = ERTS_SMP_RWMTX_OPT_DEFAULT_INITER;
+ int i;
rwmtx_opt.type = ERTS_SMP_RWMTX_TYPE_FREQUENT_READ;
rwmtx_opt.lived = ERTS_SMP_RWMTX_LONG_LIVED;
@@ -143,8 +164,10 @@ init_export_table(void)
f.alloc = (HALLOC_FUN) export_alloc;
f.free = (HFREE_FUN) NULL; /*SVERK export_free;*/
- erts_index_init(ERTS_ALC_T_EXPORT_TABLE, &export_table, "export_list",
- EXPORT_INITIAL_SIZE, EXPORT_LIMIT, f);
+ for (i=0; i<ERTS_NUM_CODE_IX; i++) {
+ erts_index_init(ERTS_ALC_T_EXPORT_TABLE, &export_tables[i], "export_list",
+ EXPORT_INITIAL_SIZE, EXPORT_LIMIT, f);
+ }
hash_init(ERTS_ALC_T_EXPORT_TABLE, &secondary_export_table,
"secondary_export_table", 50, f);
}
@@ -163,14 +186,22 @@ init_export_table(void)
*/
Export*
-erts_find_export_entry(Eterm m, Eterm f, unsigned int a)
+erts_active_export_entry(Eterm m, Eterm f, unsigned int a)
+{
+ return erts_find_export_entry(m, f, a, erts_active_code_ix());
+}
+
+
+Export*
+erts_find_export_entry(Eterm m, Eterm f, unsigned int a,
+ ErtsCodeIndex code_ix)
{
HashValue hval = EXPORT_HASH((BeamInstr) m, (BeamInstr) f, (BeamInstr) a);
int ix;
HashBucket* b;
- ix = hval % export_table.htable.size;
- b = export_table.htable.bucket[ix];
+ ix = hval % export_tables[code_ix].htable.size;
+ b = export_tables[code_ix].htable.bucket[ix];
/*
* Note: We have inlined the code from hash.c for speed.
@@ -186,14 +217,15 @@ erts_find_export_entry(Eterm m, Eterm f, unsigned int a)
return NULL;
}
-static struct export_entry* init_template(struct export_blob* blob,
+static struct export_entry* init_template(struct export_templ* templ,
Eterm m, Eterm f, unsigned a)
{
- blob->entry.ep = &blob->exp;
- blob->exp.code[0] = m;
- blob->exp.code[1] = f;
- blob->exp.code[2] = a;
- return &blob->entry;
+ templ->entry.ep = &templ->exp;
+ templ->entry.slot.index = -1;
+ templ->exp.code[0] = m;
+ templ->exp.code[1] = f;
+ templ->exp.code[2] = a;
+ return &templ->entry;
}
@@ -209,12 +241,12 @@ static struct export_entry* init_template(struct export_blob* blob,
*/
Export*
-erts_find_function(Eterm m, Eterm f, unsigned int a)
+erts_find_function(Eterm m, Eterm f, unsigned int a, ErtsCodeIndex code_ix)
{
- struct export_blob blob;
+ struct export_templ templ;
struct export_entry* ee;
- ee = hash_get(&export_table.htable, init_template(&blob, m, f, a));
+ ee = hash_get(&export_tables[code_ix].htable, init_template(&templ, m, f, a));
if (ee == NULL || (ee->ep->address == ee->ep->code+3 &&
ee->ep->code[3] != (BeamInstr) em_call_traced_function)) {
return NULL;
@@ -234,15 +266,14 @@ erts_find_function(Eterm m, Eterm f, unsigned int a)
Export*
erts_export_put(Eterm mod, Eterm func, unsigned int arity)
{
- struct export_blob blob;
+ ErtsCodeIndex code_ix = erts_loader_code_ix();
+ struct export_templ templ;
int ix;
- ERTS_SMP_LC_ASSERT(erts_initialized == 0
- || erts_smp_thr_progress_is_blocking());
ASSERT(is_atom(mod));
ASSERT(is_atom(func));
- ix = index_put(&export_table, init_template(&blob, mod, func, arity));
- return ((struct export_entry*) erts_index_lookup(&export_table, ix))->ep;
+ ix = index_put(&export_tables[code_ix], init_template(&templ, mod, func, arity));
+ return ((struct export_entry*) erts_index_lookup(&export_tables[code_ix], ix))->ep;
}
/*
@@ -258,14 +289,14 @@ erts_export_put(Eterm mod, Eterm func, unsigned int arity)
Export*
erts_export_get_or_make_stub(Eterm mod, Eterm func, unsigned int arity)
{
- struct export_blob blob;
Export* ep;
ASSERT(is_atom(mod));
ASSERT(is_atom(func));
- ep = erts_find_export_entry(mod, func, arity);
+ ep = erts_active_export_entry(mod, func, arity);
if (ep == 0) {
+ struct export_templ templ;
struct export_entry* entry;
/*
* The code is not loaded (yet). Put the export in the secondary
@@ -273,7 +304,7 @@ erts_export_get_or_make_stub(Eterm mod, Eterm func, unsigned int arity)
*/
export_write_lock();
entry = (struct export_entry *) hash_put(&secondary_export_table,
- init_template(&blob, mod, func, arity));
+ init_template(&templ, mod, func, arity));
export_write_unlock();
ep = entry->ep;
}
@@ -286,38 +317,44 @@ erts_export_get_or_make_stub(Eterm mod, Eterm func, unsigned int arity)
* export table into the primary.
*/
void
-erts_export_consolidate(void)
+erts_export_consolidate(ErtsCodeIndex code_ix)
{
#ifdef DEBUG
HashInfo hi;
#endif
- ERTS_SMP_LC_ASSERT(erts_initialized == 0
+ /*SVERK: Not sure if this is the way to go.
+ Maye we should always merge into loader ix,
+ or can loader table act as secondary_export_table?*/
+
+ ERTS_SMP_LC_ASSERT((erts_is_code_ix_locked()
+ && code_ix == erts_loader_code_ix())
+ || erts_initialized == 0
|| erts_smp_thr_progress_is_blocking());
export_write_lock();
- erts_index_merge(&secondary_export_table, &export_table);
- erts_hash_merge(&secondary_export_table, &export_table.htable);
+ erts_index_merge(&secondary_export_table, &export_tables[code_ix]);
+ erts_hash_merge(&secondary_export_table, &export_tables[code_ix].htable);
export_write_unlock();
#ifdef DEBUG
- hash_get_info(&hi, &export_table.htable);
- ASSERT(export_table.entries == hi.objs);
+ hash_get_info(&hi, &export_tables[code_ix].htable);
+ ASSERT(export_tables[code_ix].entries == hi.objs);
#endif
}
-Export *export_list(int i)
+Export *export_list(int i, ErtsCodeIndex code_ix)
{
- return ((struct export_entry*) erts_index_lookup(&export_table, i))->ep;
+ return ((struct export_entry*) erts_index_lookup(&export_tables[code_ix], i))->ep;
}
-int export_list_size(void)
+int export_list_size(ErtsCodeIndex code_ix)
{
- return export_table.entries;
+ return export_tables[code_ix].entries;
}
int export_table_sz(void)
{
- return index_table_sz(&export_table);
+ return index_table_sz(&export_tables[erts_active_code_ix()]);
}
Export *export_get(Export *e)
@@ -325,6 +362,65 @@ Export *export_get(Export *e)
struct export_entry ee;
struct export_entry* entry;
ee.ep = e;
- entry = (struct export_entry*)hash_get(&export_table.htable, &ee);
+ entry = (struct export_entry*)hash_get(&export_tables[erts_active_code_ix()].htable, &ee);
return entry ? entry->ep : NULL;
}
+
+static struct export_entry*
+export_dummy_alloc(struct export_entry* entry)
+{
+ return entry;
+}
+
+static struct export_blob* entry_to_blob(struct export_entry* ee)
+{
+ return (struct export_blob*)
+ ((char*)ee->ep - offsetof(struct export_blob,exp));
+}
+
+IF_DEBUG(static ErtsCodeIndex debug_start_load_ix = 0;)
+
+void export_start_load(void)
+{
+ ErtsCodeIndex dst_ix = erts_loader_code_ix();
+ ErtsCodeIndex src_ix = erts_active_code_ix();
+ IndexTable* dst = &export_tables[dst_ix];
+ IndexTable* src = &export_tables[src_ix];
+ int i;
+
+ ASSERT(dst_ix != src_ix);
+ ASSERT(debug_start_load_ix == -1);
+
+ /* Trick hash_put (called by index_put below)
+ * to insert an already allocated entry. */
+ dst->htable.fun.alloc = (HALLOC_FUN) &export_dummy_alloc;
+
+ for (i = dst->entries; i < src->entries; i++) {
+ struct export_entry* src_entry;
+ struct export_entry* dst_entry;
+ struct export_blob* blob;
+
+ src_entry = (struct export_entry*) erts_index_lookup(src, i);
+ blob = entry_to_blob(src_entry);
+ dst_entry = &blob->entryv[++blob->top_ix];
+ ASSERT(blob->top_ix < ERTS_NUM_CODE_IX);
+ ASSERT(dst_entry->ep == &blob->exp);
+ ASSERT(dst_entry->slot.index == -1);
+ index_put(dst, dst_entry);
+ }
+
+ dst->htable.fun.alloc = (HALLOC_FUN) &export_alloc; /* restore */
+
+ /*SVERK Remember dst->entries in order to purge on abort */
+
+ IF_DEBUG(debug_start_load_ix = dst_ix);
+}
+
+void export_end_load(int commit)
+{
+ ASSERT(debug_start_load_ix == erts_loader_code_ix());
+
+ /*SVERK Purge if abort */
+
+ IF_DEBUG(debug_start_load_ix = -1);
+}
diff --git a/erts/emulator/beam/export.h b/erts/emulator/beam/export.h
index 47e5a2c1d1..0aad921b2d 100644
--- a/erts/emulator/beam/export.h
+++ b/erts/emulator/beam/export.h
@@ -28,6 +28,8 @@
#include "index.h"
#endif
+#include "code_ix.h"
+
/*
** Export entry
*/
@@ -59,17 +61,20 @@ typedef struct export
void init_export_table(void);
void export_info(int, void *);
-Export* erts_find_export_entry(Eterm m, Eterm f, unsigned int a);
+Export* erts_find_export_entry(Eterm m, Eterm f, unsigned int a, ErtsCodeIndex);
+Export* erts_active_export_entry(Eterm m, Eterm f, unsigned int a); /*SVERK inline? */
Export* erts_export_put(Eterm mod, Eterm func, unsigned int arity);
Export* erts_export_get_or_make_stub(Eterm, Eterm, unsigned);
-void erts_export_consolidate(void);
+void erts_export_consolidate(ErtsCodeIndex);
-Export *export_list(int);
-int export_list_size(void);
+Export *export_list(int,ErtsCodeIndex);
+int export_list_size(ErtsCodeIndex);
int export_table_sz(void);
Export *export_get(Export*);
+void export_start_load(void);
+void export_end_load(int commit);
#include "beam_load.h" /* For em_* extern declarations */
#define ExportIsBuiltIn(EntryPtr) \
diff --git a/erts/emulator/beam/external.c b/erts/emulator/beam/external.c
index 152dbcf085..792bf66487 100644
--- a/erts/emulator/beam/external.c
+++ b/erts/emulator/beam/external.c
@@ -2562,7 +2562,7 @@ dec_term_atom_common:
goto error;
}
if (edep && (edep->flags & ERTS_DIST_EXT_BTT_SAFE)) {
- if (!erts_find_export_entry(mod, name, arity))
+ if (!erts_active_export_entry(mod, name, arity))
goto error;
}
*objp = make_export(hp);
diff --git a/erts/emulator/beam/global.h b/erts/emulator/beam/global.h
index 8745ca610b..4ce6ed5280 100644
--- a/erts/emulator/beam/global.h
+++ b/erts/emulator/beam/global.h
@@ -28,50 +28,7 @@
#include "hash.h"
#include "index.h"
#include "atom.h"
-
-/*SVERK maybe put this is some other header, must be before module.h and export.h */
-#define ERTS_NUM_CODE_IX 3
-typedef unsigned ErtsCodeIndex;
-
-void erts_code_ix_init(void);
-ErtsCodeIndex erts_active_code_ix(void);
-ErtsCodeIndex erts_loader_code_ix(void);
-
-/* Lock code_ix (enqueue and suspend until we get it)
-*/
-void erts_lock_code_ix(void);
-
-/*SVERK
- erts_lock_code_ix();
- wait for thread progress
- (we don't want any retarded threads with pointers to inactive Module)
- Copy active -> loader
- rlock old_code while copying Modules
- Update loader
- wait for thread progress
- (we need a membarrier for everybody to "see" the new code)
- Set loader as new active
- erts_unlock_code_ix();
-}*/
-
-
-/* Unlock code_ix (resume first waiter)
-*/
-void erts_unlock_code_ix(void);
-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);
-
-#ifdef ERTS_ENABLE_LOCK_CHECK
-int erts_is_old_code_rlocked(void);
-int erts_is_code_ix_locked(void);
-#endif
-
+#include "code_ix.h"
#include "export.h"
#include "module.h"
#include "register.h"
@@ -1529,7 +1486,7 @@ void erts_cleanup_offheap(ErlOffHeap *offheap);
Uint erts_fit_in_bits(Uint);
int list_length(Eterm);
-Export* erts_find_function(Eterm, Eterm, unsigned int);
+Export* erts_find_function(Eterm, Eterm, unsigned int, ErtsCodeIndex);
int erts_is_builtin(Eterm, Eterm, int);
Uint32 make_broken_hash(Eterm);
Uint32 block_hash(byte *, unsigned, Uint32);
@@ -1800,7 +1757,8 @@ extern int erts_call_time_breakpoint_tracing;
int erts_set_trace_pattern(Eterm* mfa, int specified,
Binary* match_prog_set, Binary *meta_match_prog_set,
int on, struct trace_pattern_flags,
- Eterm meta_tracer_pid);
+ Eterm meta_tracer_pid,
+ ErtsCodeIndex);
void
erts_get_default_trace_pattern(int *trace_pattern_is_on,
Binary **match_spec,
diff --git a/erts/emulator/hipe/hipe_bif0.c b/erts/emulator/hipe/hipe_bif0.c
index d81c50b4ae..34f58378c7 100644
--- a/erts/emulator/hipe/hipe_bif0.c
+++ b/erts/emulator/hipe/hipe_bif0.c
@@ -1591,7 +1591,7 @@ BIF_RETTYPE hipe_nonclosure_address(BIF_ALIST_2)
f = tp[2];
if (is_not_atom(m) || is_not_atom(f))
goto badfun;
- if (!erts_find_export_entry(m, f, BIF_ARG_2))
+ if (!erts_active_export_entry(m, f, BIF_ARG_2)) /*SVERK active? */
goto badfun;
} else
goto badfun;