BIF_RETTYPE open_port_2(BIF_ALIST_2) { Port *port; Eterm port_id; char *str; int err_type, err_num; port = open_port(BIF_P, BIF_ARG_1, BIF_ARG_2, &err_type, &err_num); if (!port) { if (err_type == -3) { ASSERT(err_num == BADARG || err_num == SYSTEM_LIMIT); BIF_ERROR(BIF_P, err_num); } else if (err_type == -2) { str = erl_errno_id(err_num); } else { str = "einval"; } BIF_P->fvalue = erts_atom_put((byte *) str, strlen(str), ERTS_ATOM_ENC_LATIN1, 1); BIF_ERROR(BIF_P, EXC_ERROR); } erts_smp_proc_lock(BIF_P, ERTS_PROC_LOCK_LINK); port_id = port->common.id; erts_add_link(&ERTS_P_LINKS(port), LINK_PID, BIF_P->common.id); erts_add_link(&ERTS_P_LINKS(BIF_P), LINK_PID, port_id); erts_smp_proc_unlock(BIF_P, ERTS_PROC_LOCK_LINK); erts_port_release(port); BIF_RET(port_id); }
BIF_RETTYPE open_port_2(BIF_ALIST_2) { int port_num; Eterm port_val; char *str; int err_num; if ((port_num = open_port(BIF_P, BIF_ARG_1, BIF_ARG_2, &err_num)) < 0) { if (port_num == -3) { ASSERT(err_num == BADARG || err_num == SYSTEM_LIMIT); BIF_ERROR(BIF_P, err_num); } else if (port_num == -2) { str = erl_errno_id(err_num); } else { str = "einval"; } BIF_P->fvalue = am_atom_put(str, strlen(str)); BIF_ERROR(BIF_P, EXC_ERROR); } erts_smp_proc_lock(BIF_P, ERTS_PROC_LOCK_LINK); port_val = erts_port[port_num].id; erts_add_link(&(erts_port[port_num].nlinks), LINK_PID, BIF_P->id); erts_add_link(&(BIF_P->nlinks), LINK_PID, port_val); erts_smp_proc_unlock(BIF_P, ERTS_PROC_LOCK_LINK); erts_port_release(&erts_port[port_num]); BIF_RET(port_val); }
BIF_RETTYPE port_connect_2(BIF_ALIST_2) { Port* prt; Process* rp; Eterm pid = BIF_ARG_2; if (is_not_internal_pid(pid)) { error: BIF_ERROR(BIF_P, BADARG); } prt = id_or_name2port(BIF_P, BIF_ARG_1); if (!prt) { goto error; } rp = erts_pid2proc(BIF_P, ERTS_PROC_LOCK_MAIN, pid, ERTS_PROC_LOCK_LINK); if (!rp) { erts_smp_port_unlock(prt); ERTS_SMP_ASSERT_IS_NOT_EXITING(BIF_P); goto error; } erts_add_link(&(rp->nlinks), LINK_PID, prt->id); erts_add_link(&(prt->nlinks), LINK_PID, pid); erts_smp_proc_unlock(rp, ERTS_PROC_LOCK_LINK); prt->connected = pid; /* internal pid */ erts_smp_port_unlock(prt); #ifdef USE_VM_PROBES if (DTRACE_ENABLED(port_connect)) { DTRACE_CHARBUF(process_str, DTRACE_TERM_BUF_SIZE); DTRACE_CHARBUF(port_str, DTRACE_TERM_BUF_SIZE); DTRACE_CHARBUF(newprocess_str, DTRACE_TERM_BUF_SIZE); dtrace_pid_str(prt->connected, process_str); erts_snprintf(port_str, sizeof(port_str), "%T", prt->id); dtrace_proc_str(rp, newprocess_str); DTRACE4(port_connect, process_str, port_str, prt->name, newprocess_str); } #endif BIF_RET(am_true); }
BIF_RETTYPE erts_internal_open_port_2(BIF_ALIST_2) { Port *port; Eterm res; char *str; int err_type, err_num; port = open_port(BIF_P, BIF_ARG_1, BIF_ARG_2, &err_type, &err_num); if (!port) { if (err_type == -3) { ASSERT(err_num == BADARG || err_num == SYSTEM_LIMIT); if (err_num == BADARG) res = am_badarg; else if (err_num == SYSTEM_LIMIT) res = am_system_limit; else /* this is only here to silence gcc, it should not happen */ BIF_ERROR(BIF_P, EXC_INTERNAL_ERROR); } else if (err_type == -2) { str = erl_errno_id(err_num); res = erts_atom_put((byte *) str, strlen(str), ERTS_ATOM_ENC_LATIN1, 1); } else { res = am_einval; } BIF_RET(res); } if (port->drv_ptr->flags & ERL_DRV_FLAG_USE_INIT_ACK) { /* Copied from erl_port_task.c */ port->async_open_port = erts_alloc(ERTS_ALC_T_PRTSD, sizeof(*port->async_open_port)); erts_make_ref_in_array(port->async_open_port->ref); port->async_open_port->to = BIF_P->common.id; erts_smp_proc_lock(BIF_P, ERTS_PROC_LOCKS_MSG_RECEIVE | ERTS_PROC_LOCK_LINK); if (ERTS_PROC_PENDING_EXIT(BIF_P)) { /* need to exit caller instead */ erts_smp_proc_unlock(BIF_P, ERTS_PROC_LOCKS_MSG_RECEIVE | ERTS_PROC_LOCK_LINK); KILL_CATCHES(BIF_P); BIF_P->freason = EXC_EXIT; erts_port_release(port); BIF_RET(am_badarg); } ERTS_SMP_MSGQ_MV_INQ2PRIVQ(BIF_P); BIF_P->msg.save = BIF_P->msg.last; erts_smp_proc_unlock(BIF_P, ERTS_PROC_LOCKS_MSG_RECEIVE); res = erts_proc_store_ref(BIF_P, port->async_open_port->ref); } else { res = port->common.id; erts_smp_proc_lock(BIF_P, ERTS_PROC_LOCK_LINK); } erts_add_link(&ERTS_P_LINKS(port), LINK_PID, BIF_P->common.id); erts_add_link(&ERTS_P_LINKS(BIF_P), LINK_PID, port->common.id); if (IS_TRACED_FL(BIF_P, F_TRACE_PROCS)) trace_proc(BIF_P, ERTS_PROC_LOCK_MAIN|ERTS_PROC_LOCK_LINK, BIF_P, am_link, port->common.id); erts_smp_proc_unlock(BIF_P, ERTS_PROC_LOCK_LINK); erts_port_release(port); BIF_RET(res); }
Eterm erl_create_process(ErlProcess* parent, Eterm module, Eterm function, Eterm args, ErlSpawnOpts* opts) { int i; uint16_t last_proc; for(i=0; i<MAX_PROCESSES; i++) { if(proc_tab[i].active == 0) { last_proc = i; break; } } if(last_proc == MAX_PROCESSES) { erl_exit("maximum number of processes reached!"); //@todo return NIL; } ErlProcess* p = (ErlProcess*)&proc_tab[last_proc]; Eterm pid = pix2pid(last_proc); p->parent = parent; p->id = pid; p->timer.active = 0; p->timer.arg = NULL; p->timer.cancel = NULL; p->timer.count = 0; p->timer.next = NULL; p->timer.prev = NULL; p->timer.slot = 0; p->timer.timeout = NULL; //@todo throw an error if exported was not found p->arity = 3; p->arg_reg = p->def_arg_reg; p->max_arg_reg = sizeof(p->def_arg_reg)/sizeof(p->def_arg_reg[0]); for(i=0; i<p->max_arg_reg; i++) { p->def_arg_reg[i] = 0; } p->fcalls = REDUCTIONS; p->active = 1; p->flags = 0; p->msg.len = 0; p->msg.first = NULL; p->msg.last = &p->msg.first; p->msg.save = &p->msg.first; p->msg.saved_last = NULL; p->links = NULL; if(opts && (opts->flags & SPO_LINK)) { erts_add_link(&p->links, parent->id); erts_add_link(&parent->links, p->id); } // initialize heap unsigned int arg_size = size_object(args); unsigned int heap_need = arg_size; unsigned int sz = erts_next_heap_size(heap_need); p->heap = (Eterm*)pvPortMalloc(sz * sizeof(Eterm)); p->stop = p->hend = p->heap + sz; p->htop = p->heap; p->heap_sz = sz; p->i = (BeamInstr*)(beam_apply); p->cp = (BeamInstr*)(beam_apply + 1); p->saved_i = (BeamInstr*)(beam_apply + 2); p->arg_reg[0] = module; p->arg_reg[1] = function; p->arg_reg[2] = copy_struct(args, arg_size, &p->htop); //start process inside the FreeRTOS scheduler vTaskResume(*(p->handle)); return pid; }