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 port_control_3(BIF_ALIST_3) { Port* p; Uint op; Eterm res = THE_NON_VALUE; /* Virtual schedule out calling process before lock wait */ if (IS_TRACED_FL(BIF_P, F_TRACE_SCHED_PROCS)) { trace_virtual_sched(BIF_P, am_out); } if (erts_system_profile_flags.runnable_procs && erts_system_profile_flags.exclusive) { profile_runnable_proc(BIF_P, am_inactive); } p = id_or_name2port(BIF_P, BIF_ARG_1); if (!p) { /* Schedule the process before exiting */ if (IS_TRACED_FL(BIF_P, F_TRACE_SCHED_PROCS)) { trace_virtual_sched(BIF_P, am_in); } if (erts_system_profile_flags.runnable_procs && erts_system_profile_flags.exclusive) { profile_runnable_proc(BIF_P, am_active); } BIF_ERROR(BIF_P, BADARG); } /* Trace the port for scheduling in */ if (IS_TRACED_FL(p, F_TRACE_SCHED_PORTS)) { trace_sched_ports_where(p, am_in, am_control); } if (erts_system_profile_flags.runnable_ports && !erts_port_is_scheduled(p)) { profile_runnable_port(p, am_active); } if (term_to_Uint(BIF_ARG_2, &op)) res = erts_port_control(BIF_P, p, op, BIF_ARG_3); /* Trace the port for scheduling out */ if (IS_TRACED_FL(p, F_TRACE_SCHED_PORTS)) { trace_sched_ports_where(p, am_out, am_control); } if (erts_system_profile_flags.runnable_ports && !erts_port_is_scheduled(p)) { profile_runnable_port(p, am_inactive); } erts_port_release(p); #ifdef ERTS_SMP ERTS_SMP_BIF_CHK_PENDING_EXIT(BIF_P, ERTS_PROC_LOCK_MAIN); #else ERTS_BIF_CHK_EXITED(BIF_P); #endif if (IS_TRACED_FL(BIF_P, F_TRACE_SCHED_PROCS)) { trace_virtual_sched(BIF_P, am_in); } if (erts_system_profile_flags.runnable_procs && erts_system_profile_flags.exclusive) { profile_runnable_proc(BIF_P, am_active); } if (is_non_value(res)) { BIF_ERROR(BIF_P, BADARG); } BIF_RET(res); }