Пример #1
0
term_t cbif_monitor2(proc_t *proc, term_t *regs)
{
	term_t Type = regs[0];
	term_t Item = regs[1];

	if (Type != A_PROCESS)
		badarg(Type);
	if (!is_short_pid(Item) && !is_atom(Item))
		badarg(Item);

	term_t ref = heap_make_ref(&proc->hp);

	proc_t *target = (is_short_pid(Item))
		?scheduler_lookup(Item)
		:scheduler_process_by_name(Item);
	if (target == 0)
	{
		// the process is gone already - send notification immediately

		//	{'DOWN',#Ref<0.0.0.38>,process,<0.34.0>,noproc}
		term_t msg = heap_tuple5(&proc->hp, ADOWN__, ref, A_PROCESS, Item, A_NOPROC);
		int x = scheduler_new_local_mail_N(proc, msg);
		if (x < 0)
			fail(A_NO_MEMORY);
	}
	else
	{
		uint64_t ref_id = local_ref_id(ref);
		if (monitor(ref_id, proc->pid, target->pid) < 0)
			fail(A_NO_MEMORY);
	}

	return ref;
}
Пример #2
0
static int erlang_fire(etimer_t *tm)
{
	proc_t *to_proc = (is_atom(tm->dst))
		?scheduler_process_by_name(tm->dst)
		:scheduler_lookup(tm->dst);

	int rc = 0;
	if (to_proc != 0)
	{
		term_t marsh_msg = tm->msg;
		if (tm->sender != to_proc)	// tm->sender may be zero
		{
			rc = heap_copy_terms_N(&to_proc->hp, &marsh_msg, 1);
			if (rc < 0)
				goto error;
		}

		term_t env_msg = marsh_msg;	// {timeout,TRef,Msg} or Msg
		if (tm->enveloped)
		{
			term_t tref = heap_remake_local_ref_N(&to_proc->hp, tm->ref_id);
			if (tref == noval)
			{
				rc = -NO_MEMORY;
				goto error;
			}

			uint32_t *htop = heap_alloc_N(&to_proc->hp, 1 +3);
			if (htop == 0)
			{
				rc = -NO_MEMORY;
				goto error;
			}
			heap_set_top(&to_proc->hp, htop +1 +3);
			env_msg = tag_tuple(htop);
			htop[0] = 3;
			htop[1] = A_TIMEOUT;
			htop[2] = tref;
			htop[3] = marsh_msg;
		}

		rc = scheduler_new_local_mail_N(to_proc, env_msg);
	}

error:
	if (tm->sender != 0)
	{
		assert(tm->sender->pending_timers > 0);
		tm->sender->pending_timers--;
		if (tm->sender->pending_timers == 0 &&
				tm->sender->my_queue == MY_QUEUE_PENDING_TIMERS)
			proc_destroy(tm->sender);	// destroy a zombie process
	}

	return rc;
}