diff options
Diffstat (limited to 'erts/emulator/beam/erl_nif.c')
-rw-r--r-- | erts/emulator/beam/erl_nif.c | 71 |
1 files changed, 52 insertions, 19 deletions
diff --git a/erts/emulator/beam/erl_nif.c b/erts/emulator/beam/erl_nif.c index f883b3f1e3..e208792868 100644 --- a/erts/emulator/beam/erl_nif.c +++ b/erts/emulator/beam/erl_nif.c @@ -388,12 +388,18 @@ erts_call_dirty_nif(ErtsSchedulerData *esdp, Process *c_p, BeamInstr *I, Eterm * erts_atomic32_read_band_mb(&c_p->state, ~(ERTS_PSFLG_DIRTY_CPU_PROC | ERTS_PSFLG_DIRTY_IO_PROC)); + ASSERT(esdp->current_nif == NULL); + esdp->current_nif = &env; + erts_proc_unlock(c_p, ERTS_PROC_LOCK_MAIN); result = (*dirty_nif)(&env, codemfa->arity, argv); /* Call dirty NIF */ erts_proc_lock(c_p, ERTS_PROC_LOCK_MAIN); + ASSERT(esdp->current_nif == &env); + esdp->current_nif = NULL; + ASSERT(env.proc->static_flags & ERTS_STC_FLG_SHADOW_PROC); ASSERT(env.proc->next == c_p); @@ -659,7 +665,7 @@ int erts_flush_trace_messages(Process *c_p, ErtsProcLocks c_p_locks) rp_locks = 0; if (rp->common.id == c_p->common.id) rp_locks = c_p_locks; - erts_queue_messages(rp, rp_locks, first, last, len); + erts_queue_proc_messages(c_p, rp, rp_locks, first, last, len); if (rp->common.id == c_p->common.id) rp_locks &= ~c_p_locks; if (rp_locks) @@ -850,7 +856,10 @@ int enif_send(ErlNifEnv* env, const ErlNifPid* to_pid, } } - erts_queue_message(rp, rp_locks, mp, msg, from); + if (c_p) + erts_queue_proc_message(c_p, rp, rp_locks, mp, msg); + else + erts_queue_message(rp, rp_locks, mp, msg, from); done: if (c_p == rp) @@ -3768,16 +3777,26 @@ static Eterm mkatom(const char *str) return am_atom_put(str, sys_strlen(str)); } -static struct tainted_module_t +struct tainted_module_t { struct tainted_module_t* next; Eterm module_atom; -}*first_tainted_module = NULL; +}; -static void add_taint(Eterm mod_atom) +erts_atomic_t first_taint; /* struct tainted_module_t* */ + +void erts_add_taint(Eterm mod_atom) { - struct tainted_module_t* t; - for (t=first_tainted_module ; t!=NULL; t=t->next) { +#ifdef ERTS_ENABLE_LOCK_CHECK + extern erts_rwmtx_t erts_driver_list_lock; /* Mutex for driver list */ +#endif + struct tainted_module_t *first, *t; + + ERTS_LC_ASSERT(erts_lc_rwmtx_is_rwlocked(&erts_driver_list_lock) + || erts_thr_progress_is_blocking()); + + first = (struct tainted_module_t*) erts_atomic_read_nob(&first_taint); + for (t=first ; t; t=t->next) { if (t->module_atom == mod_atom) { return; } @@ -3785,22 +3804,24 @@ static void add_taint(Eterm mod_atom) t = erts_alloc_fnf(ERTS_ALC_T_TAINT, sizeof(*t)); if (t != NULL) { t->module_atom = mod_atom; - t->next = first_tainted_module; - first_tainted_module = t; + t->next = first; + erts_atomic_set_nob(&first_taint, (erts_aint_t)t); } } Eterm erts_nif_taints(Process* p) { - struct tainted_module_t* t; + struct tainted_module_t *first, *t; unsigned cnt = 0; Eterm list = NIL; Eterm* hp; - for (t=first_tainted_module ; t!=NULL; t=t->next) { + + first = (struct tainted_module_t*) erts_atomic_read_nob(&first_taint); + for (t=first ; t!=NULL; t=t->next) { cnt++; } hp = HAlloc(p,cnt*2); - for (t=first_tainted_module ; t!=NULL; t=t->next) { + for (t=first ; t!=NULL; t=t->next) { list = CONS(hp, t->module_atom, list); hp += 2; } @@ -3809,9 +3830,11 @@ Eterm erts_nif_taints(Process* p) void erts_print_nif_taints(fmtfn_t to, void* to_arg) { - struct tainted_module_t* t; + struct tainted_module_t *t; const char* delim = ""; - for (t=first_tainted_module ; t!=NULL; t=t->next) { + + t = (struct tainted_module_t*) erts_atomic_read_nob(&first_taint); + for ( ; t; t = t->next) { const Atom* atom = atom_tab(atom_val(t->module_atom)); erts_cbprintf(to,to_arg,"%s%.*s", delim, atom->len, atom->name); delim = ","; @@ -3925,6 +3948,7 @@ BIF_RETTYPE load_nif_2(BIF_ALIST_2) ErtsSysDdllError errdesc = ERTS_SYS_DDLL_ERROR_INIT; Eterm ret = am_ok; int veto; + int taint = 1; struct erl_module_nif* lib = NULL; struct erl_module_instance* this_mi; struct erl_module_instance* prev_mi; @@ -3971,10 +3995,15 @@ BIF_RETTYPE load_nif_2(BIF_ALIST_2) ASSERT(module_p != NULL); mod_atomp = atom_tab(atom_val(mod_atom)); - init_func = erts_static_nif_get_nif_init((char*)mod_atomp->name, mod_atomp->len); - if (init_func != NULL) - handle = init_func; - + { + ErtsStaticNifEntry* sne; + sne = erts_static_nif_get_nif_init((char*)mod_atomp->name, mod_atomp->len); + if (sne != NULL) { + init_func = sne->nif_init; + handle = init_func; + taint = sne->taint; + } + } this_mi = &module_p->curr; prev_mi = &module_p->old; if (in_area(caller, module_p->old.code_hdr, module_p->old.code_length)) { @@ -4011,7 +4040,7 @@ BIF_RETTYPE load_nif_2(BIF_ALIST_2) " function: '%s'", errdesc.str); } - else if ((add_taint(mod_atom), + else if ((taint ? erts_add_taint(mod_atom) : 0, (entry = erts_sys_ddll_call_nif_init(init_func)) == NULL)) { ret = load_nif_error(BIF_P, bad_lib, "Library init-call unsuccessful"); } @@ -4238,6 +4267,10 @@ int erts_nif_get_funcs(struct erl_module_nif* mod, return mod->entry.num_of_funcs; } +Module *erts_nif_get_module(struct erl_module_nif *nif_mod) { + return nif_mod->mod; +} + Eterm erts_nif_call_function(Process *p, Process *tracee, struct erl_module_nif* mod, ErlNifFunc *fun, int argc, Eterm *argv) |