term_t cbif_unlink1(proc_t *proc, term_t *regs) { term_t PidOid = regs[0]; if (!is_short_pid(PidOid) && !is_short_oid(PidOid)) badarg(PidOid); proc_t *peer_proc = 0; outlet_t *peer_outlet = 0; if (is_short_pid(PidOid)) peer_proc = scheduler_lookup(PidOid); else peer_outlet = outlet_lookup(PidOid); inter_links_t *peer_links = 0; if (peer_proc != 0) peer_links = &peer_proc->links; else if (peer_outlet != 0) peer_links = &peer_outlet->links; if (peer_links != 0) { if (are_inter_linked(&proc->links, PidOid)) { inter_link_break(&proc->links, PidOid); inter_link_break(peer_links, proc->pid); } } return A_TRUE; }
// This function "zips" all ready items from: // `ol->accepting` queue (requests from the VM) // and `ol->accepted` queue (requests from network) static void bake_all_accepted(outlet_t *ol) { // bake_one_accepted() may close the outlet, so save oid: term_t saved_oid = ol->oid; // exhaust either ol->accepting or ol->accepted : while (ol->accepting != 0 && ol->accepted != 0) { acc_pend_t *pend = pop_from_ring(&ol->accepting); if (pend->timeout_set) tcp_accept_untimeout(pend); term_t reply_to = pend->reply_to; reuse_pending(&ol->free_pends, pend); proc_t *cont_proc = scheduler_lookup(reply_to); if (cont_proc == 0) continue; // this will pop a `pend` from ol->accepted bake_one_accepted(ol, cont_proc); if (outlet_lookup(saved_oid) == 0) break; } }
term_t cbif_link1(proc_t *proc, term_t *regs) { term_t PidOid = regs[0]; if (!is_short_pid(PidOid) && !is_short_oid(PidOid)) badarg(PidOid); if (PidOid == proc->pid) return A_TRUE; proc_t *peer_proc = 0; outlet_t *peer_outlet = 0; if (is_short_pid(PidOid)) peer_proc = scheduler_lookup(PidOid); else peer_outlet = outlet_lookup(PidOid); inter_links_t *peer_links = 0; if (peer_proc != 0) peer_links = &peer_proc->links; else if (peer_outlet != 0) peer_links = &peer_outlet->links; if (peer_proc == 0 && peer_outlet == 0) { if (proc->trap_exit == A_TRUE) { int x = scheduler_signal_exit_N(proc, proc->pid, A_NOPROC); // does not destroy the proc if (x < 0) fail(A_NOT_LINKED); return A_TRUE; } else fail(A_NOPROC); } else { if (!are_inter_linked(&proc->links, PidOid)) { int x = inter_link_establish_N(&proc->links, PidOid); if (x < 0) fail(A_NOT_LINKED); x = inter_link_establish_N(peer_links, proc->pid); if (x < 0) { inter_link_break(&proc->links, PidOid); fail(A_NOT_LINKED); } } return A_TRUE; } }