term_t cbif_spawn_link1(proc_t *proc, term_t *regs) { term_t Fun = regs[0]; if (!is_boxed(Fun)) badarg(Fun); uint32_t *fdata = peel_boxed(Fun); if (boxed_tag(fdata) != SUBTAG_FUN) badarg(Fun); t_fun_t *f = (t_fun_t *)fdata; if (f->fe == 0) not_implemented("unloaded funs"); proc_t *new_proc = proc_make(proc->group_leader); int x = proc_spawn_fun0_N(new_proc, f); if (x == 0) x = inter_link_establish_N(&new_proc->links, proc->pid); if (x == 0) x = inter_link_establish_N(&proc->links, new_proc->pid); if (x < 0) { proc_destroy(new_proc); // no need to unlink, new_proc might have a link to proc but it was destroyed anyway if (x == -TOO_DEEP) fail(A_SYSTEM_LIMIT); else fail(A_NOT_SPAWNED); } return new_proc->pid; }
term_t cbif_spawn_monitor1(proc_t *proc, term_t *regs) { term_t Fun = regs[0]; if (!is_boxed(Fun)) badarg(Fun); uint32_t *fdata = peel_boxed(Fun); if (boxed_tag(fdata) != SUBTAG_FUN) badarg(Fun); t_fun_t *f = (t_fun_t *)fdata; if (f->fe == 0) not_implemented("unloaded funs"); term_t ref = heap_make_ref(&proc->hp); proc_t *new_proc = proc_make(proc->group_leader); int x = proc_spawn_fun0_N(new_proc, f); if (x == 0) { uint64_t ref_id = local_ref_id(ref); x = monitor(ref_id, proc->pid, new_proc->pid); } if (x < 0) { // no need to demonitor proc_destroy(new_proc); if (x == -TOO_DEEP) fail(A_SYSTEM_LIMIT); else fail(A_NOT_SPAWNED); } return heap_tuple2(&proc->hp, new_proc->pid, ref); }
term_t cbif_spawn1(proc_t *proc, term_t *regs) { term_t Fun = regs[0]; if (!is_boxed(Fun)) badarg(Fun); uint32_t *fdata = peel_boxed(Fun); if (boxed_tag(fdata) != SUBTAG_FUN) badarg(Fun); t_fun_t *f = (t_fun_t *)fdata; if (f->fe == 0) not_implemented("unloaded funs"); if (fun_arity(fdata) != fun_num_free(fdata)) badarg(); proc_t *new_proc = proc_make(proc->group_leader); int x = proc_spawn_fun0_N(new_proc, f); if (x < 0) { proc_destroy(new_proc); if (x == -TOO_DEEP) fail(A_SYSTEM_LIMIT); else fail(A_NOT_SPAWNED); } return new_proc->pid; }
term_t cbif_spawn_link3(proc_t *proc, term_t *regs) { term_t m = regs[0]; term_t f = regs[1]; term_t args = regs[2]; if (!is_atom(m)) badarg(m); if (!is_atom(f)) badarg(f); if (!is_list(args)) badarg(args); if (list_len(args) < 0) badarg(args); // too odd proc_t *new_proc = proc_make(proc->group_leader); int x = proc_spawn_N(new_proc, m, f, args); if (x == 0) x = inter_link_establish_N(&new_proc->links, proc->pid); if (x == 0) x = inter_link_establish_N(&proc->links, new_proc->pid); if (x < 0) { proc_destroy(new_proc); // no need to unlink, new_proc might have a link to proc but it is destroyed anyway fail(err_to_term(x)); } return new_proc->pid; }
term_t cbif_spawn3(proc_t *proc, term_t *regs) { term_t m = regs[0]; term_t f = regs[1]; term_t args = regs[2]; if (!is_atom(m)) badarg(m); if (!is_atom(f)) badarg(f); if (!is_list(args)) badarg(args); if (list_len(args) < 0) badarg(args); // too odd proc_t *new_proc = proc_make(proc->group_leader); int x = proc_spawn_N(new_proc, m, f, args); if (x < 0) { proc_destroy(new_proc); // safe fail(err_to_term(x)); } return new_proc->pid; }
static void spawn_init_start(int8_t *cmd_line) { proc_t *init_proc = proc_make(noval); // group leader set later assert(init_proc != 0); init_proc->cap.regs[0] = parse_cmd_line(&init_proc->hp, cmd_line); assert(init_proc->cap.regs[0] != noval); init_proc->cap.live = 1; init_proc->init_call_mod = A_INIT; init_proc->init_call_func = A_BOOT; init_proc->init_call_arity = 1; export_t *exp = code_base_lookup(A_INIT, A_BOOT, 1); assert(exp != 0); init_proc->cap.ip = exp->entry; module_info_t *mi = code_base_module_by_name(A_INIT, 0); assert(mi != 0); init_proc->cap.cp = mi->code_starts + mi->code_size-1; scheduler_enlist0(init_proc); // pid assigned init_proc->group_leader = init_proc->pid; // init is its own leader proc_main(init_proc); /* UNREACHANBLE */ }
term_t cbif_spawn_monitor3(proc_t *proc, term_t *regs) { term_t m = regs[0]; term_t f = regs[1]; term_t args = regs[2]; if (!is_atom(m)) badarg(m); if (!is_atom(f)) badarg(f); if (!is_list(args)) badarg(args); if (list_len(args) < 0) badarg(args); // too odd term_t ref = heap_make_ref(&proc->hp); proc_t *new_proc = proc_make(proc->group_leader); int x = proc_spawn_N(new_proc, m, f, args); if (x == 0) { uint64_t ref_id = local_ref_id(ref); x = monitor(ref_id, proc->pid, new_proc->pid); } if (x < 0) { //NB: no need to demonitor proc_destroy(new_proc); if (x == -TOO_DEEP) fail(A_SYSTEM_LIMIT); else fail(A_NOT_SPAWNED); } return heap_tuple2(&proc->hp, new_proc->pid, ref); }