Ejemplo n.º 1
0
/*
 * erts_internal:port_connect/2 is used by the
 * erlang:port_connect/2 BIF.
 */
BIF_RETTYPE erts_internal_port_connect_2(BIF_ALIST_2)
{
    Eterm ref;
    Port* prt;

    prt = sig_lookup_port(BIF_P, BIF_ARG_1);
    if (!prt)
	BIF_RET(am_badarg);

#ifdef DEBUG
    ref = NIL;
#endif

    switch (erts_port_connect(BIF_P, 0, prt, BIF_P->common.id, BIF_ARG_2, &ref)) {
    case ERTS_PORT_OP_CALLER_EXIT:
    case ERTS_PORT_OP_BADARG:
    case ERTS_PORT_OP_DROPPED:
	BIF_RET(am_badarg);
    case ERTS_PORT_OP_SCHEDULED:
	ASSERT(is_internal_ordinary_ref(ref));
	BIF_RET(ref);
	break;
    case ERTS_PORT_OP_DONE:
	BIF_RET(am_true);
	break;
    default:
	ERTS_INTERNAL_ERROR("Unexpected erts_port_connect() result");
	BIF_RET(am_internal_error);
    }
}
Ejemplo n.º 2
0
/*
 * erts_internal:port_close/1 is used by the
 * erlang:port_close/1 BIF.
 */
BIF_RETTYPE erts_internal_port_close_1(BIF_ALIST_1)
{
    Eterm ref;
    Port *prt;

#ifdef DEBUG
    ref = NIL;
#endif

    prt = sig_lookup_port(BIF_P, BIF_ARG_1);
    if (!prt)
	BIF_RET(am_badarg);

    switch (erts_port_exit(BIF_P, 0, prt, BIF_P->common.id, am_normal, &ref)) {
    case ERTS_PORT_OP_BADARG:
    case ERTS_PORT_OP_DROPPED:
	BIF_RET(am_badarg);
    case ERTS_PORT_OP_SCHEDULED:
	ASSERT(is_internal_ordinary_ref(ref));
	BIF_RET(ref);
    case ERTS_PORT_OP_DONE:
	BIF_RET(am_true);
    default:
	ERTS_INTERNAL_ERROR("Unexpected erts_port_exit() result");
	BIF_RET(am_internal_error);
    }
}
Ejemplo n.º 3
0
void erts_add_monitor(ErtsMonitor **root, Uint type, Eterm ref, UWord entity, 
		      Eterm name)
{
    void *tstack[STACK_NEED];
    int tpos = 0;
    int dstack[STACK_NEED+1];
    int dpos = 1;
    int state = 0;
    ErtsMonitor **this = root;
    Sint c;

    ASSERT(is_internal_ordinary_ref(ref) || is_external_ref(ref));
  
    dstack[0] = DIR_END;
    for (;;) {
	if (!*this) { /* Found our place */
	    state = 1;
	    *this = create_monitor(type,ref,entity,name);
	    break;
	} else if ((c = CMP_MON_REF(ref,(*this)->ref)) < 0) { 
	    /* go left */
	    dstack[dpos++] = DIR_LEFT;
	    tstack[tpos++] = this;
	    this = &((*this)->left);
	} else if (c > 0) { /* go right */
	    dstack[dpos++] = DIR_RIGHT;
	    tstack[tpos++] = this;
	    this = &((*this)->right);
	} else { /* Equal key is an error for monitors */
	    erts_exit(ERTS_ERROR_EXIT,"Insertion of already present monitor!");
	    break;
	}
    }
    insertion_rotation(dstack, dpos, tstack, tpos, state);
}
Ejemplo n.º 4
0
static Eterm copy_ref(Eterm ref, Eterm *hp)
{
    ErtsORefThing *ptr;
    ASSERT(is_internal_ordinary_ref(ref));
    ptr = ordinary_ref_thing_ptr(ref);
    memcpy(hp, ptr, sizeof(ErtsORefThing));
    return (make_internal_ref(hp));
}
Ejemplo n.º 5
0
BIF_RETTYPE erts_internal_port_control_3(BIF_ALIST_3)
{
    Port* prt;
    Eterm retval;
    Uint uint_op;
    unsigned int op;
    erts_aint32_t state;

    prt = sig_lookup_port(BIF_P, BIF_ARG_1);
    if (!prt)
	BIF_RET(am_badarg);

    if (!term_to_Uint(BIF_ARG_2, &uint_op))
	BIF_RET(am_badarg);

    if (uint_op > (Uint) UINT_MAX)
	BIF_RET(am_badarg);

    op = (unsigned int) uint_op;

    switch (erts_port_control(BIF_P, prt, op, BIF_ARG_3, &retval)) {
    case ERTS_PORT_OP_CALLER_EXIT:
    case ERTS_PORT_OP_BADARG:
    case ERTS_PORT_OP_DROPPED:
	retval = am_badarg;
	break;
    case ERTS_PORT_OP_SCHEDULED:
	ASSERT(is_internal_ordinary_ref(retval));
	break;
    case ERTS_PORT_OP_DONE:
	ASSERT(is_not_internal_ref(retval));
	break;
    default:
	ERTS_INTERNAL_ERROR("Unexpected erts_port_control() result");
	retval = am_internal_error;
	break;
    }

    state = erts_smp_atomic32_read_acqb(&BIF_P->state);
    if (state & (ERTS_PSFLG_EXITING|ERTS_PSFLG_PENDING_EXIT)) {
#ifdef ERTS_SMP
	if (state & ERTS_PSFLG_PENDING_EXIT)
	    erts_handle_pending_exit(BIF_P, ERTS_PROC_LOCK_MAIN);
#endif
	ERTS_BIF_EXITED(BIF_P);
    }

    BIF_RET(retval);
}
Ejemplo n.º 6
0
BIF_RETTYPE erts_internal_port_call_3(BIF_ALIST_3)
{
    Port* prt;
    Eterm retval;
    Uint uint_op;
    unsigned int op;
    erts_aint32_t state;

    prt = sig_lookup_port(BIF_P, BIF_ARG_1);
    if (!prt)
	BIF_RET(am_badarg);

    if (!term_to_Uint(BIF_ARG_2, &uint_op))
	BIF_RET(am_badarg);

    if (uint_op > (Uint) UINT_MAX)
	BIF_RET(am_badarg);

    op = (unsigned int) uint_op;

    switch (erts_port_call(BIF_P, prt, op, BIF_ARG_3, &retval)) {
    case ERTS_PORT_OP_DROPPED:
    case ERTS_PORT_OP_BADARG:
	retval = am_badarg;
	break;
    case ERTS_PORT_OP_SCHEDULED:
	ASSERT(is_internal_ordinary_ref(retval));
	break;
    case ERTS_PORT_OP_DONE:
	ASSERT(is_not_internal_ref(retval));
	break;
    default:
	ERTS_INTERNAL_ERROR("Unexpected erts_port_call() result");
	retval = am_internal_error;
	break;
    }

    state = erts_atomic32_read_acqb(&BIF_P->state);
    if (state & ERTS_PSFLG_EXITING)
	ERTS_BIF_EXITED(BIF_P);

    BIF_RET(retval);
}
Ejemplo n.º 7
0
BIF_RETTYPE erts_internal_port_info_2(BIF_ALIST_2)
{
    Eterm retval;
    Port* prt;

    if (is_internal_port(BIF_ARG_1) || is_atom(BIF_ARG_1)) {
	prt = sig_lookup_port(BIF_P, BIF_ARG_1);
	if (!prt)
	    BIF_RET(am_undefined);
    }
    else if (is_external_port(BIF_ARG_1)) {
	if (external_port_dist_entry(BIF_ARG_1) == erts_this_dist_entry)
	    BIF_RET(am_undefined);
	else
	    BIF_RET(am_badarg);
    }
    else {
	BIF_RET(am_badarg);
    }

    switch (erts_port_info(BIF_P, prt, BIF_ARG_2, &retval)) {
    case ERTS_PORT_OP_CALLER_EXIT:
    case ERTS_PORT_OP_BADARG:
	BIF_RET(am_badarg);
    case ERTS_PORT_OP_DROPPED:
	BIF_RET(am_undefined);
    case ERTS_PORT_OP_SCHEDULED:
	ASSERT(is_internal_ordinary_ref(retval));
	BIF_RET(retval);
    case ERTS_PORT_OP_DONE:
	ASSERT(is_not_internal_ref(retval));
	BIF_RET(retval);
    default:
	ERTS_INTERNAL_ERROR("Unexpected erts_port_info() result");
	BIF_RET(am_internal_error);
    }
}
Ejemplo n.º 8
0
BIF_RETTYPE erts_internal_port_command_3(BIF_ALIST_3)
{
    BIF_RETTYPE res;
    Port *prt;
    int flags = 0;
    Eterm ref;

    if (is_not_nil(BIF_ARG_3)) {
	Eterm l = BIF_ARG_3;
	while (is_list(l)) {
	    Eterm* cons = list_val(l);
	    Eterm car = CAR(cons);
	    if (car == am_force)
		flags |= ERTS_PORT_SIG_FLG_FORCE;
	    else if (car == am_nosuspend)
		flags |= ERTS_PORT_SIG_FLG_NOSUSPEND;
	    else
		BIF_RET(am_badarg);
	    l = CDR(cons);
	}
	if (!is_nil(l))
	    BIF_RET(am_badarg);
    }

    prt = sig_lookup_port(BIF_P, BIF_ARG_1);
    if (!prt)
	BIF_RET(am_badarg);

    if (flags & ERTS_PORT_SIG_FLG_FORCE) {
	if (!(prt->drv_ptr->flags & ERL_DRV_FLAG_SOFT_BUSY))
	    BIF_RET(am_notsup);
    }

#ifdef DEBUG
    ref = NIL;
#endif

    switch (erts_port_output(BIF_P, flags, prt, prt->common.id, BIF_ARG_2, &ref)) {
    case ERTS_PORT_OP_CALLER_EXIT:
    case ERTS_PORT_OP_BADARG:
    case ERTS_PORT_OP_DROPPED:
 	ERTS_BIF_PREP_RET(res, am_badarg);
	break;
    case ERTS_PORT_OP_BUSY:
	ASSERT(!(flags & ERTS_PORT_SIG_FLG_FORCE));
	if (flags & ERTS_PORT_SIG_FLG_NOSUSPEND)
	    ERTS_BIF_PREP_RET(res, am_false);
	else {
	    erts_suspend(BIF_P, ERTS_PROC_LOCK_MAIN, prt);
	    ERTS_BIF_PREP_YIELD3(res, bif_export[BIF_erts_internal_port_command_3],
				 BIF_P, BIF_ARG_1, BIF_ARG_2, BIF_ARG_3);
	}
	break;
    case ERTS_PORT_OP_BUSY_SCHEDULED:
	ASSERT(!(flags & ERTS_PORT_SIG_FLG_FORCE));
	/* Fall through... */
    case ERTS_PORT_OP_SCHEDULED:
	ASSERT(is_internal_ordinary_ref(ref));
	ERTS_BIF_PREP_RET(res, ref);
	break;
    case ERTS_PORT_OP_DONE:
	ERTS_BIF_PREP_RET(res, am_true);
	break;
    default:
	ERTS_INTERNAL_ERROR("Unexpected erts_port_output() result");
	break;
    }

    if (ERTS_PROC_IS_EXITING(BIF_P)) {
	KILL_CATCHES(BIF_P);	/* Must exit */
	ERTS_BIF_PREP_ERROR(res, BIF_P, EXC_ERROR);
    }

    return res;
}