Ejemplo n.º 1
0
// inet:getaddrs0/2 [4]
term_t bif_getaddrs0_2(term_t Addr, term_t Family, proc_t *proc)
{
	apr_status_t rs;
	apr_pool_t *tmp;
	apr_sockaddr_t *sa;
	const char *host;
	term_t addrs = nil;

	if (!is_binary(Addr) || !is_atom(Family))
		bif_bad_arg0();

	if (Family != A_INET)
		bif_exception(A_NOT_SUPPORTED);

	host = (const char *)peel(Addr)->binary.data;	//null-terminated by caller

	apr_pool_create(&tmp, 0);
	rs = apr_sockaddr_info_get(&sa, host, APR_INET, 0, 0, tmp);
	if (rs == 0)
	{
		term_t first = nil;
		term_t last = nil;

		while (sa)
		{
			struct in_addr ia = *(struct in_addr *)sa->ipaddr_ptr;
			apr_byte_t qs[4];
			term_t ip;

#if APR_IS_BIGENDIAN
			PUT32(qs, ia.s_addr);
#else
			PUT32_LE(qs, ia.s_addr);
#endif

			ip = heap_tuple4(proc->heap,
				tag_int(qs[0]),
				tag_int(qs[1]),
				tag_int(qs[2]),
				tag_int(qs[3]));

			cons_up(first, last, ip, proc->heap);

			sa = sa->next;
		}

		addrs = first;
	}

	apr_pool_destroy(tmp);

	if (rs != 0)
		bif_exception(decipher_status(rs));

	return addrs;
}
Ejemplo n.º 2
0
static void disk_async(proc_t *caller,
			term_t reply, term_t oid, uint16_t tag, term_t result)
{
	//
	// no need to marshal: reply is always an atom, result is either an atom or
	// a binary allocated on the caller's heap
	//
 
	uint32_t *p = heap_alloc_N(&caller->hp, 1 +4);
	if (p == 0)
		goto nomem;
	heap_set_top(&caller->hp, p +1 +4);
	p[0] = 4;
	p[1] = reply;
	p[2] = oid;
	p[3] = tag_int(tag);
	p[4] = result;
	term_t msg = tag_tuple(p);

	int x = scheduler_new_local_mail_N(caller, msg);
	if (x < 0)
		scheduler_signal_exit_N(caller, oid, err_to_term(x));

	return;
nomem:
	scheduler_signal_exit_N(caller, oid, A_NO_MEMORY);
}
Ejemplo n.º 3
0
term_t cbif_experimental2(proc_t *proc, term_t *regs)
{
	term_t What = regs[0];
	UNUSED term_t Arg = regs[1];
	if (!is_atom(What))
		badarg(What);
	
	switch (What)
	{
	// Cloudozer's 2nd anniversary -- remove in 2016
	case A_CLOUDOZER:
		if (Arg == tag_int(2))
			cloudozer2();
		break;
	// Cloudozer's 2nd anniversary
	case A_MODULE_SIZE:
#ifdef EXP_RUNTIME_METRICS
		print_loaded_module_sizes();
#endif // EXP_RUNTIME_METRICS
		break;
	case A_VARIANT_SIZE:
#ifdef EXP_RUNTIME_METRICS
		print_variant_code_sizes();
#endif // EXP_RUNTIME_METRICS
		break;
	case A_COUNT_IOPS:
#ifdef EXP_COUNT_IOPS
		print_iop_counters();
#endif // EXP_COUNT_IOPS
		break;
	case A_PROCESSING_DELAY:
#ifdef EXP_LINC_LATENCY
		if (Arg == A_HELP)
			printk("ping -Q 42 -q -n -c 25000 -f <ip>\n");
		else
			linc_display();
#endif // EXP_LINC_LATENCY
		break;
	case A_LLSTAT:
#ifdef EXP_LINC_LLSTAT
		if (is_int(Arg))
			llstat_restart(int_value(Arg));
		else if (Arg == A_STOP)
			llstat_stop();
		else
			llstat_display();
#endif // EXP_LINC_LLSTAT
		break;
	default:
		badarg(What);
	}

	return A_OK;
}
Ejemplo n.º 4
0
static void avail_send_slots(outlet_t *ol, term_t reply_to)
{
	assert(ol != 0);
	tube_t *tube = ol->tube;
	assert(tube != 0);
	int avail = (tube->accepting)
		?available_slots(&tube->page->rx)
		:available_slots(&tube->page->tx);
	assert(ol->slots_in_progress == 0);
	if (avail == 0)
	{
		ol->slots_in_progress = 1;
		ol->slots_reply_to = reply_to;
	}
	else
		slots_reply(ol->oid, reply_to, tag_int(avail));
}
Ejemplo n.º 5
0
Archivo: tube.c Proyecto: EarlGray/ling
static void tube_send_int(uint32_t port, void *data)
{
	// peer read packets - slots available for sending
	outlet_t *ol = (outlet_t *)data;
	assert(ol != 0);
	tube_t *tube = ol->tube;
	assert(tube != 0);
	if (ol->slots_in_progress)
	{
		int avail = (tube->accepting)
			?available_slots(&tube->page->rx)
			:available_slots(&tube->page->tx);
		if (avail > 0)
		{
			ol->slots_in_progress = 0;
			slots_reply(ol->oid, ol->slots_reply_to, tag_int(avail));
		}
	}
}
Ejemplo n.º 6
0
value& value::operator=(int32_t val)
{
    if(!tag_)
        set(tag_int(val));
    else switch(tag_->get_type())
    {
    case tag_type::Int:
        static_cast<tag_int&>(*tag_).set(val);
        break;
    case tag_type::Long:
        static_cast<tag_long&>(*tag_).set(val);
        break;
    case tag_type::Float:
        static_cast<tag_float&>(*tag_).set(val);
        break;
    case tag_type::Double:
        static_cast<tag_double&>(*tag_).set(val);
        break;

    default:
        throw std::bad_cast();
    }
    return *this;
}
Ejemplo n.º 7
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);
}
value_initializer::value_initializer(int32_t val)           : value(tag_int(val)) {}
Ejemplo n.º 9
0
tag_value& tag_value::operator=(std::int32_t x) {
  *this = tag_int(x);
  return *this;
}
Ejemplo n.º 10
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
	}
}
Ejemplo n.º 11
0
int code_base_load(code_base_t *self, named_tuples_t *nm_tuples,
	term_t module, term_t exports, term_t fun_table, term_t attrs, term_t preloaded, term_t misc)
{
	module_t *m;
	apr_pool_t *pool;
	
	apr_pool_create(&pool, 0);
	m = apr_palloc(pool, sizeof(*m));
	m->mod_pool = pool;
	m->literals = heap_make(pool);
	m->key.module = module;
	m->key.is_old = 0;
	m->code_size = 0;
	m->code = 0;
	m->exports = apr_hash_make(pool);
	m->nfuns = 0;
	m->funs = 0;
	m->files = 0;
	m->source = 0;

	if (preloaded != nil)
	{
		int i;
		int n = list_length(preloaded);
		term_t cons = preloaded;
		int ok = 1;
		m->code = apr_palloc(pool, n*sizeof(codel_t));
		m->code_size = n;
		i = 0;
		while (ok && is_cons(cons))
		{
			term_box_t *cbox = peel(cons);
			if (is_int(cbox->cons.head))
			{
				m->code[i].i = int_value(cbox->cons.head);
			}
			else if (is_tuple(cbox->cons.head))
			{
				term_box_t *tbox = peel(cbox->cons.head);
				if (tbox->tuple.size == 2)
				{
					term_t selector = tbox->tuple.elts[0];
					term_t value = tbox->tuple.elts[1];
					switch (selector)
					{
					case AT__:		// {'@',Offset}
						m->code[i].l = m->code + int_value(value);
						break;
					case A_T:		// {t,Literal}
						m->code[i].t = heap_marshal(value, m->literals);
						break;
					case A_B:
						m->code[i].bif = builtins[int_value(value)].entry;
						break;
					case A_N:		// {n,{N,F}}
						if (is_tuple(value))
						{
							term_box_t *vb = peel(value);
							if (vb->tuple.size == 2)
							{
								term_t name = vb->tuple.elts[0];
								term_t field = vb->tuple.elts[1];
								int index = named_tuples_set(nm_tuples, name, field);
								m->code[i].t = tag_int(index);
							}
							else
								ok = 0;
						}
						else
							ok = 0;
						break;
					default:
						ok = 0;
					}
				}
			}
			else if (is_bignum(cbox->cons.head))
			{
				mp_int mp = bignum_to_mp(cbox->cons.head);
                m->code[i].i = mp_get_int(&mp);
			}
			else
				ok = 0;

			i++;
			cons = cbox->cons.tail;
		}

		if (!ok)
		{
			apr_pool_destroy(pool);
			return 1;
		}
	}

	// misc:
	// source line info:
	// {file,Files}
	// {source,[{F,L,S,E}]}

	if (misc != nil)
	{
		term_t cons = misc;
		while (is_cons(cons))
		{
			term_box_t *cb = peel(cons);
			term_t t = cb->cons.head;
			if (is_tuple(t))
			{
				term_box_t *tb = peel(t);
				if (tb->tuple.size >= 2)
				{
					term_t selector = tb->tuple.elts[0];
					term_t info = tb->tuple.elts[1];
					switch (selector)
					{
					case A_FILES:
						m->files = source_files_names(info, pool);
						break;
					case A_SOURCE:
						m->source = source_line_blocks(info, pool);
						break;
					}
				}
			}
			cons = cb->cons.tail;
		}
	}

	if (fun_table != nil)
	{
		int i;
		int nfuns = list_length(fun_table);
		term_t cons = fun_table;
		int ok = 1;
		m->funs = apr_palloc(pool, nfuns*sizeof(fun_slot_t));
		m->nfuns = nfuns;
		for (i = 0; ok && i < nfuns; i++)
		{
			term_box_t *cbox = peel(cons);
			if (is_tuple(cbox->cons.head))
			{
				term_box_t *tbox = peel(cbox->cons.head);
				if (tbox->tuple.size == 2)
				{
					term_t uniq = tbox->tuple.elts[0];
					term_t offset = tbox->tuple.elts[1];
					if ((is_int(uniq) || is_bignum(uniq)) && is_int(offset))
					{
						fun_slot_t *slot = &m->funs[i];
						if (is_int(uniq))
							slot->uniq = int_value(uniq);
						else
						{
							mp_int mp = bignum_to_mp(uniq);
							slot->uniq = (uint)mp_get_int(&mp);
						}
						slot->entry = m->code + int_value(offset);
					}
					else
						ok = 0;

				}
				else
					ok = 0;
			}
			else
				ok = 0;

			cons = cbox->cons.tail;
		}

		if (!ok)
		{
			apr_pool_destroy(pool);
			return 1;
		}
	}

	//TODO: attrs ingnored

	if (exports != nil)
	{
		int ok = 1;
		term_t cons = exports;
		while (ok && is_cons(cons))
		{
			term_box_t *cbox = peel(cons);
			// {Function,Arity,Offset}
			if (is_tuple(cbox->cons.head))
			{
				term_box_t *tbox = peel(cbox->cons.head);
				if (tbox->tuple.size == 3)
				{
					term_t function = tbox->tuple.elts[0];
					term_t arity = tbox->tuple.elts[1];
					term_t offset = tbox->tuple.elts[2];
					if (is_atom(function) && is_int(arity) && is_int(offset))
					{
						export_t *exp = apr_palloc(pool, sizeof(*exp));
						exp->key.function = function;
						exp->key.arity = int_value(arity);
						exp->entry = m->code + int_value(offset);
						apr_hash_set(m->exports, &exp->key, sizeof(exp->key), exp);
					}
					else
						ok = 0;
				}
				else
					ok = 0;
			}
			else
				ok = 0;

			cons = cbox->cons.tail;
		}

		if (!ok)
		{
			apr_pool_destroy(pool);
			return 1;
		}
	}

	apr_hash_set(self->modules, &m->key, sizeof(m->key), m);
	return 0;
}