aboutsummaryrefslogtreecommitdiffstats
path: root/erts/emulator/beam/beam_bif_load.c
diff options
context:
space:
mode:
Diffstat (limited to 'erts/emulator/beam/beam_bif_load.c')
-rw-r--r--erts/emulator/beam/beam_bif_load.c108
1 files changed, 50 insertions, 58 deletions
diff --git a/erts/emulator/beam/beam_bif_load.c b/erts/emulator/beam/beam_bif_load.c
index 6bb70cc5a7..a000935388 100644
--- a/erts/emulator/beam/beam_bif_load.c
+++ b/erts/emulator/beam/beam_bif_load.c
@@ -38,7 +38,7 @@
#include "erl_thr_progress.h"
static void set_default_trace_pattern(Eterm module);
-static Eterm check_process_code(Process* rp, Module* modp, int allow_gc, int *redsp);
+static Eterm check_process_code(Process* rp, Module* modp, Uint flags, int *redsp);
static void delete_code(Module* modp);
static void decrement_refc(BeamCodeHeader*);
static int any_heap_ref_ptrs(Eterm* start, Eterm* end, char* mod_start, Uint mod_size);
@@ -426,7 +426,7 @@ check_old_code_1(BIF_ALIST_1)
}
Eterm
-erts_check_process_code(Process *c_p, Eterm module, int allow_gc, int *redsp)
+erts_check_process_code(Process *c_p, Eterm module, Uint flags, int *redsp)
{
Module* modp;
Eterm res;
@@ -441,7 +441,8 @@ erts_check_process_code(Process *c_p, Eterm module, int allow_gc, int *redsp)
if (!modp)
return am_false;
erts_rlock_old_code(code_ix);
- res = modp->old.code_hdr ? check_process_code(c_p, modp, allow_gc, redsp) : am_false;
+ res = (!modp->old.code_hdr ? am_false :
+ check_process_code(c_p, modp, flags, redsp));
erts_runlock_old_code(code_ix);
return res;
@@ -450,49 +451,21 @@ erts_check_process_code(Process *c_p, Eterm module, int allow_gc, int *redsp)
BIF_RETTYPE erts_internal_check_process_code_2(BIF_ALIST_2)
{
int reds = 0;
+ Uint flags;
Eterm res;
- Eterm olist = BIF_ARG_2;
- int allow_gc = 1;
if (is_not_atom(BIF_ARG_1))
goto badarg;
- while (is_list(olist)) {
- Eterm *lp = list_val(olist);
- Eterm opt = CAR(lp);
- if (is_tuple(opt)) {
- Eterm* tp = tuple_val(opt);
- switch (arityval(tp[0])) {
- case 2:
- switch (tp[1]) {
- case am_allow_gc:
- switch (tp[2]) {
- case am_false:
- allow_gc = 0;
- break;
- case am_true:
- allow_gc = 1;
- break;
- default:
- goto badarg;
- }
- break;
- default:
- goto badarg;
- }
- break;
- default:
- goto badarg;
- }
- }
- else
- goto badarg;
- olist = CDR(lp);
+ if (is_not_small(BIF_ARG_2))
+ goto badarg;
+
+ flags = unsigned_val(BIF_ARG_2);
+ if (flags & ~ERTS_CPC_ALL) {
+ goto badarg;
}
- if (is_not_nil(olist))
- goto badarg;
- res = erts_check_process_code(BIF_P, BIF_ARG_1, allow_gc, &reds);
+ res = erts_check_process_code(BIF_P, BIF_ARG_1, flags, &reds);
ASSERT(is_value(res));
@@ -739,7 +712,7 @@ check_mod_funs(Process *p, ErlOffHeap *off_heap, char *area, size_t area_size)
static Eterm
-check_process_code(Process* rp, Module* modp, int allow_gc, int *redsp)
+check_process_code(Process* rp, Module* modp, Uint flags, int *redsp)
{
BeamInstr* start;
char* literals;
@@ -852,6 +825,12 @@ check_process_code(Process* rp, Module* modp, int allow_gc, int *redsp)
/* Check heap, stack etc... */
if (check_mod_funs(rp, &rp->off_heap, mod_start, mod_size))
goto try_gc;
+ if (!(flags & ERTS_CPC_COPY_LITERALS)) {
+ /* Process ok. May contain old literals but we will be called
+ * again before module is purged.
+ */
+ return am_false;
+ }
if (any_heap_ref_ptrs(&rp->fvalue, &rp->fvalue+1, literals, lit_bsize)) {
rp->freason = EXC_NULL;
rp->fvalue = NIL;
@@ -919,7 +898,7 @@ check_process_code(Process* rp, Module* modp, int allow_gc, int *redsp)
if ((done_gc & need_gc) == need_gc)
return am_true;
- if (!allow_gc)
+ if (!(flags & ERTS_CPC_ALLOW_GC))
return am_aborted;
need_gc &= ~done_gc;
@@ -1013,7 +992,7 @@ any_heap_refs(Eterm* start, Eterm* end, char* mod_start, Uint mod_size)
static void copy_literals_commit(void*);
#endif
-copy_literals_t erts_clrange = {NULL, 0};
+copy_literals_t erts_clrange = {NULL, 0, THE_NON_VALUE};
/* copy literals
*
@@ -1031,9 +1010,8 @@ copy_literals_t erts_clrange = {NULL, 0};
*/
-BIF_RETTYPE copy_literals_2(BIF_ALIST_2)
+BIF_RETTYPE erts_internal_copy_literals_2(BIF_ALIST_2)
{
- Module* modp;
ErtsCodeIndex code_ix;
Eterm res = am_true;
@@ -1042,26 +1020,34 @@ BIF_RETTYPE copy_literals_2(BIF_ALIST_2)
}
if (!erts_try_seize_code_write_permission(BIF_P)) {
- ERTS_BIF_YIELD2(bif_export[BIF_copy_literals_2], BIF_P, BIF_ARG_1, BIF_ARG_2);
+ ERTS_BIF_YIELD2(bif_export[BIF_erts_internal_copy_literals_2],
+ BIF_P, BIF_ARG_1, BIF_ARG_2);
}
code_ix = erts_active_code_ix();
- if ((modp = erts_get_module(BIF_ARG_1, code_ix)) == NULL || !modp->old.code_hdr) {
- res = am_false;
- goto done;
- }
-
if (BIF_ARG_2 == am_true) {
- if (erts_clrange.ptr != NULL) {
+ Module* modp = erts_get_module(BIF_ARG_1, code_ix);
+ if (!modp || !modp->old.code_hdr) {
+ res = am_false;
+ goto done;
+ }
+ if (erts_clrange.ptr != NULL
+ && !(BIF_P->static_flags & ERTS_STC_FLG_SYSTEM_PROC)) {
res = am_aborted;
goto done;
- }
- erts_clrange.ptr = (Eterm*) modp->old.code_hdr->literals_start;
- erts_clrange.sz = (Eterm*) modp->old.code_hdr->literals_end - erts_clrange.ptr;
+ }
+ erts_clrange.ptr = modp->old.code_hdr->literals_start;
+ erts_clrange.sz = modp->old.code_hdr->literals_end - erts_clrange.ptr;
+ erts_clrange.pid = BIF_P->common.id;
} else if (BIF_ARG_2 == am_false) {
+ if (erts_clrange.pid != BIF_P->common.id) {
+ res = am_false;
+ goto done;
+ }
erts_clrange.ptr = NULL;
erts_clrange.sz = 0;
+ erts_clrange.pid = THE_NON_VALUE;
}
#ifdef ERTS_SMP
@@ -1094,7 +1080,12 @@ static void copy_literals_commit(void* null) {
#endif /* ERTS_SMP */
-BIF_RETTYPE purge_module_1(BIF_ALIST_1)
+/* Do the actualy module purging and return:
+ * true for success
+ * false if no such old module
+ * BADARG if not an atom
+ */
+BIF_RETTYPE erts_internal_purge_module_1(BIF_ALIST_1)
{
ErtsCodeIndex code_ix;
BeamInstr* code;
@@ -1108,7 +1099,8 @@ BIF_RETTYPE purge_module_1(BIF_ALIST_1)
}
if (!erts_try_seize_code_write_permission(BIF_P)) {
- ERTS_BIF_YIELD1(bif_export[BIF_purge_module_1], BIF_P, BIF_ARG_1);
+ ERTS_BIF_YIELD1(bif_export[BIF_erts_internal_purge_module_1],
+ BIF_P, BIF_ARG_1);
}
code_ix = erts_active_code_ix();
@@ -1118,7 +1110,7 @@ BIF_RETTYPE purge_module_1(BIF_ALIST_1)
*/
if ((modp = erts_get_module(BIF_ARG_1, code_ix)) == NULL) {
- ERTS_BIF_PREP_ERROR(ret, BIF_P, BADARG);
+ ERTS_BIF_PREP_RET(ret, am_false);
}
else {
erts_rwlock_old_code(code_ix);
@@ -1127,7 +1119,7 @@ BIF_RETTYPE purge_module_1(BIF_ALIST_1)
* Any code to purge?
*/
if (!modp->old.code_hdr) {
- ERTS_BIF_PREP_ERROR(ret, BIF_P, BADARG);
+ ERTS_BIF_PREP_RET(ret, am_false);
}
else {
/*