BIF_RETTYPE registered_0(BIF_ALIST_0) { int i; Eterm res; Uint need; Eterm* hp; HashBucket **bucket; #ifdef ERTS_SMP ErtsProcLocks proc_locks = ERTS_PROC_LOCK_MAIN; ERTS_SMP_CHK_HAVE_ONLY_MAIN_PROC_LOCK(BIF_P); reg_safe_read_lock(BIF_P, &proc_locks); if (!proc_locks) erts_smp_proc_lock(BIF_P, ERTS_PROC_LOCK_MAIN); #endif bucket = process_reg.bucket; /* work out how much heap we need & maybe garb, by scanning through the registered process table */ need = 0; for (i = 0; i < process_reg.size; i++) { HashBucket *b = bucket[i]; while (b != NULL) { need += 2; b = b->next; } } if (need == 0) { reg_read_unlock(); BIF_RET(NIL); } hp = HAlloc(BIF_P, need); /* scan through again and make the list */ res = NIL; for (i = 0; i < process_reg.size; i++) { HashBucket *b = bucket[i]; while (b != NULL) { RegProc *reg = (RegProc *) b; res = CONS(hp, reg->name, res); hp += 2; b = b->next; } } reg_read_unlock(); BIF_RET(res); }
void register_info(fmtfn_t to, void *to_arg) { int lock = !ERTS_IS_CRASH_DUMPING; if (lock) reg_read_lock(); hash_info(to, to_arg, &process_reg); if (lock) reg_read_unlock(); }
int process_reg_sz(void) { int sz; int lock = !ERTS_IS_CRASH_DUMPING; if (lock) reg_read_lock(); sz = hash_table_sz(&process_reg); if (lock) reg_read_unlock(); return sz; }
int process_reg_size(void) { int size; int lock = !ERTS_IS_CRASH_DUMPING; if (lock) reg_read_lock(); size = process_reg.size; if (lock) reg_read_unlock(); return size; }
Eterm erts_whereis_name_to_id(Process *c_p, Eterm name) { Eterm res = am_undefined; HashValue hval; int ix; HashBucket* b; #ifdef ERTS_SMP ErtsProcLocks c_p_locks = c_p ? ERTS_PROC_LOCK_MAIN : 0; #ifdef ERTS_ENABLE_LOCK_CHECK if (c_p) ERTS_SMP_CHK_HAVE_ONLY_MAIN_PROC_LOCK(c_p); #endif reg_safe_read_lock(c_p, &c_p_locks); if (c_p && !c_p_locks) erts_smp_proc_lock(c_p, ERTS_PROC_LOCK_MAIN); #endif hval = REG_HASH(name); ix = hval % process_reg.size; b = process_reg.bucket[ix]; /* * Note: We have inlined the code from hash.c for speed. */ while (b) { RegProc* rp = (RegProc *) b; if (rp->name == name) { /* * SMP NOTE: No need to lock registered entity since it cannot * be removed without acquiring write reg lock and id on entity * is read only. */ if (rp->p) res = rp->p->common.id; else if (rp->pt) res = rp->pt->common.id; break; } b = b->next; } reg_read_unlock(); ASSERT(is_internal_pid(res) || is_internal_port(res) || res==am_undefined); return res; }
void erts_whereis_name(Process *c_p, ErtsProcLocks c_p_locks, Eterm name, Process** proc, ErtsProcLocks need_locks, int flags, Port** port, int lock_port) { RegProc* rp = NULL; HashValue hval; int ix; HashBucket* b; #ifdef ERTS_SMP ErtsProcLocks current_c_p_locks; Port *pending_port = NULL; if (!c_p) c_p_locks = 0; current_c_p_locks = c_p_locks; restart: reg_safe_read_lock(c_p, ¤t_c_p_locks); /* Locked locks: * - port lock on pending_port if pending_port != NULL * - read reg lock * - current_c_p_locks (either c_p_locks or 0) on c_p */ #endif hval = REG_HASH(name); ix = hval % process_reg.size; b = process_reg.bucket[ix]; /* * Note: We have inlined the code from hash.c for speed. */ while (b) { if (((RegProc *) b)->name == name) { rp = (RegProc *) b; break; } b = b->next; } if (proc) { if (!rp) *proc = NULL; else { #ifdef ERTS_SMP if (!rp->p) *proc = NULL; else { if (need_locks) { erts_proc_safelock(c_p, current_c_p_locks, c_p_locks, rp->p, 0, need_locks); current_c_p_locks = c_p_locks; } if ((flags & ERTS_P2P_FLG_ALLOW_OTHER_X) || is_proc_alive(rp->p)) *proc = rp->p; else { if (need_locks) erts_smp_proc_unlock(rp->p, need_locks); *proc = NULL; } } #else if (rp->p && ((flags & ERTS_P2P_FLG_ALLOW_OTHER_X) || is_proc_alive(rp->p))) *proc = rp->p; else *proc = NULL; #endif if (*proc && (flags & ERTS_P2P_FLG_INC_REFC)) erts_proc_inc_refc(*proc); } } if (port) { if (!rp || !rp->pt) *port = NULL; else { #ifdef ERTS_SMP if (lock_port) { if (pending_port == rp->pt) pending_port = NULL; else { if (pending_port) { /* Ahh! Registered port changed while reg lock was unlocked... */ erts_port_release(pending_port); pending_port = NULL; } if (erts_smp_port_trylock(rp->pt) == EBUSY) { Eterm id = rp->pt->common.id; /* id read only... */ /* Unlock all locks, acquire port lock, and restart... */ if (current_c_p_locks) { erts_smp_proc_unlock(c_p, current_c_p_locks); current_c_p_locks = 0; } reg_read_unlock(); pending_port = erts_id2port(id); goto restart; } } ERTS_SMP_LC_ASSERT(erts_lc_is_port_locked(rp->pt)); } #endif *port = rp->pt; } } #ifdef ERTS_SMP if (c_p && !current_c_p_locks) erts_smp_proc_lock(c_p, c_p_locks); if (pending_port) erts_port_release(pending_port); #endif reg_read_unlock(); }
/* * Unregister a name * Return 0 if not registered * Otherwise returns 1 * */ int erts_unregister_name(Process *c_p, ErtsProcLocks c_p_locks, Port *c_prt, Eterm name) { int res = 0; RegProc r, *rp; Port *port = c_prt; #ifdef ERTS_SMP ErtsProcLocks current_c_p_locks; /* * SMP note: If 'c_prt != NULL' and 'c_prt->reg->name == name', * we are *not* allowed to temporarily release the lock * on c_prt. */ if (!c_p) c_p_locks = 0; current_c_p_locks = c_p_locks; restart: reg_safe_write_lock(c_p, ¤t_c_p_locks); #endif r.name = name; if ((rp = (RegProc*) hash_get(&process_reg, (void*) &r)) != NULL) { if (rp->pt) { #ifdef ERTS_SMP if (port != rp->pt) { if (port) { ERTS_SMP_LC_ASSERT(port != c_prt); erts_smp_port_unlock(port); port = NULL; } if (erts_smp_port_trylock(rp->pt) == EBUSY) { Eterm id = rp->pt->id; /* id read only... */ /* Unlock all locks, acquire port lock, and restart... */ if (current_c_p_locks) { erts_smp_proc_unlock(c_p, current_c_p_locks); current_c_p_locks = 0; } reg_read_unlock(); port = erts_id2port(id, NULL, 0); goto restart; } port = rp->pt; } #endif ERTS_SMP_LC_ASSERT(rp->pt == port && erts_lc_is_port_locked(port)); rp->pt->reg = NULL; if (IS_TRACED_FL(port, F_TRACE_PORTS)) { trace_port(port, am_unregister, name); } } else if (rp->p) { Process* p = rp->p; #ifdef ERTS_SMP erts_proc_safelock(c_p, current_c_p_locks, c_p_locks, rp->p, 0, ERTS_PROC_LOCK_MAIN); current_c_p_locks = c_p_locks; #endif p->reg = NULL; #ifdef ERTS_SMP if (rp->p != c_p) erts_smp_proc_unlock(rp->p, ERTS_PROC_LOCK_MAIN); #endif if (IS_TRACED_FL(p, F_TRACE_PROCS)) { trace_proc(c_p, p, am_unregister, name); } } hash_erase(&process_reg, (void*) &r); res = 1; } reg_write_unlock(); if (c_prt != port) { if (port) erts_smp_port_unlock(port); if (c_prt) erts_smp_port_lock(c_prt); } #ifdef ERTS_SMP if (c_p && !current_c_p_locks) erts_smp_proc_lock(c_p, c_p_locks); #endif return res; }