Beispiel #1
0
term_t cbif_process_info2(proc_t *proc, term_t *regs)
{
	term_t Pid = regs[0];
	term_t What = regs[1];

	if (!is_short_pid(Pid))
		badarg(Pid);
	if (!is_atom(What))
		badarg(What);

	proc_t *probe = scheduler_lookup(Pid);
	if (probe == 0)
		return A_UNDEFINED;

	term_t val;
	if (What == A_BACKTRACE)
	{
		//TODO: current stack trace is not enough
		val = A_UNDEFINED;
	}
	else if (What == A_BINARY)
	{
		//NB: BinInfo is documented to be a list, yet its contents is unspesfied
		val = int_to_term(probe->hp.total_pb_size, &probe->hp);
	}
	else if (What == A_CATCHLEVEL)
	{
		assert(fits_int(probe->catch_level));
		val = tag_int(probe->catch_level);
	}
	else if (What == A_CURRENT_FUNCTION)
	{
		// NB: probe->cap.ip is valid even if proc == probe
		uint32_t *fi = backstep_to_func_info(probe->cap.ip);
		val = heap_tuple3(&proc->hp, fi[1], fi[2], tag_int(fi[3]));
	}
	else if (What == A_CURRENT_LOCATION)
	{
		// NB: probe->cap.ip is valid even if proc == probe
		uint32_t *fi = backstep_to_func_info(probe->cap.ip);
		term_t loc = nil;
		char fname[256];
		uint32_t line = code_base_source_line(probe->cap.ip, fname, sizeof(fname));
		if (line != 0)
		{
			term_t f = heap_strz(&proc->hp, fname);
			term_t t1 = heap_tuple2(&proc->hp, A_FILE, f);
			term_t t2 = heap_tuple2(&proc->hp, A_LINE, tag_int(line));
			loc = heap_cons(&proc->hp, t2, nil);
			loc = heap_cons(&proc->hp, t1, loc);
		}

		val = heap_tuple4(&proc->hp, fi[1], fi[2], tag_int(fi[3]), loc);
	}
	else if (What == A_CURRENT_STACKTRACE)
	{
		val = probe->stack_trace;
		if (probe != proc)
		{
			int x = heap_copy_terms_N(&proc->hp, &val, 1);
			if (x < 0)
				fail(err_to_term(x));
		}
	}
	else if (What == A_DICTIONARY)
	{
		val = probe->dictionary;
		if (probe != proc)
		{
			int x = heap_copy_terms_N(&proc->hp, &val, 1);
			if (x < 0)
				fail(err_to_term(x));
		}
	}
	else if (What == A_ERROR_HANDLER)
		val = A_ERROR_HANDLER;
	else if (What == A_GARBAGE_COLLECTION)
	{
		//TODO
		val = A_UNDEFINED;
	}
	else if (What == A_GROUP_LEADER)
		val = probe->group_leader;
	else if (What == A_HEAP_SIZE)
		val = int_to_term(probe->hp.total_size, &proc->hp);
	else if (What == A_INITIAL_CALL)
	{
		val = (probe->init_call_mod == noval)
				?A_UNDEFINED
				:heap_tuple3(&proc->hp, probe->init_call_mod,
										probe->init_call_func,
										tag_int(probe->init_call_arity));
	}
	else if (What == A_LINKS)
	{
		term_t ids = nil;
		plink_t *pl = probe->links.active;
		while (pl != 0)
		{
			ids = heap_cons(&proc->hp, pl->id, ids);
			pl = pl->next;
		}

		val = ids;
	}
	else if (What == A_LAST_CALLS)
	{
		//TODO
		val = A_FALSE;
	}
	else if (What == A_MEMORY)
	{
		int pages = 0;

		pages += probe->home_node->index;
		pages += probe->stack_node->index;
		memnode_t *node = probe->hp.nodes;
		while (node != 0)
		{
			pages += node->index;
			node = node->next;
		}
		node = probe->mailbox.nodes;
		while (node != 0)
		{
			pages += node->index;
			node = node->next;
		}
		node = probe->links.nodes;
		while (node != 0)
		{
			pages += node->index;
			node = node->next;
		}

		int bytes = pages * PAGE_SIZE;
		val = int_to_term(bytes, &proc->hp);
	}
	else if (What == A_MESSAGE_BINARY)
	{
		//TODO
		val = A_UNDEFINED;
	}
	else if (What == A_MESSAGE_QUEUE_LEN)
	{
		int len = msg_queue_len(&probe->mailbox);
		assert(fits_int(len));
		val = tag_int(len);
	}
	else if (What == A_MESSAGES)
	{
		int messages = nil;
		message_t *msg = probe->mailbox.head;
		while (msg != 0)
		{
			term_t marsh_body = msg->body;
			if (probe != proc)
			{
				int x = heap_copy_terms_N(&proc->hp, &marsh_body, 1);
				if (x < 0)
					fail(err_to_term(x));
			}
			messages = heap_cons(&proc->hp, marsh_body, messages);
			msg = msg->next;
		}

		val = list_rev(messages, &proc->hp);
	}
	else if (What == A_MIN_HEAP_SIZE)
		val = tag_int(INIT_HEAP_SIZE);
	else if (What == A_MIN_BIN_VHEAP_SIZE)
	{
		//TODO
		val = A_UNDEFINED;
	}
	else if (What == A_MONITORED_BY)
		val = list_monitored_by(probe->pid, &proc->hp);
	else if (What == A_MONITORS)
		val = list_monitors(probe->pid, &proc->hp);
	else if (What == A_PRIORITY)
		val = probe->priority;
	else if (What == A_REDUCTIONS)
		val = int_to_term(probe->total_reds, &proc->hp);
	else if (What == A_REGISTERED_NAME)
	{
		val = probe->name;
		if (val == noval)
			return nil;		// be backward compatible
	}
	else if (What == A_SEQUENTIAL_TRACE_TOKEN)
	{
		//TODO
		val = A_UNDEFINED;
	}
	else if (What == A_STACK_SIZE)
	{
		int ss = proc_stack_bottom(probe) - proc_stack_top(probe);
		assert(fits_int(ss));
		val = tag_int(ss);
	}
	else if (What == A_STATUS)
	{
		if (probe->my_queue == MY_QUEUE_NORMAL ||
			probe->my_queue == MY_QUEUE_HIGH ||
			probe->my_queue == MY_QUEUE_LOW)
				val = A_RUNNABLE;
		else if (probe->my_queue == MY_QUEUE_INF_WAIT ||
				 probe->my_queue == MY_QUEUE_TIMED_WAIT)
			val = A_WAITING;
		else
		{
			assert(probe->my_queue == MY_QUEUE_NONE);
			val = A_RUNNING;
		}
	}
	else if (What == A_SUSPENDING)
	{
		//TODO
		val = nil;
	}
	else if (What == A_TOTAL_HEAP_SIZE)
	{
		int ss = proc_stack_bottom(probe) - proc_stack_top(probe);
		int ths = probe->hp.total_size + ss;
		assert(fits_int(ths));
		val = tag_int(ths);
	}
	else if (What == A_TRACE)
	{
		//TODO
		val = A_UNDEFINED;
	}
	else if (What == A_TRAP_EXIT)
		val = probe->trap_exit;
	else
		badarg(What);

	return heap_tuple2(&proc->hp, What, val);
}
Beispiel #2
0
term_t bin2term(apr_byte_t **data, int *bytes_left, atoms_t *atoms, heap_t *heap)
{

#define require(__n) \
	do { \
		if (*bytes_left < __n) \
			return noval; \
		(*bytes_left) -= __n; \
	} while (0)

#define get_byte() (*(*data)++)

	require(1);
	switch (get_byte())
	{
	case 97:
	{
		require(1);
		return tag_int(get_byte());
	}
	case 98:
	{
		int a, b, c, d;
		require(4);
		a = get_byte();
		b = get_byte();
		c = get_byte();
		d = get_byte();
		return int_to_term((a << 24) | (b << 16) | (c << 8) | d, heap);
	}
	case 99:
	{
		double value;
		require(31);
		sscanf((const char *)*data, "%lf", &value);
		(*data) += 31;
		return heap_float(heap, value);
	}
	case 100:
	{
		int a, b;
		int len;
		cstr_t *s;
		int index;
		require(2);
		a = get_byte();
		b = get_byte();
		len = ((a << 8) | b);
		if (len > 255)
			return noval;
		require(len);
		s = (cstr_t *)heap_alloc(heap, sizeof(cstr_t) + len);
		s->size = len;
		memcpy(s->data, *data, len);
		index = atoms_set(atoms, s);
		(*data) += len;
		return tag_atom(index);
	}
	case 104:
	{
		int arity, i;
		term_t tuple;
		term_box_t *tbox;
		require(1);
		arity = get_byte();
		tuple = heap_tuple(heap, arity);
		tbox = peel(tuple);
		for (i = 0; i < arity; i++)
		{
			term_t e = bin2term(data, bytes_left, atoms, heap);
			if (e == noval)
				return noval;
			tbox->tuple.elts[i] = e;
		}
		return tuple;
	}
	case 105:
	{
		int a, b, c, d;
		int arity, i;
		term_t tuple;
		term_box_t *tbox;
		require(4);
		a = get_byte();
		b = get_byte();
		c = get_byte();
		d = get_byte();
		arity = ((a << 24) | (b << 16) | (c << 8) | d);
		tuple = heap_tuple(heap, arity);
		tbox = peel(tuple);
		for (i = 0; i < arity; i++)
		{
			term_t e = bin2term(data, bytes_left, atoms, heap);
			if (e == noval)
				return noval;
			tbox->tuple.elts[i] = e;
		}
		return tuple;
	}
	case 106:
	{
		return nil;
	}
	case 107:
	{
		int a, b;
		int len, i;
		term_t cons = nil;
		require(2);
		a = get_byte();
		b = get_byte();
		len = ((a << 8) | b);
		require(len);
		i = len-1;
		while (i >= 0)
			cons = heap_cons2(heap, tag_int((*data)[i--]), cons);
		(*data) += len;
		return cons;
	}
	case 108:
	{
		int a, b, c, d;
		int len, i;
		term_t *es;
		term_t tail;
		require(4);
		a = get_byte();
		b = get_byte();
		c = get_byte();
		d = get_byte();
		len = ((a << 24) | (b << 16) | (c << 8) | d);
		es = (term_t *)heap_alloc(heap, len*sizeof(term_t));
		for (i = 0; i < len; i++)
		{
			term_t e = bin2term(data, bytes_left, atoms, heap);
			if (e == noval)
				return noval;
			es[i] = e;
		}
		tail = bin2term(data, bytes_left, atoms, heap);
		if (tail == noval)
			return noval;
		i = len-1;
		while (i >= 0)
			tail = heap_cons2(heap, es[i--], tail);
		return tail;
	}
	case 109:
	{
		int a, b, c, d;
		int len;
		term_t bin;
		require(4);
		a = get_byte();
		b = get_byte();
		c = get_byte();
		d = get_byte();
		len = ((a << 24) | (b << 16) | (c << 8) | d);
		require(len);
		bin = heap_binary(heap, len*8, (*data));
		(*data) += len;
		return bin;
	}
	case 110:
	{
		int len;
		int sign;
		mp_size prec;
		mp_int mp;
		mp_err rs;
		require(1);
		len = get_byte();
		sign = get_byte();
		require(len);
		prec = (len + (MP_DIGIT_SIZE-1)) / MP_DIGIT_SIZE;
		mp_init_size(&mp, prec, heap);
		//TODO: use mp_read_signed_bin
		rs = mp_read_unsigned_bin_lsb(&mp, *data, len, heap);
		if (rs != MP_OKAY)
			return noval;
		(*data) += len;
		if (sign == 1)
			mp_neg(&mp, &mp, heap);
		return mp_to_term(mp);
	}
	case 111:
	{
		int a, b, c, d;
		int len;
		int sign;
		mp_size prec;
		mp_int mp;
		mp_err rs;
		require(4);
		a = get_byte();
		b = get_byte();
		c = get_byte();
		d = get_byte();
		len = ((a << 24) | (b << 16) | (c << 8) | d);
		require(1);
		sign = get_byte();
		require(len);
		prec = (len + (MP_DIGIT_SIZE-1)) / MP_DIGIT_SIZE;
		mp_init_size(&mp, prec, heap);
		rs = mp_read_unsigned_bin_lsb(&mp, *data, len, heap);
		if (rs != MP_OKAY)
			return noval;
		(*data) += len;
		if (sign == 1)
			mp_neg(&mp, &mp, heap);
		return mp_to_term(mp);
	}
	default:
		return noval;	// only a subset of tags are supported; inspired by BERT
	}
}