📄 erl_node_tables.c
字号:
#endif res = hash_table_sz(&erts_node_table) + node_entries*sizeof(ErlNode); if (lock) erts_smp_mtx_unlock(&erts_node_table_mtx); return res;}voiderts_node_table_info(int to, void *to_arg){ int lock = !ERTS_IS_CRASH_DUMPING; if (lock) erts_smp_mtx_lock(&erts_node_table_mtx); hash_info(to, to_arg, &erts_node_table); if (lock) erts_smp_mtx_unlock(&erts_node_table_mtx);}ErlNode *erts_find_or_insert_node(Eterm sysname, Uint creation){ ErlNode *res; ErlNode ne; ne.sysname = sysname; ne.creation = creation; erts_smp_mtx_lock(&erts_node_table_mtx); res = hash_put(&erts_node_table, (void *) &ne); ASSERT(res); if (res != erts_this_node) { long refc = erts_refc_inctest(&res->refc, 0); if (refc < 2) /* New or pending delete */ erts_refc_inc(&res->refc, 1); } erts_smp_mtx_unlock(&erts_node_table_mtx); return res;}void erts_delete_node(ErlNode *enp){ ASSERT(enp != erts_this_node); if(enp != erts_this_node) { erts_smp_mtx_lock(&erts_node_table_mtx); /* * Another thread might have looked up this node after we * decided to delete it (refc became zero). If so, the other * thread incremented refc twice. Once for the new reference * and once for this thread. Therefore, delete node if refc * is 0 or -1 after a decrement. */ if (erts_refc_dectest(&enp->refc, -1) <= 0) (void) hash_erase(&erts_node_table, (void *) enp); erts_smp_mtx_unlock(&erts_node_table_mtx); }}struct pn_data { int to; void *to_arg; Eterm sysname; int no_sysname; int no_total;};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_print_node_info(int to, void *to_arg, Eterm sysname, int *no_sysname, int *no_total){ int lock = !ERTS_IS_CRASH_DUMPING; struct pn_data pnd; pnd.to = to; pnd.to_arg = to_arg; pnd.sysname = sysname; pnd.no_sysname = 0; pnd.no_total = 0; if (lock) erts_smp_mtx_lock(&erts_node_table_mtx); hash_foreach(&erts_node_table, print_node, (void *) &pnd); if (pnd.no_sysname != 0) { erts_print(to, to_arg, "\n"); } if (lock) erts_smp_mtx_unlock(&erts_node_table_mtx); if(no_sysname) *no_sysname = pnd.no_sysname; if(no_total) *no_total = pnd.no_total;}/* ----------------------------------------------------------------------- */voiderts_set_this_node(Eterm sysname, Uint creation){ erts_smp_mtx_lock(&erts_node_table_mtx); erts_smp_mtx_lock(&erts_dist_table_mtx); (void) hash_erase(&erts_dist_table, (void *) erts_this_dist_entry); erts_this_dist_entry->sysname = sysname; erts_this_dist_entry->creation = creation; (void) hash_put(&erts_dist_table, (void *) erts_this_dist_entry); (void) hash_erase(&erts_node_table, (void *) erts_this_node); erts_this_node->sysname = sysname; erts_this_node->creation = creation; (void) hash_put(&erts_node_table, (void *) erts_this_node); erts_smp_mtx_unlock(&erts_dist_table_mtx); erts_smp_mtx_unlock(&erts_node_table_mtx);}void erts_init_node_tables(void){ HashFunctions f; f.hash = (H_FUN) dist_table_hash; f.cmp = (HCMP_FUN) dist_table_cmp; f.alloc = (HALLOC_FUN) dist_table_alloc; f.free = (HFREE_FUN) dist_table_free; erts_this_dist_entry = erts_alloc(ERTS_ALC_T_DIST_ENTRY, sizeof(DistEntry)); dist_entries = 1; hash_init(ERTS_ALC_T_DIST_TABLE, &erts_dist_table, "dist_table", 11, f); erts_hidden_dist_entries = NULL; erts_visible_dist_entries = NULL; erts_not_connected_dist_entries = NULL; erts_no_of_hidden_dist_entries = 0; erts_no_of_visible_dist_entries = 0; erts_no_of_not_connected_dist_entries = 0; erts_this_dist_entry->next = NULL; erts_this_dist_entry->prev = NULL; erts_refc_init(&erts_this_dist_entry->refc, 1); /* erts_this_node */ erts_this_dist_entry->sysname = am_Noname; erts_this_dist_entry->cid = NIL; erts_this_dist_entry->node_links = NULL; erts_this_dist_entry->nlinks = NULL; erts_this_dist_entry->monitors = NULL; erts_this_dist_entry->status = 0; erts_this_dist_entry->flags = 0; erts_this_dist_entry->cache = NULL; erts_this_dist_entry->version = 0; (void) hash_put(&erts_dist_table, (void *) erts_this_dist_entry); f.hash = (H_FUN) node_table_hash; f.cmp = (HCMP_FUN) node_table_cmp; f.alloc = (HALLOC_FUN) node_table_alloc; f.free = (HFREE_FUN) node_table_free; hash_init(ERTS_ALC_T_NODE_TABLE, &erts_node_table, "node_table", 11, f); erts_this_node = erts_alloc(ERTS_ALC_T_NODE_ENTRY, sizeof(ErlNode)); node_entries = 1; erts_refc_init(&erts_this_node->refc, 1); /* The system itself */ erts_this_node->sysname = am_Noname; erts_this_node->creation = 0; erts_this_node->dist_entry = erts_this_dist_entry; (void) hash_put(&erts_node_table, (void *) erts_this_node);#ifdef ERTS_SMP { int i; for (i = 0; i < ERTS_NO_OF_DIST_ENTRY_MUTEXES; i++) erts_smp_mtx_init(&dist_entry_mutexes[i], "dist_entry"); erts_this_dist_entry->mtxp = &dist_entry_mutexes[0]; erts_smp_mtx_init(&erts_node_table_mtx, "node_table"); erts_smp_mtx_init(&erts_dist_table_mtx, "dist_table"); }#endif references_atoms_need_init = 1;}#ifdef ERTS_SMPvoiderts_lock_node_tables_and_entries(void){ int i; for (i = 0; i < ERTS_NO_OF_DIST_ENTRY_MUTEXES; i++) erts_smp_mtx_lock(&dist_entry_mutexes[i]); erts_smp_mtx_lock(&erts_node_table_mtx); erts_smp_mtx_lock(&erts_dist_table_mtx);}voiderts_unlock_node_tables_and_entries(void){ int i; erts_smp_mtx_unlock(&erts_dist_table_mtx); erts_smp_mtx_unlock(&erts_node_table_mtx); for (i = ERTS_NO_OF_DIST_ENTRY_MUTEXES-1; i >= 0; i--) erts_smp_mtx_unlock(&dist_entry_mutexes[i]);}#ifdef ERTS_ENABLE_LOCK_CHECKint erts_lc_is_dist_entry_locked(DistEntry *dep){ return erts_smp_lc_mtx_is_locked(dep->mtxp);}#endif#endif/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\ * The following is only supposed to be used for testing, and debugging. * * * * erts_get_node_and_dist_references() returns a table of all references to * * all entries in the node and dist tables. The hole system will be searched * * at once. This will give a consistent view over the references, but can * * can damage the real-time properties of the system. *\* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */#include "erl_db.h"#undef INIT_AM#define INIT_AM(S) AM_ ## S = am_atom_put(#S, sizeof(#S) - 1)static Eterm AM_heap;static Eterm AM_link;static Eterm AM_monitor;static Eterm AM_process;static Eterm AM_port;static Eterm AM_ets;static Eterm AM_binary;static Eterm AM_match_spec;static Eterm AM_control;static Eterm AM_dist;static Eterm AM_node;static Eterm AM_dist_references;static Eterm AM_node_references;static Eterm AM_system;static Eterm AM_timer;#ifdef HYBRIDstatic Eterm AM_processes;#endifstatic void setup_reference_table(void);static Eterm reference_table_term(Uint **hpp, Uint *szp);static void delete_reference_table(void);#if BIG_UINT_HEAP_SIZE > 3 /* 2-tuple */#define ID_HEAP_SIZE BIG_UINT_HEAP_SIZE#else#define ID_HEAP_SIZE 3 /* 2-tuple */#endiftypedef struct node_referrer_ { struct node_referrer_ *next; int heap_ref; int link_ref; int monitor_ref; int ets_ref; int bin_ref; int timer_ref; int system_ref; Eterm id; Uint id_heap[ID_HEAP_SIZE];} NodeReferrer;typedef struct { ErlNode *node; NodeReferrer *referrers;} ReferredNode;typedef struct dist_referrer_ { struct dist_referrer_ *next; int node_ref; int ctrl_ref; Eterm id; Uint creation;} DistReferrer;typedef struct { DistEntry *dist; DistReferrer *referrers;} ReferredDist;typedef struct inserted_bin_ { struct inserted_bin_ *next; Binary *bin_val;} InsertedBin;static ReferredNode *referred_nodes;static int no_referred_nodes;static ReferredDist *referred_dists;static int no_referred_dists;static InsertedBin *inserted_bins;Etermerts_get_node_and_dist_references(struct process *proc){ Uint *hp; Uint size; Eterm res;#ifdef DEBUG Uint *endp;#endif erts_smp_proc_unlock(proc, ERTS_PROC_LOCK_MAIN); erts_smp_block_system(0); /* No need to lock any thing since we are alone... */ if (references_atoms_need_init) { INIT_AM(heap); INIT_AM(link); INIT_AM(monitor); INIT_AM(process); INIT_AM(port); INIT_AM(ets); INIT_AM(binary); INIT_AM(match_spec); INIT_AM(control); INIT_AM(dist); INIT_AM(node); INIT_AM(dist_references); INIT_AM(node_references); INIT_AM(timer); INIT_AM(system);#ifdef HYBRID INIT_AM(processes);#endif references_atoms_need_init = 0; } setup_reference_table(); /* Get term size */ size = 0; (void) reference_table_term(NULL, &size); hp = HAlloc(proc, size);#ifdef DEBUG ASSERT(size > 0); endp = hp + size;#endif /* Write term */ res = reference_table_term(&hp, NULL); ASSERT(endp == hp); delete_reference_table(); erts_smp_release_system(); erts_smp_proc_lock(proc, ERTS_PROC_LOCK_MAIN); return res;}#define HEAP_REF 1#define LINK_REF 2#define ETS_REF 3 #define BIN_REF 4#define NODE_REF 5#define CTRL_REF 6#define MONITOR_REF 7#define TIMER_REF 8#define SYSTEM_REF 9#define INC_TAB_SZ 10static voidinsert_dist_referrer(ReferredDist *referred_dist, int type, Eterm id, Uint creation){ DistReferrer *drp; for(drp = referred_dist->referrers; drp; drp = drp->next) if(id == drp->id && (type == CTRL_REF || creation == drp->creation)) break; if(!drp) { drp = (DistReferrer *) erts_alloc(ERTS_ALC_T_NC_TMP, sizeof(DistReferrer)); drp->next = referred_dist->referrers; referred_dist->referrers = drp; drp->id = id; drp->creation = creation; drp->node_ref = 0; drp->ctrl_ref = 0; } switch (type) { case NODE_REF: drp->node_ref++; break; case CTRL_REF: drp->ctrl_ref++; break; default: ASSERT(0); }}static voidinsert_dist_entry(DistEntry *dist, int type, Eterm id, Uint creation){ ReferredDist *rdp = NULL; int i; for(i = 0; i < no_referred_dists; i++) { if(dist == referred_dists[i].dist) { rdp = &referred_dists[i]; break; } } if(!rdp) erl_exit(1, "Reference to non-existing distribution table entry found!\n"); insert_dist_referrer(rdp, type, id, creation);}static voidinsert_node_referrer(ReferredNode *referred_node, int type, Eterm id){ NodeReferrer *nrp; for(nrp = referred_node->referrers; nrp; nrp = nrp->next) if(EQ(id, nrp->id)) break; if(!nrp) { nrp = (NodeReferrer *) erts_alloc(ERTS_ALC_T_NC_TMP, sizeof(NodeReferrer)); nrp->next = referred_node->referrers; referred_node->referrers = nrp; if(IS_CONST(id)) nrp->id = id; else { Uint *hp = &nrp->id_heap[0]; ASSERT(is_big(id) || is_tuple(id)); nrp->id = copy_struct(id, size_object(id), &hp, NULL); } nrp->heap_ref = 0; nrp->link_ref = 0; nrp->monitor_ref = 0; nrp->ets_ref = 0; nrp->bin_ref = 0; nrp->timer_ref = 0; nrp->system_ref = 0; } switch (type) { case HEAP_REF: nrp->heap_ref++; break; case LINK_REF: nrp->link_ref++; break; case ETS_REF: nrp->ets_ref++; break; case BIN_REF: nrp->bin_ref++; break; case MONITOR_REF: nrp->monitor_ref++; break; case TIMER_REF: nrp->timer_ref++; break; case SYSTEM_REF: nrp->system_ref++; break; default: ASSERT(0); }}static voidinsert_node(ErlNode *node, int type, Eterm id){ int i; ReferredNode *rnp = NULL; for(i = 0; i < no_referred_nodes; i++) { if(node == referred_nodes[i].node) { rnp = &referred_nodes[i]; break; } } if (!rnp) erl_exit(1, "Reference to non-existing node table entry found!\n"); insert_node_referrer(rnp, type, id);}static voidinsert_erl_node(void *venp, void *unused){ ErlNode *enp = (ErlNode *) venp; insert_dist_entry(enp->dist_entry, NODE_REF, enp->sysname, enp->creation);}struct insert_offheap2_arg { int type; Eterm id;};static void insert_offheap(ErlOffHeap *, int, Eterm);static voidinsert_offheap2(ErlOffHeap *oh, void *arg) { struct insert_offheap2_arg *a = (struct insert_offheap2_arg *) arg; insert_offheap(oh, a->type, a->id);}static voidinsert_offheap(ErlOffHeap *oh, int type, Eterm id){ if(oh->externals) { ExternalThing *etp = oh->externals; while (etp) { insert_node(etp->node, type, id); etp = etp->next; } } if(oh->mso) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -