aboutsummaryrefslogtreecommitdiffstats
path: root/erts
diff options
context:
space:
mode:
authorSverker Eriksson <[email protected]>2012-01-24 14:28:39 +0100
committerSverker Eriksson <[email protected]>2012-02-21 12:23:03 +0100
commit72cab3a723925d0e369466d7de7567d8482b1318 (patch)
treef0e1eb90fff6ff4f14712d6c9571bec40532bd06 /erts
parent725ebf78ac6d47c760f64f11c07eeb8b850ef920 (diff)
downloadotp-72cab3a723925d0e369466d7de7567d8482b1318.tar.gz
otp-72cab3a723925d0e369466d7de7567d8482b1318.tar.bz2
otp-72cab3a723925d0e369466d7de7567d8482b1318.zip
erts: Fix purge of module with loaded nif library
Easy fallback solution that goes single threaded if the module to be purged has a loaded nif lib.
Diffstat (limited to 'erts')
-rw-r--r--erts/emulator/beam/beam_bif_load.c26
1 files changed, 22 insertions, 4 deletions
diff --git a/erts/emulator/beam/beam_bif_load.c b/erts/emulator/beam/beam_bif_load.c
index 7a65552d76..4a01e62dc8 100644
--- a/erts/emulator/beam/beam_bif_load.c
+++ b/erts/emulator/beam/beam_bif_load.c
@@ -40,7 +40,7 @@ static Eterm check_process_code(Process* rp, Module* modp);
static void ensure_no_breakpoints(Process *, ErtsProcLocks, Eterm module);
static void delete_code(Process *c_p, ErtsProcLocks c_p_locks, Module* modp);
static void delete_export_references(Eterm module);
-static int purge_module(int module);
+static int purge_module(Process*, int module);
static void decrement_refc(BeamInstr* code);
static int is_native(BeamInstr* code);
static int any_heap_ref_ptrs(Eterm* start, Eterm* end, char* mod_start, Uint mod_size);
@@ -128,7 +128,7 @@ BIF_RETTYPE purge_module_1(BIF_ALIST_1)
erts_export_consolidate(erts_active_code_ix());*/
- purge_res = purge_module(atom_val(BIF_ARG_1));
+ purge_res = purge_module(BIF_P, atom_val(BIF_ARG_1));
/*SVERK
erts_smp_thr_progress_unblock();
@@ -721,15 +721,17 @@ any_heap_refs(Eterm* start, Eterm* end, char* mod_start, Uint mod_size)
static int
-purge_module(int module)
+purge_module(Process* c_p, int module)
{
ErtsCodeIndex code_ix;
BeamInstr* code;
BeamInstr* end;
Module* modp;
+ int is_blocked = 0;
int ret;
erts_lock_code_ix();
+retry:
code_ix = erts_active_code_ix();
/*
@@ -753,6 +755,16 @@ purge_module(int module)
* Unload any NIF library
*/
if (modp->old.nif != NULL) {
+ if (!is_blocked) {
+ /*SVERK Do unload nif without blocking */
+ erts_rwunlock_old_code(code_ix);
+ erts_unlock_code_ix();
+ erts_smp_proc_unlock(c_p, ERTS_PROC_LOCK_MAIN);
+ erts_smp_thr_progress_block();
+ is_blocked = 1;
+ goto retry;
+ }
+
erts_unload_nif(modp->old.nif);
modp->old.nif = NULL;
}
@@ -777,7 +789,13 @@ purge_module(int module)
}
erts_rwunlock_old_code(code_ix);
}
- erts_unlock_code_ix();
+ if (is_blocked) {
+ erts_smp_thr_progress_unblock();
+ erts_smp_proc_lock(c_p, ERTS_PROC_LOCK_MAIN);
+ }
+ else {
+ erts_unlock_code_ix();
+ }
return ret;
}