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); } }
static int dirty_send_message(Process *c_p, Eterm to, Eterm tag) { ErtsProcLocks c_p_locks, rp_locks; Process *rp, *real_c_p; Eterm msg, *hp; ErlOffHeap *ohp; ErtsMessage *mp; ASSERT(is_immed(tag)); real_c_p = erts_proc_shadow2real(c_p); if (real_c_p != c_p) c_p_locks = 0; else c_p_locks = ERTS_PROC_LOCK_MAIN; ASSERT(real_c_p->common.id == c_p->common.id); rp = erts_pid2proc_opt(real_c_p, c_p_locks, to, 0, ERTS_P2P_FLG_INC_REFC); if (!rp) return 0; rp_locks = 0; mp = erts_alloc_message_heap(rp, &rp_locks, 3, &hp, &ohp); msg = TUPLE2(hp, tag, c_p->common.id); erts_queue_message(rp, rp_locks, mp, msg, c_p->common.id); if (rp == real_c_p) rp_locks &= ~c_p_locks; if (rp_locks) erts_proc_unlock(rp, rp_locks); erts_proc_dec_refc(rp); return 1; }
int enif_send(ErlNifEnv* env, const ErlNifPid* to_pid, ErlNifEnv* msg_env, ERL_NIF_TERM msg) { struct enif_msg_environment_t* menv = (struct enif_msg_environment_t*)msg_env; ErtsProcLocks rp_locks = 0; Process* rp; Process* c_p; ErlHeapFragment* frags; #if defined(ERTS_ENABLE_LOCK_CHECK) && defined(ERTS_SMP) ErtsProcLocks rp_had_locks; #endif Eterm receiver = to_pid->pid; int flush_me = 0; if (env != NULL) { c_p = env->proc; if (receiver == c_p->id) { rp_locks = ERTS_PROC_LOCK_MAIN; flush_me = 1; } } else { #ifdef ERTS_SMP c_p = NULL; #else erl_exit(ERTS_ABORT_EXIT,"enif_send: env==NULL on non-SMP VM"); #endif } #if defined(ERTS_ENABLE_LOCK_CHECK) && defined(ERTS_SMP) rp_had_locks = rp_locks; #endif rp = erts_pid2proc_opt(c_p, ERTS_PROC_LOCK_MAIN, receiver, rp_locks, ERTS_P2P_FLG_SMP_INC_REFC); if (rp == NULL) { ASSERT(env == NULL || receiver != c_p->id); return 0; } flush_env(msg_env); frags = menv->env.heap_frag; ASSERT(frags == MBUF(&menv->phony_proc)); if (frags != NULL) { /* Move all offheap's from phony proc to the first fragment. Quick and dirty, but erts_move_msg_mbuf_to_heap doesn't care. */ ASSERT(!is_offheap(&frags->off_heap)); frags->off_heap = MSO(&menv->phony_proc); clear_offheap(&MSO(&menv->phony_proc)); menv->env.heap_frag = NULL; MBUF(&menv->phony_proc) = NULL; } ASSERT(!is_offheap(&MSO(&menv->phony_proc))); if (flush_me) { flush_env(env); /* Needed for ERTS_HOLE_CHECK */ } erts_queue_message(rp, &rp_locks, frags, msg, am_undefined); if (rp_locks) { ERTS_SMP_LC_ASSERT(rp_locks == (rp_had_locks | (ERTS_PROC_LOCK_MSGQ | ERTS_PROC_LOCK_STATUS))); erts_smp_proc_unlock(rp, (ERTS_PROC_LOCK_MSGQ | ERTS_PROC_LOCK_STATUS)); } erts_smp_proc_dec_refc(rp); if (flush_me) { cache_env(env); } return 1; }