static int reload_driver_entry(DE_Handle *dh) { char *path = dh->reload_full_path; char *name = dh->reload_driver_name; int loadres; Uint flags = dh->reload_flags; assert_drv_list_rwlocked(); dh->reload_full_path = NULL; dh->reload_driver_name = NULL; ASSERT(erts_refc_read(&(dh->refc),0) == 0); ASSERT(dh->full_path != NULL); erts_free(ERTS_ALC_T_DDLL_HANDLE, (void *) dh->full_path); dh->full_path = NULL; loadres = do_load_driver_entry(dh, path, name); erts_free(ERTS_ALC_T_DDLL_HANDLE, (void *) path); erts_free(ERTS_ALC_T_DDLL_HANDLE, (void *) name); if (loadres == ERL_DE_NO_ERROR) { dh->status = ERL_DE_OK; dh->flags = flags; } restore_process_references(dh); return loadres; }
void erts_unload_nif(struct erl_module_nif* lib) { ErlNifResourceType* rt; ErlNifResourceType* next; ASSERT(erts_smp_thr_progress_is_blocking()); ASSERT(lib != NULL); ASSERT(lib->mod != NULL); for (rt = resource_type_list.next; rt != &resource_type_list; rt = next) { next = rt->next; if (rt->owner == lib) { rt->next->prev = rt->prev; rt->prev->next = rt->next; rt->next = NULL; rt->prev = NULL; if (erts_refc_dectest(&rt->refc, 0) == 0) { if (rt->dtor != NULL) { erts_refc_dec(&lib->rt_dtor_cnt, 0); } erts_refc_dec(&lib->rt_cnt, 0); erts_free(ERTS_ALC_T_NIF, rt); } } } if (erts_refc_read(&lib->rt_dtor_cnt, 0) == 0) { close_lib(lib); if (erts_refc_read(&lib->rt_cnt, 0) == 0) { erts_free(ERTS_ALC_T_NIF, lib); return; } } else { ASSERT(erts_refc_read(&lib->rt_cnt, 1) > 0); } lib->mod = NULL; /* orphan lib */ }
static void restore_process_references(DE_Handle *dh) { DE_ProcEntry *p; assert_drv_list_rwlocked(); ASSERT(erts_refc_read(&(dh->refc),0) == 0); for(p = dh->procs;p != NULL; p = p->next) { if (p->awaiting_status == ERL_DE_PROC_LOADED) { ASSERT(p->flags & ERL_DE_FL_DEREFERENCED); erts_refc_inc(&(dh->refc),1); p->flags &= ~ERL_DE_FL_DEREFERENCED; } } }
static void close_lib(struct erl_module_nif* lib) { ASSERT(lib != NULL); ASSERT(lib->handle != NULL); ASSERT(erts_refc_read(&lib->rt_dtor_cnt,0) == 0); if (lib->entry != NULL && lib->entry->unload != NULL) { ErlNifEnv env; pre_nif_noproc(&env, lib); lib->entry->unload(&env, lib->priv_data); post_nif_noproc(&env); } erts_sys_ddll_close(lib->handle); lib->handle = NULL; }
static void print_node(void *venp, void *vpndp) { struct pn_data *pndp = ((struct pn_data *) vpndp); ErlNode *enp = ((ErlNode *) venp); if(pndp->sysname == NIL || enp->sysname == pndp->sysname) { if (pndp->no_sysname == 0) { erts_print(pndp->to, pndp->to_arg, "Creation:"); } if(pndp->sysname == NIL) { erts_print(pndp->to, pndp->to_arg, "Name: %T ", enp->sysname); } erts_print(pndp->to, pndp->to_arg, " %d", enp->creation); #ifdef DEBUG erts_print(pndp->to, pndp->to_arg, " (refc=%ld)", erts_refc_read(&enp->refc, 1)); #endif pndp->no_sysname++; } pndp->no_total++; }
void erts_set_this_node(Eterm sysname, Uint creation) { ERTS_SMP_LC_ASSERT(erts_thr_progress_is_blocking()); ASSERT(erts_refc_read(&erts_this_dist_entry->refc, 2)); if (erts_refc_dectest(&erts_this_node->refc, 0) == 0) try_delete_node(erts_this_node); if (erts_refc_dectest(&erts_this_dist_entry->refc, 0) == 0) try_delete_dist_entry(erts_this_dist_entry); erts_this_node = NULL; /* to make sure refc is bumped for this node */ erts_this_node = erts_find_or_insert_node(sysname, creation); erts_this_dist_entry = erts_this_node->dist_entry; erts_refc_inc(&erts_this_dist_entry->refc, 2); erts_this_node_sysname = erts_this_node_sysname_BUFFER; erts_snprintf(erts_this_node_sysname, sizeof(erts_this_node_sysname_BUFFER), "%T", sysname); }
Eterm enif_make_binary(ErlNifEnv* env, ErlNifBinary* bin) { if (bin->bin_term != THE_NON_VALUE) { return bin->bin_term; } else if (bin->ref_bin != NULL) { Binary* bptr = bin->ref_bin; ProcBin* pb; Eterm bin_term; /* !! Copy-paste from new_binary() !! */ pb = (ProcBin *) alloc_heap(env, PROC_BIN_SIZE); pb->thing_word = HEADER_PROC_BIN; pb->size = bptr->orig_size; pb->next = MSO(env->proc).first; MSO(env->proc).first = (struct erl_off_heap_header*) pb; pb->val = bptr; pb->bytes = (byte*) bptr->orig_bytes; pb->flags = 0; OH_OVERHEAD(&(MSO(env->proc)), pb->size / sizeof(Eterm)); bin_term = make_binary(pb); if (erts_refc_read(&bptr->refc, 1) == 1) { /* Total ownership transfer */ bin->ref_bin = NULL; bin->bin_term = bin_term; } return bin_term; } else { flush_env(env); bin->bin_term = new_binary(env->proc, bin->data, bin->size); cache_env(env); return bin->bin_term; } }
static void ddll_no_more_references(void *vdh) { DE_Handle *dh = (DE_Handle *) vdh; erts_aint_t x; lock_drv_list(); x = erts_refc_read(&(dh->refc),0); if (x > 0) { x = erts_refc_dectest(&(dh->refc),0); /* delete the reference added for me */ } if (x == 0) { DE_ProcEntry **p = &(dh->procs); Eterm save_driver_name = am_undefined; ASSERT(dh->status != ERL_DE_OK); do_unload_driver_entry(dh,&save_driver_name); while (*p != NULL) { DE_ProcEntry *q; if ((*p)->awaiting_status == ERL_DE_PROC_AWAIT_UNLOAD || (*p)->awaiting_status == ERL_DE_PROC_AWAIT_UNLOAD_ONLY) { notify_proc((*p)->proc, make_internal_ref(&((*p)->heap)), save_driver_name,am_DOWN,am_unloaded, 0); q = *p; *p = q->next; erts_free(ERTS_ALC_T_DDLL_PROCESS, (void *) q); } else { ASSERT(dh->status == ERL_DE_RELOAD || dh->status == ERL_DE_FORCE_RELOAD); p = &((*p)->next); } } if (dh->status == ERL_DE_UNLOAD || dh->status == ERL_DE_FORCE_UNLOAD) { ASSERT(dh->full_path != NULL); erts_free(ERTS_ALC_T_DDLL_HANDLE, (void *) dh->full_path); erts_free(ERTS_ALC_T_DDLL_HANDLE, (void *) dh); } else { /* ERL_DE_RELOAD || ERL_DE_FORCE_RELOAD */ int reload_res = reload_driver_entry(dh); p = &(dh->procs); while (*p != NULL) { DE_ProcEntry *q; if ((*p)->awaiting_status == ERL_DE_PROC_AWAIT_LOAD) { if (reload_res == 0) { notify_proc((*p)->proc, make_internal_ref(&((*p)->heap)), save_driver_name, am_UP, am_loaded, 0); } else { notify_proc((*p)->proc, make_internal_ref(&((*p)->heap)), save_driver_name, am_DOWN, am_load_failure, reload_res); } q = *p; *p = q->next; erts_free(ERTS_ALC_T_DDLL_PROCESS, (void *) q); } else { if (reload_res != 0) { DE_ProcEntry *q = *p; *p = q->next; erts_free(ERTS_ALC_T_DDLL_PROCESS, (void *) q); } else { p = &((*p)->next); } } } if (reload_res != 0) { ASSERT(dh->full_path == NULL); erts_free(ERTS_ALC_T_DDLL_HANDLE, (void *) dh); } } } unlock_drv_list(); }
static Eterm reference_table_term(Uint **hpp, Uint *szp) { #undef MK_2TUP #undef MK_3TUP #undef MK_CONS #undef MK_UINT #define MK_2TUP(E1, E2) erts_bld_tuple(hpp, szp, 2, (E1), (E2)) #define MK_3TUP(E1, E2, E3) erts_bld_tuple(hpp, szp, 3, (E1), (E2), (E3)) #define MK_CONS(CAR, CDR) erts_bld_cons(hpp, szp, (CAR), (CDR)) #define MK_UINT(UI) erts_bld_uint(hpp, szp, (UI)) int i; Eterm tup; Eterm tup2; Eterm nl = NIL; Eterm dl = NIL; Eterm nrid; for(i = 0; i < no_referred_nodes; i++) { NodeReferrer *nrp; Eterm nril = NIL; for(nrp = referred_nodes[i].referrers; nrp; nrp = nrp->next) { Eterm nrl = NIL; /* NodeReferenceList = [{ReferenceType,References}] */ if(nrp->heap_ref) { tup = MK_2TUP(AM_heap, MK_UINT(nrp->heap_ref)); nrl = MK_CONS(tup, nrl); } if(nrp->link_ref) { tup = MK_2TUP(AM_link, MK_UINT(nrp->link_ref)); nrl = MK_CONS(tup, nrl); } if(nrp->monitor_ref) { tup = MK_2TUP(AM_monitor, MK_UINT(nrp->monitor_ref)); nrl = MK_CONS(tup, nrl); } if(nrp->ets_ref) { tup = MK_2TUP(AM_ets, MK_UINT(nrp->ets_ref)); nrl = MK_CONS(tup, nrl); } if(nrp->bin_ref) { tup = MK_2TUP(AM_binary, MK_UINT(nrp->bin_ref)); nrl = MK_CONS(tup, nrl); } if(nrp->timer_ref) { tup = MK_2TUP(AM_timer, MK_UINT(nrp->timer_ref)); nrl = MK_CONS(tup, nrl); } if(nrp->system_ref) { tup = MK_2TUP(AM_system, MK_UINT(nrp->system_ref)); nrl = MK_CONS(tup, nrl); } nrid = nrp->id; if (!IS_CONST(nrp->id)) { Uint nrid_sz = size_object(nrp->id); if (szp) *szp += nrid_sz; if (hpp) nrid = copy_struct(nrp->id, nrid_sz, hpp, NULL); } if (is_internal_pid(nrid) || nrid == am_error_logger) { ASSERT(!nrp->ets_ref && !nrp->bin_ref && !nrp->system_ref); tup = MK_2TUP(AM_process, nrid); } else if (is_tuple(nrid)) { Eterm *t; ASSERT(!nrp->ets_ref && !nrp->bin_ref); t = tuple_val(nrid); ASSERT(2 == arityval(t[0])); tup = MK_2TUP(t[1], t[2]); } else if(is_internal_port(nrid)) { ASSERT(!nrp->heap_ref && !nrp->ets_ref && !nrp->bin_ref && !nrp->timer_ref && !nrp->system_ref); tup = MK_2TUP(AM_port, nrid); } else if(nrp->ets_ref) { ASSERT(!nrp->heap_ref && !nrp->link_ref && !nrp->monitor_ref && !nrp->bin_ref && !nrp->timer_ref && !nrp->system_ref); tup = MK_2TUP(AM_ets, nrid); } else if(nrp->bin_ref) { ASSERT(is_small(nrid) || is_big(nrid)); ASSERT(!nrp->heap_ref && !nrp->ets_ref && !nrp->link_ref && !nrp->monitor_ref && !nrp->timer_ref && !nrp->system_ref); tup = MK_2TUP(AM_match_spec, nrid); } else { ASSERT(!nrp->heap_ref && !nrp->ets_ref && !nrp->bin_ref); ASSERT(is_atom(nrid)); tup = MK_2TUP(AM_dist, nrid); } tup = MK_2TUP(tup, nrl); /* NodeReferenceIdList = [{{ReferrerType, ID}, NodeReferenceList}] */ nril = MK_CONS(tup, nril); } /* NodeList = [{{Node, Creation}, Refc, NodeReferenceIdList}] */ tup = MK_2TUP(referred_nodes[i].node->sysname, MK_UINT(referred_nodes[i].node->creation)); tup = MK_3TUP(tup, MK_UINT(erts_refc_read(&referred_nodes[i].node->refc, 1)), nril); nl = MK_CONS(tup, nl); } for(i = 0; i < no_referred_dists; i++) { DistReferrer *drp; Eterm dril = NIL; for(drp = referred_dists[i].referrers; drp; drp = drp->next) { Eterm drl = NIL; /* DistReferenceList = [{ReferenceType,References}] */ if(drp->node_ref) { tup = MK_2TUP(AM_node, MK_UINT(drp->node_ref)); drl = MK_CONS(tup, drl); } if(drp->ctrl_ref) { tup = MK_2TUP(AM_control, MK_UINT(drp->ctrl_ref)); drl = MK_CONS(tup, drl); } if (is_internal_pid(drp->id)) { ASSERT(drp->ctrl_ref && !drp->node_ref); tup = MK_2TUP(AM_process, drp->id); } else if(is_internal_port(drp->id)) { ASSERT(drp->ctrl_ref && !drp->node_ref); tup = MK_2TUP(AM_port, drp->id); } else { ASSERT(!drp->ctrl_ref && drp->node_ref); ASSERT(is_atom(drp->id)); tup = MK_2TUP(drp->id, MK_UINT(drp->creation)); tup = MK_2TUP(AM_node, tup); } tup = MK_2TUP(tup, drl); /* DistReferenceIdList = [{{ReferrerType, ID}, DistReferenceList}] */ dril = MK_CONS(tup, dril); } /* DistList = [{Dist, Refc, ReferenceIdList}] */ tup = MK_3TUP(referred_dists[i].dist->sysname, MK_UINT(erts_refc_read(&referred_dists[i].dist->refc, 1)), dril); dl = MK_CONS(tup, dl); } /* {{node_references, NodeList}, {dist_references, DistList}} */ tup = MK_2TUP(AM_node_references, nl); tup2 = MK_2TUP(AM_dist_references, dl); tup = MK_2TUP(tup, tup2); return tup; #undef MK_2TUP #undef MK_3TUP #undef MK_CONS #undef MK_UINT }