ErlNode *erts_find_or_insert_node(Eterm sysname, Uint creation) { ErlNode *res; ErlNode ne; ne.sysname = sysname; ne.creation = creation; erts_smp_rwmtx_rlock(&erts_node_table_rwmtx); res = hash_get(&erts_node_table, (void *) &ne); if (res && res != erts_this_node) { erts_aint_t refc = erts_refc_inctest(&res->refc, 0); if (refc < 2) /* New or pending delete */ erts_refc_inc(&res->refc, 1); } erts_smp_rwmtx_runlock(&erts_node_table_rwmtx); if (res) return res; erts_smp_rwmtx_rwlock(&erts_node_table_rwmtx); res = hash_put(&erts_node_table, (void *) &ne); ASSERT(res); if (res != erts_this_node) { erts_aint_t refc = erts_refc_inctest(&res->refc, 0); if (refc < 2) /* New or pending delete */ erts_refc_inc(&res->refc, 1); } erts_smp_rwmtx_rwunlock(&erts_node_table_rwmtx); return res; }
static void try_delete_node(void *venp) { ErlNode *enp = (ErlNode *) venp; erts_aint_t refc; erts_smp_rwmtx_rwlock(&erts_node_table_rwmtx); /* * 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. * * If refc reach -1, noone has used the entry since we * set up the timer. Delete the entry. * * If refc reach 0, the entry is currently not in use * but has been used since we set up the timer. Set up a * new timer. * * If refc > 0, the entry is in use. Keep the entry. */ refc = erts_refc_dectest(&enp->refc, -1); if (refc == -1) (void) hash_erase(&erts_node_table, (void *) enp); erts_smp_rwmtx_rwunlock(&erts_node_table_rwmtx); if (refc == 0) erts_schedule_delete_node(enp); }
int erts_sys_unsetenv(char *key) { int res; erts_smp_rwmtx_rwlock(&environ_rwmtx); res = unsetenv(key); erts_smp_rwmtx_rwunlock(&environ_rwmtx); return res; }
int erts_sys_putenv_raw(char *key, char *value) { int res; erts_smp_rwmtx_rwlock(&environ_rwmtx); res = (SetEnvironmentVariable((LPCTSTR) key, (LPCTSTR) value) ? 0 : 1); erts_smp_rwmtx_rwunlock(&environ_rwmtx); return res; }
void erts_set_dist_entry_not_connected(DistEntry *dep) { ERTS_SMP_LC_ASSERT(erts_lc_is_de_rwlocked(dep)); erts_smp_rwmtx_rwlock(&erts_dist_table_rwmtx); ASSERT(dep != erts_this_dist_entry); ASSERT(is_internal_port(dep->cid)); if(dep->flags & DFLAG_PUBLISHED) { if(dep->prev) { ASSERT(is_in_de_list(dep, erts_visible_dist_entries)); dep->prev->next = dep->next; } else { ASSERT(erts_visible_dist_entries == dep); erts_visible_dist_entries = dep->next; } ASSERT(erts_no_of_visible_dist_entries > 0); erts_no_of_visible_dist_entries--; } else { if(dep->prev) { ASSERT(is_in_de_list(dep, erts_hidden_dist_entries)); dep->prev->next = dep->next; } else { ASSERT(erts_hidden_dist_entries == dep); erts_hidden_dist_entries = dep->next; } ASSERT(erts_no_of_hidden_dist_entries > 0); erts_no_of_hidden_dist_entries--; } if(dep->next) dep->next->prev = dep->prev; dep->status &= ~ERTS_DE_SFLG_CONNECTED; dep->flags = 0; dep->prev = NULL; dep->cid = NIL; dep->next = erts_not_connected_dist_entries; if(erts_not_connected_dist_entries) { ASSERT(erts_not_connected_dist_entries->prev == NULL); erts_not_connected_dist_entries->prev = dep; } erts_not_connected_dist_entries = dep; erts_no_of_not_connected_dist_entries++; erts_smp_rwmtx_rwunlock(&erts_dist_table_rwmtx); }
int erts_sys_putenv(char *key, char *value) { int res; WCHAR *wkey = (WCHAR *) key; WCHAR *wvalue = (WCHAR *) value; erts_smp_rwmtx_rwlock(&environ_rwmtx); res = (SetEnvironmentVariableW(wkey, wvalue) ? 0 : 1); erts_smp_rwmtx_rwunlock(&environ_rwmtx); return res; }
void erts_set_dist_entry_connected(DistEntry *dep, Eterm cid, Uint flags) { ERTS_SMP_LC_ASSERT(erts_lc_is_de_rwlocked(dep)); erts_smp_rwmtx_rwlock(&erts_dist_table_rwmtx); ASSERT(dep != erts_this_dist_entry); ASSERT(is_nil(dep->cid)); ASSERT(is_internal_port(cid)); if(dep->prev) { ASSERT(is_in_de_list(dep, erts_not_connected_dist_entries)); dep->prev->next = dep->next; } else { ASSERT(erts_not_connected_dist_entries == dep); erts_not_connected_dist_entries = dep->next; } if(dep->next) dep->next->prev = dep->prev; ASSERT(erts_no_of_not_connected_dist_entries > 0); erts_no_of_not_connected_dist_entries--; dep->status |= ERTS_DE_SFLG_CONNECTED; dep->flags = flags; dep->cid = cid; dep->connection_id++; dep->connection_id &= ERTS_DIST_EXT_CON_ID_MASK; dep->prev = NULL; if(flags & DFLAG_PUBLISHED) { dep->next = erts_visible_dist_entries; if(erts_visible_dist_entries) { ASSERT(erts_visible_dist_entries->prev == NULL); erts_visible_dist_entries->prev = dep; } erts_visible_dist_entries = dep; erts_no_of_visible_dist_entries++; } else { dep->next = erts_hidden_dist_entries; if(erts_hidden_dist_entries) { ASSERT(erts_hidden_dist_entries->prev == NULL); erts_hidden_dist_entries->prev = dep; } erts_hidden_dist_entries = dep; erts_no_of_hidden_dist_entries++; } erts_smp_rwmtx_rwunlock(&erts_dist_table_rwmtx); }
void erts_set_this_node(Eterm sysname, Uint creation) { erts_smp_rwmtx_rwlock(&erts_node_table_rwmtx); erts_smp_rwmtx_rwlock(&erts_dist_table_rwmtx); (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; erts_this_node_sysname = erts_this_node_sysname_BUFFER; erts_snprintf(erts_this_node_sysname, sizeof(erts_this_node_sysname_BUFFER), "%T", sysname); (void) hash_put(&erts_node_table, (void *) erts_this_node); erts_smp_rwmtx_rwunlock(&erts_dist_table_rwmtx); erts_smp_rwmtx_rwunlock(&erts_node_table_rwmtx); }
int erts_sys_putenv(char *key_value, int sep_ix) { int res; char sep = key_value[sep_ix]; ASSERT(sep == '='); key_value[sep_ix] = '\0'; erts_smp_rwmtx_rwlock(&environ_rwmtx); res = (SetEnvironmentVariable((LPCTSTR) key_value, (LPCTSTR) &key_value[sep_ix+1]) ? 0 : 1); erts_smp_rwmtx_rwunlock(&environ_rwmtx); key_value[sep_ix] = sep; return res; }
DistEntry *erts_find_or_insert_dist_entry(Eterm sysname) { DistEntry *res; DistEntry de; erts_aint_t refc; res = erts_find_dist_entry(sysname); if (res) return res; de.sysname = sysname; erts_smp_rwmtx_rwlock(&erts_dist_table_rwmtx); res = hash_put(&erts_dist_table, (void *) &de); refc = erts_refc_inctest(&res->refc, 0); if (refc < 2) /* New or pending delete */ erts_refc_inc(&res->refc, 1); erts_smp_rwmtx_rwunlock(&erts_dist_table_rwmtx); return res; }
int erts_sys_putenv(char *key, char *value) { int res; char *env; Uint need = strlen(key) + strlen(value) + 2; #ifdef HAVE_COPYING_PUTENV env = erts_alloc(ERTS_ALC_T_TMP, need); #else env = erts_alloc(ERTS_ALC_T_PUTENV_STR, need); erts_smp_atomic_add_nob(&sys_misc_mem_sz, need); #endif strcpy(env,key); strcat(env,"="); strcat(env,value); erts_smp_rwmtx_rwlock(&environ_rwmtx); res = putenv(env); erts_smp_rwmtx_rwunlock(&environ_rwmtx); #ifdef HAVE_COPYING_PUTENV erts_free(ERTS_ALC_T_TMP, env); #endif return res; }
Process * erts_pid2proc_opt(Process *c_p, ErtsProcLocks c_p_have_locks, Eterm pid, ErtsProcLocks pid_need_locks, int flags) { Process *dec_refc_proc = NULL; int need_ptl; ErtsProcLocks need_locks; Uint pix; Process *proc; #if ERTS_PROC_LOCK_OWN_IMPL && defined(ERTS_ENABLE_LOCK_COUNT) ErtsProcLocks lcnt_locks; #endif #ifdef ERTS_ENABLE_LOCK_CHECK if (c_p) { ErtsProcLocks might_unlock = c_p_have_locks & pid_need_locks; if (might_unlock) erts_proc_lc_might_unlock(c_p, might_unlock); } #endif if (is_not_internal_pid(pid)) return NULL; pix = internal_pid_index(pid); ERTS_LC_ASSERT((pid_need_locks & ERTS_PROC_LOCKS_ALL) == pid_need_locks); need_locks = pid_need_locks; if (c_p && c_p->id == pid) { ASSERT(c_p->id != ERTS_INVALID_PID); ASSERT(c_p == erts_pix2proc(pix)); if (!(flags & ERTS_P2P_FLG_ALLOW_OTHER_X) && ERTS_PROC_IS_EXITING(c_p)) return NULL; need_locks &= ~c_p_have_locks; if (!need_locks) { if (flags & ERTS_P2P_FLG_SMP_INC_REFC) erts_smp_proc_inc_refc(c_p); return c_p; } } need_ptl = !erts_get_scheduler_id(); if (need_ptl) erts_smp_rwmtx_rwlock(&erts_proc_tab_rwmtx); proc = (Process *) erts_smp_atomic_read_ddrb(&erts_proc.tab[pix]); if (proc) { if (proc->id != pid) proc = NULL; else if (!need_locks) { if (flags & ERTS_P2P_FLG_SMP_INC_REFC) erts_smp_proc_inc_refc(proc); } else { int busy; #if ERTS_PROC_LOCK_OWN_IMPL #ifdef ERTS_ENABLE_LOCK_COUNT lcnt_locks = need_locks; if (!(flags & ERTS_P2P_FLG_TRY_LOCK)) { erts_lcnt_proc_lock(&proc->lock, need_locks); } #endif #ifdef ERTS_ENABLE_LOCK_CHECK /* Make sure erts_pid2proc_safelock() is enough to handle a potential lock order violation situation... */ busy = erts_proc_lc_trylock_force_busy(proc, need_locks); if (!busy) #endif #endif /* ERTS_PROC_LOCK_OWN_IMPL */ { /* Try a quick trylock to grab all the locks we need. */ busy = (int) erts_smp_proc_raw_trylock__(proc, need_locks); #if ERTS_PROC_LOCK_OWN_IMPL && defined(ERTS_ENABLE_LOCK_CHECK) erts_proc_lc_trylock(proc, need_locks, !busy); #endif #ifdef ERTS_PROC_LOCK_DEBUG if (!busy) erts_proc_lock_op_debug(proc, need_locks, 1); #endif } #if ERTS_PROC_LOCK_OWN_IMPL && defined(ERTS_ENABLE_LOCK_COUNT) if (flags & ERTS_P2P_FLG_TRY_LOCK) erts_lcnt_proc_trylock(&proc->lock, need_locks, busy ? EBUSY : 0); #endif if (!busy) { if (flags & ERTS_P2P_FLG_SMP_INC_REFC) erts_smp_proc_inc_refc(proc); #if ERTS_PROC_LOCK_OWN_IMPL && defined(ERTS_ENABLE_LOCK_COUNT) /* all is great */ if (!(flags & ERTS_P2P_FLG_TRY_LOCK)) erts_lcnt_proc_lock_post_x(&proc->lock, lcnt_locks, __FILE__, __LINE__); #endif } else { if (flags & ERTS_P2P_FLG_TRY_LOCK) proc = ERTS_PROC_LOCK_BUSY; else { if (flags & ERTS_P2P_FLG_SMP_INC_REFC) erts_smp_proc_inc_refc(proc); #if ERTS_PROC_LOCK_OWN_IMPL && defined(ERTS_ENABLE_LOCK_COUNT) erts_lcnt_proc_lock_unaquire(&proc->lock, lcnt_locks); #endif if (need_ptl) { erts_smp_proc_inc_refc(proc); dec_refc_proc = proc; erts_smp_rwmtx_rwunlock(&erts_proc_tab_rwmtx); need_ptl = 0; } proc_safelock(!need_ptl, c_p, c_p_have_locks, c_p_have_locks, proc, 0, need_locks); } } } } if (need_ptl) erts_smp_rwmtx_rwunlock(&erts_proc_tab_rwmtx); if (need_locks && proc && proc != ERTS_PROC_LOCK_BUSY && (!(flags & ERTS_P2P_FLG_ALLOW_OTHER_X) ? ERTS_PROC_IS_EXITING(proc) : (proc != (Process *) erts_smp_atomic_read_nob(&erts_proc.tab[pix])))) { erts_smp_proc_unlock(proc, need_locks); if (flags & ERTS_P2P_FLG_SMP_INC_REFC) dec_refc_proc = proc; proc = NULL; } if (dec_refc_proc) erts_smp_proc_dec_refc(dec_refc_proc); #if ERTS_PROC_LOCK_OWN_IMPL && defined(ERTS_PROC_LOCK_DEBUG) ERTS_LC_ASSERT(!proc || proc == ERTS_PROC_LOCK_BUSY || (pid_need_locks == (ERTS_PROC_LOCK_FLGS_READ_(&proc->lock) & pid_need_locks))); #endif return proc; }