static void finalize_purge_operation(Process *c_p, int succeded) { Uint ix; if (c_p) erts_smp_proc_unlock(c_p, ERTS_PROC_LOCK_MAIN); erts_smp_mtx_lock(&purge_state.mtx); ASSERT(purge_state.module != THE_NON_VALUE); purge_state.module = THE_NON_VALUE; /* * Resume all processes that have tried to call * funs in this code. */ for (ix = 0; ix < purge_state.sp_ix; ix++) { Process *rp = erts_pid2proc(NULL, 0, purge_state.sprocs[ix], ERTS_PROC_LOCK_STATUS); if (rp) { erts_resume(rp, ERTS_PROC_LOCK_STATUS); erts_smp_proc_unlock(rp, ERTS_PROC_LOCK_STATUS); } } erts_smp_mtx_unlock(&purge_state.mtx); if (c_p) erts_smp_proc_lock(c_p, ERTS_PROC_LOCK_MAIN); if (purge_state.sprocs != &purge_state.def_sprocs[0]) { erts_free(ERTS_ALC_T_PURGE_DATA, purge_state.sprocs); purge_state.sprocs = &purge_state.def_sprocs[0]; purge_state.sp_size = sizeof(purge_state.def_sprocs); purge_state.sp_size /= sizeof(purge_state.def_sprocs[0]); } purge_state.sp_ix = 0; if (purge_state.funs != &purge_state.def_funs[0]) { erts_free(ERTS_ALC_T_PURGE_DATA, purge_state.funs); purge_state.funs = &purge_state.def_funs[0]; purge_state.fe_size = sizeof(purge_state.def_funs); purge_state.fe_size /= sizeof(purge_state.def_funs[0]); } purge_state.fe_ix = 0; }
Sint erts_complete_off_heap_message_queue_change(Process *c_p) { int reds = 1; ERTS_SMP_LC_ASSERT(ERTS_PROC_LOCK_MAIN == erts_proc_lc_my_proc_locks(c_p)); ASSERT(c_p->flags & F_OFF_HEAP_MSGQ_CHNG); ASSERT(erts_smp_atomic32_read_nob(&c_p->state) & ERTS_PSFLG_OFF_HEAP_MSGQ); /* * This job was first initiated when the process changed to off heap * message queue management. Since then ERTS_PSFLG_OFF_HEAP_MSGQ * has been set. However, the management state might have been changed * again (multiple times) since then. Check users last requested state * (the flags F_OFF_HEAP_MSGQ, and F_ON_HEAP_MSGQ), and make the state * consistent with that. */ if (!(c_p->flags & F_OFF_HEAP_MSGQ)) erts_smp_atomic32_read_band_nob(&c_p->state, ~ERTS_PSFLG_OFF_HEAP_MSGQ); else { reds += 2; erts_smp_proc_lock(c_p, ERTS_PROC_LOCK_MSGQ); ERTS_SMP_MSGQ_MV_INQ2PRIVQ(c_p); erts_smp_proc_unlock(c_p, ERTS_PROC_LOCK_MSGQ); reds += erts_move_messages_off_heap(c_p); } c_p->flags &= ~F_OFF_HEAP_MSGQ_CHNG; return reds; }
BIF_RETTYPE open_port_2(BIF_ALIST_2) { Port *port; Eterm port_id; char *str; int err_type, err_num; port = open_port(BIF_P, BIF_ARG_1, BIF_ARG_2, &err_type, &err_num); if (!port) { if (err_type == -3) { ASSERT(err_num == BADARG || err_num == SYSTEM_LIMIT); BIF_ERROR(BIF_P, err_num); } else if (err_type == -2) { str = erl_errno_id(err_num); } else { str = "einval"; } BIF_P->fvalue = erts_atom_put((byte *) str, strlen(str), ERTS_ATOM_ENC_LATIN1, 1); BIF_ERROR(BIF_P, EXC_ERROR); } erts_smp_proc_lock(BIF_P, ERTS_PROC_LOCK_LINK); port_id = port->common.id; erts_add_link(&ERTS_P_LINKS(port), LINK_PID, BIF_P->common.id); erts_add_link(&ERTS_P_LINKS(BIF_P), LINK_PID, port_id); erts_smp_proc_unlock(BIF_P, ERTS_PROC_LOCK_LINK); erts_port_release(port); BIF_RET(port_id); }
BIF_RETTYPE finish_after_on_load_2(BIF_ALIST_2) { Module* modp = erts_get_module(BIF_ARG_1); Eterm on_load; if (!modp || modp->code == 0) { error: BIF_ERROR(BIF_P, BADARG); } if ((on_load = modp->code[MI_ON_LOAD_FUNCTION_PTR]) == 0) { goto error; } if (BIF_ARG_2 != am_false && BIF_ARG_2 != am_true) { goto error; } erts_smp_proc_unlock(BIF_P, ERTS_PROC_LOCK_MAIN); erts_smp_thr_progress_block(); if (BIF_ARG_2 == am_true) { int i; /* * The on_load function succeded. Fix up export entries. */ for (i = 0; i < export_list_size(); i++) { Export *ep = export_list(i); if (ep != NULL && ep->code[0] == BIF_ARG_1 && ep->code[4] != 0) { ep->address = (void *) ep->code[4]; ep->code[4] = 0; } } modp->code[MI_ON_LOAD_FUNCTION_PTR] = 0; set_default_trace_pattern(BIF_ARG_1); } else if (BIF_ARG_2 == am_false) { BeamInstr* code; BeamInstr* end; /* * The on_load function failed. Remove the loaded code. * This is an combination of delete and purge. We purge * the current code; the old code is not touched. */ erts_total_code_size -= modp->code_length; code = modp->code; end = (BeamInstr *)((char *)code + modp->code_length); erts_cleanup_funs_on_purge(code, end); beam_catches_delmod(modp->catches, code, modp->code_length); erts_free(ERTS_ALC_T_CODE, (void *) code); modp->code = NULL; modp->code_length = 0; modp->catches = BEAM_CATCHES_NIL; remove_from_address_table(code); } erts_smp_thr_progress_unblock(); erts_smp_proc_lock(BIF_P, ERTS_PROC_LOCK_MAIN); BIF_RET(am_true); }
BIF_RETTYPE open_port_2(BIF_ALIST_2) { int port_num; Eterm port_val; char *str; int err_num; if ((port_num = open_port(BIF_P, BIF_ARG_1, BIF_ARG_2, &err_num)) < 0) { if (port_num == -3) { ASSERT(err_num == BADARG || err_num == SYSTEM_LIMIT); BIF_ERROR(BIF_P, err_num); } else if (port_num == -2) { str = erl_errno_id(err_num); } else { str = "einval"; } BIF_P->fvalue = am_atom_put(str, strlen(str)); BIF_ERROR(BIF_P, EXC_ERROR); } erts_smp_proc_lock(BIF_P, ERTS_PROC_LOCK_LINK); port_val = erts_port[port_num].id; erts_add_link(&(erts_port[port_num].nlinks), LINK_PID, BIF_P->id); erts_add_link(&(BIF_P->nlinks), LINK_PID, port_val); erts_smp_proc_unlock(BIF_P, ERTS_PROC_LOCK_LINK); erts_port_release(&erts_port[port_num]); BIF_RET(port_val); }
static void delete_code(Process *c_p, ErtsProcLocks c_p_locks, Module* modp) { #ifdef ERTS_ENABLE_LOCK_CHECK #ifdef ERTS_SMP if (c_p && c_p_locks) erts_proc_lc_chk_only_proc_main(c_p); else #endif erts_lc_check_exact(NULL, 0); #endif /* * Clear breakpoints if any */ if (modp->code != NULL && modp->code[MI_NUM_BREAKPOINTS] > 0) { if (c_p && c_p_locks) erts_smp_proc_unlock(c_p, ERTS_PROC_LOCK_MAIN); erts_smp_block_system(0); erts_clear_module_break(modp); modp->code[MI_NUM_BREAKPOINTS] = 0; erts_smp_release_system(); if (c_p && c_p_locks) erts_smp_proc_lock(c_p, ERTS_PROC_LOCK_MAIN); } modp->old_code = modp->code; modp->old_code_length = modp->code_length; modp->old_catches = modp->catches; modp->code = NULL; modp->code_length = 0; modp->catches = BEAM_CATCHES_NIL; }
Eterm erts_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; }
static void resume_purger(void *unused) { Process *p = erts_code_purger; erts_smp_proc_lock(p, ERTS_PROC_LOCK_STATUS); erts_resume(p, ERTS_PROC_LOCK_STATUS); erts_smp_proc_unlock(p, ERTS_PROC_LOCK_STATUS); }
BIF_RETTYPE delete_module_1(BIF_ALIST_1) { ErtsCodeIndex code_ix; Module* modp; int is_blocking = 0; int success = 0; Eterm res = NIL; if (is_not_atom(BIF_ARG_1)) { BIF_ERROR(BIF_P, BADARG); } if (!erts_try_seize_code_write_permission(BIF_P)) { ERTS_BIF_YIELD1(bif_export[BIF_delete_module_1], BIF_P, BIF_ARG_1); } { erts_start_staging_code_ix(0); code_ix = erts_staging_code_ix(); modp = erts_get_module(BIF_ARG_1, code_ix); if (!modp) { res = am_undefined; } else if (modp->old.code_hdr) { erts_dsprintf_buf_t *dsbufp = erts_create_logger_dsbuf(); erts_dsprintf(dsbufp, "Module %T must be purged before loading\n", BIF_ARG_1); erts_send_error_to_logger(BIF_P->group_leader, dsbufp); ERTS_BIF_PREP_ERROR(res, BIF_P, BADARG); } else { if (modp->curr.num_breakpoints > 0 || modp->curr.num_traced_exports > 0 || IF_HIPE(hipe_need_blocking(modp))) { /* tracing or hipe need to go single threaded */ erts_smp_proc_unlock(BIF_P, ERTS_PROC_LOCK_MAIN); erts_smp_thr_progress_block(); is_blocking = 1; if (modp->curr.num_breakpoints) { erts_clear_module_break(modp); ASSERT(modp->curr.num_breakpoints == 0); } } delete_code(modp); res = am_true; success = 1; } } { struct m mod; Eterm retval; mod.module = BIF_ARG_1; mod.modp = modp; retval = staging_epilogue(BIF_P, success, res, is_blocking, &mod, 1, 0); return retval; } }
static void process_killer(void) { int i, j, max = erts_ptab_max(&erts_proc); Process* rp; erts_printf("\n\nProcess Information\n\n"); erts_printf("--------------------------------------------------\n"); for (i = max-1; i >= 0; i--) { rp = erts_pix2proc(i); if (rp && rp->i != ENULL) { int br; print_process_info(ERTS_PRINT_STDOUT, NULL, rp); erts_printf("(k)ill (n)ext (r)eturn:\n"); while(1) { if ((j = sys_get_key(0)) <= 0) erts_exit(0, ""); switch(j) { case 'k': { ErtsProcLocks rp_locks = ERTS_PROC_LOCKS_XSIG_SEND; erts_aint32_t state; erts_proc_inc_refc(rp); erts_smp_proc_lock(rp, rp_locks); state = erts_smp_atomic32_read_acqb(&rp->state); if (state & (ERTS_PSFLG_FREE | ERTS_PSFLG_EXITING | ERTS_PSFLG_ACTIVE | ERTS_PSFLG_ACTIVE_SYS | ERTS_PSFLG_IN_RUNQ | ERTS_PSFLG_RUNNING | ERTS_PSFLG_RUNNING_SYS | ERTS_PSFLG_DIRTY_RUNNING | ERTS_PSFLG_DIRTY_RUNNING_SYS)) { erts_printf("Can only kill WAITING processes this way\n"); } else { (void) erts_send_exit_signal(NULL, NIL, rp, &rp_locks, am_kill, NIL, NULL, 0); } erts_smp_proc_unlock(rp, rp_locks); erts_proc_dec_refc(rp); } case 'n': br = 1; break; case 'r': return; default: return; } if (br == 1) break; } } } }
static void complete_literal_area_switch(void *literal_area) { Process *p = erts_literal_area_collector; erts_smp_proc_lock(p, ERTS_PROC_LOCK_STATUS); erts_resume(p, ERTS_PROC_LOCK_STATUS); erts_smp_proc_unlock(p, ERTS_PROC_LOCK_STATUS); if (literal_area) erts_release_literal_area((ErtsLiteralArea *) literal_area); }
static void proc_unlock(Process* c_p, Process* rp) { ErtsProcLocks locks = ERTS_PROC_LOCKS_ALL; if (rp == c_p) { locks &= ~ERTS_PROC_LOCK_MAIN; } if (rp && locks) { erts_smp_proc_unlock(rp, locks); } }
static void copy_literals_commit(void* null) { Process* p = committer_state.stager; #ifdef DEBUG committer_state.stager = NULL; #endif erts_release_code_write_permission(); erts_smp_proc_lock(p, ERTS_PROC_LOCK_STATUS); if (!ERTS_PROC_IS_EXITING(p)) { erts_resume(p, ERTS_PROC_LOCK_STATUS); } erts_smp_proc_unlock(p, ERTS_PROC_LOCK_STATUS); erts_proc_dec_refc(p); }
BIF_RETTYPE code_make_stub_module_3(BIF_ALIST_3) { #if !defined(HIPE) BIF_ERROR(BIF_P, EXC_NOTSUP); #else Module* modp; Eterm res, mod; if (!ERTS_TERM_IS_MAGIC_BINARY(BIF_ARG_1) || is_not_atom(mod = erts_module_for_prepared_code (((ProcBin*)binary_val(BIF_ARG_1))->val))) { BIF_ERROR(BIF_P, BADARG); } if (!erts_try_seize_code_write_permission(BIF_P)) { ERTS_BIF_YIELD3(bif_export[BIF_code_make_stub_module_3], BIF_P, BIF_ARG_1, BIF_ARG_2, BIF_ARG_3); } erts_smp_proc_unlock(BIF_P, ERTS_PROC_LOCK_MAIN); erts_smp_thr_progress_block(); modp = erts_get_module(mod, erts_active_code_ix()); if (modp && modp->curr.num_breakpoints > 0) { ASSERT(modp->curr.code_hdr != NULL); erts_clear_module_break(modp); ASSERT(modp->curr.num_breakpoints == 0); } erts_start_staging_code_ix(1); res = erts_make_stub_module(BIF_P, BIF_ARG_1, BIF_ARG_2, BIF_ARG_3); if (res == mod) { erts_end_staging_code_ix(); erts_commit_staging_code_ix(); if (!modp) modp = erts_get_module(mod, erts_active_code_ix()); hipe_redirect_to_module(modp); } else { erts_abort_staging_code_ix(); } erts_smp_thr_progress_unblock(); erts_smp_proc_lock(BIF_P, ERTS_PROC_LOCK_MAIN); erts_release_code_write_permission(); return res; #endif }
BIF_RETTYPE code_make_stub_module_3(BIF_ALIST_3) { Eterm res; erts_smp_proc_unlock(BIF_P, ERTS_PROC_LOCK_MAIN); erts_smp_block_system(0); erts_export_consolidate(); res = erts_make_stub_module(BIF_P, BIF_ARG_1, BIF_ARG_2, BIF_ARG_3); erts_smp_release_system(); erts_smp_proc_lock(BIF_P, ERTS_PROC_LOCK_MAIN); return res; }
Eterm check_process_code_2(BIF_ALIST_2) { Process* rp; Module* modp; if (is_not_atom(BIF_ARG_2)) { goto error; } if (is_internal_pid(BIF_ARG_1)) { Eterm res; if (internal_pid_index(BIF_ARG_1) >= erts_max_processes) goto error; modp = erts_get_module(BIF_ARG_2); if (modp == NULL) { /* Doesn't exist. */ return am_false; } else if (modp->old_code == NULL) { /* No old code. */ return am_false; } #ifdef ERTS_SMP rp = erts_pid2proc_suspend(BIF_P, ERTS_PROC_LOCK_MAIN, BIF_ARG_1, ERTS_PROC_LOCK_MAIN); #else rp = erts_pid2proc(BIF_P, 0, BIF_ARG_1, 0); #endif if (!rp) { BIF_RET(am_false); } if (rp == ERTS_PROC_LOCK_BUSY) { ERTS_BIF_YIELD2(bif_export[BIF_check_process_code_2], BIF_P, BIF_ARG_1, BIF_ARG_2); } res = check_process_code(rp, modp); #ifdef ERTS_SMP if (BIF_P != rp) { erts_resume(rp, ERTS_PROC_LOCK_MAIN); erts_smp_proc_unlock(rp, ERTS_PROC_LOCK_MAIN); } #endif BIF_RET(res); } else if (is_external_pid(BIF_ARG_1) && external_pid_dist_entry(BIF_ARG_1) == erts_this_dist_entry) { BIF_RET(am_false); } error: BIF_ERROR(BIF_P, BADARG); }
static void send_reply(ErtsMsAcc *msacc, ErtsMSAccReq *msaccrp) { ErtsSchedulerData *esdp = erts_get_scheduler_data(); Process *rp = msaccrp->proc; ErtsMessage *msgp = NULL; Eterm **hpp, *hp; Eterm ref_copy = NIL, msg; Uint sz, *szp; ErlOffHeap *ohp = NULL; ErtsProcLocks rp_locks = (esdp && msaccrp->req_sched == esdp->no ? ERTS_PROC_LOCK_MAIN : 0); sz = 0; hpp = NULL; szp = &sz; if (msacc->unmanaged) erts_mtx_lock(&msacc->mtx); while (1) { if (hpp) ref_copy = STORE_NC(hpp, ohp, msaccrp->ref); else *szp += REF_THING_SIZE; if (msaccrp->action != ERTS_MSACC_GATHER) msg = ref_copy; else { msg = erts_msacc_gather_stats(msacc, hpp, szp); msg = erts_bld_tuple(hpp, szp, 2, ref_copy, msg); } if (hpp) break; msgp = erts_alloc_message_heap(rp, &rp_locks, sz, &hp, &ohp); hpp = &hp; szp = NULL; } if (msacc->unmanaged) erts_mtx_unlock(&msacc->mtx); erts_queue_message(rp, rp_locks, msgp, msg, am_system); if (esdp && msaccrp->req_sched == esdp->no) rp_locks &= ~ERTS_PROC_LOCK_MAIN; if (rp_locks) erts_smp_proc_unlock(rp, rp_locks); }
BIF_RETTYPE port_close_1(BIF_ALIST_1) { Port* p; erts_smp_proc_unlock(BIF_P, ERTS_PROC_LOCK_MAIN); p = id_or_name2port(NULL, BIF_ARG_1); if (!p) { erts_smp_proc_lock(BIF_P, ERTS_PROC_LOCK_MAIN); BIF_ERROR(BIF_P, BADARG); } erts_do_exit_port(p, p->connected, am_normal); /* if !ERTS_SMP: since we terminate port with reason normal we SHOULD never get an exit signal ourselves */ erts_port_release(p); erts_smp_proc_lock(BIF_P, ERTS_PROC_LOCK_MAIN); BIF_RET(am_true); }
void erts_release_code_write_permission(void) { erts_smp_mtx_lock(&the_code_ix_queue_lock); while (the_code_ix_queue != NULL) { /* unleash the entire herd */ struct code_ix_queue_item* qitem = the_code_ix_queue; erts_smp_proc_lock(qitem->p, ERTS_PROC_LOCK_STATUS); if (!ERTS_PROC_IS_EXITING(qitem->p)) { erts_resume(qitem->p, ERTS_PROC_LOCK_STATUS); } erts_smp_proc_unlock(qitem->p, ERTS_PROC_LOCK_STATUS); the_code_ix_queue = qitem->next; erts_smp_proc_dec_refc(qitem->p); erts_free(ERTS_ALC_T_CODE_IX_LOCK_Q, qitem); } the_code_ix_lock = 0; erts_smp_mtx_unlock(&the_code_ix_queue_lock); }
BIF_RETTYPE port_connect_2(BIF_ALIST_2) { Port* prt; Process* rp; Eterm pid = BIF_ARG_2; if (is_not_internal_pid(pid)) { error: BIF_ERROR(BIF_P, BADARG); } prt = id_or_name2port(BIF_P, BIF_ARG_1); if (!prt) { goto error; } rp = erts_pid2proc(BIF_P, ERTS_PROC_LOCK_MAIN, pid, ERTS_PROC_LOCK_LINK); if (!rp) { erts_smp_port_unlock(prt); ERTS_SMP_ASSERT_IS_NOT_EXITING(BIF_P); goto error; } erts_add_link(&(rp->nlinks), LINK_PID, prt->id); erts_add_link(&(prt->nlinks), LINK_PID, pid); erts_smp_proc_unlock(rp, ERTS_PROC_LOCK_LINK); prt->connected = pid; /* internal pid */ erts_smp_port_unlock(prt); #ifdef USE_VM_PROBES if (DTRACE_ENABLED(port_connect)) { DTRACE_CHARBUF(process_str, DTRACE_TERM_BUF_SIZE); DTRACE_CHARBUF(port_str, DTRACE_TERM_BUF_SIZE); DTRACE_CHARBUF(newprocess_str, DTRACE_TERM_BUF_SIZE); dtrace_pid_str(prt->connected, process_str); erts_snprintf(port_str, sizeof(port_str), "%T", prt->id); dtrace_proc_str(rp, newprocess_str); DTRACE4(port_connect, process_str, port_str, prt->name, newprocess_str); } #endif BIF_RET(am_true); }
static void signal_notify_requested(Eterm type) { Process* p = NULL; Eterm msg, *hp; ErtsProcLocks locks = 0; ErlOffHeap *ohp; Eterm id = erts_whereis_name_to_id(NULL, am_erl_signal_server); if ((p = (erts_pid2proc_opt(NULL, 0, id, 0, ERTS_P2P_FLG_INC_REFC))) != NULL) { ErtsMessage *msgp = erts_alloc_message_heap(p, &locks, 3, &hp, &ohp); /* erl_signal_server ! {notify, sighup} */ msg = TUPLE2(hp, am_notify, type); erts_queue_message(p, locks, msgp, msg, am_system); if (locks) erts_smp_proc_unlock(p, locks); erts_proc_dec_refc(p); } }
void erts_release_code_write_permission(void) { erts_smp_mtx_lock(&code_write_permission_mtx); ERTS_SMP_LC_ASSERT(erts_has_code_write_permission()); while (code_write_queue != NULL) { /* unleash the entire herd */ struct code_write_queue_item* qitem = code_write_queue; erts_smp_proc_lock(qitem->p, ERTS_PROC_LOCK_STATUS); if (!ERTS_PROC_IS_EXITING(qitem->p)) { erts_resume(qitem->p, ERTS_PROC_LOCK_STATUS); } erts_smp_proc_unlock(qitem->p, ERTS_PROC_LOCK_STATUS); code_write_queue = qitem->next; erts_proc_dec_refc(qitem->p); erts_free(ERTS_ALC_T_CODE_IX_LOCK_Q, qitem); } code_writing_process = NULL; #ifdef ERTS_ENABLE_LOCK_CHECK erts_tsd_set(has_code_write_permission, (void *) 0); #endif erts_smp_mtx_unlock(&code_write_permission_mtx); }
static void erl_first_process_otp(char* modname, void* code, unsigned size, int argc, char** argv) { int i; Eterm start_mod; Eterm args; Eterm* hp; Process parent; ErlSpawnOpts so; Eterm env; start_mod = am_atom_put(modname, sys_strlen(modname)); if (erts_find_function(start_mod, am_start, 2, erts_active_code_ix()) == NULL) { erl_exit(5, "No function %s:start/2\n", modname); } /* * We need a dummy parent process to be able to call erl_create_process(). */ erts_init_empty_process(&parent); erts_smp_proc_lock(&parent, ERTS_PROC_LOCK_MAIN); hp = HAlloc(&parent, argc*2 + 4); args = NIL; for (i = argc-1; i >= 0; i--) { int len = sys_strlen(argv[i]); args = CONS(hp, new_binary(&parent, (byte*)argv[i], len), args); hp += 2; } env = new_binary(&parent, code, size); args = CONS(hp, args, NIL); hp += 2; args = CONS(hp, env, args); so.flags = 0; (void) erl_create_process(&parent, start_mod, am_start, args, &so); erts_smp_proc_unlock(&parent, ERTS_PROC_LOCK_MAIN); erts_cleanup_empty_process(&parent); }
BIF_RETTYPE purge_module_1(BIF_ALIST_1) { int purge_res; if (is_not_atom(BIF_ARG_1)) { BIF_ERROR(BIF_P, BADARG); } erts_smp_proc_unlock(BIF_P, ERTS_PROC_LOCK_MAIN); erts_smp_block_system(0); erts_export_consolidate(); purge_res = purge_module(atom_val(BIF_ARG_1)); erts_smp_release_system(); erts_smp_proc_lock(BIF_P, ERTS_PROC_LOCK_MAIN); if (purge_res < 0) { BIF_ERROR(BIF_P, BADARG); } BIF_RET(am_true); }
static ERTS_INLINE void reg_safe_write_lock(Process *c_p, ErtsProcLocks *c_p_locks) { if (*c_p_locks) { ASSERT(c_p); ASSERT(c_p_locks); ASSERT(*c_p_locks); if (reg_try_write_lock() != EBUSY) { #ifdef ERTS_ENABLE_LOCK_CHECK erts_proc_lc_might_unlock(c_p, *c_p_locks); #endif return; } /* Release process locks in order to avoid deadlock */ erts_smp_proc_unlock(c_p, *c_p_locks); *c_p_locks = 0; } reg_write_lock(); }
static void send_reply(ErtsMsAcc *msacc, ErtsMSAccReq *msaccrp) { ErtsSchedulerData *esdp = erts_get_scheduler_data(); Process *rp = msaccrp->proc; ErtsMessage *msgp = NULL; Eterm *hp; Eterm ref_copy = NIL, msg; ErtsProcLocks rp_locks = (esdp && msaccrp->req_sched == esdp->no ? ERTS_PROC_LOCK_MAIN : 0); ErtsHeapFactory factory; if (msaccrp->action == ERTS_MSACC_GATHER) { msgp = erts_factory_message_create(&factory, rp, &rp_locks, DEFAULT_MSACC_MSG_SIZE); if (msacc->unmanaged) erts_mtx_lock(&msacc->mtx); hp = erts_produce_heap(&factory, REF_THING_SIZE + 3 /* tuple */, 0); ref_copy = STORE_NC(&hp, &msgp->hfrag.off_heap, msaccrp->ref); msg = erts_msacc_gather_stats(msacc, &factory); msg = TUPLE2(hp, ref_copy, msg); if (msacc->unmanaged) erts_mtx_unlock(&msacc->mtx); erts_factory_close(&factory); } else { ErlOffHeap *ohp = NULL; msgp = erts_alloc_message_heap(rp, &rp_locks, REF_THING_SIZE, &hp, &ohp); msg = STORE_NC(&hp, &msgp->hfrag.off_heap, msaccrp->ref); } erts_queue_message(rp, rp_locks, msgp, msg, am_system); if (esdp && msaccrp->req_sched == esdp->no) rp_locks &= ~ERTS_PROC_LOCK_MAIN; if (rp_locks) erts_smp_proc_unlock(rp, rp_locks); }
Eterm check_process_code_2(BIF_ALIST_2) { Process* rp; Module* modp; if (is_not_atom(BIF_ARG_2)) { goto error; } if (is_internal_pid(BIF_ARG_1)) { Eterm res; if (internal_pid_index(BIF_ARG_1) >= erts_max_processes) goto error; rp = erts_pid2proc_not_running(BIF_P, ERTS_PROC_LOCK_MAIN, BIF_ARG_1, ERTS_PROC_LOCK_MAIN); if (!rp) { BIF_RET(am_false); } if (rp == ERTS_PROC_LOCK_BUSY) { ERTS_BIF_YIELD2(bif_export[BIF_check_process_code_2], BIF_P, BIF_ARG_1, BIF_ARG_2); } modp = erts_get_module(BIF_ARG_2); res = check_process_code(rp, modp); #ifdef ERTS_SMP if (BIF_P != rp) erts_smp_proc_unlock(rp, ERTS_PROC_LOCK_MAIN); #endif BIF_RET(res); } else if (is_external_pid(BIF_ARG_1) && external_pid_dist_entry(BIF_ARG_1) == erts_this_dist_entry) { BIF_RET(am_false); } error: BIF_ERROR(BIF_P, BADARG); }
BIF_RETTYPE delete_module_1(BIF_ALIST_1) { int res; if (is_not_atom(BIF_ARG_1)) goto badarg; erts_smp_proc_unlock(BIF_P, ERTS_PROC_LOCK_MAIN); erts_smp_block_system(0); { Module *modp = erts_get_module(BIF_ARG_1); if (!modp) { res = am_undefined; } else if (modp->old_code != 0) { erts_dsprintf_buf_t *dsbufp = erts_create_logger_dsbuf(); erts_dsprintf(dsbufp, "Module %T must be purged before loading\n", BIF_ARG_1); erts_send_error_to_logger(BIF_P->group_leader, dsbufp); res = am_badarg; } else { delete_export_references(BIF_ARG_1); delete_code(BIF_P, 0, modp); res = am_true; } } erts_smp_release_system(); erts_smp_proc_lock(BIF_P, ERTS_PROC_LOCK_MAIN); if (res == am_badarg) { badarg: BIF_ERROR(BIF_P, BADARG); } BIF_RET(res); }
BIF_RETTYPE code_make_stub_module_3(BIF_ALIST_3) { Module* modp; Eterm res; if (!erts_try_seize_code_write_permission(BIF_P)) { ERTS_BIF_YIELD3(bif_export[BIF_code_make_stub_module_3], BIF_P, BIF_ARG_1, BIF_ARG_2, BIF_ARG_3); } erts_smp_proc_unlock(BIF_P, ERTS_PROC_LOCK_MAIN); erts_smp_thr_progress_block(); modp = erts_get_module(BIF_ARG_1, erts_active_code_ix()); if (modp && modp->curr.num_breakpoints > 0) { ASSERT(modp->curr.code_hdr != NULL); erts_clear_module_break(modp); ASSERT(modp->curr.num_breakpoints == 0); } erts_start_staging_code_ix(1); res = erts_make_stub_module(BIF_P, BIF_ARG_1, BIF_ARG_2, BIF_ARG_3); if (res == BIF_ARG_1) { erts_end_staging_code_ix(); erts_commit_staging_code_ix(); } else { erts_abort_staging_code_ix(); } erts_smp_thr_progress_unblock(); erts_smp_proc_lock(BIF_P, ERTS_PROC_LOCK_MAIN); erts_release_code_write_permission(); return res; }
BIF_RETTYPE erts_internal_check_dirty_process_code_2(BIF_ALIST_2) { #if !defined(ERTS_DIRTY_SCHEDULERS) BIF_ERROR(BIF_P, EXC_NOTSUP); #else Process *rp; int reds = 0; Eterm res; if (BIF_P != erts_dirty_process_code_checker) BIF_ERROR(BIF_P, EXC_NOTSUP); if (is_not_internal_pid(BIF_ARG_1)) BIF_ERROR(BIF_P, BADARG); if (is_not_atom(BIF_ARG_2)) BIF_ERROR(BIF_P, BADARG); rp = erts_pid2proc_not_running(BIF_P, ERTS_PROC_LOCK_MAIN, BIF_ARG_1, ERTS_PROC_LOCK_MAIN); if (rp == ERTS_PROC_LOCK_BUSY) ERTS_BIF_YIELD2(bif_export[BIF_erts_internal_check_dirty_process_code_2], BIF_P, BIF_ARG_1, BIF_ARG_2); if (!rp) BIF_RET(am_false); res = erts_check_process_code(rp, BIF_ARG_2, &reds, BIF_P->fcalls); if (BIF_P != rp) erts_smp_proc_unlock(rp, ERTS_PROC_LOCK_MAIN); ASSERT(is_value(res)); BIF_RET2(res, reds); #endif }