/* * 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); } }
/* * 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, prt->common.id, am_normal, &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_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); } }
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); }
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); }
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); } }
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; }