diff options
Diffstat (limited to 'erts/emulator')
112 files changed, 10020 insertions, 6203 deletions
diff --git a/erts/emulator/Makefile.in b/erts/emulator/Makefile.in index a8b1728b90..70718575e9 100644 --- a/erts/emulator/Makefile.in +++ b/erts/emulator/Makefile.in @@ -599,7 +599,6 @@ endif $(TTF_DIR)/erl_bif_table.c \ $(TTF_DIR)/erl_bif_table.h \ -$(TTF_DIR)/erl_bif_wrap.c \ $(TTF_DIR)/erl_bif_list.h \ $(TTF_DIR)/erl_atom_table.c \ $(TTF_DIR)/erl_atom_table.h \ @@ -741,8 +740,8 @@ $(OBJDIR)/PROFILE: $(BINDIR)/$(PROFILE_EXECUTABLE) $(V_at)echo " PROFILE ${PROFILE_EXECUTABLE}" $(V_at)rm -f $(OBJDIR)/erl*.profraw $(V_at)set -e; LLVM_PROFILE_FILE="$(OBJDIR)/erlc-%m.profraw" \ - ERL_FLAGS="-emu_type prof${TYPEMARKER} +S 1" $(ERLC) -DPGO \ - -o $(OBJDIR) test/estone_SUITE.erl > $(OBJDIR)/PROFILE_LOG + ERL_FLAGS="-emu_type prof${TYPEMARKER} +S 1" $(ERLC) -no-server \ + -DPGO -o $(OBJDIR) test/estone_SUITE.erl > $(OBJDIR)/PROFILE_LOG $(V_at)set -e; LLVM_PROFILE_FILE="$(OBJDIR)/erl-%m.profraw" \ ERL_FLAGS="-emu_type prof${TYPEMARKER} +S 1" $(ERL) -pa $(OBJDIR) \ -noshell -s estone_SUITE pgo -s init stop >> $(OBJDIR)/PROFILE_LOG @@ -885,7 +884,6 @@ RUN_OBJS += \ $(OBJDIR)/erl_bif_persistent.o \ $(OBJDIR)/erl_bif_atomics.o $(OBJDIR)/erl_bif_counters.o \ $(OBJDIR)/erl_bif_trace.o $(OBJDIR)/erl_bif_unique.o \ - $(OBJDIR)/erl_bif_wrap.o $(OBJDIR)/erl_nfunc_sched.o \ $(OBJDIR)/erl_guard_bifs.o $(OBJDIR)/erl_dirty_bif_wrap.o \ $(OBJDIR)/erl_trace.o $(OBJDIR)/copy.o \ $(OBJDIR)/utils.o $(OBJDIR)/bif.o \ @@ -920,7 +918,8 @@ RUN_OBJS += \ $(OBJDIR)/erl_ptab.o $(OBJDIR)/erl_map.o \ $(OBJDIR)/erl_msacc.o $(OBJDIR)/erl_lock_flags.o \ $(OBJDIR)/erl_io_queue.o $(OBJDIR)/erl_db_catree.o \ - $(ESOCK_RUN_OBJS) $(OBJDIR)/erl_flxctr.o + $(ESOCK_RUN_OBJS) $(OBJDIR)/erl_flxctr.o \ + $(OBJDIR)/erl_nfunc_sched.o LTTNG_OBJS = $(OBJDIR)/erlang_lttng.o diff --git a/erts/emulator/beam/atom.names b/erts/emulator/beam/atom.names index 412d689246..4c67c2029f 100644 --- a/erts/emulator/beam/atom.names +++ b/erts/emulator/beam/atom.names @@ -248,6 +248,7 @@ atom erts_debug atom erts_dflags atom erts_internal atom ets +atom ets_info_binary atom ETS_TRANSFER='ETS-TRANSFER' atom exact_reductions atom exception_from @@ -403,6 +404,7 @@ atom min_bin_vheap_size atom minor atom minor_version atom Minus='-' +atom MinusMinus='--' atom module atom module_info atom monitored_by @@ -493,6 +495,7 @@ atom packet atom packet_size atom parallelism atom Plus='+' +atom PlusPlus='++' atom pause atom pending atom pending_driver diff --git a/erts/emulator/beam/beam_bif_load.c b/erts/emulator/beam/beam_bif_load.c index bb1b2e5b27..dcbff99f54 100644 --- a/erts/emulator/beam/beam_bif_load.c +++ b/erts/emulator/beam/beam_bif_load.c @@ -835,21 +835,25 @@ BIF_RETTYPE finish_after_on_load_2(BIF_ALIST_2) */ num_exps = export_list_size(code_ix); for (i = 0; i < num_exps; i++) { - Export *ep = export_list(i,code_ix); - if (ep == NULL || ep->info.mfa.module != BIF_ARG_1) { - continue; - } - if (ep->beam[1] != 0) { - ep->addressv[code_ix] = (void *) ep->beam[1]; - ep->beam[1] = 0; - } else { - if (ep->addressv[code_ix] == ep->beam && - BeamIsOpCode(ep->beam[0], op_apply_bif)) { - continue; - } - ep->addressv[code_ix] = ep->beam; - ep->beam[0] = BeamOpCodeAddr(op_call_error_handler); - } + Export *ep = export_list(i, code_ix); + + if (ep == NULL || ep->info.mfa.module != BIF_ARG_1) { + continue; + } + + DBG_CHECK_EXPORT(ep, code_ix); + + if (ep->trampoline.not_loaded.deferred != 0) { + ep->addressv[code_ix] = (void*)ep->trampoline.not_loaded.deferred; + ep->trampoline.not_loaded.deferred = 0; + } else { + if (ep->bif_table_index != -1) { + continue; + } + + ep->addressv[code_ix] = ep->trampoline.raw; + ep->trampoline.op = BeamOpCodeAddr(op_call_error_handler); + } } modp->curr.code_hdr->on_load_function_ptr = NULL; @@ -872,10 +876,11 @@ BIF_RETTYPE finish_after_on_load_2(BIF_ALIST_2) if (ep == NULL || ep->info.mfa.module != BIF_ARG_1) { continue; } - if (BeamIsOpCode(ep->beam[0], op_apply_bif)) { + if (ep->bif_table_index != -1) { continue; } - ep->beam[1] = 0; + + ep->trampoline.not_loaded.deferred = 0; } } erts_release_code_write_permission(); @@ -1125,16 +1130,15 @@ check_process_code(Process* rp, Module* modp, int *redsp, int fcalls) mod_size = modp->old.code_length; /* - * Check if current instruction or continuation pointer points into module. + * Check if the instruction pointer points into module. */ - if (ErtsInArea(rp->i, mod_start, mod_size) - || ErtsInArea(rp->cp, mod_start, mod_size)) { + if (ErtsInArea(rp->i, mod_start, mod_size)) { return am_true; } - + *redsp += 1; - if (erts_check_nif_export_in_area(rp, mod_start, mod_size)) + if (erts_check_nfunc_in_area(rp, mod_start, mod_size)) return am_true; *redsp += (STACK_START(rp) - rp->stop) / 32; @@ -1799,6 +1803,78 @@ erts_queue_release_literals(Process* c_p, ErtsLiteralArea* literals) } } +struct debug_la_oh { + void (*func)(ErlOffHeap *, void *); + void *arg; +}; + +static void debug_later_cleanup_literal_area_off_heap(void *vfap, + ErtsThrPrgrVal val, + void *vlrlap) +{ + struct debug_la_oh *fap = vfap; + ErtsLaterReleasLiteralArea *lrlap = vlrlap; + ErtsLiteralArea *lap = lrlap->la; + if (!erts_debug_have_accessed_literal_area(lap)) { + ErlOffHeap oh; + ERTS_INIT_OFF_HEAP(&oh); + oh.first = lap->off_heap; + (*fap->func)(&oh, fap->arg); + erts_debug_save_accessed_literal_area(lap); + } +} + +static void debug_later_complete_literal_area_switch_off_heap(void *vfap, + ErtsThrPrgrVal val, + void *vlap) +{ + struct debug_la_oh *fap = vfap; + ErtsLiteralArea *lap = vlap; + if (lap && !erts_debug_have_accessed_literal_area(lap)) { + ErlOffHeap oh; + ERTS_INIT_OFF_HEAP(&oh); + oh.first = lap->off_heap; + (*fap->func)(&oh, fap->arg); + erts_debug_save_accessed_literal_area(lap); + } +} + + +void +erts_debug_foreach_release_literal_area_off_heap(void (*func)(ErlOffHeap *, void *), void *arg) +{ + ErtsLiteralArea *lap; + ErlOffHeap oh; + ErtsLiteralAreaRef *ref; + struct debug_la_oh fa; + erts_mtx_lock(&release_literal_areas.mtx); + for (ref = release_literal_areas.first; ref; ref = ref->next) { + lap = ref->literal_area; + if (!erts_debug_have_accessed_literal_area(lap)) { + ERTS_INIT_OFF_HEAP(&oh); + oh.first = lap->off_heap; + (*func)(&oh, arg); + erts_debug_save_accessed_literal_area(lap); + } + } + erts_mtx_unlock(&release_literal_areas.mtx); + lap = ERTS_COPY_LITERAL_AREA(); + if (lap && !erts_debug_have_accessed_literal_area(lap)) { + ERTS_INIT_OFF_HEAP(&oh); + oh.first = lap->off_heap; + (*func)(&oh, arg); + erts_debug_save_accessed_literal_area(lap); + } + fa.func = func; + fa.arg = arg; + erts_debug_later_op_foreach(later_release_literal_area, + debug_later_cleanup_literal_area_off_heap, + (void *) &fa); + erts_debug_later_op_foreach(complete_literal_area_switch, + debug_later_complete_literal_area_switch_off_heap, + (void *) &fa); +} + /* * Move code from current to old and null all export entries for the module */ @@ -1813,25 +1889,28 @@ delete_code(Module* modp) for (i = 0; i < num_exps; i++) { Export *ep = export_list(i, code_ix); if (ep != NULL && (ep->info.mfa.module == module)) { - if (ep->addressv[code_ix] == ep->beam) { - if (BeamIsOpCode(ep->beam[0], op_apply_bif)) { - continue; - } - else if (BeamIsOpCode(ep->beam[0], op_i_generic_breakpoint)) { + if (ep->addressv[code_ix] == ep->trampoline.raw) { + if (BeamIsOpCode(ep->trampoline.op, op_i_generic_breakpoint)) { ERTS_LC_ASSERT(erts_thr_progress_is_blocking()); ASSERT(modp->curr.num_traced_exports > 0); DBG_TRACE_MFA_P(&ep->info.mfa, "export trace cleared, code_ix=%d", code_ix); - erts_clear_export_break(modp, &ep->info); + erts_clear_export_break(modp, ep); } else { - ASSERT(BeamIsOpCode(ep->beam[0], op_call_error_handler) || + ASSERT(BeamIsOpCode(ep->trampoline.op, op_call_error_handler) || !erts_initialized); } } - ep->addressv[code_ix] = ep->beam; - ep->beam[0] = BeamOpCodeAddr(op_call_error_handler); - ep->beam[1] = 0; + + if (ep->bif_table_index != -1 && ep->is_bif_traced) { + /* Code unloading kills both global and local call tracing. */ + ep->is_bif_traced = 0; + } + + ep->addressv[code_ix] = ep->trampoline.raw; + ep->trampoline.op = BeamOpCodeAddr(op_call_error_handler); + ep->trampoline.not_loaded.deferred = 0; DBG_TRACE_MFA_P(&ep->info.mfa, "export invalidation, code_ix=%d", code_ix); } diff --git a/erts/emulator/beam/beam_bp.c b/erts/emulator/beam/beam_bp.c index 0832b3f374..1bb20f6ae3 100644 --- a/erts/emulator/beam/beam_bp.c +++ b/erts/emulator/beam/beam_bp.c @@ -207,9 +207,6 @@ erts_bp_match_functions(BpFunctions* f, ErtsCodeMFA *mfa, int specified) if (erts_is_function_native(ci)) { continue; } - if (is_nil(ci->mfa.module)) { /* Ignore BIF stub */ - continue; - } switch (specified) { case 3: if (ci->mfa.arity != mfa->arity) @@ -244,8 +241,10 @@ erts_bp_match_export(BpFunctions* f, ErtsCodeMFA *mfa, int specified) f->matching = (BpFunction *) Alloc(num_exps*sizeof(BpFunction)); ne = 0; for (i = 0; i < num_exps; i++) { - Export* ep = export_list(i, code_ix); - BeamInstr* pc; + BeamInstr *func; + Export* ep; + + ep = export_list(i, code_ix); switch (specified) { case 3: @@ -263,19 +262,20 @@ erts_bp_match_export(BpFunctions* f, ErtsCodeMFA *mfa, int specified) ASSERT(0); } - pc = ep->beam; - if (ep->addressv[code_ix] == pc) { - if (BeamIsOpCode(*pc, op_apply_bif) || - BeamIsOpCode(*pc, op_call_error_handler)) { - continue; - } - ASSERT(BeamIsOpCode(*pc, op_i_generic_breakpoint)); - } else if (erts_is_function_native(erts_code_to_codeinfo(ep->addressv[code_ix]))) { - continue; - } + func = ep->addressv[code_ix]; + + if (func == ep->trampoline.raw) { + if (BeamIsOpCode(*func, op_call_error_handler)) { + continue; + } + ASSERT(BeamIsOpCode(*func, op_i_generic_breakpoint)); + } else if (erts_is_function_native(erts_code_to_codeinfo(func))) { + continue; + } f->matching[ne].ci = &ep->info; f->matching[ne].mod = erts_get_module(ep->info.mfa.module, code_ix); + ne++; } @@ -305,18 +305,6 @@ erts_consolidate_bp_data(BpFunctions* f, int local) } } -void -erts_consolidate_bif_bp_data(void) -{ - int i; - - ERTS_LC_ASSERT(erts_has_code_write_permission()); - for (i = 0; i < BIF_SIZE; i++) { - Export *ep = bif_export[i]; - consolidate_bp_data(0, &ep->info, 0); - } -} - static void consolidate_bp_data(Module* modp, ErtsCodeInfo *ci, int local) { @@ -495,7 +483,7 @@ erts_set_mtrace_break(BpFunctions* f, Binary *match_spec, ErtsTracer tracer) } void -erts_set_call_trace_bif(ErtsCodeInfo *ci, Binary *match_spec, int local) +erts_set_export_trace(ErtsCodeInfo *ci, Binary *match_spec, int local) { Uint flags = local ? ERTS_BPF_LOCAL_TRACE : ERTS_BPF_GLOBAL_TRACE; @@ -503,25 +491,6 @@ erts_set_call_trace_bif(ErtsCodeInfo *ci, Binary *match_spec, int local) } void -erts_set_mtrace_bif(ErtsCodeInfo *ci, Binary *match_spec, ErtsTracer tracer) -{ - set_function_break(ci, match_spec, ERTS_BPF_META_TRACE, 0, tracer); -} - -void -erts_set_time_trace_bif(ErtsCodeInfo *ci, enum erts_break_op count_op) -{ - set_function_break(ci, NULL, - ERTS_BPF_TIME_TRACE|ERTS_BPF_TIME_TRACE_ACTIVE, - count_op, erts_tracer_nil); -} - -void -erts_clear_time_trace_bif(ErtsCodeInfo *ci) { - clear_function_break(ci, ERTS_BPF_TIME_TRACE|ERTS_BPF_TIME_TRACE_ACTIVE); -} - -void erts_set_debug_break(BpFunctions* f) { set_break(f, NULL, ERTS_BPF_DEBUG, 0, erts_tracer_nil); } @@ -547,7 +516,7 @@ erts_clear_trace_break(BpFunctions* f) } void -erts_clear_call_trace_bif(ErtsCodeInfo *ci, int local) +erts_clear_export_trace(ErtsCodeInfo *ci, int local) { GenericBp* g = ci->u.gen_bp; @@ -566,12 +535,6 @@ erts_clear_mtrace_break(BpFunctions* f) } void -erts_clear_mtrace_bif(ErtsCodeInfo *ci) -{ - clear_function_break(ci, ERTS_BPF_META_TRACE); -} - -void erts_clear_debug_break(BpFunctions* f) { ERTS_LC_ASSERT(erts_thr_progress_is_blocking()); @@ -630,58 +593,56 @@ erts_clear_module_break(Module *modp) { } void -erts_clear_export_break(Module* modp, ErtsCodeInfo *ci) +erts_clear_export_break(Module* modp, Export *ep) { + ErtsCodeInfo *ci; + ERTS_LC_ASSERT(erts_thr_progress_is_blocking()); + ci = &ep->info; + + ASSERT(erts_codeinfo_to_code(ci) == ep->trampoline.raw); + + ASSERT(BeamIsOpCode(ep->trampoline.op, op_i_generic_breakpoint)); + ep->trampoline.op = 0; + clear_function_break(ci, ERTS_BPF_ALL); erts_commit_staged_bp(); - *erts_codeinfo_to_code(ci) = (BeamInstr) 0; + consolidate_bp_data(modp, ci, 0); ASSERT(ci->u.gen_bp == NULL); } /* - * If c_p->cp is a trace return instruction, we set cp - * to be the place where we again start to execute code. + * If the topmost continuation pointer on the stack is a trace return + * instruction, we modify it to be the place where we again start to + * execute code. * - * cp is used by match spec {caller} to get the calling - * function, and if we don't do this fixup it will be - * 'undefined'. This has the odd side effect of {caller} - * not really being which function is the caller, but - * rather which function we are about to return to. + * This continuation pointer is used by match spec {caller} to get the + * calling function, and if we don't do this fixup it will be + * 'undefined'. This has the odd side effect of {caller} not really + * being the function which is the caller, but rather the function + * which we are about to return to. */ static void fixup_cp_before_trace(Process *c_p, int *return_to_trace) { - Eterm *cpp, *E = c_p->stop; - BeamInstr w = *c_p->cp; - if (BeamIsOpCode(w, op_return_trace)) { - cpp = &E[2]; - } else if (BeamIsOpCode(w, op_i_return_to_trace)) { - *return_to_trace = 1; - cpp = &E[0]; - } else if (BeamIsOpCode(w, op_i_return_time_trace)) { - cpp = &E[0]; - } else { - cpp = NULL; - } - if (cpp) { - for (;;) { - BeamInstr w = *cp_val(*cpp); - if (BeamIsOpCode(w, op_return_trace)) { - cpp += 3; - } else if (BeamIsOpCode(w, op_i_return_to_trace)) { - *return_to_trace = 1; - cpp += 1; - } else if (BeamIsOpCode(w, op_i_return_time_trace)) { - cpp += 2; - } else { - break; - } + Eterm *cpp = c_p->stop; + + for (;;) { + BeamInstr w = *cp_val(*cpp); + if (BeamIsOpCode(w, op_return_trace)) { + cpp += 3; + } else if (BeamIsOpCode(w, op_i_return_to_trace)) { + *return_to_trace = 1; + cpp += 1; + } else if (BeamIsOpCode(w, op_i_return_time_trace)) { + cpp += 2; + } else { + break; } - c_p->cp = (BeamInstr *) cp_val(*cpp); - ASSERT(is_CP(*cpp)); } + c_p->stop[0] = (Eterm) cp_val(*cpp); + ASSERT(is_CP(*cpp)); } BeamInstr @@ -743,12 +704,13 @@ erts_generic_breakpoint(Process* c_p, ErtsCodeInfo *info, Eterm* reg) if (bp_flags & ERTS_BPF_TIME_TRACE_ACTIVE) { Eterm w; + Eterm* E; erts_trace_time_call(c_p, info, bp->time); - w = (BeamInstr) *c_p->cp; + E = c_p->stop; + w = (BeamInstr) E[0]; if (! (BeamIsOpCode(w, op_i_return_time_trace) || BeamIsOpCode(w, op_return_trace) || BeamIsOpCode(w, op_i_return_to_trace)) ) { - Eterm* E = c_p->stop; ASSERT(c_p->htop <= E && E <= c_p->hend); if (E - 2 < c_p->htop) { (void) erts_garbage_collect(c_p, 2, reg, info->mfa.arity); @@ -759,9 +721,8 @@ erts_generic_breakpoint(Process* c_p, ErtsCodeInfo *info, Eterm* reg) ASSERT(c_p->htop <= E && E <= c_p->hend); E -= 2; - E[0] = make_cp(erts_codeinfo_to_code(info)); - E[1] = make_cp(c_p->cp); /* original return address */ - c_p->cp = beam_return_time_trace; + E[1] = make_cp(erts_codeinfo_to_code(info)); + E[0] = (Eterm) beam_return_time_trace; c_p->stop = E; } } @@ -773,237 +734,24 @@ erts_generic_breakpoint(Process* c_p, ErtsCodeInfo *info, Eterm* reg) } } -/* - * Entry point called by the trace wrap functions in erl_bif_wrap.c - * - * The trace wrap functions are themselves called through the export - * entries instead of the original BIF functions. - */ -Eterm -erts_bif_trace(int bif_index, Process* p, Eterm* args, BeamInstr* I) -{ - Eterm result; - Eterm (*func)(Process*, Eterm*, BeamInstr*); - Export* ep = bif_export[bif_index]; - Uint32 flags = 0, flags_meta = 0; - ErtsTracer meta_tracer = erts_tracer_nil; - int applying = (I == ep->beam); /* Yup, the apply code for a bif - * is actually in the - * export entry */ - BeamInstr *cp = p->cp; - GenericBp* g; - GenericBpData* bp = NULL; - Uint bp_flags = 0; - int return_to_trace = 0; - - ERTS_CHK_HAVE_ONLY_MAIN_PROC_LOCK(p); - - g = ep->info.u.gen_bp; - if (g) { - bp = &g->data[erts_active_bp_ix()]; - bp_flags = bp->flags; - } - - /* - * Make continuation pointer OK, it is not during direct BIF calls, - * but it is correct during apply of bif. - */ - if (!applying) { - p->cp = I; - } else { - fixup_cp_before_trace(p, &return_to_trace); - } - if (bp_flags & (ERTS_BPF_LOCAL_TRACE|ERTS_BPF_GLOBAL_TRACE) && - IS_TRACED_FL(p, F_TRACE_CALLS)) { - int local = !!(bp_flags & ERTS_BPF_LOCAL_TRACE); - flags = erts_call_trace(p, &ep->info, bp->local_ms, args, - local, &ERTS_TRACER(p)); - } - if (bp_flags & ERTS_BPF_META_TRACE) { - ErtsTracer old_tracer; - - meta_tracer = erts_atomic_read_nob(&bp->meta_tracer->tracer); - old_tracer = meta_tracer; - flags_meta = erts_call_trace(p, &ep->info, bp->meta_ms, args, - 0, &meta_tracer); - - if (!ERTS_TRACER_COMPARE(old_tracer, meta_tracer)) { - ErtsTracer new_tracer = erts_tracer_nil; - erts_tracer_update(&new_tracer, meta_tracer); - if (old_tracer == erts_atomic_cmpxchg_acqb( - &bp->meta_tracer->tracer, - (erts_aint_t)new_tracer, - (erts_aint_t)old_tracer)) { - ERTS_TRACER_CLEAR(&old_tracer); - } else { - ERTS_TRACER_CLEAR(&new_tracer); - } - } - } - if (bp_flags & ERTS_BPF_TIME_TRACE_ACTIVE && - IS_TRACED_FL(p, F_TRACE_CALLS)) { - erts_trace_time_call(p, &ep->info, bp->time); - } - - /* Restore original continuation pointer (if changed). */ - p->cp = cp; - - func = bif_table[bif_index].f; - - result = func(p, args, I); - - if (erts_nif_export_check_save_trace(p, result, - applying, ep, - cp, flags, - flags_meta, I, - meta_tracer)) { - /* - * erts_bif_trace_epilogue() will be called - * later when appropriate via the NIF export - * scheduling functionality... - */ - return result; - } - - return erts_bif_trace_epilogue(p, result, applying, ep, cp, - flags, flags_meta, I, - meta_tracer); -} - -Eterm -erts_bif_trace_epilogue(Process *p, Eterm result, int applying, - Export* ep, BeamInstr *cp, Uint32 flags, - Uint32 flags_meta, BeamInstr* I, - ErtsTracer meta_tracer) -{ - if (applying && (flags & MATCH_SET_RETURN_TO_TRACE)) { - BeamInstr i_return_trace = beam_return_trace[0]; - BeamInstr i_return_to_trace = beam_return_to_trace[0]; - BeamInstr i_return_time_trace = beam_return_time_trace[0]; - Eterm *cpp; - /* Maybe advance cp to skip trace stack frames */ - for (cpp = p->stop; ; cp = cp_val(*cpp++)) { - if (*cp == i_return_trace) { - /* Skip stack frame variables */ - while (is_not_CP(*cpp)) cpp++; - cpp += 2; /* Skip return_trace parameters */ - } else if (*cp == i_return_time_trace) { - /* Skip stack frame variables */ - while (is_not_CP(*cpp)) cpp++; - cpp += 1; /* Skip return_time_trace parameters */ - } else if (*cp == i_return_to_trace) { - /* A return_to trace message is going to be generated - * by normal means, so we do not have to. - */ - cp = NULL; - break; - } else break; - } - } - - /* Try to get these in the order - * they usually appear in normal code... */ - if (is_non_value(result)) { - Uint reason = p->freason; - if (reason != TRAP) { - Eterm class; - Eterm value = p->fvalue; - /* Expand error value like in handle_error() */ - if (reason & EXF_ARGLIST) { - Eterm *tp; - ASSERT(is_tuple(value)); - tp = tuple_val(value); - value = tp[1]; - } - if ((reason & EXF_THROWN) && (p->catches <= 0)) { - Eterm *hp = HAlloc(p, 3); - value = TUPLE2(hp, am_nocatch, value); - reason = EXC_ERROR; - } - /* Note: expand_error_value() could theoretically - * allocate on the heap, but not for any error - * returned by a BIF, and it would do no harm, - * just be annoying. - */ - value = expand_error_value(p, reason, value); - class = exception_tag[GET_EXC_CLASS(reason)]; - - if (flags_meta & MATCH_SET_EXCEPTION_TRACE) { - erts_trace_exception(p, &ep->info.mfa, class, value, - &meta_tracer); - } - if (flags & MATCH_SET_EXCEPTION_TRACE) { - erts_trace_exception(p, &ep->info.mfa, class, value, - &ERTS_TRACER(p)); - } - if ((flags & MATCH_SET_RETURN_TO_TRACE) && p->catches > 0) { - /* can only happen if(local)*/ - Eterm *ptr = p->stop; - ASSERT(is_CP(*ptr)); - ASSERT(ptr <= STACK_START(p)); - /* Search the nearest stack frame for a catch */ - while (++ptr < STACK_START(p)) { - if (is_CP(*ptr)) break; - if (is_catch(*ptr)) { - if (applying) { - /* Apply of BIF, cp is in calling function */ - if (cp) erts_trace_return_to(p, cp); - } else { - /* Direct bif call, I points into - * calling function */ - erts_trace_return_to(p, I); - } - } - } - } - if ((flags_meta|flags) & MATCH_SET_EXCEPTION_TRACE) { - erts_proc_lock(p, ERTS_PROC_LOCKS_ALL_MINOR); - ERTS_TRACE_FLAGS(p) |= F_EXCEPTION_TRACE; - erts_proc_unlock(p, ERTS_PROC_LOCKS_ALL_MINOR); - } - } - } else { - if (flags_meta & MATCH_SET_RX_TRACE) { - erts_trace_return(p, &ep->info.mfa, result, &meta_tracer); - } - /* MATCH_SET_RETURN_TO_TRACE cannot occur if(meta) */ - if (flags & MATCH_SET_RX_TRACE) { - erts_trace_return(p, &ep->info.mfa, result, &ERTS_TRACER(p)); - } - if (flags & MATCH_SET_RETURN_TO_TRACE && - IS_TRACED_FL(p, F_TRACE_RETURN_TO)) { - /* can only happen if(local)*/ - if (applying) { - /* Apply of BIF, cp is in calling function */ - if (cp) erts_trace_return_to(p, cp); - } else { - /* Direct bif call, I points into calling function */ - erts_trace_return_to(p, I); - } - } - } - ERTS_CHK_HAVE_ONLY_MAIN_PROC_LOCK(p); - return result; -} - static ErtsTracer do_call_trace(Process* c_p, ErtsCodeInfo* info, Eterm* reg, int local, Binary* ms, ErtsTracer tracer) { int return_to_trace = 0; - BeamInstr *cp_save = c_p->cp; Uint32 flags; Uint need = 0; + Eterm cp_save; Eterm* E = c_p->stop; - fixup_cp_before_trace(c_p, &return_to_trace); + cp_save = E[0]; + fixup_cp_before_trace(c_p, &return_to_trace); ERTS_UNREQ_PROC_MAIN_LOCK(c_p); flags = erts_call_trace(c_p, info, ms, reg, local, &tracer); ERTS_REQ_PROC_MAIN_LOCK(c_p); - /* restore cp after potential fixup */ - c_p->cp = cp_save; + E[0] = cp_save; ASSERT(!ERTS_PROC_IS_EXITING(c_p)); if ((flags & MATCH_SET_RETURN_TO_TRACE) && !return_to_trace) { @@ -1023,28 +771,23 @@ do_call_trace(Process* c_p, ErtsCodeInfo* info, Eterm* reg, if (flags & MATCH_SET_RETURN_TO_TRACE && !return_to_trace) { E -= 1; ASSERT(c_p->htop <= E && E <= c_p->hend); - E[0] = make_cp(c_p->cp); - c_p->cp = beam_return_to_trace; + E[0] = (Eterm) beam_return_to_trace; + c_p->stop = E; } - if (flags & MATCH_SET_RX_TRACE) - { + if (flags & MATCH_SET_RX_TRACE) { E -= 3; c_p->stop = E; ASSERT(c_p->htop <= E && E <= c_p->hend); ASSERT(is_CP((Eterm) (UWord) (&info->mfa.module))); ASSERT(IS_TRACER_VALID(tracer)); - E[2] = make_cp(c_p->cp); - E[1] = copy_object(tracer, c_p); - E[0] = make_cp(&info->mfa.module); - /* We ARE at the beginning of an instruction, - the funcinfo is above i. */ - c_p->cp = (flags & MATCH_SET_EXCEPTION_TRACE) ? - beam_exception_trace : beam_return_trace; + E[2] = copy_object(tracer, c_p); + E[1] = make_cp(&info->mfa.module); + E[0] = (Eterm) ((flags & MATCH_SET_EXCEPTION_TRACE) ? + beam_exception_trace : beam_return_trace); erts_proc_lock(c_p, ERTS_PROC_LOCKS_ALL_MINOR); ERTS_TRACE_FLAGS(c_p) |= F_EXCEPTION_TRACE; erts_proc_unlock(c_p, ERTS_PROC_LOCKS_ALL_MINOR); - } else - c_p->stop = E; + } return tracer; } diff --git a/erts/emulator/beam/beam_bp.h b/erts/emulator/beam/beam_bp.h index a64765822b..54e84e7e4f 100644 --- a/erts/emulator/beam/beam_bp.h +++ b/erts/emulator/beam/beam_bp.h @@ -119,20 +119,16 @@ void erts_bp_free_matched_functions(BpFunctions* f); void erts_install_breakpoints(BpFunctions* f); void erts_uninstall_breakpoints(BpFunctions* f); void erts_consolidate_bp_data(BpFunctions* f, int local); -void erts_consolidate_bif_bp_data(void); void erts_set_trace_break(BpFunctions *f, Binary *match_spec); void erts_clear_trace_break(BpFunctions *f); -void erts_set_call_trace_bif(ErtsCodeInfo *ci, Binary *match_spec, int local); -void erts_clear_call_trace_bif(ErtsCodeInfo *ci, int local); +void erts_set_export_trace(ErtsCodeInfo *ci, Binary *match_spec, int local); +void erts_clear_export_trace(ErtsCodeInfo *ci, int local); void erts_set_mtrace_break(BpFunctions *f, Binary *match_spec, ErtsTracer tracer); void erts_clear_mtrace_break(BpFunctions *f); -void erts_set_mtrace_bif(ErtsCodeInfo *ci, Binary *match_spec, - ErtsTracer tracer); -void erts_clear_mtrace_bif(ErtsCodeInfo *ci); void erts_set_debug_break(BpFunctions *f); void erts_clear_debug_break(BpFunctions *f); @@ -142,7 +138,7 @@ void erts_clear_count_break(BpFunctions *f); void erts_clear_all_breaks(BpFunctions* f); int erts_clear_module_break(Module *modp); -void erts_clear_export_break(Module *modp, ErtsCodeInfo* ci); +void erts_clear_export_break(Module *modp, Export *ep); BeamInstr erts_generic_breakpoint(Process* c_p, ErtsCodeInfo *ci, Eterm* reg); BeamInstr erts_trace_break(Process *p, ErtsCodeInfo *ci, Eterm *args, @@ -151,8 +147,6 @@ BeamInstr erts_trace_break(Process *p, ErtsCodeInfo *ci, Eterm *args, int erts_is_trace_break(ErtsCodeInfo *ci, Binary **match_spec_ret, int local); int erts_is_mtrace_break(ErtsCodeInfo *ci, Binary **match_spec_ret, ErtsTracer *tracer_ret); -int erts_is_mtrace_bif(ErtsCodeInfo *ci, Binary **match_spec_ret, - ErtsTracer *tracer_ret); int erts_is_native_break(ErtsCodeInfo *ci); int erts_is_count_break(ErtsCodeInfo *ci, Uint *count_ret); int erts_is_time_break(Process *p, ErtsCodeInfo *ci, Eterm *call_time); @@ -163,10 +157,6 @@ void erts_schedule_time_break(Process *p, Uint out); void erts_set_time_break(BpFunctions *f, enum erts_break_op); void erts_clear_time_break(BpFunctions *f); -int erts_is_time_trace_bif(Process *p, ErtsCodeInfo *ci, Eterm *call_time); -void erts_set_time_trace_bif(ErtsCodeInfo *ci, enum erts_break_op); -void erts_clear_time_trace_bif(ErtsCodeInfo *ci); - ErtsCodeInfo *erts_find_local_func(ErtsCodeMFA *mfa); #if ERTS_GLB_INLINE_INCL_FUNC_DEF diff --git a/erts/emulator/beam/beam_debug.c b/erts/emulator/beam/beam_debug.c index 4d52435139..6a9a6b7dc9 100644 --- a/erts/emulator/beam/beam_debug.c +++ b/erts/emulator/beam/beam_debug.c @@ -332,7 +332,7 @@ erts_debug_disassemble_1(BIF_ALIST_1) "unknown " HEXF "\n", instr); code_ptr++; } - if (i == op_call_nif) { + if (i == op_call_nif_WWW) { /* * The rest of the code will not be executed. Don't disassemble any * more code in this function. diff --git a/erts/emulator/beam/beam_emu.c b/erts/emulator/beam/beam_emu.c index 07c16e3415..e8a0c666e3 100644 --- a/erts/emulator/beam/beam_emu.c +++ b/erts/emulator/beam/beam_emu.c @@ -111,10 +111,9 @@ do { \ #define CHECK_ALIGNED(Dst) ASSERT((((Uint)&Dst) & (sizeof(Uint)-1)) == 0) -#define GET_BIF_MODULE(p) (p->info.mfa.module) -#define GET_BIF_FUNCTION(p) (p->info.mfa.function) -#define GET_BIF_ARITY(p) (p->info.mfa.arity) -#define GET_BIF_ADDRESS(p) ((BifFunction) (p->beam[1])) +#define GET_EXPORT_MODULE(p) ((p)->info.mfa.module) +#define GET_EXPORT_FUNCTION(p) ((p)->info.mfa.function) +#define GET_EXPORT_ARITY(p) ((p)->info.mfa.arity) #define TermWords(t) (((t) / (sizeof(BeamInstr)/sizeof(Eterm))) + !!((t) % (sizeof(BeamInstr)/sizeof(Eterm)))) @@ -141,10 +140,6 @@ do { \ BeamCodeAddr(IP) < (BeamInstr)LabelAddr(end_emulator_loop)) #endif /* NO_JUMP_TABLE */ -#define SET_CP(p, ip) \ - ASSERT(VALID_INSTR(*(ip))); \ - (p)->cp = (ip) - #define SET_I(ip) \ ASSERT(VALID_INSTR(* (Eterm *)(ip))); \ I = (ip) @@ -254,72 +249,6 @@ void** beam_ops; #define Q(N) (N*sizeof(Eterm *)) #define l(N) (freg[N].fd) -/* - * Check that we haven't used the reductions and jump to function pointed to by - * the I register. If we are out of reductions, do a context switch. - */ - -#define DispatchMacro() \ - do { \ - BeamInstr dis_next; \ - dis_next = *I; \ - CHECK_ARGS(I); \ - if (FCALLS > 0 || FCALLS > neg_o_reds) { \ - FCALLS--; \ - Goto(dis_next); \ - } else { \ - goto context_switch; \ - } \ - } while (0) \ - -#define DispatchMacroFun() \ - do { \ - BeamInstr dis_next; \ - dis_next = *I; \ - CHECK_ARGS(I); \ - if (FCALLS > 0 || FCALLS > neg_o_reds) { \ - FCALLS--; \ - Goto(dis_next); \ - } else { \ - goto context_switch_fun; \ - } \ - } while (0) - -#define DispatchMacrox() \ - do { \ - if (FCALLS > 0) { \ - BeamInstr dis_next; \ - SET_I(((Export *) Arg(0))->addressv[erts_active_code_ix()]); \ - dis_next = *I; \ - FCALLS--; \ - CHECK_ARGS(I); \ - Goto(dis_next); \ - } else if (ERTS_PROC_GET_SAVED_CALLS_BUF(c_p) \ - && FCALLS > neg_o_reds) { \ - goto save_calls1; \ - } else { \ - SET_I(((Export *) Arg(0))->addressv[erts_active_code_ix()]); \ - CHECK_ARGS(I); \ - goto context_switch; \ - } \ - } while (0) - -#ifdef DEBUG -/* - * To simplify breakpoint setting, put the code in one place only and jump to it. - */ -# define Dispatch() goto do_dispatch -# define Dispatchx() goto do_dispatchx -# define Dispatchfun() goto do_dispatchfun -#else -/* - * Inline for speed. - */ -# define Dispatch() DispatchMacro() -# define Dispatchx() DispatchMacrox() -# define Dispatchfun() DispatchMacroFun() -#endif - #define Arg(N) I[(N)+1] #define GetSource(raw, dst) \ @@ -352,19 +281,6 @@ do { \ } \ } while(0) -#define DispatchReturn \ -do { \ - if (FCALLS > 0 || FCALLS > neg_o_reds) { \ - FCALLS--; \ - Goto(*I); \ - } \ - else { \ - c_p->current = NULL; \ - c_p->arity = 1; \ - goto context_switch3; \ - } \ -} while (0) - #ifdef DEBUG /* Better static type testing by the C compiler */ # define BEAM_IS_TUPLE(Src) is_tuple(Src) @@ -524,7 +440,7 @@ init_emulator(void) #define DTRACE_RETURN_FROM_PC(p) \ do { \ ErtsCodeMFA* cmfa; \ - if (DTRACE_ENABLED(function_return) && (cmfa = find_function_from_pc((p)->cp))) { \ + if (DTRACE_ENABLED(function_return) && (cmfa = find_function_from_pc(cp_val((p)->stop[0])))) { \ DTRACE_RETURN((p), cmfa); \ } \ } while(0) @@ -772,27 +688,9 @@ void process_main(Eterm * x_reg_array, FloatDef* f_reg_array) #endif #include "beam_hot.h" - -#ifdef DEBUG /* - * Set a breakpoint here to get control just after a call instruction. - * I points to the first instruction in the called function. - * - * In gdb, use 'call dis(I-5, 1)' to show the name of the function. - */ - do_dispatch: - DispatchMacro(); - - do_dispatchx: - DispatchMacrox(); - - do_dispatchfun: - DispatchMacroFun(); - -#endif - - /* - * Jumped to from the Dispatch() macro when the reductions are used up. + * The labels are jumped to from the $DISPATCH() macros when the reductions + * are used up. * * Since the I register points just beyond the FuncBegin instruction, we * can get the module, function, and arity for the function being @@ -986,18 +884,42 @@ void process_main(Eterm * x_reg_array, FloatDef* f_reg_array) } #endif return; /* Never executed */ +} - save_calls1: - { - BeamInstr dis_next; +/* + * Enter all BIFs into the export table. + * + * Note that they will all call the error_handler until their modules have been + * loaded, which may prevent the system from booting if BIFs from non-preloaded + * modules are apply/3'd while loading code. Ordinary BIF calls will work fine + * however since they won't go through export entries. + */ +static void install_bifs(void) { + int i; + + for (i = 0; i < BIF_SIZE; i++) { + BifEntry *entry; + Export *ep; + int j; - save_calls(c_p, (Export *) Arg(0)); + entry = &bif_table[i]; - SET_I(((Export *) Arg(0))->addressv[erts_active_code_ix()]); + ep = erts_export_put(entry->module, entry->name, entry->arity); - dis_next = *I; - FCALLS--; - Goto(dis_next); + ep->info.op = BeamOpCodeAddr(op_i_func_info_IaaI); + ep->info.mfa.module = entry->module; + ep->info.mfa.function = entry->name; + ep->info.mfa.arity = entry->arity; + ep->bif_table_index = i; + + memset(&ep->trampoline, 0, sizeof(ep->trampoline)); + ep->trampoline.op = BeamOpCodeAddr(op_call_error_handler); + + for (j = 0; j < ERTS_NUM_CODE_IX; j++) { + ep->addressv[j] = ep->trampoline.raw; + } + + bif_export[i] = ep; } } @@ -1008,43 +930,30 @@ void process_main(Eterm * x_reg_array, FloatDef* f_reg_array) static void init_emulator_finish(void) { - int i; - Export* ep; - #if defined(ARCH_64) && defined(CODE_MODEL_SMALL) - for (i = 0; i < NUMBER_OF_OPCODES; i++) { - BeamInstr instr = BeamOpCodeAddr(i); - if (instr >= (1ull << 32)) { - erts_exit(ERTS_ERROR_EXIT, - "This run-time was supposed be compiled with all code below 2Gb,\n" - "but the instruction '%s' is located at %016lx.\n", - opc[i].name, instr); - } - } + int i; + + for (i = 0; i < NUMBER_OF_OPCODES; i++) { + BeamInstr instr = BeamOpCodeAddr(i); + if (instr >= (1ull << 32)) { + erts_exit(ERTS_ERROR_EXIT, + "This run-time was supposed be compiled with all code below 2Gb,\n" + "but the instruction '%s' is located at %016lx.\n", + opc[i].name, instr); + } + } #endif - beam_apply[0] = BeamOpCodeAddr(op_i_apply); - beam_apply[1] = BeamOpCodeAddr(op_normal_exit); - beam_exit[0] = BeamOpCodeAddr(op_error_action_code); - beam_continue_exit[0] = BeamOpCodeAddr(op_continue_exit); - beam_return_to_trace[0] = BeamOpCodeAddr(op_i_return_to_trace); - beam_return_trace[0] = BeamOpCodeAddr(op_return_trace); - beam_exception_trace[0] = BeamOpCodeAddr(op_return_trace); /* UGLY */ - beam_return_time_trace[0] = BeamOpCodeAddr(op_i_return_time_trace); + beam_apply[0] = BeamOpCodeAddr(op_i_apply); + beam_apply[1] = BeamOpCodeAddr(op_normal_exit); + beam_exit[0] = BeamOpCodeAddr(op_error_action_code); + beam_continue_exit[0] = BeamOpCodeAddr(op_continue_exit); + beam_return_to_trace[0] = BeamOpCodeAddr(op_i_return_to_trace); + beam_return_trace[0] = BeamOpCodeAddr(op_return_trace); + beam_exception_trace[0] = BeamOpCodeAddr(op_return_trace); /* UGLY */ + beam_return_time_trace[0] = BeamOpCodeAddr(op_i_return_time_trace); - /* - * Enter all BIFs into the export table. - */ - for (i = 0; i < BIF_SIZE; i++) { - ep = erts_export_put(bif_table[i].module, - bif_table[i].name, - bif_table[i].arity); - bif_export[i] = ep; - ep->beam[0] = BeamOpCodeAddr(op_apply_bif); - ep->beam[1] = (BeamInstr) bif_table[i].f; - /* XXX: set func info for bifs */ - ep->info.op = BeamOpCodeAddr(op_i_func_info_IaaI); - } + install_bifs(); } /* @@ -1257,7 +1166,7 @@ void erts_dirty_process_main(ErtsSchedulerData *esdp) * I[2]: Pointer to erl_module_nif * I[3]: Function pointer to dirty NIF * - * This layout is determined by the NifExport struct + * This layout is determined by the ErtsNativeFunc struct */ ERTS_MSACC_SET_STATE_CACHED_M_X(ERTS_MSACC_STATE_NIF); @@ -1271,11 +1180,11 @@ void erts_dirty_process_main(ErtsSchedulerData *esdp) ERTS_UNREQ_PROC_MAIN_LOCK(c_p); ASSERT(!ERTS_PROC_IS_EXITING(c_p)); - if (BeamIsOpCode(*I, op_apply_bif)) { + if (BeamIsOpCode(*I, op_call_bif_W)) { exiting = erts_call_dirty_bif(esdp, c_p, I, reg); } else { - ASSERT(BeamIsOpCode(*I, op_call_nif)); + ASSERT(BeamIsOpCode(*I, op_call_nif_WWW)); exiting = erts_call_dirty_nif(esdp, c_p, I, reg); } @@ -1344,6 +1253,33 @@ Eterm error_atom[NUMBER_EXIT_CODES] = { am_badkey, /* 19 */ }; +/* Returns the return address at E[0] in printable form, skipping tracing in + * the same manner as gather_stacktrace. + * + * This is needed to generate correct stacktraces when throwing errors from + * instructions that return like an ordinary function, such as call_nif. */ +BeamInstr *erts_printable_return_address(Process* p, Eterm *E) { + Eterm *ptr = E; + + ASSERT(is_CP(*ptr)); + + while (ptr < STACK_START(p)) { + BeamInstr *cp = cp_val(*ptr); + + if (cp == beam_exception_trace || cp == beam_return_trace) { + ptr += 3; + } else if (cp == beam_return_time_trace) { + ptr += 2; + } else if (cp == beam_return_to_trace) { + ptr += 1; + } else { + return cp; + } + } + + ERTS_ASSERT(!"No continuation pointer on stack"); +} + /* * To fully understand the error handling, one must keep in mind that * when an exception is thrown, the search for a handler can jump back @@ -1373,14 +1309,14 @@ handle_error(Process* c_p, BeamInstr* pc, Eterm* reg, ErtsCodeMFA *bif_mfa) ASSERT(c_p->freason != TRAP); /* Should have been handled earlier. */ - if (c_p->freason & EXF_RESTORE_NIF) - erts_nif_export_restore_error(c_p, &pc, reg, &bif_mfa); + if (c_p->freason & EXF_RESTORE_NFUNC) + erts_nfunc_restore_error(c_p, &pc, reg, &bif_mfa); #ifdef DEBUG if (bif_mfa) { - /* Verify that bif_mfa does not point into our nif export */ - NifExport *nep = ERTS_PROC_GET_NIF_TRAP_EXPORT(c_p); - ASSERT(!nep || !ErtsInArea(bif_mfa, (char *)nep, sizeof(NifExport))); + /* Verify that bif_mfa does not point into our native function wrapper */ + ErtsNativeFunc *nep = ERTS_PROC_GET_NFUNC_TRAP_WRAPPER(c_p); + ASSERT(!nep || !ErtsInArea(bif_mfa, (char *)nep, sizeof(ErtsNativeFunc))); } #endif @@ -1443,7 +1379,7 @@ handle_error(Process* c_p, BeamInstr* pc, Eterm* reg, ErtsCodeMFA *bif_mfa) reg[2] = Value; reg[3] = c_p->ftrace; if ((new_pc = next_catch(c_p, reg))) { - c_p->cp = 0; /* To avoid keeping stale references. */ + c_p->stop[0] = NIL; /* To avoid keeping stale references. */ ERTS_RECV_MARK_CLEAR(c_p); /* No longer safe to use this position */ return new_pc; } @@ -1481,35 +1417,6 @@ next_catch(Process* c_p, Eterm *reg) { return NULL; } - /* - * Better safe than sorry here. In debug builds, produce a core - * dump if the top of the stack doesn't point to a continuation - * pointer. In other builds, ignore a non-CP at the top of stack. - */ - ASSERT(is_CP(*ptr)); - if ((is_not_CP(*ptr) || (*cp_val(*ptr) != i_return_trace && - *cp_val(*ptr) != i_return_to_trace && - *cp_val(*ptr) != i_return_time_trace )) - && c_p->cp) { - /* Can not follow cp here - code may be unloaded */ - BeamInstr *cpp = c_p->cp; - if (cpp == beam_exception_trace) { - ErtsCodeMFA *mfa = (ErtsCodeMFA*)cp_val(ptr[0]); - erts_trace_exception(c_p, mfa, - reg[1], reg[2], - ERTS_TRACER_FROM_ETERM(ptr+1)); - /* Skip return_trace parameters */ - ptr += 2; - } else if (cpp == beam_return_trace) { - /* Skip return_trace parameters */ - ptr += 2; - } else if (cpp == beam_return_time_trace) { - /* Skip return_trace parameters */ - ptr += 1; - } else if (cpp == beam_return_to_trace) { - have_return_to_trace = !0; /* Record next cp */ - } - } while (ptr < STACK_START(c_p)) { if (is_catch(*ptr)) { if (active_catches) goto found_catch; @@ -1664,6 +1571,54 @@ expand_error_value(Process* c_p, Uint freason, Eterm Value) { return Value; } + +static void +gather_stacktrace(Process* p, struct StackTrace* s, int depth) +{ + BeamInstr *prev; + Eterm *ptr; + + if (depth == 0) { + return; + } + + prev = s->depth ? s->trace[s->depth - 1] : s->pc; + ptr = p->stop; + + /* + * Traverse the stack backwards and add all unique continuation + * pointers to the buffer, up to the maximum stack trace size. + * + * Skip trace stack frames. + */ + + ASSERT(ptr >= STACK_TOP(p) && ptr <= STACK_START(p)); + + while (ptr < STACK_START(p) && depth > 0) { + if (is_CP(*ptr)) { + BeamInstr *cp = cp_val(*ptr); + + if (cp == beam_exception_trace || cp == beam_return_trace) { + ptr += 3; + } else if (cp == beam_return_time_trace) { + ptr += 2; + } else if (cp == beam_return_to_trace) { + ptr += 1; + } else { + if (cp != prev) { + /* Record non-duplicates only */ + prev = cp; + s->trace[s->depth++] = cp - 1; + depth--; + } + ptr++; + } + } else { + ptr++; + } + } +} + /* * Quick-saving the stack trace in an internal form on the heap. Note * that c_p->ftrace will point to a cons cell which holds the given args @@ -1750,11 +1705,6 @@ save_stacktrace(Process* c_p, BeamInstr* pc, Eterm* reg, s->trace[s->depth++] = pc; depth--; } - /* Save second stack entry if CP is valid and different from pc */ - if (depth > 0 && c_p->cp != 0 && c_p->cp != pc) { - s->trace[s->depth++] = c_p->cp - 1; - depth--; - } s->pc = NULL; args = make_arglist(c_p, reg, bif_mfa->arity); /* Overwrite CAR(c_p->ftrace) */ } else { @@ -1762,9 +1712,9 @@ save_stacktrace(Process* c_p, BeamInstr* pc, Eterm* reg, non_bif_stacktrace: s->current = c_p->current; - /* + /* * For a function_clause error, the arguments are in the beam - * registers, c_p->cp is valid, and c_p->current is set. + * registers and c_p->current is set. */ if ( (GET_EXC_INDEX(s->freason)) == (GET_EXC_INDEX(EXC_FUNCTION_CLAUSE)) ) { @@ -1772,18 +1722,8 @@ save_stacktrace(Process* c_p, BeamInstr* pc, Eterm* reg, ASSERT(s->current); a = s->current->arity; args = make_arglist(c_p, reg, a); /* Overwrite CAR(c_p->ftrace) */ - /* Save first stack entry */ - ASSERT(c_p->cp); - if (depth > 0) { - s->trace[s->depth++] = c_p->cp - 1; - depth--; - } s->pc = NULL; /* Ignore pc */ } else { - if (depth > 0 && c_p->cp != 0 && c_p->cp != pc) { - s->trace[s->depth++] = c_p->cp - 1; - depth--; - } s->pc = pc; } } @@ -1796,80 +1736,13 @@ save_stacktrace(Process* c_p, BeamInstr* pc, Eterm* reg, } /* Save the actual stack trace */ - erts_save_stacktrace(c_p, s, depth); + gather_stacktrace(c_p, s, depth); } void erts_save_stacktrace(Process* p, struct StackTrace* s, int depth) { - if (depth > 0) { - Eterm *ptr; - BeamInstr *prev = s->depth ? s->trace[s->depth-1] : NULL; - BeamInstr i_return_trace = beam_return_trace[0]; - BeamInstr i_return_to_trace = beam_return_to_trace[0]; - - /* - * Traverse the stack backwards and add all unique continuation - * pointers to the buffer, up to the maximum stack trace size. - * - * Skip trace stack frames. - */ - ptr = p->stop; - if (ptr < STACK_START(p) && - (is_not_CP(*ptr)|| (*cp_val(*ptr) != i_return_trace && - *cp_val(*ptr) != i_return_to_trace)) && - p->cp) { - /* Cannot follow cp here - code may be unloaded */ - BeamInstr *cpp = p->cp; - int trace_cp; - if (cpp == beam_exception_trace || cpp == beam_return_trace) { - /* Skip return_trace parameters */ - ptr += 2; - trace_cp = 1; - } else if (cpp == beam_return_to_trace) { - /* Skip return_to_trace parameters */ - ptr += 1; - trace_cp = 1; - } - else { - trace_cp = 0; - } - if (trace_cp && s->pc == cpp) { - /* - * If process 'cp' points to a return/exception trace - * instruction and 'cp' has been saved as 'pc' in - * stacktrace, we need to update 'pc' in stacktrace - * with the actual 'cp' located on the top of the - * stack; otherwise, we will lose the top stackframe - * when building the stack trace. - */ - ASSERT(is_CP(p->stop[0])); - s->pc = cp_val(p->stop[0]); - } - } - while (ptr < STACK_START(p) && depth > 0) { - if (is_CP(*ptr)) { - if (*cp_val(*ptr) == i_return_trace) { - /* Skip stack frame variables */ - do ++ptr; while (is_not_CP(*ptr)); - /* Skip return_trace parameters */ - ptr += 2; - } else if (*cp_val(*ptr) == i_return_to_trace) { - /* Skip stack frame variables */ - do ++ptr; while (is_not_CP(*ptr)); - } else { - BeamInstr *cp = cp_val(*ptr); - if (cp != prev) { - /* Record non-duplicates only */ - prev = cp; - s->trace[s->depth++] = cp - 1; - depth--; - } - ptr++; - } - } else ptr++; - } - } + gather_stacktrace(p, s, depth); } /* @@ -2128,95 +2001,66 @@ apply_bif_error_adjustment(Process *p, Export *ep, Eterm *reg, Uint arity, BeamInstr *I, Uint stack_offset) { + int apply_only; + Uint need; + + need = stack_offset /* bytes */ / sizeof(Eterm); + apply_only = stack_offset == 0; + /* * I is only set when the apply is a tail call, i.e., * from the instructions i_apply_only, i_apply_last_P, * and apply_last_IP. */ - if (I - && BeamIsOpCode(ep->beam[0], op_apply_bif) - && (ep == bif_export[BIF_error_1] - || ep == bif_export[BIF_error_2] - || ep == bif_export[BIF_exit_1] - || ep == bif_export[BIF_throw_1])) { - /* - * We are about to tail apply one of the BIFs - * erlang:error/1, erlang:error/2, erlang:exit/1, - * or erlang:throw/1. Error handling of these BIFs is - * special! - * - * We need 'p->cp' to point into the calling - * function when handling the error after the BIF has - * been applied. This in order to get the topmost - * stackframe correct. Without the following adjustment, - * 'p->cp' will point into the function that called - * current function when handling the error. We add a - * dummy stackframe in order to achieve this. - * - * Note that these BIFs unconditionally will cause - * an exception to be raised. That is, our modifications - * of 'p->cp' as well as the stack will be corrected by - * the error handling code. - * - * If we find an exception/return-to trace continuation - * pointer as the topmost continuation pointer, we do not - * need to do anything since the information already will - * be available for generation of the stacktrace. - */ - int apply_only = stack_offset == 0; - BeamInstr *cpp; + if (!(I && (ep == bif_export[BIF_error_1] || + ep == bif_export[BIF_error_2] || + ep == bif_export[BIF_exit_1] || + ep == bif_export[BIF_throw_1]))) { + return; + } - if (apply_only) { - ASSERT(p->cp != NULL); - cpp = p->cp; - } - else { - ASSERT(is_CP(p->stop[0])); - cpp = cp_val(p->stop[0]); - } + /* + * We are about to tail apply one of the BIFs erlang:error/1, + * erlang:error/2, erlang:exit/1, or erlang:throw/1. Error handling of + * these BIFs is special! + * + * We need the topmost continuation pointer to point into the calling + * function when handling the error after the BIF has been applied. This in + * order to get the topmost stackframe correct. + * + * Note that these BIFs will unconditionally cause an exception to be + * raised. That is, our modifications of the stack will be corrected by the + * error handling code. + */ + if (need == 0) { + need = 1; /* i_apply_only */ + } - if (cpp != beam_exception_trace - && cpp != beam_return_trace - && cpp != beam_return_to_trace) { - Uint need = stack_offset /* bytes */ / sizeof(Eterm); - if (need == 0) - need = 1; /* i_apply_only */ - if (p->stop - p->htop < need) - erts_garbage_collect(p, (int) need, reg, arity+1); - p->stop -= need; - - if (apply_only) { - /* - * Called from the i_apply_only instruction. - * - * 'p->cp' contains continuation pointer pointing - * into the function that called current function. - * We push that continuation pointer onto the stack, - * and set 'p->cp' to point into current function. - */ + if (p->stop - p->htop < need) { + erts_garbage_collect(p, (int) need, reg, arity+1); + } - p->stop[0] = make_cp(p->cp); - p->cp = I; - } - else { - /* - * Called from an i_apply_last_p, or apply_last_IP, - * instruction. - * - * Calling instruction will after we return read - * a continuation pointer from the stack and write - * it to 'p->cp', and then remove the topmost - * stackframe of size 'stack_offset'. - * - * We have sized the dummy-stackframe so that it - * will be removed by the instruction we currently - * are executing, and leave the stackframe that - * normally would have been removed intact. - * - */ - p->stop[0] = make_cp(I); - } - } + if (apply_only) { + /* + * Called from the i_apply_only instruction. + * + * Push the continuation pointer for the current function to the stack. + */ + p->stop -= need; + p->stop[0] = make_cp(I); + } else { + /* + * Called from an i_apply_last_* instruction. + * + * The calling instruction will deallocate a stack frame of size + * 'stack_offset'. + * + * Push the continuation pointer for the current function to the stack, + * and then add a dummy stackframe for the i_apply_last* instruction + * to discard. + */ + p->stop[0] = make_cp(I); + p->stop -= need; } } @@ -2437,10 +2281,10 @@ erts_hibernate(Process* c_p, Eterm* reg) c_p->arg_reg[0] = module; c_p->arg_reg[1] = function; c_p->arg_reg[2] = args; - c_p->stop = STACK_START(c_p); + c_p->stop = c_p->hend - 1; /* Keep first continuation pointer */ + ASSERT(c_p->stop[0] == make_cp(beam_apply+1)); c_p->catches = 0; c_p->i = beam_apply; - c_p->cp = (BeamInstr *) beam_apply+1; /* * If there are no waiting messages, garbage collect and @@ -3268,10 +3112,10 @@ erts_is_builtin(Eterm Mod, Eterm Name, int arity) e.info.mfa.arity = arity; if ((ep = export_get(&e)) == NULL) { - return 0; + return 0; } - return ep->addressv[erts_active_code_ix()] == ep->beam && - BeamIsOpCode(ep->beam[0], op_apply_bif); + + return ep->bif_table_index != -1; } diff --git a/erts/emulator/beam/beam_load.c b/erts/emulator/beam/beam_load.c index 3d5683f19f..8fe046095f 100644 --- a/erts/emulator/beam/beam_load.c +++ b/erts/emulator/beam/beam_load.c @@ -141,7 +141,7 @@ typedef struct { * eventually patch with a pointer into * the export entry. */ - BifFunction bf; /* Pointer to BIF function if BIF; + Export *bif; /* Pointer to export entry if BIF; * NULL otherwise. */ } ImportEntry; @@ -845,17 +845,23 @@ erts_finish_loading(Binary* magic, Process* c_p, if (ep == NULL || ep->info.mfa.module != module) { continue; } - if (ep->addressv[code_ix] == ep->beam) { - if (BeamIsOpCode(ep->beam[0], op_apply_bif)) { - continue; - } else if (BeamIsOpCode(ep->beam[0], op_i_generic_breakpoint)) { + + DBG_CHECK_EXPORT(ep, code_ix); + + if (ep->addressv[code_ix] == ep->trampoline.raw) { + if (BeamIsOpCode(ep->trampoline.op, op_i_generic_breakpoint)) { ERTS_LC_ASSERT(erts_thr_progress_is_blocking()); ASSERT(mod_tab_p->curr.num_traced_exports > 0); - erts_clear_export_break(mod_tab_p, &ep->info); - ep->addressv[code_ix] = (BeamInstr *) ep->beam[1]; - ep->beam[1] = 0; + + erts_clear_export_break(mod_tab_p, ep); + + ep->addressv[code_ix] = + (BeamInstr*)ep->trampoline.breakpoint.address; + ep->trampoline.breakpoint.address = 0; + + ASSERT(ep->addressv[code_ix] != ep->trampoline.raw); } - ASSERT(ep->beam[1] == 0); + ASSERT(ep->trampoline.breakpoint.address == 0); } } ASSERT(mod_tab_p->curr.num_breakpoints == 0); @@ -1471,15 +1477,14 @@ load_import_table(LoaderState* stp) } stp->import[i].arity = arity; stp->import[i].patches = 0; - stp->import[i].bf = NULL; + stp->import[i].bif = NULL; /* - * If the export entry refers to a BIF, get the pointer to - * the BIF function. + * If the export entry refers to a BIF, save a pointer to the BIF entry. */ if ((e = erts_active_export_entry(mod, func, arity)) != NULL) { - if (BeamIsOpCode(e->beam[0], op_apply_bif)) { - stp->import[i].bf = (BifFunction) e->beam[1]; + if (e->bif_table_index != -1) { + stp->import[i].bif = e; if (func == am_load_nif && mod == am_erlang && arity == 2) { stp->may_load_nif = 1; } @@ -1530,33 +1535,6 @@ read_export_table(LoaderState* stp) LoadError2(stp, "export table entry %u: label %u not resolved", i, n); } stp->export[i].address = address = stp->codev + value; - - /* - * Find out if there is a BIF with the same name. - */ - - if (!is_bif(stp->module, func, arity)) { - continue; - } - - /* - * This is a stub for a BIF. - * - * It should not be exported, and the information in its - * func_info instruction should be invalidated so that it - * can be filtered out by module_info(functions) and by - * any other functions that walk through all local functions. - */ - - if (stp->labels[n].num_patches > 0) { - LoadError3(stp, "there are local calls to the stub for " - "the BIF %T:%T/%d", - stp->module, func, arity); - } - stp->export[i].address = NULL; - address[-1] = 0; - address[-2] = NIL; - address[-3] = NIL; } return 1; @@ -1564,25 +1542,16 @@ read_export_table(LoaderState* stp) return 0; } - static int is_bif(Eterm mod, Eterm func, unsigned arity) { - Export* e = erts_active_export_entry(mod, func, arity); - if (e == NULL) { - return 0; - } - if (! BeamIsOpCode(e->beam[0], op_apply_bif)) { - return 0; - } - if (mod == am_erlang && func == am_apply && arity == 3) { - /* - * erlang:apply/3 is a special case -- it is implemented - * as an instruction and it is OK to redefine it. - */ - return 0; + Export *e = erts_active_export_entry(mod, func, arity); + + if (e != NULL) { + return e->bif_table_index != -1; } - return 1; + + return 0; } static int @@ -2534,10 +2503,14 @@ load_code(LoaderState* stp) if (i >= stp->num_imports) { LoadError1(stp, "invalid import table index %d", i); } - if (stp->import[i].bf == NULL) { + if (stp->import[i].bif == NULL) { LoadError1(stp, "not a BIF: import table index %d", i); } - code[ci++] = (BeamInstr) stp->import[i].bf; + { + int bif_index = stp->import[i].bif->bif_table_index; + BifEntry *bif_entry = &bif_table[bif_index]; + code[ci++] = (BeamInstr) bif_entry->f; + } break; case 'P': /* Byte offset into tuple or stack */ case 'Q': /* Like 'P', but packable */ @@ -2845,18 +2818,43 @@ load_code(LoaderState* stp) switch (stp->specific_op) { case op_i_func_info_IaaI: { + int padding_required; Sint offset; + if (function_number >= stp->num_functions) { LoadError1(stp, "too many functions in module (header said %u)", stp->num_functions); } - if (stp->may_load_nif) { + /* Native function calls may be larger than their stubs, so + * we'll need to make sure any potentially-native function stub + * is padded with enough room. + * + * Note that the padding is applied for the previous function, + * not the current one, so we check whether the old F/A is + * a BIF. */ + padding_required = last_func_start && (stp->may_load_nif || + is_bif(stp->module, stp->function, stp->arity)); + + /* + * Save context for error messages. + */ + stp->function = code[ci-2]; + stp->arity = code[ci-1]; + + /* + * Save current offset of into the line instruction array. + */ + if (stp->func_line) { + stp->func_line[function_number] = stp->current_li; + } + + if (padding_required) { const int finfo_ix = ci - FUNC_INFO_SZ; - if (finfo_ix - last_func_start < BEAM_NIF_MIN_FUNC_SZ && last_func_start) { + if (finfo_ix - last_func_start < BEAM_NATIVE_MIN_FUNC_SZ) { /* Must make room for call_nif op */ - int pad = BEAM_NIF_MIN_FUNC_SZ - (finfo_ix - last_func_start); - ASSERT(pad > 0 && pad < BEAM_NIF_MIN_FUNC_SZ); + int pad = BEAM_NATIVE_MIN_FUNC_SZ - (finfo_ix - last_func_start); + ASSERT(pad > 0 && pad < BEAM_NATIVE_MIN_FUNC_SZ); CodeNeed(pad); sys_memmove(&code[finfo_ix+pad], &code[finfo_ix], FUNC_INFO_SZ*sizeof(BeamInstr)); @@ -2867,20 +2865,6 @@ load_code(LoaderState* stp) } last_func_start = ci; - /* - * Save current offset of into the line instruction array. - */ - - if (stp->func_line) { - stp->func_line[function_number] = stp->current_li; - } - - /* - * Save context for error messages. - */ - stp->function = code[ci-2]; - stp->arity = code[ci-1]; - /* When this assert is triggered, it is normally a sign that the size of the ops.tab i_func_info instruction is not the same as FUNC_INFO_SZ */ @@ -2910,7 +2894,6 @@ load_code(LoaderState* stp) case op_i_bs_match_string_yfWW: new_string_patch(stp, ci-1); break; - case op_catch_yf: /* code[ci-3] &&lb_catch_yf * code[ci-2] y-register offset in E @@ -3184,6 +3167,26 @@ is_killed_by_make_fun(LoaderState* stp, GenOpArg Reg, GenOpArg idx) } } +/* Test whether Bif is "heavy" and should always go through its export entry */ +static int +is_heavy_bif(LoaderState* stp, GenOpArg Bif) +{ + Export *bif_export; + + if (Bif.type != TAG_u || Bif.val >= stp->num_imports) { + return 0; + } + + bif_export = stp->import[Bif.val].bif; + + if (bif_export) { + int bif_index = bif_export->bif_table_index; + return bif_table[bif_index].kind == BIF_KIND_HEAVY; + } + + return 0; +} + /* * Generate an instruction for element/2. */ @@ -5211,27 +5214,52 @@ final_touch(LoaderState* stp, struct erl_module_instance* inst_p) */ for (i = 0; i < stp->num_exps; i++) { - Export* ep; - BeamInstr* address = stp->export[i].address; + Export* ep; + BeamInstr* address = stp->export[i].address; - if (address == NULL) { - /* Skip stub for a BIF */ - continue; - } - ep = erts_export_put(stp->module, stp->export[i].function, - stp->export[i].arity); - if (on_load) { - /* - * on_load: Don't make any of the exported functions - * callable yet. Keep any function in the current - * code callable. - */ - ep->beam[1] = (BeamInstr) address; - } - else + ep = erts_export_put(stp->module, + stp->export[i].function, + stp->export[i].arity); + + /* Fill in BIF stubs with a proper call to said BIF. */ + if (ep->bif_table_index != -1) { + erts_write_bif_wrapper(ep, address); + } + + if (on_load) { + /* + * on_load: Don't make any of the exported functions + * callable yet. Keep any function in the current + * code callable. + */ + ep->trampoline.not_loaded.deferred = (BeamInstr) address; + } else { ep->addressv[erts_staging_code_ix()] = address; + } } +#ifdef DEBUG + /* Ensure that we've loaded stubs for all BIFs in this module. */ + for (i = 0; i < BIF_SIZE; i++) { + BifEntry *entry = &bif_table[i]; + + if (stp->module == entry->module) { + Export *ep = erts_export_put(entry->module, + entry->name, + entry->arity); + BeamInstr *addr = ep->addressv[erts_staging_code_ix()]; + + if (!ErtsInArea(addr, stp->codev, stp->ci * sizeof(BeamInstr))) { + erts_exit(ERTS_ABORT_EXIT, + "Module %T doesn't export BIF %T/%i\n", + entry->module, + entry->name, + entry->arity); + } + } + } +#endif + /* * Import functions and patch all callers. */ @@ -5403,15 +5431,14 @@ transform_engine(LoaderState* st) i = instr->a[ap].val; ASSERT(i < st->num_imports); - if (i >= st->num_imports || st->import[i].bf == NULL) + if (i >= st->num_imports || st->import[i].bif == NULL) goto restart; if (bif_number != -1 && - bif_export[bif_number]->beam[1] != (BeamInstr) st->import[i].bf) { + bif_export[bif_number] != st->import[i].bif) { goto restart; } } break; - #endif #if defined(TOP_is_not_bif) case TOP_is_not_bif: @@ -5441,7 +5468,7 @@ transform_engine(LoaderState* st) * they are special. */ if (i < st->num_imports) { - if (st->import[i].bf != NULL || + if (st->import[i].bif != NULL || (st->import[i].module == am_erlang && st->import[i].function == am_apply && (st->import[i].arity == 2 || st->import[i].arity == 3))) { @@ -6286,12 +6313,12 @@ exported_from_module(Process* p, /* Process whose heap to use. */ if (ep->info.mfa.module == mod) { Eterm tuple; - - if (ep->addressv[code_ix] == ep->beam && - BeamIsOpCode(ep->beam[0], op_call_error_handler)) { - /* There is a call to the function, but it does not exist. */ - continue; - } + + if (ep->addressv[code_ix] == ep->trampoline.raw && + BeamIsOpCode(ep->trampoline.op, op_call_error_handler)) { + /* There is a call to the function, but it does not exist. */ + continue; + } if (hp == hend) { int need = 10 * 5; diff --git a/erts/emulator/beam/beam_load.h b/erts/emulator/beam/beam_load.h index 156c3c45e2..e7127c5b08 100644 --- a/erts/emulator/beam/beam_load.h +++ b/erts/emulator/beam/beam_load.h @@ -106,7 +106,7 @@ typedef struct beam_code_header { }BeamCodeHeader; -# define BEAM_NIF_MIN_FUNC_SZ 4 +# define BEAM_NATIVE_MIN_FUNC_SZ 4 void erts_release_literal_area(struct ErtsLiteralArea_* literal_area); int erts_is_module_native(BeamCodeHeader* code); diff --git a/erts/emulator/beam/bif.c b/erts/emulator/beam/bif.c index 9f67f46b31..d3fd99932a 100644 --- a/erts/emulator/beam/bif.c +++ b/erts/emulator/beam/bif.c @@ -4971,15 +4971,28 @@ void erts_init_trap_export(Export* ep, Eterm m, Eterm f, Uint a, Eterm (*bif)(BIF_ALIST)) { int i; + sys_memset((void *) ep, 0, sizeof(Export)); + for (i=0; i<ERTS_NUM_CODE_IX; i++) { - ep->addressv[i] = ep->beam; + ep->addressv[i] = ep->trampoline.raw; } + ep->info.mfa.module = m; ep->info.mfa.function = f; ep->info.mfa.arity = a; - ep->beam[0] = BeamOpCodeAddr(op_apply_bif); - ep->beam[1] = (BeamInstr) bif; + ep->trampoline.op = BeamOpCodeAddr(op_call_bif_W); + ep->trampoline.raw[1] = (BeamInstr)bif; +} + +/* + * Writes a BIF call wrapper to the given address. + */ +void erts_write_bif_wrapper(Export *export, BeamInstr *address) { + BifEntry *entry = &bif_table[export->bif_table_index]; + + address[0] = BeamOpCodeAddr(op_call_bif_W); + address[1] = (BeamInstr)entry->f; } void erts_init_bif(void) @@ -5031,7 +5044,7 @@ void erts_init_bif(void) } /* - * Scheduling of BIFs via NifExport... + * Scheduling of BIFs via ErtsNativeFunc... */ #define ERTS_WANT_NFUNC_SCHED_INTERNALS__ #include "erl_nfunc_sched.h" @@ -5046,8 +5059,8 @@ schedule(Process *c_p, Process *dirty_shadow_proc, int argc, Eterm *argv) { ERTS_LC_ASSERT(ERTS_PROC_LOCK_MAIN & erts_proc_lc_my_proc_locks(c_p)); - (void) erts_nif_export_schedule(c_p, dirty_shadow_proc, - mfa, pc, BeamOpCodeAddr(op_apply_bif), + (void) erts_nfunc_schedule(c_p, dirty_shadow_proc, + mfa, pc, BeamOpCodeAddr(op_call_bif_W), dfunc, ifunc, module, function, argc, argv); @@ -5056,23 +5069,23 @@ schedule(Process *c_p, Process *dirty_shadow_proc, static BIF_RETTYPE dirty_bif_result(BIF_ALIST_1) { - NifExport *nep = (NifExport *) ERTS_PROC_GET_NIF_TRAP_EXPORT(BIF_P); - erts_nif_export_restore(BIF_P, nep, BIF_ARG_1); + ErtsNativeFunc *nep = (ErtsNativeFunc *) ERTS_PROC_GET_NFUNC_TRAP_WRAPPER(BIF_P); + erts_nfunc_restore(BIF_P, nep, BIF_ARG_1); BIF_RET(BIF_ARG_1); } static BIF_RETTYPE dirty_bif_trap(BIF_ALIST) { - NifExport *nep = (NifExport *) ERTS_PROC_GET_NIF_TRAP_EXPORT(BIF_P); + ErtsNativeFunc *nep = (ErtsNativeFunc *) ERTS_PROC_GET_NFUNC_TRAP_WRAPPER(BIF_P); /* * Arity and argument registers already set * correct by call to dirty_bif_trap()... */ - ASSERT(BIF_P->arity == nep->exp.info.mfa.arity); + ASSERT(BIF_P->arity == nep->trampoline.info.mfa.arity); - erts_nif_export_restore(BIF_P, nep, THE_NON_VALUE); + erts_nfunc_restore(BIF_P, nep, THE_NON_VALUE); BIF_P->i = (BeamInstr *) nep->func; BIF_P->freason = TRAP; @@ -5087,8 +5100,8 @@ static BIF_RETTYPE dirty_bif_exception(BIF_ALIST_2) freason = signed_val(BIF_ARG_1); - /* Restore orig info for error and clear nif export in handle_error() */ - freason |= EXF_RESTORE_NIF; + /* Restore orig info for error and clear nif wrapper in handle_error() */ + freason |= EXF_RESTORE_NFUNC; BIF_P->fvalue = BIF_ARG_2; @@ -5126,6 +5139,7 @@ erts_schedule_bif(Process *proc, if (!ERTS_PROC_IS_EXITING(c_p)) { Export *exp; BifFunction dbif, ibif; + BeamInstr call_instr; BeamInstr *pc; /* @@ -5160,29 +5174,41 @@ erts_schedule_bif(Process *proc, if (i == NULL) { ERTS_INTERNAL_ERROR("Missing instruction pointer"); } + + if (BeamIsOpCode(*i, op_i_generic_breakpoint)) { + ErtsCodeInfo *ci; + GenericBp *bp; + + ci = erts_code_to_codeinfo(i); + bp = ci->u.gen_bp; + + call_instr = bp->orig_instr; + } else { + call_instr = *i; + } + #ifdef HIPE - else if (proc->flags & F_HIPE_MODE) { + if (proc->flags & F_HIPE_MODE) { /* Pointer to bif export in i */ exp = (Export *) i; - pc = c_p->cp; + pc = cp_val(c_p->stop[0]); mfa = &exp->info.mfa; - } + } else /* !! This is part of the if clause below !! */ #endif - else if (BeamIsOpCode(*i, op_call_bif_e)) { - /* Pointer to bif export in i+1 */ - exp = (Export *) i[1]; + if (BeamIsOpCode(call_instr, op_call_light_bif_be)) { + /* Pointer to bif export in i+2 */ + exp = (Export *) i[2]; pc = i; mfa = &exp->info.mfa; } - else if (BeamIsOpCode(*i, op_call_bif_only_e)) { - /* Pointer to bif export in i+1 */ - exp = (Export *) i[1]; + else if (BeamIsOpCode(call_instr, op_call_light_bif_only_be)) { + /* Pointer to bif export in i+2 */ + exp = (Export *) i[2]; pc = i; mfa = &exp->info.mfa; } - else if (BeamIsOpCode(*i, op_apply_bif)) { - /* Pointer to bif in i+1, and mfa in i-3 */ - pc = c_p->cp; + else if (BeamIsOpCode(call_instr, op_call_bif_W)) { + pc = cp_val(c_p->stop[0]); mfa = erts_code_to_codemfa(i); } else { @@ -5210,7 +5236,7 @@ erts_schedule_bif(Process *proc, static BIF_RETTYPE call_bif(Process *c_p, Eterm *reg, BeamInstr *I) { - NifExport *nep = ERTS_I_BEAM_OP_TO_NIF_EXPORT(I); + ErtsNativeFunc *nep = ERTS_I_BEAM_OP_TO_NFUNC(I); ErtsBifFunc bif = (ErtsBifFunc) nep->func; BIF_RETTYPE ret; @@ -5223,12 +5249,12 @@ call_bif(Process *c_p, Eterm *reg, BeamInstr *I) ret = (*bif)(c_p, reg, I); if (is_value(ret)) - erts_nif_export_restore(c_p, nep, ret); + erts_nfunc_restore(c_p, nep, ret); else if (c_p->freason != TRAP) - c_p->freason |= EXF_RESTORE_NIF; /* restore in handle_error() */ + c_p->freason |= EXF_RESTORE_NFUNC; /* restore in handle_error() */ else if (nep->func == ERTS_SCHED_BIF_TRAP_MARKER) { /* BIF did an ordinary trap... */ - erts_nif_export_restore(c_p, nep, ret); + erts_nfunc_restore(c_p, nep, ret); } /* else: * BIF rescheduled itself using erts_schedule_bif(). @@ -5245,7 +5271,7 @@ erts_call_dirty_bif(ErtsSchedulerData *esdp, Process *c_p, BeamInstr *I, Eterm * int exiting; Process *dirty_shadow_proc; ErtsBifFunc bf; - NifExport *nep; + ErtsNativeFunc *nep; #ifdef DEBUG Eterm *c_p_htop; erts_aint32_t state; @@ -5258,8 +5284,8 @@ erts_call_dirty_bif(ErtsSchedulerData *esdp, Process *c_p, BeamInstr *I, Eterm * #endif - nep = ERTS_I_BEAM_OP_TO_NIF_EXPORT(I); - ASSERT(nep == ERTS_PROC_GET_NIF_TRAP_EXPORT(c_p)); + nep = ERTS_I_BEAM_OP_TO_NFUNC(I); + ASSERT(nep == ERTS_PROC_GET_NFUNC_TRAP_WRAPPER(c_p)); nep->func = ERTS_SCHED_BIF_TRAP_MARKER; @@ -5273,7 +5299,6 @@ erts_call_dirty_bif(ErtsSchedulerData *esdp, Process *c_p, BeamInstr *I, Eterm * dirty_shadow_proc->freason = c_p->freason; dirty_shadow_proc->fvalue = c_p->fvalue; dirty_shadow_proc->ftrace = c_p->ftrace; - dirty_shadow_proc->cp = c_p->cp; dirty_shadow_proc->i = c_p->i; #ifdef DEBUG @@ -5320,7 +5345,6 @@ erts_call_dirty_bif(ErtsSchedulerData *esdp, Process *c_p, BeamInstr *I, Eterm * c_p->freason = dirty_shadow_proc->freason; c_p->fvalue = dirty_shadow_proc->fvalue; c_p->ftrace = dirty_shadow_proc->ftrace; - c_p->cp = dirty_shadow_proc->cp; c_p->i = dirty_shadow_proc->i; c_p->arity = dirty_shadow_proc->arity; } diff --git a/erts/emulator/beam/bif.tab b/erts/emulator/beam/bif.tab index 602db106b1..19dabc0514 100644 --- a/erts/emulator/beam/bif.tab +++ b/erts/emulator/beam/bif.tab @@ -25,13 +25,14 @@ # # <bif-decl> ::= "bif" <bif> <C-name>* | # "ubif" <bif> <C-name>* | -# "gcbif" <bif> <C-name>* +# "hbif" <bif> <C-name>* # <bif> ::= <module> ":" <name> "/" <arity> # -# ubif: Use for operators and guard BIFs that never build anything -# on the heap (such as tuple_size/1) and operators. +# ubif: Use for operators and guard BIFs. # -# gcbif: Use for guard BIFs that may build on the heap (such as abs/1). +# hbif: Use for BIFs that perform garbage collection or need up-to-date +# information on where they were called from. These must be called +# through the export entry. # # bif: Use for all other BIFs. # @@ -60,7 +61,7 @@ bif erlang:display_string/1 bif erlang:display_nl/0 ubif erlang:element/2 bif erlang:erase/0 -bif erlang:erase/1 +hbif erlang:erase/1 bif erlang:exit/1 bif erlang:exit/2 bif erlang:exit_signal/2 @@ -70,7 +71,7 @@ ubif erlang:float/1 bif erlang:float_to_list/1 bif erlang:float_to_list/2 bif erlang:fun_info/2 -bif erts_internal:garbage_collect/1 +hbif erts_internal:garbage_collect/1 bif erlang:get/0 bif erlang:get/1 bif erlang:get_keys/1 @@ -127,10 +128,10 @@ bif erlang:ports/0 bif erlang:pre_loaded/0 bif erlang:process_flag/2 bif erts_internal:process_flag/3 -bif erlang:process_info/1 -bif erlang:process_info/2 +hbif erlang:process_info/1 +hbif erlang:process_info/2 bif erlang:processes/0 -bif erlang:put/2 +hbif erlang:put/2 bif erlang:register/2 bif erlang:registered/0 ubif erlang:round/1 @@ -174,7 +175,7 @@ bif erts_internal:port_connect/2 bif erts_internal:request_system_task/3 bif erts_internal:request_system_task/4 -bif erts_internal:check_process_code/1 +hbif erts_internal:check_process_code/1 bif erts_internal:map_to_tuple_keys/1 bif erts_internal:term_type/1 @@ -195,6 +196,8 @@ bif erts_internal:dirty_process_handle_signals/1 bif erts_internal:create_dist_channel/4 +bif erts_internal:ets_super_user/1 + # inet_db support bif erlang:port_set_data/2 bif erlang:port_get_data/1 @@ -464,7 +467,7 @@ bif code:is_module_native/1 # New Bifs in R9C. # -bif erlang:hibernate/3 +hbif erlang:hibernate/3 bif error_logger:warning_map/0 # @@ -742,3 +745,11 @@ bif erts_internal:spawn_system_process/3 bif erlang:integer_to_list/2 bif erlang:integer_to_binary/2 bif persistent_term:get/2 + +# +# New in 22.1 +# + +bif erts_internal:ets_lookup_binary_info/2 +bif erts_internal:ets_raw_first/1 +bif erts_internal:ets_raw_next/2 diff --git a/erts/emulator/beam/bif_instrs.tab b/erts/emulator/beam/bif_instrs.tab index 8e0caa38a3..de5305bde4 100644 --- a/erts/emulator/beam/bif_instrs.tab +++ b/erts/emulator/beam/bif_instrs.tab @@ -212,26 +212,32 @@ i_length.execute(Fail, Live, Dst) { // Call a BIF, store the result in x(0) and transfer control to the // next instruction. // -call_bif(Exp) { +call_light_bif(Bif, Exp) { + Export *export; ErtsBifFunc bf; + Eterm result; ErlHeapFragment *live_hf_end; - Export *export = (Export*) $Exp; + + bf = (ErtsBifFunc) $Bif; + export = (Export*) $Exp; if (!((FCALLS - 1) > 0 || (FCALLS-1) > neg_o_reds)) { /* * If we have run out of reductions, do a context * switch before calling the BIF. */ - c_p->arity = GET_BIF_ARITY(export); + c_p->arity = GET_EXPORT_ARITY(export); c_p->current = &export->info.mfa; goto context_switch3; } - ERTS_MSACC_SET_BIF_STATE_CACHED_X(GET_BIF_MODULE(export), - GET_BIF_ADDRESS(export)); + if (ERTS_UNLIKELY(export->is_bif_traced)) { + $SAVE_CONTINUATION_POINTER($NEXT_INSTRUCTION); + $DISPATCH_EXPORT(export); + } - bf = GET_BIF_ADDRESS(export); + ERTS_MSACC_SET_BIF_STATE_CACHED_X(GET_EXPORT_MODULE(export), bf); PRE_BIF_SWAPOUT(c_p); ERTS_DBG_CHK_REDS(c_p, FCALLS); @@ -243,21 +249,26 @@ call_bif(Exp) { ERTS_VERIFY_UNUSED_TEMP_ALLOC(c_p); live_hf_end = c_p->mbuf; ERTS_CHK_MBUF_SZ(c_p); + result = (*bf)(c_p, reg, I); + + /* Only heavy BIFs may GC. */ + ASSERT(E == c_p->stop); + ERTS_CHK_MBUF_SZ(c_p); ASSERT(!ERTS_PROC_IS_EXITING(c_p) || is_non_value(result)); ERTS_VERIFY_UNUSED_TEMP_ALLOC(c_p); ERTS_HOLE_CHECK(c_p); ERTS_REQ_PROC_MAIN_LOCK(c_p); if (ERTS_IS_GC_DESIRED(c_p)) { - Uint arity = GET_BIF_ARITY(export); + Uint arity = GET_EXPORT_ARITY(export); result = erts_gc_after_bif_call_lhf(c_p, live_hf_end, result, reg, arity); E = c_p->stop; } - PROCESS_MAIN_CHK_LOCKS(c_p); HTOP = HEAP_TOP(c_p); FCALLS = c_p->fcalls; + PROCESS_MAIN_CHK_LOCKS(c_p); ERTS_DBG_CHK_REDS(c_p, FCALLS); /* @@ -280,10 +291,9 @@ call_bif(Exp) { * erlang code or by nif_bif.epilogue() when the BIF * is done). */ - SET_CP(c_p, $NEXT_INSTRUCTION); + $SAVE_CONTINUATION_POINTER($NEXT_INSTRUCTION); SET_I(c_p->i); - SWAPIN; - Dispatch(); + $DISPATCH(); } /* @@ -297,29 +307,38 @@ call_bif(Exp) { // // Call a BIF tail-recursively, storing the result in x(0) and doing -// a return to the continuation poiner (c_p->cp). +// a return to the continuation poiner. // - -call_bif_only(Exp) { +call_light_bif_only(Bif, Exp) { + ErlHeapFragment *live_hf_end; ErtsBifFunc bf; + Export *export; Eterm result; - ErlHeapFragment *live_hf_end; - Export *export = (Export*) $Exp; + + bf = (ErtsBifFunc) $Bif; + export = (Export*) $Exp; if (!((FCALLS - 1) > 0 || (FCALLS-1) > neg_o_reds)) { /* * If we have run out of reductions, do a context * switch before calling the BIF. */ - c_p->arity = GET_BIF_ARITY(export); + c_p->arity = GET_EXPORT_ARITY(export); c_p->current = &export->info.mfa; goto context_switch3; } - ERTS_MSACC_SET_BIF_STATE_CACHED_X(GET_BIF_MODULE(export), - GET_BIF_ADDRESS(export)); + if (ERTS_UNLIKELY(export->is_bif_traced)) { + /* Set up a dummy stack frame so we can perform a normal call. Loader + * transformations ensure that the next instruction after this is + * 'deallocate_return 0'. */ + $AH(0, 0, GET_EXPORT_ARITY(export)); + + $SAVE_CONTINUATION_POINTER($NEXT_INSTRUCTION); + $DISPATCH_EXPORT(export); + } - bf = GET_BIF_ADDRESS(export); + ERTS_MSACC_SET_BIF_STATE_CACHED_X(GET_EXPORT_MODULE(export), bf); PRE_BIF_SWAPOUT(c_p); ERTS_DBG_CHK_REDS(c_p, FCALLS); @@ -331,21 +350,26 @@ call_bif_only(Exp) { ERTS_VERIFY_UNUSED_TEMP_ALLOC(c_p); live_hf_end = c_p->mbuf; ERTS_CHK_MBUF_SZ(c_p); + result = (*bf)(c_p, reg, I); + + /* Only heavy BIFs may GC. */ + ASSERT(E == c_p->stop); + ERTS_CHK_MBUF_SZ(c_p); ASSERT(!ERTS_PROC_IS_EXITING(c_p) || is_non_value(result)); ERTS_VERIFY_UNUSED_TEMP_ALLOC(c_p); ERTS_HOLE_CHECK(c_p); ERTS_REQ_PROC_MAIN_LOCK(c_p); if (ERTS_IS_GC_DESIRED(c_p)) { - Uint arity = GET_BIF_ARITY(export); + Uint arity = GET_EXPORT_ARITY(export); result = erts_gc_after_bif_call_lhf(c_p, live_hf_end, result, reg, arity); E = c_p->stop; } - PROCESS_MAIN_CHK_LOCKS(c_p); HTOP = HEAP_TOP(c_p); FCALLS = c_p->fcalls; + PROCESS_MAIN_CHK_LOCKS(c_p); ERTS_DBG_CHK_REDS(c_p, FCALLS); /* @@ -367,11 +391,10 @@ call_bif_only(Exp) { } else if (c_p->freason == TRAP) { /* * Dispatch to a trap. When the trap is done, a jump - * to the continuation pointer (c_p->cp) will be done. + * to the continuation pointer on the stack will be done. */ SET_I(c_p->i); - SWAPIN; - Dispatch(); + $DISPATCH(); } /* @@ -413,17 +436,17 @@ send() { r(0) = result; CHECK_TERM(r(0)); } else if (c_p->freason == TRAP) { - SET_CP(c_p, $NEXT_INSTRUCTION); + $SAVE_CONTINUATION_POINTER($NEXT_INSTRUCTION); SET_I(c_p->i); SWAPIN; - Dispatch(); + $DISPATCH(); } else { goto find_func_info; } } call_nif := nif_bif.call_nif.epilogue; -apply_bif := nif_bif.apply_bif.epilogue; +call_bif := nif_bif.call_bif.epilogue; nif_bif.head() { Eterm nif_bif_result; @@ -433,7 +456,7 @@ nif_bif.head() { ErtsCodeMFA *codemfa; } -nif_bif.call_nif() { +nif_bif.call_nif(Func, NifMod, DirtyFunc) { /* * call_nif is always first instruction in function: * @@ -443,11 +466,14 @@ nif_bif.call_nif() { * I[0]: &&call_nif * I[1]: Function pointer to NIF function * I[2]: Pointer to erl_module_nif - * I[3]: Function pointer to dirty NIF + * I[3]: Function pointer to dirty NIF. This is not used in this + * instruction, but dirty schedulers look at it. * - * This layout is determined by the NifExport struct + * This layout is determined by the ErtsNativeFunc struct */ + (void)$DirtyFunc; + ERTS_MSACC_SET_STATE_CACHED_M_X(ERTS_MSACC_STATE_NIF); codemfa = erts_code_to_codemfa(I); @@ -465,12 +491,12 @@ nif_bif.call_nif() { ASSERT(!ERTS_PROC_IS_EXITING(c_p)); { typedef Eterm NifF(struct enif_environment_t*, int argc, Eterm argv[]); - NifF* fp = vbf = (NifF*) I[1]; + NifF* fp = vbf = (NifF*) $Func; struct enif_environment_t env; ASSERT(c_p->scheduler_data); live_hf_end = c_p->mbuf; ERTS_CHK_MBUF_SZ(c_p); - erts_pre_nif(&env, c_p, (struct erl_module_nif*)I[2], NULL); + erts_pre_nif(&env, c_p, (struct erl_module_nif*)$NifMod, NULL); ASSERT((c_p->scheduler_data)->current_nif == NULL); (c_p->scheduler_data)->current_nif = &env; @@ -495,15 +521,15 @@ nif_bif.call_nif() { DTRACE_NIF_RETURN(c_p, codemfa); } -nif_bif.apply_bif() { +nif_bif.call_bif(Func) { /* - * At this point, I points to the code[0] in the export entry for - * the BIF: + * At this point, I points to the code[0] in the native function wrapper + * for the BIF: * * code[-3]: Module * code[-2]: Function * code[-1]: Arity - * code[0]: &&apply_bif + * code[0]: &&call_bif * code[1]: Function pointer to BIF function */ @@ -515,21 +541,19 @@ nif_bif.apply_bif() { codemfa = erts_code_to_codemfa(I); - ERTS_MSACC_SET_BIF_STATE_CACHED_X(codemfa->module, (BifFunction)Arg(0)); - + ERTS_MSACC_SET_BIF_STATE_CACHED_X(codemfa->module, (BifFunction)$Func); /* In case we apply process_info/1,2 or load_nif/1 */ c_p->current = codemfa; $SET_CP_I_ABS(I); /* In case we apply check_process_code/2. */ c_p->arity = 0; /* To allow garbage collection on ourselves - * (check_process_code/2). - */ + * (check_process_code/2, put/2, etc). */ DTRACE_BIF_ENTRY(c_p, codemfa); SWAPOUT; ERTS_DBG_CHK_REDS(c_p, FCALLS - 1); c_p->fcalls = FCALLS - 1; - vbf = (BifFunction) Arg(0); + vbf = (BifFunction)$Func; PROCESS_MAIN_CHK_LOCKS(c_p); bif_nif_arity = codemfa->arity; ASSERT(bif_nif_arity <= 4); @@ -557,6 +581,7 @@ nif_bif.apply_bif() { } nif_bif.epilogue() { + //| -no_next ERTS_REQ_PROC_MAIN_LOCK(c_p); ERTS_HOLE_CHECK(c_p); if (ERTS_IS_GC_DESIRED(c_p)) { @@ -570,8 +595,7 @@ nif_bif.epilogue() { if (ERTS_LIKELY(is_value(nif_bif_result))) { r(0) = nif_bif_result; CHECK_TERM(r(0)); - SET_I(c_p->cp); - c_p->cp = 0; + $RETURN(); Goto(*I); } else if (c_p->freason == TRAP) { SET_I(c_p->i); @@ -579,8 +603,42 @@ nif_bif.epilogue() { c_p->flags &= ~F_HIBERNATE_SCHED; goto do_schedule; } - Dispatch(); + $DISPATCH(); + } + { + BeamInstr *cp = erts_printable_return_address(c_p, E); + ASSERT(VALID_INSTR(*cp)); + I = handle_error(c_p, cp, reg, c_p->current); } - I = handle_error(c_p, c_p->cp, reg, c_p->current); goto post_error_handling; } + +i_load_nif() { + //| -no_next + if (erts_try_seize_code_write_permission(c_p)) { + Eterm result; + + PRE_BIF_SWAPOUT(c_p); + result = erts_load_nif(c_p, I, r(0), r(1)); + erts_release_code_write_permission(); + ERTS_REQ_PROC_MAIN_LOCK(c_p); + SWAPIN; + + if (ERTS_LIKELY(is_value(result))) { + r(0) = result; + $NEXT0(); + } else { + static ErtsCodeMFA mfa = {am_erlang, am_load_nif, 2}; + c_p->freason = BADARG; + I = handle_error(c_p, I, reg, &mfa); + goto post_error_handling; + } + } else { + /* Yield and try again */ + $SET_CP_I_ABS(I); + SWAPOUT; + c_p->current = NULL; + c_p->arity = 2; + goto do_schedule; + } +} diff --git a/erts/emulator/beam/binary.c b/erts/emulator/beam/binary.c index a18228b84a..4ddf59092a 100644 --- a/erts/emulator/beam/binary.c +++ b/erts/emulator/beam/binary.c @@ -1153,51 +1153,47 @@ BIF_RETTYPE list_to_bitstring_1(BIF_ALIST_1) BIF_RETTYPE split_binary_2(BIF_ALIST_2) { - Uint pos; - ErlSubBin* sb1; - ErlSubBin* sb2; - size_t orig_size; - Eterm orig; - Uint offset; - Uint bit_offset; - Uint bit_size; - Eterm* hp; + size_t orig_size, left_size, right_size; + Uint byte_offset, bit_offset, bit_size; + Uint split_at; + + Eterm *hp, *hp_end; + Eterm left, right; + Eterm real_bin; + Eterm result; + byte *bptr; if (is_not_binary(BIF_ARG_1)) { - goto error; - } - if (!term_to_Uint(BIF_ARG_2, &pos)) { - goto error; - } - if ((orig_size = binary_size(BIF_ARG_1)) < pos) { - goto error; + BIF_ERROR(BIF_P, BADARG); + } else if (!term_to_Uint(BIF_ARG_2, &split_at)) { + BIF_ERROR(BIF_P, BADARG); + } else if ((orig_size = binary_size(BIF_ARG_1)) < split_at) { + BIF_ERROR(BIF_P, BADARG); } - hp = HAlloc(BIF_P, 2*ERL_SUB_BIN_SIZE+3); - ERTS_GET_REAL_BIN(BIF_ARG_1, orig, offset, bit_offset, bit_size); - sb1 = (ErlSubBin *) hp; - sb1->thing_word = HEADER_SUB_BIN; - sb1->size = pos; - sb1->offs = offset; - sb1->orig = orig; - sb1->bitoffs = bit_offset; - sb1->bitsize = 0; - sb1->is_writable = 0; - hp += ERL_SUB_BIN_SIZE; - - sb2 = (ErlSubBin *) hp; - sb2->thing_word = HEADER_SUB_BIN; - sb2->size = orig_size - pos; - sb2->offs = offset + pos; - sb2->orig = orig; - sb2->bitoffs = bit_offset; - sb2->bitsize = bit_size; /* The extra bits go into the second binary. */ - sb2->is_writable = 0; - hp += ERL_SUB_BIN_SIZE; - - return TUPLE2(hp, make_binary(sb1), make_binary(sb2)); - - error: - BIF_ERROR(BIF_P, BADARG); + + left_size = split_at; + right_size = orig_size - split_at; + + ERTS_GET_REAL_BIN(BIF_ARG_1, real_bin, byte_offset, bit_offset, bit_size); + bptr = binary_bytes(real_bin); + + hp = HAlloc(BIF_P, EXTRACT_SUB_BIN_HEAP_NEED * 2 + 3); + hp_end = hp + (EXTRACT_SUB_BIN_HEAP_NEED * 2 + 3); + + left = erts_extract_sub_binary(&hp, real_bin, bptr, + byte_offset * 8 + bit_offset, + left_size * 8); + + right = erts_extract_sub_binary(&hp, real_bin, bptr, + (byte_offset + split_at) * 8 + bit_offset, + right_size * 8 + bit_size); + + result = TUPLE2(hp, left, right); + hp += 3; + + HRelease(BIF_P, hp_end, hp); + + return result; } diff --git a/erts/emulator/beam/bs_instrs.tab b/erts/emulator/beam/bs_instrs.tab index bd1ad91e45..5f25bc2ad3 100644 --- a/erts/emulator/beam/bs_instrs.tab +++ b/erts/emulator/beam/bs_instrs.tab @@ -149,7 +149,7 @@ i_bs_get_binary_all2.execute(Fail, Live, Unit, Dst) { ErlBinMatchBuffer *_mb; Eterm _result; - $GC_TEST_PRESERVE(ERL_SUB_BIN_SIZE, $Live, context); + $GC_TEST_PRESERVE(EXTRACT_SUB_BIN_HEAP_NEED, $Live, context); _mb = ms_matchbuffer(context); if (((_mb->size - _mb->offset) % $Unit) == 0) { LIGHT_SWAPOUT; @@ -179,7 +179,7 @@ i_bs_get_binary2.execute(Fail, Live, Sz, Flags, Dst) { Eterm _result; Uint _size; $BS_GET_FIELD_SIZE($Sz, (($Flags) >> 3), $FAIL($Fail), _size); - $GC_TEST_PRESERVE(ERL_SUB_BIN_SIZE, $Live, context); + $GC_TEST_PRESERVE(EXTRACT_SUB_BIN_HEAP_NEED, $Live, context); _mb = ms_matchbuffer(context); LIGHT_SWAPOUT; _result = erts_bs_get_binary_2(c_p, _size, $Flags, _mb); @@ -206,8 +206,7 @@ i_bs_get_binary_imm2.fetch(Ctx) { i_bs_get_binary_imm2.execute(Fail, Live, Sz, Flags, Dst) { ErlBinMatchBuffer *_mb; Eterm _result; - $GC_TEST_PRESERVE(heap_bin_size(ERL_ONHEAP_BIN_LIMIT), - $Live, context); + $GC_TEST_PRESERVE(EXTRACT_SUB_BIN_HEAP_NEED, $Live, context); _mb = ms_matchbuffer(context); LIGHT_SWAPOUT; _result = erts_bs_get_binary_2(c_p, $Sz, $Flags, _mb); @@ -876,9 +875,7 @@ bs_start_match.execute(Fail, Live, Slots, Dst) { result = erts_bs_start_match_2(c_p, context, slots); HTOP = HEAP_TOP(c_p); HEAP_SPACE_VERIFIED(0); - if (is_non_value(result)) { - $FAIL($Fail); - } + $REFRESH_GEN_DEST(); $Dst = result; } else { @@ -1296,10 +1293,6 @@ i_bs_start_match3_gp.execute(Live, Fail, Dst, Pos) { HTOP = HEAP_TOP(c_p); HEAP_SPACE_VERIFIED(0); - if (ms == NULL) { - $FAIL($Fail); - } - $REFRESH_GEN_DEST(); $Dst = make_matchstate(ms); position = ms->mb.offset; @@ -1348,10 +1341,6 @@ i_bs_start_match3.execute(Live, Fail, Dst) { HTOP = HEAP_TOP(c_p); HEAP_SPACE_VERIFIED(0); - if (ms == NULL) { - $FAIL($Fail); - } - $REFRESH_GEN_DEST(); $Dst = make_matchstate(ms); } else { @@ -1523,10 +1512,6 @@ i_bs_start_match3.execute(Live, Fail, Dst) { HTOP = HEAP_TOP(c_p); HEAP_SPACE_VERIFIED(0); - if (is_non_value(result)) { - $FAIL($Fail); - } - $REFRESH_GEN_DEST(); $Dst = result; } else { diff --git a/erts/emulator/beam/copy.c b/erts/emulator/beam/copy.c index db74b06cc5..9bbcba6f3b 100644 --- a/erts/emulator/beam/copy.c +++ b/erts/emulator/beam/copy.c @@ -604,7 +604,12 @@ cleanup: /* * Copy a structure to a heap. */ -Eterm copy_struct_x(Eterm obj, Uint sz, Eterm** hpp, ErlOffHeap* off_heap, Uint *bsz, erts_literal_area_t *litopt) +Eterm copy_struct_x(Eterm obj, Uint sz, Eterm** hpp, ErlOffHeap* off_heap, + Uint *bsz, erts_literal_area_t *litopt +#ifdef ERTS_COPY_REGISTER_LOCATION + , char *file, int line +#endif + ) { char* hstart; Uint hsize; @@ -854,7 +859,11 @@ Eterm copy_struct_x(Eterm obj, Uint sz, Eterm** hpp, ErlOffHeap* off_heap, Uint case EXTERNAL_REF_SUBTAG: { ExternalThing *etp = (ExternalThing *) objp; +#if defined(ERTS_COPY_REGISTER_LOCATION) && defined(ERL_NODE_BOOKKEEP) + erts_ref_node_entry__(etp->node, 2, make_boxed(htop), file, line); +#else erts_ref_node_entry(etp->node, 2, make_boxed(htop)); +#endif } L_off_heap_node_container_common: { @@ -1326,8 +1335,13 @@ Uint copy_shared_calculate(Eterm obj, erts_shcopy_t *info) * Copy object "obj" preserving sharing. * Second half: copy and restore the object. */ -Uint copy_shared_perform(Eterm obj, Uint size, erts_shcopy_t *info, - Eterm** hpp, ErlOffHeap* off_heap) { +Uint copy_shared_perform_x(Eterm obj, Uint size, erts_shcopy_t *info, + Eterm** hpp, ErlOffHeap* off_heap +#ifdef ERTS_COPY_REGISTER_LOCATION + , char *file, int line +#endif + ) +{ Uint e; unsigned sz; Eterm* ptr; @@ -1393,7 +1407,11 @@ Uint copy_shared_perform(Eterm obj, Uint size, erts_shcopy_t *info, *resp = obj; } else { Uint bsz = 0; - *resp = copy_struct_x(obj, hbot - hp, &hp, off_heap, &bsz, NULL); /* copy literal */ + *resp = copy_struct_x(obj, hbot - hp, &hp, off_heap, &bsz, NULL +#ifdef ERTS_COPY_REGISTER_LOCATION + , file, line +#endif + ); /* copy literal */ hbot -= bsz; } goto cleanup_next; @@ -1461,7 +1479,11 @@ Uint copy_shared_perform(Eterm obj, Uint size, erts_shcopy_t *info, *resp = obj; } else { Uint bsz = 0; - *resp = copy_struct_x(obj, hbot - hp, &hp, off_heap, &bsz, NULL); /* copy literal */ + *resp = copy_struct_x(obj, hbot - hp, &hp, off_heap, &bsz, NULL +#ifdef ERTS_COPY_REGISTER_LOCATION + , file, line +#endif + ); /* copy literal */ hbot -= bsz; } goto cleanup_next; @@ -1660,7 +1682,12 @@ Uint copy_shared_perform(Eterm obj, Uint size, erts_shcopy_t *info, case EXTERNAL_REF_SUBTAG: { ExternalThing *etp = (ExternalThing *) ptr; + +#if defined(ERTS_COPY_REGISTER_LOCATION) && defined(ERL_NODE_BOOKKEEP) + erts_ref_node_entry__(etp->node, 2, make_boxed(hp), file, line); +#else erts_ref_node_entry(etp->node, 2, make_boxed(hp)); +#endif } off_heap_node_container_common: { @@ -1823,8 +1850,12 @@ all_clean: * * NOTE: Assumes that term is a tuple (ptr is an untagged tuple ptr). */ -Eterm copy_shallow(Eterm* ERTS_RESTRICT ptr, Uint sz, Eterm** hpp, - ErlOffHeap* off_heap) +Eterm +copy_shallow_x(Eterm* ERTS_RESTRICT ptr, Uint sz, Eterm** hpp, ErlOffHeap* off_heap +#ifdef ERTS_COPY_REGISTER_LOCATION + , char *file, int line +#endif + ) { Eterm* tp = ptr; Eterm* hp = *hpp; @@ -1866,7 +1897,11 @@ Eterm copy_shallow(Eterm* ERTS_RESTRICT ptr, Uint sz, Eterm** hpp, case EXTERNAL_REF_SUBTAG: { ExternalThing* etp = (ExternalThing *) (tp-1); +#if defined(ERTS_COPY_REGISTER_LOCATION) && defined(ERL_NODE_BOOKKEEP) + erts_ref_node_entry__(etp->node, 2, make_boxed(hp-1), file, line); +#else erts_ref_node_entry(etp->node, 2, make_boxed(hp-1)); +#endif } off_heap_common: { diff --git a/erts/emulator/beam/dist.c b/erts/emulator/beam/dist.c index 83ef10cbec..dafe805a6f 100644 --- a/erts/emulator/beam/dist.c +++ b/erts/emulator/beam/dist.c @@ -1266,18 +1266,6 @@ erts_dsig_send_group_leader(ErtsDSigSendContext *ctx, Eterm leader, Eterm remote return dsig_send_ctl(ctx, ctl); } -struct dist_sequences { - ErlHeapFragment hfrag; - struct dist_sequences *parent; - struct dist_sequences *left; - struct dist_sequences *right; - char is_red; - - Uint64 seq_id; - int cnt; - Sint ctl_len; -}; - #define ERTS_RBT_PREFIX dist_seq #define ERTS_RBT_T DistSeqNode #define ERTS_RBT_KEY_T Uint @@ -1312,25 +1300,25 @@ struct dist_sequences { #include "erl_rbtree.h" -struct erts_dist_seq_tree_foreach_iter_arg { - int (*func)(ErtsDistExternal *, void *, Sint); +struct erts_debug_dist_seq_tree_foreach_iter_arg { + int (*func)(DistSeqNode *, void *, Sint); void *arg; }; static int -erts_dist_seq_tree_foreach_iter(DistSeqNode *seq, void *arg, Sint reds) +erts_debug_dist_seq_tree_foreach_iter(DistSeqNode *seq, void *arg, Sint reds) { - struct erts_dist_seq_tree_foreach_iter_arg *state = arg; - return state->func(erts_get_dist_ext(&seq->hfrag), state->arg, reds); + struct erts_debug_dist_seq_tree_foreach_iter_arg *state = arg; + return state->func(seq, state->arg, reds); } void -erts_dist_seq_tree_foreach(DistEntry *dep, int (*func)(ErtsDistExternal *, void *, Sint), void *arg) +erts_debug_dist_seq_tree_foreach(DistEntry *dep, int (*func)(DistSeqNode *, void *, Sint), void *arg) { - struct erts_dist_seq_tree_foreach_iter_arg state; + struct erts_debug_dist_seq_tree_foreach_iter_arg state; state.func = func; state.arg = arg; - dist_seq_rbt_foreach(dep->sequences, erts_dist_seq_tree_foreach_iter, &state); + dist_seq_rbt_foreach(dep->sequences, erts_debug_dist_seq_tree_foreach_iter, &state); } static int dist_seq_cleanup(DistSeqNode *seq, void *unused, Sint reds) diff --git a/erts/emulator/beam/dist.h b/erts/emulator/beam/dist.h index f953a2ab8c..37ec88cc55 100644 --- a/erts/emulator/beam/dist.h +++ b/erts/emulator/beam/dist.h @@ -274,6 +274,18 @@ typedef struct erts_dsig_send_context { typedef struct dist_sequences DistSeqNode; +struct dist_sequences { + ErlHeapFragment hfrag; + struct dist_sequences *parent; + struct dist_sequences *left; + struct dist_sequences *right; + char is_red; + + Uint64 seq_id; + int cnt; + Sint ctl_len; +}; + /* * erts_dsig_send_* return values. */ @@ -306,9 +318,9 @@ extern Uint erts_dist_cache_size(void); extern Sint erts_abort_connection_rwunlock(DistEntry *dep); -extern void erts_dist_seq_tree_foreach( +extern void erts_debug_dist_seq_tree_foreach( DistEntry *dep, - int (*func)(ErtsDistExternal *, void*, Sint), void *args); + int (*func)(DistSeqNode *, void*, Sint), void *args); extern int erts_dsig_prepare(ErtsDSigSendContext *, DistEntry*, diff --git a/erts/emulator/beam/erl_alloc.c b/erts/emulator/beam/erl_alloc.c index b9f0334172..1bbc7d7f1e 100644 --- a/erts/emulator/beam/erl_alloc.c +++ b/erts/emulator/beam/erl_alloc.c @@ -653,8 +653,6 @@ erts_alloc_init(int *argc, char **argv, ErtsAllocInitOpts *eaiop) = erts_timer_type_size(ERTS_ALC_T_HL_PTIMER); fix_type_sizes[ERTS_ALC_FIX_TYPE_IX(ERTS_ALC_T_BIF_TIMER)] = erts_timer_type_size(ERTS_ALC_T_BIF_TIMER); - fix_type_sizes[ERTS_ALC_FIX_TYPE_IX(ERTS_ALC_T_NIF_EXP_TRACE)] - = sizeof(NifExportTrace); fix_type_sizes[ERTS_ALC_FIX_TYPE_IX(ERTS_ALC_T_MREF_NSCHED_ENT)] = sizeof(ErtsNSchedMagicRefTableEntry); fix_type_sizes[ERTS_ALC_FIX_TYPE_IX(ERTS_ALC_T_MINDIRECTION)] @@ -2392,10 +2390,6 @@ erts_memory(fmtfn_t *print_to_p, void *print_to_arg, void *proc, Eterm earg) &size.processes_used, fi, ERTS_ALC_T_BIF_TIMER); - add_fix_values(&size.processes, - &size.processes_used, - fi, - ERTS_ALC_T_NIF_EXP_TRACE); } if (want.atom || want.atom_used) { diff --git a/erts/emulator/beam/erl_alloc.types b/erts/emulator/beam/erl_alloc.types index 58d586453c..3e643a6223 100644 --- a/erts/emulator/beam/erl_alloc.types +++ b/erts/emulator/beam/erl_alloc.types @@ -149,6 +149,7 @@ type MODULE_TABLE LONG_LIVED CODE module_tab type TAINT LONG_LIVED CODE taint_list type MODULE_REFS STANDARD CODE module_refs type NC_TMP TEMPORARY SYSTEM nc_tmp +type NC_STD STANDARD SYSTEM nc_std type TMP TEMPORARY SYSTEM tmp type UNDEF SYSTEM SYSTEM undefined type DCACHE STANDARD SYSTEM dcache @@ -330,8 +331,7 @@ type DB_HEIR_DATA STANDARD ETS db_heir_data type DB_MS_PSDO_PROC LONG_LIVED ETS db_match_pseudo_proc type SCHDLR_DATA LONG_LIVED SYSTEM scheduler_data -type NIF_TRAP_EXPORT STANDARD PROCESSES nif_trap_export_entry -type NIF_EXP_TRACE FIXED_SIZE PROCESSES nif_export_trace +type NFUNC_TRAP_WRAPPER STANDARD PROCESSES nfunc_trap_wrapper type EXPORT LONG_LIVED CODE export_entry type MONITOR FIXED_SIZE PROCESSES monitor type MONITOR_SUSPEND STANDARD PROCESSES monitor_suspend diff --git a/erts/emulator/beam/erl_alloc_util.c b/erts/emulator/beam/erl_alloc_util.c index 25ac3bc5af..bfc2f5992c 100644 --- a/erts/emulator/beam/erl_alloc_util.c +++ b/erts/emulator/beam/erl_alloc_util.c @@ -7112,12 +7112,21 @@ static int blockscan_cpool_yielding(blockscan_t *state) return 0; } -static int blockscan_yield_helper(blockscan_t *state, - int (*yielding_op)(blockscan_t*)) +/* */ + +static int blockscan_finish(blockscan_t *state) { - /* Note that we don't check whether to abort here; only yielding_op knows - * whether the carrier is still in the list/pool. */ + if (ERTS_PROC_IS_EXITING(state->process)) { + state->abort(state->user_data); + return 0; + } + state->current_op = blockscan_finish; + + return state->finish(state->user_data); +} + +static void blockscan_lock_helper(blockscan_t *state) { if ((state->allocator)->thread_safe) { /* Locked scans have to be as short as possible. */ state->reductions = 1; @@ -7126,34 +7135,18 @@ static int blockscan_yield_helper(blockscan_t *state, } else { state->reductions = BLOCKSCAN_REDUCTIONS; } +} - if (yielding_op(state)) { - state->next_op = state->current_op; - } - +static void blockscan_unlock_helper(blockscan_t *state) { if ((state->allocator)->thread_safe) { erts_mtx_unlock(&(state->allocator)->mutex); } - - return 1; -} - -/* */ - -static int blockscan_finish(blockscan_t *state) -{ - if (ERTS_PROC_IS_EXITING(state->process)) { - state->abort(state->user_data); - return 0; - } - - state->current_op = blockscan_finish; - - return state->finish(state->user_data); } static int blockscan_sweep_sbcs(blockscan_t *state) { + blockscan_lock_helper(state); + if (state->current_op != blockscan_sweep_sbcs) { SET_CARRIER_HDR(&state->dummy_carrier, 0, SCH_SBC, state->allocator); state->current_clist = &(state->allocator)->sbc_list; @@ -7163,11 +7156,19 @@ static int blockscan_sweep_sbcs(blockscan_t *state) state->current_op = blockscan_sweep_sbcs; state->next_op = blockscan_finish; - return blockscan_yield_helper(state, blockscan_clist_yielding); + if (blockscan_clist_yielding(state)) { + state->next_op = state->current_op; + } + + blockscan_unlock_helper(state); + + return 1; } static int blockscan_sweep_mbcs(blockscan_t *state) { + blockscan_lock_helper(state); + if (state->current_op != blockscan_sweep_mbcs) { SET_CARRIER_HDR(&state->dummy_carrier, 0, SCH_MBC, state->allocator); state->current_clist = &(state->allocator)->mbc_list; @@ -7177,11 +7178,19 @@ static int blockscan_sweep_mbcs(blockscan_t *state) state->current_op = blockscan_sweep_mbcs; state->next_op = blockscan_sweep_sbcs; - return blockscan_yield_helper(state, blockscan_clist_yielding); + if (blockscan_clist_yielding(state)) { + state->next_op = state->current_op; + } + + blockscan_unlock_helper(state); + + return 1; } static int blockscan_sweep_cpool(blockscan_t *state) { + blockscan_lock_helper(state); + if (state->current_op != blockscan_sweep_cpool) { SET_CARRIER_HDR(&state->dummy_carrier, 0, SCH_MBC, state->allocator); state->cpool_cursor = (state->allocator)->cpool.sentinel; @@ -7190,7 +7199,13 @@ static int blockscan_sweep_cpool(blockscan_t *state) state->current_op = blockscan_sweep_cpool; state->next_op = blockscan_sweep_mbcs; - return blockscan_yield_helper(state, blockscan_cpool_yielding); + if (blockscan_cpool_yielding(state)) { + state->next_op = state->current_op; + } + + blockscan_unlock_helper(state); + + return 1; } static int blockscan_get_specific_allocator(int allocator_num, diff --git a/erts/emulator/beam/erl_bif_binary.c b/erts/emulator/beam/erl_bif_binary.c index 4d6d31cd76..b8e56390c1 100644 --- a/erts/emulator/beam/erl_bif_binary.c +++ b/erts/emulator/beam/erl_bif_binary.c @@ -1750,9 +1750,8 @@ static Eterm do_split_single_result(Process *p, Eterm subject, BinaryFindContext Uint offset; Uint bit_offset; Uint bit_size; - ErlSubBin *sb1; - ErlSubBin *sb2; - Eterm *hp; + Uint hp_need; + Eterm *hp, *hp_end; Eterm ret; pos = ff->pos; @@ -1765,57 +1764,58 @@ static Eterm do_split_single_result(Process *p, Eterm subject, BinaryFindContext if (pos == 0) { ret = NIL; } else { - hp = HAlloc(p, (ERL_SUB_BIN_SIZE + 2)); + Eterm extracted; + + hp_need = EXTRACT_SUB_BIN_HEAP_NEED + 2; + + hp = HAlloc(p, hp_need); + hp_end = hp + hp_need; + ERTS_GET_REAL_BIN(subject, orig, offset, bit_offset, bit_size); - sb1 = (ErlSubBin *) hp; - sb1->thing_word = HEADER_SUB_BIN; - sb1->size = pos; - sb1->offs = offset; - sb1->orig = orig; - sb1->bitoffs = bit_offset; - sb1->bitsize = bit_size; - sb1->is_writable = 0; - hp += ERL_SUB_BIN_SIZE; - - ret = CONS(hp, make_binary(sb1), NIL); + extracted = erts_extract_sub_binary(&hp, orig, binary_bytes(orig), + offset * 8 + bit_offset, + pos * 8 + bit_size); + + ret = CONS(hp, extracted, NIL); hp += 2; + + HRelease(p, hp_end, hp); + + return ret; } } else { - if ((ctx->flags & BF_FLAG_SPLIT_TRIM_ALL) && (pos == 0)) { - hp = HAlloc(p, 1 * (ERL_SUB_BIN_SIZE + 2)); - ERTS_GET_REAL_BIN(subject, orig, offset, bit_offset, bit_size); - sb1 = NULL; - } else { - hp = HAlloc(p, 2 * (ERL_SUB_BIN_SIZE + 2)); - ERTS_GET_REAL_BIN(subject, orig, offset, bit_offset, bit_size); - sb1 = (ErlSubBin *) hp; - sb1->thing_word = HEADER_SUB_BIN; - sb1->size = pos; - sb1->offs = offset; - sb1->orig = orig; - sb1->bitoffs = bit_offset; - sb1->bitsize = 0; - sb1->is_writable = 0; - hp += ERL_SUB_BIN_SIZE; - } - - sb2 = (ErlSubBin *) hp; - sb2->thing_word = HEADER_SUB_BIN; - sb2->size = orig_size - pos - len; - sb2->offs = offset + pos + len; - sb2->orig = orig; - sb2->bitoffs = bit_offset; - sb2->bitsize = bit_size; - sb2->is_writable = 0; - hp += ERL_SUB_BIN_SIZE; - - ret = CONS(hp, make_binary(sb2), NIL); - hp += 2; - if (sb1 != NULL) { - ret = CONS(hp, make_binary(sb1), ret); - hp += 2; - } + Eterm first, rest; + + hp_need = (EXTRACT_SUB_BIN_HEAP_NEED + 2) * 2; + + hp = HAlloc(p, hp_need); + hp_end = hp + hp_need; + + ERTS_GET_REAL_BIN(subject, orig, offset, bit_offset, bit_size); + + if ((ctx->flags & BF_FLAG_SPLIT_TRIM_ALL) && (pos == 0)) { + first = NIL; + } else { + first = erts_extract_sub_binary(&hp, orig, binary_bytes(orig), + offset * 8 + bit_offset, + pos * 8); + } + + rest = erts_extract_sub_binary(&hp, orig, binary_bytes(orig), + (offset + pos + len) * 8 + bit_offset, + (orig_size - pos - len) * 8 + bit_size); + + ret = CONS(hp, rest, NIL); + hp += 2; + + if (first != NIL) { + ret = CONS(hp, first, ret); + hp += 2; + } + + HRelease(p, hp_end, hp); } + return ret; } @@ -1829,7 +1829,9 @@ static Eterm do_split_global_result(Process *p, Eterm subject, BinaryFindContext Uint offset; Uint bit_offset; Uint bit_size; - ErlSubBin *sb; + Uint extracted_offset; + Uint extracted_size; + Eterm extracted; Uint do_trim; Sint i; register Uint reds = ctx->reds; @@ -1852,7 +1854,8 @@ static Eterm do_split_global_result(Process *p, Eterm subject, BinaryFindContext *ctxp = ctx; fa = &(ctx->u.fa); } - erts_factory_proc_prealloc_init(&(fa->factory), p, (fa->size + 1) * (ERL_SUB_BIN_SIZE + 2)); + erts_factory_proc_prealloc_init(&(fa->factory), p, (fa->size + 1) * + (EXTRACT_SUB_BIN_HEAP_NEED + 2)); ctx->state = BFResult; } @@ -1871,39 +1874,39 @@ static Eterm do_split_global_result(Process *p, Eterm subject, BinaryFindContext } return THE_NON_VALUE; } - sb = (ErlSubBin *)(fa->factory.hp); - sb->size = fa->end_pos - (fad[i].pos + fad[i].len); - if (!(sb->size == 0 && do_trim)) { - sb->thing_word = HEADER_SUB_BIN; - sb->offs = offset + fad[i].pos + fad[i].len; - sb->orig = orig; - sb->bitoffs = bit_offset; - sb->bitsize = 0; - sb->is_writable = 0; - fa->factory.hp += ERL_SUB_BIN_SIZE; - fa->term = CONS(fa->factory.hp, make_binary(sb), fa->term); - fa->factory.hp += 2; - do_trim &= ~BF_FLAG_SPLIT_TRIM; - } - fa->end_pos = fad[i].pos; + + extracted_offset = (offset + fad[i].pos + fad[i].len) * 8 + bit_offset; + extracted_size = (fa->end_pos - (fad[i].pos + fad[i].len)) * 8; + + if (!(extracted_size == 0 && do_trim)) { + extracted = erts_extract_sub_binary(&fa->factory.hp, orig, + binary_bytes(orig), + extracted_offset, + extracted_size); + fa->term = CONS(fa->factory.hp, extracted, fa->term); + fa->factory.hp += 2; + + do_trim &= ~BF_FLAG_SPLIT_TRIM; + } + + fa->end_pos = fad[i].pos; } fa->head = i; ctx->reds = reds; - sb = (ErlSubBin *)(fa->factory.hp); - sb->size = fad[0].pos; - if (!(sb->size == 0 && do_trim)) { - sb->thing_word = HEADER_SUB_BIN; - sb->offs = offset; - sb->orig = orig; - sb->bitoffs = bit_offset; - sb->bitsize = 0; - sb->is_writable = 0; - fa->factory.hp += ERL_SUB_BIN_SIZE; - fa->term = CONS(fa->factory.hp, make_binary(sb), fa->term); - fa->factory.hp += 2; + extracted_offset = offset * 8 + bit_offset; + extracted_size = fad[0].pos * 8; + + if (!(extracted_size == 0 && do_trim)) { + extracted = erts_extract_sub_binary(&fa->factory.hp, orig, + binary_bytes(orig), + extracted_offset, + extracted_size); + fa->term = CONS(fa->factory.hp, extracted, fa->term); + fa->factory.hp += 2; } + erts_factory_close(&(fa->factory)); return fa->term; @@ -1937,8 +1940,8 @@ BIF_RETTYPE erts_binary_part(Process *p, Eterm binary, Eterm epos, Eterm elen) Uint offset; Uint bit_offset; Uint bit_size; - Eterm* hp; - ErlSubBin* sb; + Eterm *hp, *hp_end; + Eterm result; if (is_not_binary(binary)) { goto badarg; @@ -1970,19 +1973,18 @@ BIF_RETTYPE erts_binary_part(Process *p, Eterm binary, Eterm epos, Eterm elen) goto badarg; } - hp = HeapFragOnlyAlloc(p, ERL_SUB_BIN_SIZE); + hp = HeapFragOnlyAlloc(p, EXTRACT_SUB_BIN_HEAP_NEED); + hp_end = hp + EXTRACT_SUB_BIN_HEAP_NEED; ERTS_GET_REAL_BIN(binary, orig, offset, bit_offset, bit_size); - sb = (ErlSubBin *) hp; - sb->thing_word = HEADER_SUB_BIN; - sb->size = len; - sb->offs = offset + pos; - sb->orig = orig; - sb->bitoffs = bit_offset; - sb->bitsize = 0; - sb->is_writable = 0; - - BIF_RET(make_binary(sb)); + + result = erts_extract_sub_binary(&hp, orig, binary_bytes(orig), + (offset + pos) * 8 + bit_offset, + len * 8); + + HRelease(p, hp_end, hp); + + BIF_RET(result); badarg: BIF_ERROR(p, BADARG); diff --git a/erts/emulator/beam/erl_bif_info.c b/erts/emulator/beam/erl_bif_info.c index aa55bdab6a..57fc5ec131 100644 --- a/erts/emulator/beam/erl_bif_info.c +++ b/erts/emulator/beam/erl_bif_info.c @@ -158,26 +158,28 @@ static Eterm os_version_tuple; static Eterm current_function(Process* p, ErtsHeapFactory *hfact, Process* rp, int full_info, Uint reserve_size, int flags); -static Eterm current_stacktrace(ErtsHeapFactory *hfact, Process* rp, - Uint reserve_size); - static Eterm -bld_bin_list(Uint **hpp, Uint *szp, ErlOffHeap* oh) +current_stacktrace(Process* p, ErtsHeapFactory *hfact, Process* rp, + Uint reserve_size, int flags); + +Eterm +erts_bld_bin_list(Uint **hpp, Uint *szp, ErlOffHeap* oh, Eterm tail) { - struct erl_off_heap_header* ohh; - Eterm res = NIL; + union erl_off_heap_ptr u; + Eterm res = tail; Eterm tuple; + struct erts_tmp_aligned_offheap tmp; - for (ohh = oh->first; ohh; ohh = ohh->next) { - if (ohh->thing_word == HEADER_PROC_BIN) { - ProcBin* pb = (ProcBin*) ohh; - Eterm val = erts_bld_uword(hpp, szp, (UWord) pb->val); - Eterm orig_size = erts_bld_uint(hpp, szp, pb->val->orig_size); + for (u.hdr = oh->first; u.hdr; u.hdr = u.hdr->next) { + erts_align_offheap(&u, &tmp); + if (u.hdr->thing_word == HEADER_PROC_BIN) { + Eterm val = erts_bld_uword(hpp, szp, (UWord) u.pb->val); + Eterm orig_size = erts_bld_uint(hpp, szp, u.pb->val->orig_size); if (szp) *szp += 4+2; if (hpp) { - Uint refc = (Uint) erts_refc_read(&pb->val->intern.refc, 1); + Uint refc = (Uint) erts_refc_read(&u.pb->val->intern.refc, 1); tuple = TUPLE3(*hpp, val, orig_size, make_small(refc)); res = CONS(*hpp + 4, tuple, res); *hpp += 4+2; @@ -1383,7 +1385,7 @@ process_info_aux(Process *c_p, break; case ERTS_PI_IX_CURRENT_STACKTRACE: - res = current_stacktrace(hfact, rp, reserve_size); + res = current_stacktrace(c_p, hfact, rp, reserve_size, flags); break; case ERTS_PI_IX_INITIAL_CALL: @@ -1864,11 +1866,25 @@ process_info_aux(Process *c_p, break; case ERTS_PI_IX_BINARY: { - Uint sz = 0; - (void) bld_bin_list(NULL, &sz, &MSO(rp)); + ErlHeapFragment *hfrag; + Uint sz; + + res = NIL; + sz = 0; + + (void)erts_bld_bin_list(NULL, &sz, &MSO(rp), NIL); + for (hfrag = rp->mbuf; hfrag != NULL; hfrag = hfrag->next) { + (void)erts_bld_bin_list(NULL, &sz, &hfrag->off_heap, NIL); + } + hp = erts_produce_heap(hfact, sz, reserve_size); - res = bld_bin_list(&hp, NULL, &MSO(rp)); - break; + + res = erts_bld_bin_list(&hp, NULL, &MSO(rp), NIL); + for (hfrag = rp->mbuf; hfrag != NULL; hfrag = hfrag->next) { + res = erts_bld_bin_list(&hp, NULL, &hfrag->off_heap, res); + } + + break; } case ERTS_PI_IX_SEQUENTIAL_TRACE_TOKEN: { @@ -2007,19 +2023,23 @@ current_function(Process *c_p, ErtsHeapFactory *hfact, Process* rp, } if (c_p == rp && !(flags & ERTS_PI_FLAG_REQUEST_FOR_OTHER)) { - FunctionInfo fi2; + BeamInstr* return_address; + FunctionInfo caller_fi; - /* - * The current function is erlang:process_info/{1,2}, - * which is not the answer that the application want. - * We will use the function pointed into by rp->cp - * instead if it can be looked up. - */ - erts_lookup_function_info(&fi2, rp->cp, full_info); - if (fi2.mfa) { - fi = fi2; - rp->current = fi2.mfa; - } + /* + * The current function is erlang:process_info/{1,2}, and we've + * historically returned the *calling* function in that case. We + * therefore use the continuation pointer stored at the top of the + * stack instead, which is safe since process_info is a "heavy" BIF + * that is only called through its export entry. + */ + return_address = erts_printable_return_address(rp, STACK_TOP(rp)); + + erts_lookup_function_info(&caller_fi, return_address, full_info); + if (caller_fi.mfa) { + fi = caller_fi; + rp->current = caller_fi.mfa; + } } /* @@ -2040,8 +2060,8 @@ current_function(Process *c_p, ErtsHeapFactory *hfact, Process* rp, } static Eterm -current_stacktrace(ErtsHeapFactory *hfact, Process* rp, - Uint reserve_size) +current_stacktrace(Process *p, ErtsHeapFactory *hfact, Process* rp, + Uint reserve_size, int flags) { Uint sz; struct StackTrace* s; @@ -2058,13 +2078,14 @@ current_stacktrace(ErtsHeapFactory *hfact, Process* rp, sz = offsetof(struct StackTrace, trace) + sizeof(BeamInstr *)*depth; s = (struct StackTrace *) erts_alloc(ERTS_ALC_T_TMP, sz); s->depth = 0; - if (depth > 0 && rp->i) { - s->trace[s->depth++] = rp->i; - depth--; - } - if (depth > 0 && rp->cp != 0) { - s->trace[s->depth++] = rp->cp - 1; - depth--; + s->pc = NULL; + + /* We skip current pc when requesting our own stack trace since it will + * inevitably point to process_info/1,2 */ + if ((p != rp || (flags & ERTS_PI_FLAG_REQUEST_FOR_OTHER)) && + depth > 0 && rp->i) { + s->trace[s->depth++] = rp->i; + depth--; } erts_save_stacktrace(rp, s, depth); diff --git a/erts/emulator/beam/erl_bif_lists.c b/erts/emulator/beam/erl_bif_lists.c index fa2edfef1e..9d485abc35 100644 --- a/erts/emulator/beam/erl_bif_lists.c +++ b/erts/emulator/beam/erl_bif_lists.c @@ -32,8 +32,46 @@ #include "bif.h" #include "erl_binary.h" +static Export plusplus_trap_export; +static Export append_trap_export; -static Eterm keyfind(int Bif, Process* p, Eterm Key, Eterm Pos, Eterm List); +static Export minusminus_trap_export; +static Export subtract_trap_export; + +static Export member_trap_export; + +static Export reverse_trap_export; + +static Export keymember_trap_export; +static Export keysearch_trap_export; +static Export keyfind_trap_export; + +void erts_init_bif_lists(void) { + erts_init_trap_export(&plusplus_trap_export, am_erlang, am_PlusPlus, 2, + ebif_plusplus_2); + erts_init_trap_export(&append_trap_export, am_erlang, am_append, 2, + append_2); + + erts_init_trap_export(&minusminus_trap_export, am_erlang, am_MinusMinus, 2, + ebif_minusminus_2); + erts_init_trap_export(&subtract_trap_export, am_lists, am_subtract, 2, + subtract_2); + + erts_init_trap_export(&reverse_trap_export, am_lists, am_reverse, 2, + lists_reverse_2); + + erts_init_trap_export(&member_trap_export, am_lists, am_member, 2, + lists_member_2); + + erts_init_trap_export(&keymember_trap_export, am_lists, am_keymember, 3, + lists_keymember_3); + erts_init_trap_export(&keysearch_trap_export, am_lists, am_keysearch, 3, + lists_keysearch_3); + erts_init_trap_export(&keyfind_trap_export, am_lists, am_keyfind, 3, + lists_keyfind_3); +} + +static Eterm keyfind(Export* Bif, Process* p, Eterm Key, Eterm Pos, Eterm List); /* erlang:'++'/2 * @@ -308,12 +346,12 @@ static Eterm append(Export *bif_entry, BIF_ALIST_2) { Eterm ebif_plusplus_2(BIF_ALIST_2) { - return append(bif_export[BIF_ebif_plusplus_2], BIF_CALL_ARGS); + return append(&plusplus_trap_export, BIF_CALL_ARGS); } BIF_RETTYPE append_2(BIF_ALIST_2) { - return append(bif_export[BIF_append_2], BIF_CALL_ARGS); + return append(&append_trap_export, BIF_CALL_ARGS); } /* erlang:'--'/2 @@ -1039,11 +1077,11 @@ static Eterm subtract(Export *bif_entry, BIF_ALIST_2) { } BIF_RETTYPE ebif_minusminus_2(BIF_ALIST_2) { - return subtract(bif_export[BIF_ebif_minusminus_2], BIF_CALL_ARGS); + return subtract(&minusminus_trap_export, BIF_CALL_ARGS); } BIF_RETTYPE subtract_2(BIF_ALIST_2) { - return subtract(bif_export[BIF_subtract_2], BIF_CALL_ARGS); + return subtract(&subtract_trap_export, BIF_CALL_ARGS); } @@ -1068,7 +1106,7 @@ BIF_RETTYPE lists_member_2(BIF_ALIST_2) while (is_list(list)) { if (--max_iter < 0) { BUMP_ALL_REDS(BIF_P); - BIF_TRAP2(bif_export[BIF_lists_member_2], BIF_P, term, list); + BIF_TRAP2(&member_trap_export, BIF_P, term, list); } item = CAR(list_val(list)); if ((item == term) || (non_immed_key && eq(item, term))) { @@ -1130,7 +1168,7 @@ static BIF_RETTYPE lists_reverse_alloc(Process *c_p, } ASSERT(is_list(tail) && cells_left == 0); - BIF_TRAP2(bif_export[BIF_lists_reverse_2], c_p, list, tail); + BIF_TRAP2(&reverse_trap_export, c_p, list, tail); } static BIF_RETTYPE lists_reverse_onheap(Process *c_p, @@ -1179,7 +1217,7 @@ static BIF_RETTYPE lists_reverse_onheap(Process *c_p, } BUMP_ALL_REDS(c_p); - BIF_TRAP2(bif_export[BIF_lists_reverse_2], c_p, list, tail); + BIF_TRAP2(&reverse_trap_export, c_p, list, tail); } BIF_ERROR(c_p, BADARG); @@ -1209,7 +1247,7 @@ lists_keymember_3(BIF_ALIST_3) { Eterm res; - res = keyfind(BIF_lists_keymember_3, BIF_P, + res = keyfind(&keymember_trap_export, BIF_P, BIF_ARG_1, BIF_ARG_2, BIF_ARG_3); if (is_value(res) && is_tuple(res)) { return am_true; @@ -1223,7 +1261,7 @@ lists_keysearch_3(BIF_ALIST_3) { Eterm res; - res = keyfind(BIF_lists_keysearch_3, BIF_P, + res = keyfind(&keysearch_trap_export, BIF_P, BIF_ARG_1, BIF_ARG_2, BIF_ARG_3); if (is_non_value(res) || is_not_tuple(res)) { return res; @@ -1236,12 +1274,12 @@ lists_keysearch_3(BIF_ALIST_3) BIF_RETTYPE lists_keyfind_3(BIF_ALIST_3) { - return keyfind(BIF_lists_keyfind_3, BIF_P, + return keyfind(&keyfind_trap_export, BIF_P, BIF_ARG_1, BIF_ARG_2, BIF_ARG_3); } static Eterm -keyfind(int Bif, Process* p, Eterm Key, Eterm Pos, Eterm List) +keyfind(Export *Bif, Process* p, Eterm Key, Eterm Pos, Eterm List) { int max_iter = 10 * CONTEXT_REDS; Sint pos; @@ -1257,7 +1295,7 @@ keyfind(int Bif, Process* p, Eterm Key, Eterm Pos, Eterm List) while (is_list(List)) { if (--max_iter < 0) { BUMP_ALL_REDS(p); - BIF_TRAP3(bif_export[Bif], p, Key, Pos, List); + BIF_TRAP3(Bif, p, Key, Pos, List); } term = CAR(list_val(List)); List = CDR(list_val(List)); @@ -1282,7 +1320,7 @@ keyfind(int Bif, Process* p, Eterm Key, Eterm Pos, Eterm List) while (is_list(List)) { if (--max_iter < 0) { BUMP_ALL_REDS(p); - BIF_TRAP3(bif_export[Bif], p, Key, Pos, List); + BIF_TRAP3(Bif, p, Key, Pos, List); } term = CAR(list_val(List)); List = CDR(list_val(List)); @@ -1300,7 +1338,7 @@ keyfind(int Bif, Process* p, Eterm Key, Eterm Pos, Eterm List) while (is_list(List)) { if (--max_iter < 0) { BUMP_ALL_REDS(p); - BIF_TRAP3(bif_export[Bif], p, Key, Pos, List); + BIF_TRAP3(Bif, p, Key, Pos, List); } term = CAR(list_val(List)); List = CDR(list_val(List)); diff --git a/erts/emulator/beam/erl_bif_persistent.c b/erts/emulator/beam/erl_bif_persistent.c index f38e0cc5cb..9dc5c66a0a 100644 --- a/erts/emulator/beam/erl_bif_persistent.c +++ b/erts/emulator/beam/erl_bif_persistent.c @@ -1167,6 +1167,7 @@ release_update_permission(int release_updater) erts_resume(updater_process, ERTS_PROC_LOCK_STATUS); } erts_proc_unlock(updater_process, ERTS_PROC_LOCK_STATUS); + erts_proc_dec_refc(updater_process); } updater_process = NULL; @@ -1193,6 +1194,7 @@ suspend_updater(Process* c_p) ASSERT(updater_process == c_p); erts_mtx_unlock(&update_table_permission_mtx); #endif + erts_proc_inc_refc(c_p); erts_suspend(c_p, ERTS_PROC_LOCK_MAIN, NULL); } @@ -1234,3 +1236,102 @@ next_to_delete(void) erts_mtx_unlock(&delete_queue_mtx); return table; } + +/* + * test/debug functionality follow... + */ + +static Uint accessed_literal_areas_size; +static Uint accessed_no_literal_areas; +static ErtsLiteralArea **accessed_literal_areas; + +int +erts_debug_have_accessed_literal_area(ErtsLiteralArea *lap) +{ + Uint i; + for (i = 0; i < accessed_no_literal_areas; i++) { + if (accessed_literal_areas[i] == lap) + return !0; + } + return 0; +} + +void +erts_debug_save_accessed_literal_area(ErtsLiteralArea *lap) +{ + if (accessed_no_literal_areas == accessed_literal_areas_size) { + accessed_literal_areas_size += 10; + accessed_literal_areas = erts_realloc(ERTS_ALC_T_TMP, + accessed_literal_areas, + (sizeof(ErtsLiteralArea *) + *accessed_literal_areas_size)); + } + accessed_literal_areas[accessed_no_literal_areas++] = lap; +} + +static void debug_foreach_off_heap(HashTable *tbl, void (*func)(ErlOffHeap *, void *), void *arg) +{ + int i; + + for (i = 0; i < tbl->allocated; i++) { + Eterm term = tbl->term[i]; + if (is_tuple_arity(term, 2)) { + ErtsLiteralArea *lap = term_to_area(term); + ErlOffHeap oh; + if (!erts_debug_have_accessed_literal_area(lap)) { + ERTS_INIT_OFF_HEAP(&oh); + oh.first = lap->off_heap; + (*func)(&oh, arg); + erts_debug_save_accessed_literal_area(lap); + } + } + } +} + +struct debug_la_oh { + void (*func)(ErlOffHeap *, void *); + void *arg; +}; + +static void debug_handle_table(void *vfap, + ErtsThrPrgrVal val, + void *vtbl) +{ + struct debug_la_oh *fap = vfap; + HashTable *tbl = vtbl; + debug_foreach_off_heap(tbl, fap->func, fap->arg); +} + +void +erts_debug_foreach_persistent_term_off_heap(void (*func)(ErlOffHeap *, void *), void *arg) +{ + HashTable *tbl; + struct debug_la_oh fa; + accessed_no_literal_areas = 0; + accessed_literal_areas_size = 10; + accessed_literal_areas = erts_alloc(ERTS_ALC_T_TMP, + (sizeof(ErtsLiteralArea *) + * accessed_literal_areas_size)); + + tbl = (HashTable *) erts_atomic_read_nob(&the_hash_table); + debug_foreach_off_heap(tbl, func, arg); + erts_mtx_lock(&delete_queue_mtx); + for (tbl = delete_queue_head; tbl; tbl = tbl->delete_next) + debug_foreach_off_heap(tbl, func, arg); + erts_mtx_unlock(&delete_queue_mtx); + fa.func = func; + fa.arg = arg; + erts_debug_later_op_foreach(table_updater, + debug_handle_table, + (void *) &fa); + erts_debug_later_op_foreach(table_deleter, + debug_handle_table, + (void *) &fa); + erts_debug_foreach_release_literal_area_off_heap(func, arg); + + erts_free(ERTS_ALC_T_TMP, accessed_literal_areas); + accessed_no_literal_areas = 0; + accessed_literal_areas_size = 0; + accessed_literal_areas = NULL; +} + diff --git a/erts/emulator/beam/erl_bif_port.c b/erts/emulator/beam/erl_bif_port.c index ed825d3dda..dd1e884705 100644 --- a/erts/emulator/beam/erl_bif_port.c +++ b/erts/emulator/beam/erl_bif_port.c @@ -44,6 +44,7 @@ #include "erl_bif_unique.h" #include "dtrace-wrapper.h" #include "erl_proc_sig_queue.h" +#include "erl_osenv.h" static Port *open_port(Process* p, Eterm name, Eterm settings, int *err_typep, int *err_nump); static int merge_global_environment(erts_osenv_t *env, Eterm key_value_pairs); diff --git a/erts/emulator/beam/erl_bif_trace.c b/erts/emulator/beam/erl_bif_trace.c index 80ba7d1b3c..e03c97fe10 100644 --- a/erts/emulator/beam/erl_bif_trace.c +++ b/erts/emulator/beam/erl_bif_trace.c @@ -80,9 +80,6 @@ static Eterm trace_info_func(Process* p, Eterm pid_spec, Eterm key); static Eterm trace_info_on_load(Process* p, Eterm key); static Eterm trace_info_event(Process* p, Eterm event, Eterm key); - -static void reset_bif_trace(void); -static void setup_bif_trace(void); static void install_exp_breakpoints(BpFunctions* f); static void uninstall_exp_breakpoints(BpFunctions* f); static void clean_export_entries(BpFunctions* f); @@ -1047,14 +1044,13 @@ static int function_is_traced(Process *p, e.info.mfa.function = mfa[1]; e.info.mfa.arity = mfa[2]; if ((ep = export_get(&e)) != NULL) { - pc = ep->beam; + pc = ep->trampoline.raw; if (ep->addressv[erts_active_code_ix()] == pc && ! BeamIsOpCode(*pc, op_call_error_handler)) { int r = 0; - ASSERT(BeamIsOpCode(*pc, op_apply_bif) || - BeamIsOpCode(*pc, op_i_generic_breakpoint)); + ASSERT(BeamIsOpCode(*pc, op_i_generic_breakpoint)); if (erts_is_trace_break(&ep->info, ms, 0)) { return FUNC_TRACE_GLOBAL_TRACE; @@ -1426,18 +1422,21 @@ erts_set_trace_pattern(Process*p, ErtsCodeMFA *mfa, int specified, int n; BpFunction* fp; - /* - * First work on normal functions (not real BIFs). - */ - erts_bp_match_export(&finish_bp.e, mfa, specified); fp = finish_bp.e.matching; n = finish_bp.e.matched; for (i = 0; i < n; i++) { ErtsCodeInfo *ci = fp[i].ci; - BeamInstr* pc = erts_codeinfo_to_code(ci); - Export* ep = ErtsContainerStruct(ci, Export, info); + BeamInstr* pc; + Export* ep; + + pc = erts_codeinfo_to_code(ci); + ep = ErtsContainerStruct(ci, Export, info); + + if (ep->bif_table_index != -1) { + ep->is_bif_traced = !!on; + } if (on && !flags.breakpoint) { /* Turn on global call tracing */ @@ -1446,12 +1445,12 @@ erts_set_trace_pattern(Process*p, ErtsCodeMFA *mfa, int specified, #ifdef DEBUG ep->info.op = BeamOpCodeAddr(op_i_func_info_IaaI); #endif - ep->beam[0] = BeamOpCodeAddr(op_trace_jump_W); - ep->beam[1] = (BeamInstr) ep->addressv[code_ix]; + ep->trampoline.op = BeamOpCodeAddr(op_trace_jump_W); + ep->trampoline.trace.address = (BeamInstr) ep->addressv[code_ix]; } - erts_set_call_trace_bif(ci, match_prog_set, 0); + erts_set_export_trace(ci, match_prog_set, 0); if (ep->addressv[code_ix] != pc) { - ep->beam[0] = BeamOpCodeAddr(op_i_generic_breakpoint); + ep->trampoline.op = BeamOpCodeAddr(op_i_generic_breakpoint); } } else if (!on && flags.breakpoint) { /* Turn off breakpoint tracing -- nothing to do here. */ @@ -1460,91 +1459,14 @@ erts_set_trace_pattern(Process*p, ErtsCodeMFA *mfa, int specified, * Turn off global tracing, either explicitly or implicitly * before turning on breakpoint tracing. */ - erts_clear_call_trace_bif(ci, 0); - if (BeamIsOpCode(ep->beam[0], op_i_generic_breakpoint)) { - ep->beam[0] = BeamOpCodeAddr(op_trace_jump_W); + erts_clear_export_trace(ci, 0); + if (BeamIsOpCode(ep->trampoline.op, op_i_generic_breakpoint)) { + ep->trampoline.op = BeamOpCodeAddr(op_trace_jump_W); } } } /* - ** OK, now for the bif's - */ - for (i = 0; i < BIF_SIZE; ++i) { - Export *ep = bif_export[i]; - - if (!ExportIsBuiltIn(ep)) { - continue; - } - - if (bif_table[i].f == bif_table[i].traced) { - /* Trace wrapper same as regular function - untraceable */ - continue; - } - - switch (specified) { - case 3: - if (mfa->arity != ep->info.mfa.arity) - continue; - case 2: - if (mfa->function != ep->info.mfa.function) - continue; - case 1: - if (mfa->module != ep->info.mfa.module) - continue; - case 0: - break; - default: - ASSERT(0); - } - - if (! flags.breakpoint) { /* Export entry call trace */ - if (on) { - erts_clear_call_trace_bif(&ep->info, 1); - erts_clear_mtrace_bif(&ep->info); - erts_set_call_trace_bif(&ep->info, match_prog_set, 0); - } else { /* off */ - erts_clear_call_trace_bif(&ep->info, 0); - } - matches++; - } else { /* Breakpoint call trace */ - int m = 0; - - if (on) { - if (flags.local) { - erts_clear_call_trace_bif(&ep->info, 0); - erts_set_call_trace_bif(&ep->info, match_prog_set, 1); - m = 1; - } - if (flags.meta) { - erts_set_mtrace_bif(&ep->info, meta_match_prog_set, - meta_tracer); - m = 1; - } - if (flags.call_time) { - erts_set_time_trace_bif(&ep->info, on); - /* I don't want to remove any other tracers */ - m = 1; - } - } else { /* off */ - if (flags.local) { - erts_clear_call_trace_bif(&ep->info, 1); - m = 1; - } - if (flags.meta) { - erts_clear_mtrace_bif(&ep->info); - m = 1; - } - if (flags.call_time) { - erts_clear_time_trace_bif(&ep->info); - m = 1; - } - } - matches += m; - } - } - - /* ** So, now for breakpoint tracing */ erts_bp_match_functions(&finish_bp.f, mfa, specified); @@ -1670,7 +1592,6 @@ erts_finish_breakpointing(void) install_exp_breakpoints(&finish_bp.e); } } - setup_bif_trace(); return 1; case 1: /* @@ -1699,7 +1620,6 @@ erts_finish_breakpointing(void) uninstall_exp_breakpoints(&finish_bp.e); } } - reset_bif_trace(); return 1; case 3: /* @@ -1710,7 +1630,6 @@ erts_finish_breakpointing(void) * updated). If any breakpoints have been totally disabled, * deallocate the GenericBp structs for them. */ - erts_consolidate_bif_bp_data(); clean_export_entries(&finish_bp.e); erts_consolidate_bp_data(&finish_bp.e, 0); erts_consolidate_bp_data(&finish_bp.f, 1); @@ -1736,7 +1655,7 @@ install_exp_breakpoints(BpFunctions* f) for (i = 0; i < ne; i++) { Export* ep = ErtsContainerStruct(fp[i].ci, Export, info); - ep->addressv[code_ix] = ep->beam; + ep->addressv[code_ix] = ep->trampoline.raw; } } @@ -1751,11 +1670,12 @@ uninstall_exp_breakpoints(BpFunctions* f) for (i = 0; i < ne; i++) { Export* ep = ErtsContainerStruct(fp[i].ci, Export, info); - if (ep->addressv[code_ix] != ep->beam) { - continue; - } - ASSERT(BeamIsOpCode(ep->beam[0], op_trace_jump_W)); - ep->addressv[code_ix] = (BeamInstr *) ep->beam[1]; + if (ep->addressv[code_ix] != ep->trampoline.raw) { + continue; + } + + ASSERT(BeamIsOpCode(ep->trampoline.op, op_trace_jump_W)); + ep->addressv[code_ix] = (BeamInstr *) ep->trampoline.trace.address; } } @@ -1770,48 +1690,14 @@ clean_export_entries(BpFunctions* f) for (i = 0; i < ne; i++) { Export* ep = ErtsContainerStruct(fp[i].ci, Export, info); - if (ep->addressv[code_ix] == ep->beam) { - continue; - } - if (BeamIsOpCode(ep->beam[0], op_trace_jump_W)) { - ep->beam[0] = (BeamInstr) 0; - ep->beam[1] = (BeamInstr) 0; - } - } -} - -static void -setup_bif_trace(void) -{ - int i; - - for (i = 0; i < BIF_SIZE; ++i) { - Export *ep = bif_export[i]; - GenericBp* g = ep->info.u.gen_bp; - if (g) { - if (ExportIsBuiltIn(ep)) { - ASSERT(ep->beam[1]); - ep->beam[1] = (BeamInstr) bif_table[i].traced; - } - } - } -} + if (ep->addressv[code_ix] == ep->trampoline.raw) { + continue; + } -static void -reset_bif_trace(void) -{ - int i; - ErtsBpIndex active = erts_active_bp_ix(); - - for (i = 0; i < BIF_SIZE; ++i) { - Export *ep = bif_export[i]; - GenericBp* g = ep->info.u.gen_bp; - if (g && g->data[active].flags == 0) { - if (ExportIsBuiltIn(ep)) { - ASSERT(ep->beam[1]); - ep->beam[1] = (BeamInstr) bif_table[i].f; - } - } + if (BeamIsOpCode(ep->trampoline.op, op_trace_jump_W)) { + ep->trampoline.op = (BeamInstr) 0; + ep->trampoline.trace.address = (BeamInstr) 0; + } } } diff --git a/erts/emulator/beam/erl_binary.h b/erts/emulator/beam/erl_binary.h index c9c047255a..f5a35f2222 100644 --- a/erts/emulator/beam/erl_binary.h +++ b/erts/emulator/beam/erl_binary.h @@ -311,6 +311,7 @@ ERTS_GLB_INLINE void erts_free_aligned_binary_bytes(byte* buf); ERTS_GLB_INLINE void erts_free_aligned_binary_bytes_extra(byte* buf, ErtsAlcType_t); ERTS_GLB_INLINE Binary *erts_bin_drv_alloc_fnf(Uint size); ERTS_GLB_INLINE Binary *erts_bin_drv_alloc(Uint size); +ERTS_GLB_INLINE Binary *erts_bin_nrml_alloc_fnf(Uint size); ERTS_GLB_INLINE Binary *erts_bin_nrml_alloc(Uint size); ERTS_GLB_INLINE Binary *erts_bin_realloc_fnf(Binary *bp, Uint size); ERTS_GLB_INLINE Binary *erts_bin_realloc(Binary *bp, Uint size); @@ -351,6 +352,19 @@ erts_free_aligned_binary_bytes(byte* buf) erts_free_aligned_binary_bytes_extra(buf,ERTS_ALC_T_TMP); } +/* A binary's size in bits must fit into a word for matching to work. We used + * to allow creating larger binaries than this, but they acted really strangely + * in Erlang code and were pretty much only usable in drivers and NIFs. + * + * This check also ensures, indirectly, that there won't be an overflow when + * the size is bumped by CHICKEN_PAD and the binary struct itself. */ +#define BINARY_OVERFLOW_CHECK(BYTE_SIZE) \ + do { \ + if (ERTS_UNLIKELY(BYTE_SIZE > ERTS_UWORD_MAX / CHAR_BIT)) { \ + return NULL; \ + } \ + } while(0) + /* Explicit extra bytes allocated to counter buggy drivers. ** These extra bytes where earlier (< R13B04) added by an alignment-bug ** in this code. Do we dare remove this in some major release (R14?) maybe? @@ -364,86 +378,107 @@ erts_free_aligned_binary_bytes(byte* buf) ERTS_GLB_INLINE Binary * erts_bin_drv_alloc_fnf(Uint size) { - Uint bsize = ERTS_SIZEOF_Binary(size) + CHICKEN_PAD; Binary *res; + Uint bsize; + + BINARY_OVERFLOW_CHECK(size); + bsize = ERTS_SIZEOF_Binary(size) + CHICKEN_PAD; - if (bsize < size) /* overflow */ - return NULL; res = erts_alloc_fnf(ERTS_ALC_T_DRV_BINARY, bsize); ERTS_CHK_BIN_ALIGNMENT(res); + if (res) { - res->orig_size = size; - res->intern.flags = BIN_FLAG_DRV; + res->orig_size = size; + res->intern.flags = BIN_FLAG_DRV; erts_refc_init(&res->intern.refc, 1); } + return res; } ERTS_GLB_INLINE Binary * erts_bin_drv_alloc(Uint size) { - Uint bsize = ERTS_SIZEOF_Binary(size) + CHICKEN_PAD; + Binary *res = erts_bin_drv_alloc_fnf(size); + + if (res) { + return res; + } + + erts_alloc_enomem(ERTS_ALC_T_DRV_BINARY, size); +} + +ERTS_GLB_INLINE Binary * +erts_bin_nrml_alloc_fnf(Uint size) +{ Binary *res; + Uint bsize; - if (bsize < size) /* overflow */ - erts_alloc_enomem(ERTS_ALC_T_DRV_BINARY, size); - res = erts_alloc(ERTS_ALC_T_DRV_BINARY, bsize); + BINARY_OVERFLOW_CHECK(size); + bsize = ERTS_SIZEOF_Binary(size) + CHICKEN_PAD; + + res = erts_alloc_fnf(ERTS_ALC_T_BINARY, bsize); ERTS_CHK_BIN_ALIGNMENT(res); - res->orig_size = size; - res->intern.flags = BIN_FLAG_DRV; - erts_refc_init(&res->intern.refc, 1); + + if (res) { + res->orig_size = size; + res->intern.flags = 0; + erts_refc_init(&res->intern.refc, 1); + } + return res; } ERTS_GLB_INLINE Binary * erts_bin_nrml_alloc(Uint size) { - Uint bsize = ERTS_SIZEOF_Binary(size) + CHICKEN_PAD; - Binary *res; + Binary *res = erts_bin_drv_alloc_fnf(size); - if (bsize < size) /* overflow */ - erts_alloc_enomem(ERTS_ALC_T_BINARY, size); - res = erts_alloc(ERTS_ALC_T_BINARY, bsize); - ERTS_CHK_BIN_ALIGNMENT(res); - res->orig_size = size; - res->intern.flags = 0; - erts_refc_init(&res->intern.refc, 1); - return res; + if (res) { + return res; + } + + erts_alloc_enomem(ERTS_ALC_T_BINARY, size); } ERTS_GLB_INLINE Binary * erts_bin_realloc_fnf(Binary *bp, Uint size) { + ErtsAlcType_t type; Binary *nbp; - Uint bsize = ERTS_SIZEOF_Binary(size) + CHICKEN_PAD; - ErtsAlcType_t type = (bp->intern.flags & BIN_FLAG_DRV) ? ERTS_ALC_T_DRV_BINARY - : ERTS_ALC_T_BINARY; + Uint bsize; + + type = (bp->intern.flags & BIN_FLAG_DRV) ? ERTS_ALC_T_DRV_BINARY + : ERTS_ALC_T_BINARY; ASSERT((bp->intern.flags & BIN_FLAG_MAGIC) == 0); - if (bsize < size) /* overflow */ - return NULL; + + BINARY_OVERFLOW_CHECK(size); + bsize = ERTS_SIZEOF_Binary(size) + CHICKEN_PAD; + nbp = erts_realloc_fnf(type, (void *) bp, bsize); ERTS_CHK_BIN_ALIGNMENT(nbp); - if (nbp) - nbp->orig_size = size; + + if (nbp) { + nbp->orig_size = size; + } + return nbp; } ERTS_GLB_INLINE Binary * erts_bin_realloc(Binary *bp, Uint size) { - Binary *nbp; - Uint bsize = ERTS_SIZEOF_Binary(size) + CHICKEN_PAD; - ErtsAlcType_t type = (bp->intern.flags & BIN_FLAG_DRV) ? ERTS_ALC_T_DRV_BINARY - : ERTS_ALC_T_BINARY; - ASSERT((bp->intern.flags & BIN_FLAG_MAGIC) == 0); - if (bsize < size) /* overflow */ - erts_realloc_enomem(type, bp, size); - nbp = erts_realloc_fnf(type, (void *) bp, bsize); - if (!nbp) - erts_realloc_enomem(type, bp, bsize); - ERTS_CHK_BIN_ALIGNMENT(nbp); - nbp->orig_size = size; - return nbp; + Binary *nbp = erts_bin_realloc_fnf(bp, size); + + if (nbp) { + return nbp; + } + + if (bp->intern.flags & BIN_FLAG_DRV) { + erts_realloc_enomem(ERTS_ALC_T_DRV_BINARY, bp, size); + } else { + erts_realloc_enomem(ERTS_ALC_T_BINARY, bp, size); + } } ERTS_GLB_INLINE void diff --git a/erts/emulator/beam/erl_bits.c b/erts/emulator/beam/erl_bits.c index f5807d25d7..a0edbc81a4 100644 --- a/erts/emulator/beam/erl_bits.c +++ b/erts/emulator/beam/erl_bits.c @@ -124,10 +124,10 @@ erts_bs_start_match_2(Process *p, Eterm Binary, Uint Max) ProcBin* pb; ASSERT(is_binary(Binary)); + total_bin_size = binary_size(Binary); - if ((total_bin_size >> (8*sizeof(Uint)-3)) != 0) { - return THE_NON_VALUE; - } + ASSERT(total_bin_size <= ERTS_UWORD_MAX / CHAR_BIT); + NeededSize = ERL_BIN_MATCHSTATE_SIZE(Max); hp = HeapOnlyAlloc(p, NeededSize); ms = (ErlBinMatchState *) hp; @@ -157,10 +157,9 @@ ErlBinMatchState *erts_bs_start_match_3(Process *p, Eterm Binary) ProcBin* pb; ASSERT(is_binary(Binary)); + total_bin_size = binary_size(Binary); - if ((total_bin_size >> (8*sizeof(Uint)-3)) != 0) { - return NULL; - } + ASSERT(total_bin_size <= ERTS_UWORD_MAX / CHAR_BIT); NeededSize = ERL_BIN_MATCHSTATE_SIZE(0); hp = HeapOnlyAlloc(p, NeededSize); @@ -459,29 +458,25 @@ erts_bs_get_integer_2(Process *p, Uint num_bits, unsigned flags, ErlBinMatchBuff Eterm erts_bs_get_binary_2(Process *p, Uint num_bits, unsigned flags, ErlBinMatchBuffer* mb) { - ErlSubBin* sb; + Eterm result; CHECK_MATCH_BUFFER(mb); - if (mb->size - mb->offset < num_bits) { /* Asked for too many bits. */ - return THE_NON_VALUE; + if (mb->size - mb->offset < num_bits) { + /* Asked for too many bits. */ + return THE_NON_VALUE; } /* * From now on, we can't fail. */ - sb = (ErlSubBin *) HeapOnlyAlloc(p, ERL_SUB_BIN_SIZE); - - sb->thing_word = HEADER_SUB_BIN; - sb->orig = mb->orig; - sb->size = BYTE_OFFSET(num_bits); - sb->bitsize = BIT_OFFSET(num_bits); - sb->offs = BYTE_OFFSET(mb->offset); - sb->bitoffs = BIT_OFFSET(mb->offset); - sb->is_writable = 0; + result = erts_extract_sub_binary(&HEAP_TOP(p), + mb->orig, mb->base, + mb->offset, num_bits); + mb->offset += num_bits; - - return make_binary(sb); + + return result; } Eterm @@ -545,21 +540,19 @@ erts_bs_get_float_2(Process *p, Uint num_bits, unsigned flags, ErlBinMatchBuffer Eterm erts_bs_get_binary_all_2(Process *p, ErlBinMatchBuffer* mb) { - ErlSubBin* sb; - Uint size; + Uint bit_size; + Eterm result; CHECK_MATCH_BUFFER(mb); - size = mb->size-mb->offset; - sb = (ErlSubBin *) HeapOnlyAlloc(p, ERL_SUB_BIN_SIZE); - sb->thing_word = HEADER_SUB_BIN; - sb->size = BYTE_OFFSET(size); - sb->bitsize = BIT_OFFSET(size); - sb->offs = BYTE_OFFSET(mb->offset); - sb->bitoffs = BIT_OFFSET(mb->offset); - sb->is_writable = 0; - sb->orig = mb->orig; - mb->offset = mb->size; - return make_binary(sb); + bit_size = mb->size - mb->offset; + + result = erts_extract_sub_binary(&HEAP_TOP(p), + mb->orig, mb->base, + mb->offset, bit_size); + + mb->offset = mb->size; + + return result; } /**************************************************************** @@ -2097,3 +2090,39 @@ erts_copy_bits(byte* src, /* Base pointer to source. */ } } +Eterm erts_extract_sub_binary(Eterm **hp, Eterm base_bin, byte *base_data, + Uint bit_offset, Uint bit_size) +{ + Uint byte_offset, byte_size; + + ERTS_CT_ASSERT(ERL_SUB_BIN_SIZE <= ERL_ONHEAP_BIN_LIMIT); + + byte_offset = BYTE_OFFSET(bit_offset); + byte_size = BYTE_OFFSET(bit_size); + + if (BIT_OFFSET(bit_size) == 0 && byte_size <= ERL_ONHEAP_BIN_LIMIT) { + ErlHeapBin *hb = (ErlHeapBin*)*hp; + *hp += heap_bin_size(byte_size); + + hb->thing_word = header_heap_bin(byte_size); + hb->size = byte_size; + + copy_binary_to_buffer(hb->data, 0, base_data, bit_offset, bit_size); + + return make_binary(hb); + } else { + ErlSubBin *sb = (ErlSubBin*)*hp; + *hp += ERL_SUB_BIN_SIZE; + + sb->thing_word = HEADER_SUB_BIN; + sb->size = byte_size; + sb->offs = byte_offset; + sb->orig = base_bin; + sb->bitoffs = BIT_OFFSET(bit_offset); + sb->bitsize = BIT_OFFSET(bit_size); + sb->is_writable = 0; + + return make_binary(sb); + } +} + diff --git a/erts/emulator/beam/erl_bits.h b/erts/emulator/beam/erl_bits.h index 50d353e1fa..0b2a6f3760 100644 --- a/erts/emulator/beam/erl_bits.h +++ b/erts/emulator/beam/erl_bits.h @@ -116,7 +116,7 @@ typedef struct erl_bin_match_struct{ do { \ if (BIT_OFFSET(DstBufOffset) == 0 && (SrcBufferOffset == 0) && \ (BIT_OFFSET(NumBits)==0) && (NumBits != 0)) { \ - sys_memcpy(DstBuffer+BYTE_OFFSET(DstBufOffset), \ + sys_memcpy(((byte*)DstBuffer)+BYTE_OFFSET(DstBufOffset), \ SrcBuffer, NBYTES(NumBits)); \ } else { \ erts_copy_bits(SrcBuffer, SrcBufferOffset, 1, \ @@ -150,8 +150,11 @@ void erts_bits_destroy_state(ERL_BITS_PROTO_0); Eterm erts_bs_start_match_2(Process *p, Eterm Bin, Uint Max); ErlBinMatchState *erts_bs_start_match_3(Process *p, Eterm Bin); Eterm erts_bs_get_integer_2(Process *p, Uint num_bits, unsigned flags, ErlBinMatchBuffer* mb); -Eterm erts_bs_get_binary_2(Process *p, Uint num_bits, unsigned flags, ErlBinMatchBuffer* mb); Eterm erts_bs_get_float_2(Process *p, Uint num_bits, unsigned flags, ErlBinMatchBuffer* mb); + +/* These will create heap binaries when appropriate, so they require free space + * up to EXTRACT_SUB_BIN_HEAP_NEED. */ +Eterm erts_bs_get_binary_2(Process *p, Uint num_bits, unsigned flags, ErlBinMatchBuffer* mb); Eterm erts_bs_get_binary_all_2(Process *p, ErlBinMatchBuffer* mb); /* @@ -182,6 +185,17 @@ void erts_copy_bits(byte* src, size_t soffs, int sdir, byte* dst, size_t doffs,int ddir, size_t n); int erts_cmp_bits(byte* a_ptr, size_t a_offs, byte* b_ptr, size_t b_offs, size_t size); + +/* Extracts a region from base_bin as a sub-binary or heap binary, whichever + * is the most appropriate. + * + * The caller must ensure that there's enough free space at *hp */ +Eterm erts_extract_sub_binary(Eterm **hp, Eterm base_bin, byte *base_data, + Uint bit_offset, Uint num_bits); + +/* Pessimistic estimate of the words required for erts_extract_sub_binary */ +#define EXTRACT_SUB_BIN_HEAP_NEED (heap_bin_size(ERL_ONHEAP_BIN_LIMIT)) + /* * Flags for bs_get_* / bs_put_* / bs_init* instructions. */ diff --git a/erts/emulator/beam/erl_db.c b/erts/emulator/beam/erl_db.c index d24f30f126..285c23ea01 100644 --- a/erts/emulator/beam/erl_db.c +++ b/erts/emulator/beam/erl_db.c @@ -399,7 +399,9 @@ Export ets_select_continue_exp; * Static traps */ static Export ets_delete_continue_exp; - + +static Export *ets_info_binary_trap = NULL; + static void free_dbtable(void *vtb) { @@ -675,7 +677,8 @@ static DbTable* handle_lacking_permission(Process* p, DbTable* tb, tb = NULL; *freason_p = TRAP; } - else if (p->common.id != tb->common.owner) { + else if (p->common.id != tb->common.owner + && !(p->flags & F_ETS_SUPER_USER)) { db_unlock(tb, kind); tb = NULL; *freason_p = BADARG; @@ -3411,6 +3414,10 @@ BIF_RETTYPE ets_info_2(BIF_ALIST_2) } BIF_RET(erts_make_integer(res, BIF_P)); } + + if (BIF_ARG_2 == am_binary) + BIF_TRAP1(ets_info_binary_trap, BIF_P, BIF_ARG_1); + if ((tb = db_get_table(BIF_P, BIF_ARG_1, DB_INFO, LCK_READ, &freason)) == NULL) { if (freason == BADARG && (is_atom(BIF_ARG_1) || is_ref(BIF_ARG_1))) BIF_RET(am_undefined); @@ -3509,6 +3516,81 @@ BIF_RETTYPE ets_match_spec_run_r_3(BIF_ALIST_3) BIF_RET2(ret,i); } +BIF_RETTYPE erts_internal_ets_lookup_binary_info_2(BIF_ALIST_2) +{ + DbTable* tb; + int cret; + Eterm ret; + + CHECK_TABLES(); + + DB_BIF_GET_TABLE(tb, DB_READ, LCK_READ, BIF_erts_internal_ets_lookup_binary_info_2); + + cret = tb->common.meth->db_get_binary_info(BIF_P, tb, BIF_ARG_2, &ret); + + db_unlock(tb, LCK_READ); + + switch (cret) { + case DB_ERROR_NONE: + BIF_RET(ret); + case DB_ERROR_SYSRES: + BIF_ERROR(BIF_P, SYSTEM_LIMIT); + default: + BIF_ERROR(BIF_P, BADARG); + } +} + +BIF_RETTYPE erts_internal_ets_raw_first_1(BIF_ALIST_1) +{ + DbTable* tb; + int cret; + Eterm ret; + + CHECK_TABLES(); + + DB_BIF_GET_TABLE(tb, DB_READ, LCK_READ, BIF_erts_internal_ets_raw_first_1); + + cret = tb->common.meth->db_raw_first(BIF_P, tb, &ret); + + db_unlock(tb, LCK_READ); + + if (cret != DB_ERROR_NONE) { + BIF_ERROR(BIF_P, BADARG); + } + BIF_RET(ret); +} + +BIF_RETTYPE erts_internal_ets_raw_next_2(BIF_ALIST_2) +{ + DbTable* tb; + int cret; + Eterm ret; + + CHECK_TABLES(); + + DB_BIF_GET_TABLE(tb, DB_READ, LCK_READ, BIF_erts_internal_ets_raw_next_2); + + cret = tb->common.meth->db_raw_next(BIF_P, tb, BIF_ARG_2, &ret); + + db_unlock(tb, LCK_READ); + + if (cret != DB_ERROR_NONE) { + BIF_ERROR(BIF_P, BADARG); + } + BIF_RET(ret); +} + +BIF_RETTYPE +erts_internal_ets_super_user_1(BIF_ALIST_1) +{ + if (BIF_ARG_1 == am_true) + BIF_P->flags |= F_ETS_SUPER_USER; + else if (BIF_ARG_1 == am_false) + BIF_P->flags &= ~F_ETS_SUPER_USER; + else + BIF_ERROR(BIF_P, BADARG); + BIF_RET(am_ok); +} /* ** External interface (NOT BIF's) @@ -3628,6 +3710,12 @@ void init_db(ErtsDbSpinCount db_spin_count) erts_init_trap_export(&ets_delete_continue_exp, am_ets, ERTS_MAKE_AM("delete_trap"), 1, &ets_delete_trap); + + /* ets:info(Tab, binary) trap... */ + + ets_info_binary_trap = erts_export_put(am_erts_internal, + am_ets_info_binary, + 1); } void @@ -4415,7 +4503,7 @@ void db_info(fmtfn_t to, void *to_arg, int show) /* Called by break handler * pdbi.to_arg = to_arg; pdbi.show = show; - erts_db_foreach_table(db_info_print, &pdbi); + erts_db_foreach_table(db_info_print, &pdbi, !0); } Uint @@ -4428,7 +4516,7 @@ erts_get_ets_misc_mem_size(void) /* SMP Note: May only be used when system is locked */ void -erts_db_foreach_table(void (*func)(DbTable *, void *), void *arg) +erts_db_foreach_table(void (*func)(DbTable *, void *), void *arg, int alive_only) { int ix; @@ -4440,7 +4528,7 @@ erts_db_foreach_table(void (*func)(DbTable *, void *), void *arg) if (first) { DbTable *tb = first; do { - if (is_table_alive(tb)) + if (!alive_only || is_table_alive(tb)) (*func)(tb, arg); tb = tb->common.all.next; } while (tb != first); @@ -4457,6 +4545,15 @@ erts_db_foreach_offheap(DbTable *tb, tb->common.meth->db_foreach_offheap(tb, func, arg); } +void +erts_db_foreach_thr_prgr_offheap(void (*func)(ErlOffHeap *, void *), + void *arg) +{ + erts_db_foreach_thr_prgr_offheap_hash(func, arg); + erts_db_foreach_thr_prgr_offheap_tree(func, arg); + erts_db_foreach_thr_prgr_offheap_catree(func, arg); +} + /* retrieve max number of ets tables */ Uint erts_db_get_max_tabs() diff --git a/erts/emulator/beam/erl_db.h b/erts/emulator/beam/erl_db.h index b3dc1b9ba3..c604744687 100644 --- a/erts/emulator/beam/erl_db.h +++ b/erts/emulator/beam/erl_db.h @@ -114,10 +114,12 @@ void init_db(ErtsDbSpinCount); int erts_db_process_exiting(Process *, ErtsProcLocks, void **); int erts_db_execute_free_fixation(Process*, DbFixation*); void db_info(fmtfn_t, void *, int); -void erts_db_foreach_table(void (*)(DbTable *, void *), void *); +void erts_db_foreach_table(void (*)(DbTable *, void *), void *, int); void erts_db_foreach_offheap(DbTable *, void (*func)(ErlOffHeap *, void *), void *); +void erts_db_foreach_thr_prgr_offheap(void (*func)(ErlOffHeap *, void *), + void *); extern int erts_ets_rwmtx_spin_count; extern int user_requested_db_max_tabs; /* set in erl_init */ diff --git a/erts/emulator/beam/erl_db_catree.c b/erts/emulator/beam/erl_db_catree.c index fed4b44a9b..176966edb5 100644 --- a/erts/emulator/beam/erl_db_catree.c +++ b/erts/emulator/beam/erl_db_catree.c @@ -90,9 +90,9 @@ ** Forward declarations */ -static SWord do_free_base_node_cont(DbTableCATree *tb, SWord num_left); -static SWord do_free_routing_nodes_catree_cont(DbTableCATree *tb, SWord num_left); -static DbTableCATreeNode *catree_first_base_node_from_free_list(DbTableCATree *tb); +static SWord do_delete_base_node_cont(DbTableCATree *tb, + DbTableCATreeNode *base_node, + SWord num_left); /* Method interface functions */ static int db_first_catree(Process *p, DbTable *tbl, @@ -159,6 +159,7 @@ static int db_lookup_dbterm_catree(Process *, DbTable *, Eterm key, Eterm obj, DbUpdateHandle*); static void db_finalize_dbterm_catree(int cret, DbUpdateHandle *); +static int db_get_binary_info_catree(Process*, DbTable*, Eterm key, Eterm *ret); static void split_catree(DbTableCATree *tb, DbTableCATreeNode* ERTS_RESTRICT base, @@ -211,8 +212,10 @@ DbTableMethod db_catree = db_print_catree, db_foreach_offheap_catree, db_lookup_dbterm_catree, - db_finalize_dbterm_catree - + db_finalize_dbterm_catree, + db_get_binary_info_catree, + db_first_catree, /* raw_first same as first */ + db_next_catree /* raw_next same as next */ }; /* @@ -1364,113 +1367,152 @@ static void split_catree(DbTableCATree *tb, } } -/* - * Helper functions for removing the table +/* @brief Free the entire catree and its sub-trees. + * + * @param reds Reductions to spend. + * @return Reductions left. Negative value if not done. */ - -static void catree_add_base_node_to_free_list( - DbTableCATree *tb, - DbTableCATreeNode *base_node_container) +static SWord db_free_table_continue_catree(DbTable *tbl, SWord reds) { - base_node_container->u.base.next = - tb->base_nodes_to_free_list; - tb->base_nodes_to_free_list = base_node_container; -} + DbTableCATree *tb = &tbl->catree; + DbTableCATreeNode *node; + DbTableCATreeNode *parent; + CATreeNodeStack rnode_stack; + DbTableCATreeNode *rnode_stack_array[STACK_NEED]; -static void catree_deque_base_node_from_free_list(DbTableCATree *tb) -{ - if (tb->base_nodes_to_free_list == NULL) { - return; /* List empty */ - } else { - DbTableCATreeNode *first = tb->base_nodes_to_free_list; - tb->base_nodes_to_free_list = first->u.base.next; + if (!tb->deletion) { + /* First call */ + tb->deletion = 1; + tb->nr_of_deleted_items = 0; } -} -static DbTableCATreeNode *catree_first_base_node_from_free_list( - DbTableCATree *tb) -{ - return tb->base_nodes_to_free_list; -} + /* + * The route tree is traversed and freed while keeping it consistent + * during yields. + */ + rnode_stack.array = rnode_stack_array; + rnode_stack.pos = 0; + rnode_stack.size = STACK_NEED; -static SWord do_free_routing_nodes_catree_cont(DbTableCATree *tb, SWord num_left) -{ - DbTableCATreeNode *root; - DbTableCATreeNode *p; - for (;;) { - root = POP_NODE(&tb->free_stack_rnodes); - if (root == NULL) break; - else if(root->is_base_node) { - catree_add_base_node_to_free_list(tb, root); - break; + node = GET_ROOT(tb); + if (node->is_base_node) { + if (node->u.base.root) { + reds = do_delete_base_node_cont(tb, node, reds); + if (reds < 0) + return reds; /* Yield */ } - for (;;) { - if ((GET_LEFT(root) != NULL) && - (p = GET_LEFT(root))->is_base_node) { - SET_LEFT(root, NULL); - catree_add_base_node_to_free_list(tb, p); - } else if ((GET_RIGHT(root) != NULL) && - (p = GET_RIGHT(root))->is_base_node) { - SET_RIGHT(root, NULL); - catree_add_base_node_to_free_list(tb, p); - } else if ((p = GET_LEFT(root)) != NULL) { - SET_LEFT(root, NULL); - PUSH_NODE(&tb->free_stack_rnodes, root); - root = p; - } else if ((p = GET_RIGHT(root)) != NULL) { - SET_RIGHT(root, NULL); - PUSH_NODE(&tb->free_stack_rnodes, root); - root = p; - } else { - free_catree_route_node(tb, root); - if (--num_left >= 0) { + free_catree_base_node(tb, node); + } + else { + for (;;) { + DbTableCATreeNode* left = GET_LEFT(node); + DbTableCATreeNode* right = GET_RIGHT(node); + + if (!left->is_base_node) { + PUSH_NODE(&rnode_stack, node); + node = left; + } + else if (!right->is_base_node) { + PUSH_NODE(&rnode_stack, node); + node = right; + } + else { + if (left->u.base.root) { + reds = do_delete_base_node_cont(tb, left, reds); + if (reds < 0) + return reds; /* Yield */ + } + if (right->u.base.root) { + reds = do_delete_base_node_cont(tb, right, reds); + if (reds < 0) + return reds; /* Yield */ + } + + free_catree_base_node(tb, right); + free_catree_route_node(tb, node); + /* + * Keep empty left base node to join with its grandparent + * for tree consistency during yields. + */ + + parent = POP_NODE(&rnode_stack); + if (parent) { + if (node == GET_LEFT(parent)) { + SET_LEFT(parent, left); + } + else { + ASSERT(node == GET_RIGHT(parent)); + SET_RIGHT(parent, left); + } + + reds -= 2; + if (reds < 0) + return reds; /* Yield */ + + node = parent; + } + else { /* Done */ + free_catree_base_node(tb, left); break; - } else { - return num_left; /* Done enough for now */ } } } } - return num_left; + + ASSERT(reds >= 0); + SET_ROOT(tb, NULL); + return reds; } -static SWord do_free_base_node_cont(DbTableCATree *tb, SWord num_left) +/* @brief Free all objects of a base node, but keep the base node. + * + * @param reds Reductions to spend. + * @return Reductions left. Negative value if not done. + */ +static SWord do_delete_base_node_cont(DbTableCATree *tb, + DbTableCATreeNode *base_node, + SWord reds) { - TreeDbTerm *root; TreeDbTerm *p; - DbTableCATreeNode *base_node_container = - catree_first_base_node_from_free_list(tb); + DbTreeStack stack; + TreeDbTerm* stack_array[STACK_NEED]; + + stack.pos = 0; + stack.array = stack_array; + + p = base_node->u.base.root; for (;;) { - root = POP_NODE(&tb->free_stack_elems); - if (root == NULL) break; - for (;;) { - if ((p = root->left) != NULL) { - root->left = NULL; - PUSH_NODE(&tb->free_stack_elems, root); - root = p; - } else if ((p = root->right) != NULL) { - root->right = NULL; - PUSH_NODE(&tb->free_stack_elems, root); - root = p; - } else { - DEC_NITEMS((DbTable*)tb); - tb->nr_of_deleted_items++; - free_term((DbTable*)tb, root); - if (--num_left >= 0) { - break; - } else { - return num_left; /* Done enough for now */ - } + if (p->left) { + PUSH_NODE(&stack, p); + p = p->left; + } + else if (p->right) { + PUSH_NODE(&stack, p); + p = p->right; + } + else { + TreeDbTerm *parent; + + DEC_NITEMS((DbTable*)tb); + tb->nr_of_deleted_items++; + free_term((DbTable*)tb, p); + + parent = POP_NODE(&stack); + if (!parent) + break; + if (parent->left == p) + parent->left = NULL; + else { + ASSERT(parent->right == p); + parent->right = NULL; } + if (--reds < 0) + return reds; /* Yield */ + p = parent; } } - catree_deque_base_node_from_free_list(tb); - free_catree_base_node(tb, base_node_container); - base_node_container = catree_first_base_node_from_free_list(tb); - if (base_node_container != NULL) { - PUSH_NODE(&tb->free_stack_elems, base_node_container->u.base.root); - } - return num_left; + base_node->u.base.root = NULL; + return reds; } @@ -1494,7 +1536,6 @@ int db_create_catree(Process *p, DbTable *tbl) root = create_base_node(tb, NULL); tb->deletion = 0; - tb->base_nodes_to_free_list = NULL; tb->nr_of_deleted_items = 0; #ifdef DEBUG tbl->common.status |= DB_CATREE_DEBUG_RANDOM_SPLIT_JOIN; @@ -2131,57 +2172,6 @@ static int db_free_table_catree(DbTable *tbl) return 1; } -static SWord db_free_table_continue_catree(DbTable *tbl, SWord reds) -{ - DbTableCATreeNode *first_base_node; - DbTableCATree *tb = &tbl->catree; - if (!tb->deletion) { - tb->deletion = 1; - tb->free_stack_elems.array = - erts_db_alloc(ERTS_ALC_T_DB_STK, - (DbTable *) tb, - sizeof(TreeDbTerm *) * STACK_NEED); - tb->free_stack_elems.pos = 0; - tb->free_stack_elems.slot = 0; - tb->free_stack_rnodes.array = - erts_db_alloc(ERTS_ALC_T_DB_STK, - (DbTable *) tb, - sizeof(DbTableCATreeNode *) * STACK_NEED); - tb->free_stack_rnodes.pos = 0; - tb->free_stack_rnodes.size = STACK_NEED; - PUSH_NODE(&tb->free_stack_rnodes, GET_ROOT(tb)); - tb->is_routing_nodes_freed = 0; - tb->base_nodes_to_free_list = NULL; - tb->nr_of_deleted_items = 0; - } - if ( ! tb->is_routing_nodes_freed ) { - reds = do_free_routing_nodes_catree_cont(tb, reds); - if (reds < 0) { - return reds; /* Not finished */ - } else { - tb->is_routing_nodes_freed = 1; /* Ready with the routing nodes */ - first_base_node = catree_first_base_node_from_free_list(tb); - PUSH_NODE(&tb->free_stack_elems, first_base_node->u.base.root); - } - } - while (catree_first_base_node_from_free_list(tb) != NULL) { - reds = do_free_base_node_cont(tb, reds); - if (reds < 0) { - return reds; /* Continue later */ - } - } - /* Time to free the main structure*/ - erts_db_free(ERTS_ALC_T_DB_STK, - (DbTable *) tb, - (void *) tb->free_stack_elems.array, - sizeof(TreeDbTerm *) * STACK_NEED); - erts_db_free(ERTS_ALC_T_DB_STK, - (DbTable *) tb, - (void *) tb->free_stack_rnodes.array, - sizeof(DbTableCATreeNode *) * STACK_NEED); - return 1; -} - static int db_catree_nr_of_items_deleted_wb_dtor(Binary *context_bin) { (void)context_bin; @@ -2258,10 +2248,15 @@ static void db_foreach_offheap_catree(DbTable *tbl, void (*func)(ErlOffHeap *, void *), void *arg) { + DbTableCATree* tb = &tbl->catree; CATreeRootIterator iter; TreeDbTerm** root; - init_root_iterator(&tbl->catree, &iter, 1); + if (!GET_ROOT(tb)) { + ASSERT(tb->common.status & DB_DELETE); + return; + } + init_root_iterator(tb, &iter, 1); root = catree_find_first_root(&iter); do { db_foreach_offheap_tree_common(*root, func, arg); @@ -2269,7 +2264,7 @@ static void db_foreach_offheap_catree(DbTable *tbl, } while (root); destroy_root_iterator(&iter); - do_for_route_nodes(GET_ROOT(&tbl->catree), func, arg); + do_for_route_nodes(GET_ROOT(tb), func, arg); } static int db_lookup_dbterm_catree(Process *p, DbTable *tbl, Eterm key, Eterm obj, @@ -2301,6 +2296,19 @@ static void db_finalize_dbterm_catree(int cret, DbUpdateHandle *handle) return; } +static int db_get_binary_info_catree(Process *p, DbTable *tbl, Eterm key, + Eterm *ret) +{ + DbTableCATree *tb = &tbl->catree; + FindBaseNode fbn; + DbTableCATreeNode* node = find_wlock_valid_base_node(tb, key, &fbn); + TreeDbTerm* this = db_find_tree_node_common(&tbl->common, node->u.base.root, + key); + *ret = db_binary_info_tree_common(p, this); + wunlock_base_node(node); + return DB_ERROR_NONE; +} + #ifdef ERTS_ENABLE_LOCK_COUNT static void erts_lcnt_enable_db_catree_lock_count_helper(DbTableCATree *tb, DbTableCATreeNode *node, @@ -2395,6 +2403,34 @@ void db_calc_stats_catree(DbTableCATree* tb, DbCATreeStats* stats) } while (depth > 0); } +struct debug_catree_fa { + void (*func)(ErlOffHeap *, void *); + void *arg; +}; + +static void debug_free_route_node(void *vfap, ErtsThrPrgrVal val, void *vnp) +{ + DbTableCATreeNode *np = vnp; + if (np->u.route.key.oh) { + struct debug_catree_fa *fap = vfap; + ErlOffHeap oh; + ERTS_INIT_OFF_HEAP(&oh); + oh.first = np->u.route.key.oh; + (*fap->func)(&oh, fap->arg); + } +} + +void +erts_db_foreach_thr_prgr_offheap_catree(void (*func)(ErlOffHeap *, void *), + void *arg) +{ + struct debug_catree_fa fa; + fa.func = func; + fa.arg = arg; + erts_debug_later_op_foreach(do_free_route_node, debug_free_route_node, &fa); +} + + #ifdef HARDDEBUG /* diff --git a/erts/emulator/beam/erl_db_catree.h b/erts/emulator/beam/erl_db_catree.h index c2c884eee3..00141ef86d 100644 --- a/erts/emulator/beam/erl_db_catree.h +++ b/erts/emulator/beam/erl_db_catree.h @@ -46,7 +46,6 @@ typedef struct { int is_valid; /* If this base node is still valid */ TreeDbTerm *root; /* The root of the sequential tree */ ErtsThrPrgrLaterOp free_item; /* Used when freeing using thread progress */ - struct DbTableCATreeNode * next; /* Used when gradually deleting */ char end_of_struct__; } DbTableCATreeBaseNode; @@ -83,9 +82,6 @@ typedef struct db_table_catree { /* CA Tree-specific fields */ erts_atomic_t root; /* The tree root (DbTableCATreeNode*) */ Uint deletion; /* Being deleted */ - DbTreeStack free_stack_elems;/* Used for deletion ...*/ - CATreeNodeStack free_stack_rnodes; - DbTableCATreeNode *base_nodes_to_free_list; int is_routing_nodes_freed; /* The fields below are used by delete_all_objects and select_delete(DeleteAll)*/ @@ -132,6 +128,9 @@ typedef struct { Uint max_depth; } DbCATreeStats; void db_calc_stats_catree(DbTableCATree*, DbCATreeStats*); +void +erts_db_foreach_thr_prgr_offheap_catree(void (*func)(ErlOffHeap *, void *), + void *arg); #endif /* _DB_CATREE_H */ diff --git a/erts/emulator/beam/erl_db_hash.c b/erts/emulator/beam/erl_db_hash.c index d80d7985cb..2bcdb47a54 100644 --- a/erts/emulator/beam/erl_db_hash.c +++ b/erts/emulator/beam/erl_db_hash.c @@ -472,6 +472,11 @@ db_lookup_dbterm_hash(Process *p, DbTable *tbl, Eterm key, Eterm obj, static void db_finalize_dbterm_hash(int cret, DbUpdateHandle* handle); +static int +db_get_binary_info_hash(Process *p, DbTable *tbl, Eterm key, Eterm *ret); +static int db_raw_first_hash(Process* p, DbTable *tbl, Eterm *ret); +static int db_raw_next_hash(Process* p, DbTable *tbl, Eterm key, Eterm *ret); + static ERTS_INLINE void try_shrink(DbTableHash* tb) { int nitems = NITEMS(tb); @@ -570,7 +575,10 @@ DbTableMethod db_hash = db_print_hash, db_foreach_offheap_hash, db_lookup_dbterm_hash, - db_finalize_dbterm_hash + db_finalize_dbterm_hash, + db_get_binary_info_hash, + db_raw_first_hash, + db_raw_next_hash }; #ifdef DEBUG @@ -3320,6 +3328,12 @@ void db_foreach_offheap_hash(DbTable *tbl, int i; int nactive = NACTIVE(tb); + if (nactive > tb->nslots) { + /* Table is being emptied by delete/1 or delete_all_objects/1 */ + ASSERT(!(tb->common.status & (DB_PRIVATE|DB_PROTECTED|DB_PUBLIC))); + nactive = tb->nslots; + } + for (i = 0; i < nactive; i++) { list = BUCKET(tb,i); while(list != 0) { @@ -3368,12 +3382,142 @@ void db_calc_stats_hash(DbTableHash* tb, DbHashStats* stats) stats->kept_items = kept_items; } + +/* + * erts_internal:ets_lookup_binary_info/2 + */ +static int db_get_binary_info_hash(Process *p, DbTable *tbl, Eterm key, Eterm *ret) +{ + DbTableHash *tb = &tbl->hash; + HashValue hval; + int ix; + HashDbTerm *b, *first, *end; + erts_rwmtx_t* lck; + Eterm *hp, *hp_end; + Uint hsz; + Eterm list; + + hval = MAKE_HASH(key); + lck = RLOCK_HASH(tb,hval); + ix = hash_to_ix(tb, hval); + b = BUCKET(tb, ix); + + while(b != 0) { + if (has_key(tb, b, key, hval)) { + goto found_key; + } + b = b->next; + } + RUNLOCK_HASH(lck); + *ret = NIL; + return DB_ERROR_NONE; + +found_key: + + first = b; + hsz = 0; + do { + ErlOffHeap oh; + oh.first = b->dbterm.first_oh; + erts_bld_bin_list(NULL, &hsz, &oh, NIL); + b = b->next; + } while (b && has_key(tb, b, key, hval)); + end = b; + + hp = HAlloc(p, hsz); + hp_end = hp + hsz; + list = NIL; + for (b = first; b != end; b = b->next) { + ErlOffHeap oh; + oh.first = b->dbterm.first_oh; + list = erts_bld_bin_list(&hp, NULL, &oh, list); + } + ASSERT(hp == hp_end); (void)hp_end; + + RUNLOCK_HASH(lck); + *ret = list; + return DB_ERROR_NONE; +} + +static int raw_find_next(Process *p, DbTable* tbl, Uint ix, + erts_rwmtx_t* lck, Eterm *ret) +{ + DbTableHash *tb = &tbl->hash; + HashDbTerm *b; + + do { + b = BUCKET(tb,ix); + if (b) { + *ret = db_copy_key(p, tbl, &b->dbterm); + RUNLOCK_HASH(lck); + return DB_ERROR_NONE; + } + ix = next_slot(tb, ix, &lck); + } while (ix); + + *ret = am_EOT; + return DB_ERROR_NONE; +} + +static int db_raw_first_hash(Process *p, DbTable *tbl, Eterm *ret) +{ + const Uint ix = 0; + return raw_find_next(p, tbl, ix, RLOCK_HASH(&tbl->hash, ix), ret); +} + +static int db_raw_next_hash(Process *p, DbTable *tbl, Eterm key, Eterm *ret) +{ + DbTableHash *tb = &tbl->hash; + HashValue hval; + Uint ix; + HashDbTerm* b; + erts_rwmtx_t* lck; + + hval = MAKE_HASH(key); + lck = RLOCK_HASH(tb,hval); + ix = hash_to_ix(tb, hval); + b = BUCKET(tb, ix); + + for (;;) { + if (b == NULL) { + RUNLOCK_HASH(lck); + return DB_ERROR_BADKEY; + } + if (has_key(tb, b, key, hval)) { + break; + } + b = b->next; + } + /* Key found */ + + for (b = b->next; b; b = b->next) { + if (!has_key(tb, b, key, hval)) { + *ret = db_copy_key(p, tbl, &b->dbterm); + RUNLOCK_HASH(lck); + return DB_ERROR_NONE; + } + } + + ix = next_slot(tb, ix, &lck); + if (ix) + return raw_find_next(p, tbl, ix, lck, ret); + + *ret = am_EOT; + return DB_ERROR_NONE; +} + /* For testing only */ Eterm erts_ets_hash_sizeof_ext_segtab(void) { return make_small(((SIZEOF_EXT_SEGTAB(0)-1) / sizeof(UWord)) + 1); } +void +erts_db_foreach_thr_prgr_offheap_hash(void (*func)(ErlOffHeap *, void *), + void *arg) +{ +} + #ifdef ERTS_ENABLE_LOCK_COUNT void erts_lcnt_enable_db_hash_lock_count(DbTableHash *tb, int enable) { int i; diff --git a/erts/emulator/beam/erl_db_hash.h b/erts/emulator/beam/erl_db_hash.h index ecd2ca74a1..b26b82056f 100644 --- a/erts/emulator/beam/erl_db_hash.h +++ b/erts/emulator/beam/erl_db_hash.h @@ -111,6 +111,9 @@ typedef struct { void db_calc_stats_hash(DbTableHash* tb, DbHashStats*); Eterm erts_ets_hash_sizeof_ext_segtab(void); +void +erts_db_foreach_thr_prgr_offheap_hash(void (*func)(ErlOffHeap *, void *), + void *arg); #ifdef ERTS_ENABLE_LOCK_COUNT void erts_lcnt_enable_db_hash_lock_count(DbTableHash *tb, int enable); diff --git a/erts/emulator/beam/erl_db_tree.c b/erts/emulator/beam/erl_db_tree.c index 492ea81b63..723b3c5d29 100644 --- a/erts/emulator/beam/erl_db_tree.c +++ b/erts/emulator/beam/erl_db_tree.c @@ -459,6 +459,9 @@ db_lookup_dbterm_tree(Process *, DbTable *, Eterm key, Eterm obj, static void db_finalize_dbterm_tree(int cret, DbUpdateHandle *); +static int db_get_binary_info_tree(Process*, DbTable*, Eterm key, Eterm *ret); + + /* ** Static variables */ @@ -499,8 +502,10 @@ DbTableMethod db_tree = db_print_tree, db_foreach_offheap_tree, db_lookup_dbterm_tree, - db_finalize_dbterm_tree - + db_finalize_dbterm_tree, + db_get_binary_info_tree, + db_first_tree, /* raw_first same as first */ + db_next_tree /* raw_next same as next */ }; @@ -3151,6 +3156,14 @@ static TreeDbTerm *find_node(DbTableCommon *tb, TreeDbTerm *root, return this; } + +TreeDbTerm *db_find_tree_node_common(DbTableCommon *tb, TreeDbTerm *root, + Eterm key) +{ + return find_node(tb, root, key, NULL); +} + + /* * Lookup a node and return the address of the node pointer in the tree */ @@ -3303,6 +3316,38 @@ db_finalize_dbterm_tree(int cret, DbUpdateHandle *handle) db_finalize_dbterm_tree_common(cret, handle, tb); } +static int db_get_binary_info_tree(Process *p, DbTable *tbl, Eterm key, Eterm *ret) +{ + *ret = db_binary_info_tree_common(p, find_node(&tbl->common, tbl->tree.root, + key, &tbl->tree)); + return DB_ERROR_NONE; +} + +Eterm db_binary_info_tree_common(Process* p, TreeDbTerm* this) +{ + Eterm *hp, *hp_end; + Uint hsz; + Eterm ret; + + if (this == NULL) { + ret = NIL; + } else { + ErlOffHeap oh; + hsz = 0; + + oh.first = this->dbterm.first_oh; + erts_bld_bin_list(NULL, &hsz, &oh, NIL); + + hp = HAlloc(p, hsz); + hp_end = hp + hsz; + oh.first = this->dbterm.first_oh; + ret = erts_bld_bin_list(&hp, NULL, &oh, NIL); + ASSERT(hp == hp_end); (void)hp_end; + } + return ret; +} + + /* * Traverse the tree with a callback function, used by db_match_xxx */ @@ -3936,6 +3981,12 @@ static int doit_select_replace(DbTableCommon *tb, TreeDbTerm **this, return 1; } +void +erts_db_foreach_thr_prgr_offheap_tree(void (*func)(ErlOffHeap *, void *), + void *arg) +{ +} + #ifdef TREE_DEBUG static void do_dump_tree2(DbTableCommon* tb, int to, void *to_arg, int show, TreeDbTerm *t, int offset) diff --git a/erts/emulator/beam/erl_db_tree.h b/erts/emulator/beam/erl_db_tree.h index 54da2a6bc1..06e0005801 100644 --- a/erts/emulator/beam/erl_db_tree.h +++ b/erts/emulator/beam/erl_db_tree.h @@ -53,4 +53,8 @@ void db_initialize_tree(void); int db_create_tree(Process *p, DbTable *tbl); +void +erts_db_foreach_thr_prgr_offheap_tree(void (*func)(ErlOffHeap *, void *), + void *arg); + #endif /* _DB_TREE_H */ diff --git a/erts/emulator/beam/erl_db_tree_util.h b/erts/emulator/beam/erl_db_tree_util.h index ba4a8f79e5..14afbd56f7 100644 --- a/erts/emulator/beam/erl_db_tree_util.h +++ b/erts/emulator/beam/erl_db_tree_util.h @@ -171,4 +171,8 @@ void db_finalize_dbterm_tree_common(int cret, DbUpdateHandle *handle, DbTableTree *stack_container); Sint cmp_partly_bound(Eterm partly_bound_key, Eterm bound_key); +TreeDbTerm *db_find_tree_node_common(DbTableCommon*, TreeDbTerm *root, + Eterm key); +Eterm db_binary_info_tree_common(Process*, TreeDbTerm*); + #endif /* _DB_TREE_UTIL_H */ diff --git a/erts/emulator/beam/erl_db_util.c b/erts/emulator/beam/erl_db_util.c index 1ea7074d21..096cb8a778 100644 --- a/erts/emulator/beam/erl_db_util.c +++ b/erts/emulator/beam/erl_db_util.c @@ -2612,7 +2612,10 @@ restart: break; case matchCaller: ASSERT(c_p == self); - if (!(c_p->cp) || !(cp = find_function_from_pc(c_p->cp))) { + t = c_p->stop[0]; + if (is_not_CP(t)) { + *esp++ = am_undefined; + } else if (!(cp = find_function_from_pc(cp_val(t)))) { *esp++ = am_undefined; } else { ehp = HAllocX(build_proc, 4, HEAP_XTRA); @@ -3285,22 +3288,15 @@ Eterm db_copy_element_from_ets(DbTableCommon* tb, Process* p, void db_cleanup_offheap_comp(DbTerm* obj) { union erl_off_heap_ptr u; - ProcBin tmp; + struct erts_tmp_aligned_offheap tmp; for (u.hdr = obj->first_oh; u.hdr; u.hdr = u.hdr->next) { - if ((UWord)u.voidp % sizeof(Uint) != 0) { /* unaligned ptr */ - sys_memcpy(&tmp, u.voidp, sizeof(tmp)); - /* Warning, must pass (void*)-variable to memcpy. Otherwise it will - cause Bus error on Sparc due to false compile time assumptions - about word aligned memory (type cast is not enough) */ - u.pb = &tmp; - } + erts_align_offheap(&u, &tmp); switch (thing_subtag(u.hdr->thing_word)) { case REFC_BINARY_SUBTAG: erts_bin_release(u.pb->val); break; case FUN_SUBTAG: - ASSERT(u.pb != &tmp); if (erts_refc_dectest(&u.fun->fe->refc, 0) == 0) { erts_erase_fun_entry(u.fun->fe); } @@ -3311,7 +3307,6 @@ void db_cleanup_offheap_comp(DbTerm* obj) break; default: ASSERT(is_external_header(u.hdr->thing_word)); - ASSERT(u.pb != &tmp); erts_deref_node_entry(u.ext->node, make_boxed(u.ep)); break; } @@ -5226,7 +5221,7 @@ static Eterm match_spec_test(Process *p, Eterm against, Eterm spec, int trace) Eterm l; Uint32 ret_flags; Uint sz; - BeamInstr *save_cp; + Eterm save_cp; if (trace && !(is_list(against) || against == NIL)) { return THE_NON_VALUE; @@ -5270,13 +5265,13 @@ static Eterm match_spec_test(Process *p, Eterm against, Eterm spec, int trace) ++n; l = CDR(list_val(l)); } - save_cp = p->cp; - p->cp = NULL; + save_cp = p->stop[0]; + p->stop[0] = NIL; res = erts_match_set_run_trace(p, p, mps, arr, n, ERTS_PAM_COPY_RESULT|ERTS_PAM_IGNORE_TRACE_SILENT, &ret_flags); - p->cp = save_cp; + p->stop[0] = save_cp; } else { n = 0; arr = NULL; diff --git a/erts/emulator/beam/erl_db_util.h b/erts/emulator/beam/erl_db_util.h index 02d4dd6c9a..f038dba89a 100644 --- a/erts/emulator/beam/erl_db_util.h +++ b/erts/emulator/beam/erl_db_util.h @@ -235,6 +235,13 @@ typedef struct db_table_method ** not DB_ERROR_NONE, the object is removed from the table. */ void (*db_finalize_dbterm)(int cret, DbUpdateHandle* handle); + int (*db_get_binary_info)(Process*, DbTable* tb, Eterm key, Eterm* ret); + + /* Raw first/next same as first/next but also return pseudo deleted keys. + Only internal use by ets:info(_,binary) */ + int (*db_raw_first)(Process*, DbTable*, Eterm* ret); + int (*db_raw_next)(Process*, DbTable*, Eterm key, Eterm* ret); + } DbTableMethod; typedef struct db_fixation { @@ -536,6 +543,17 @@ ERTS_GLB_INLINE Eterm erts_db_make_match_prog_ref(Process *p, Binary *mp, Eterm ERTS_GLB_INLINE Binary *erts_db_get_match_prog_binary(Eterm term); ERTS_GLB_INLINE Binary *erts_db_get_match_prog_binary_unchecked(Eterm term); +/* @brief Ensure off-heap header is word aligned, make a temporary copy if not. + * Needed when inspecting ETS off-heap lists that may contain unaligned + * ProcBins if table is 'compressed'. + */ +struct erts_tmp_aligned_offheap +{ + ProcBin proc_bin; +}; +ERTS_GLB_INLINE void erts_align_offheap(union erl_off_heap_ptr*, + struct erts_tmp_aligned_offheap* tmp); + #if ERTS_GLB_INLINE_INCL_FUNC_DEF /* @@ -568,6 +586,25 @@ erts_db_get_match_prog_binary(Eterm term) return bp; } +ERTS_GLB_INLINE void +erts_align_offheap(union erl_off_heap_ptr* ohp, + struct erts_tmp_aligned_offheap* tmp) +{ + if ((UWord)ohp->voidp % sizeof(UWord) != 0) { + /* + * ETS store word unaligned ProcBins in its compressed format. + * Make a temporary aligned copy. + * + * Warning, must pass (void*)-variable to memcpy. Otherwise it will + * cause Bus error on Sparc due to false compile time assumptions + * about word aligned memory (type cast is not enough). + */ + sys_memcpy(tmp, ohp->voidp, sizeof(*tmp)); + ASSERT(tmp->proc_bin.thing_word == HEADER_PROC_BIN); + ohp->pb = &tmp->proc_bin; + } +} + #endif /* diff --git a/erts/emulator/beam/erl_fun.c b/erts/emulator/beam/erl_fun.c index 257f9bf5b3..79a1fdb8b9 100644 --- a/erts/emulator/beam/erl_fun.c +++ b/erts/emulator/beam/erl_fun.c @@ -171,36 +171,33 @@ erts_erase_fun_entry(ErlFunEntry* fe) erts_fun_write_unlock(); } +struct fun_purge_foreach_args { + BeamInstr *start; + BeamInstr *end; +}; + +static void fun_purge_foreach(ErlFunEntry *fe, struct fun_purge_foreach_args *arg) +{ + BeamInstr* addr = fe->address; + if (arg->start <= addr && addr < arg->end) { + fe->pend_purge_address = addr; + ERTS_THR_WRITE_MEMORY_BARRIER; + fe->address = unloaded_fun; +#ifdef HIPE + fe->pend_purge_native_address = fe->native_address; + hipe_set_closure_stub(fe); +#endif + erts_purge_state_add_fun(fe); + } +} + void erts_fun_purge_prepare(BeamInstr* start, BeamInstr* end) { - int limit; - HashBucket** bucket; - int i; + struct fun_purge_foreach_args args = {start, end}; erts_fun_read_lock(); - limit = erts_fun_table.size; - bucket = erts_fun_table.bucket; - for (i = 0; i < limit; i++) { - HashBucket* b = bucket[i]; - - while (b) { - ErlFunEntry* fe = (ErlFunEntry *) b; - BeamInstr* addr = fe->address; - - if (start <= addr && addr < end) { - fe->pend_purge_address = addr; - ERTS_THR_WRITE_MEMORY_BARRIER; - fe->address = unloaded_fun; -#ifdef HIPE - fe->pend_purge_native_address = fe->native_address; - hipe_set_closure_stub(fe); -#endif - erts_purge_state_add_fun(fe); - } - b = b->next; - } - } + hash_foreach(&erts_fun_table, (HFOREACH_FUN)fun_purge_foreach, &args); erts_fun_read_unlock(); } @@ -250,36 +247,34 @@ erts_fun_purge_complete(ErlFunEntry **funs, Uint no) ERTS_THR_WRITE_MEMORY_BARRIER; } +struct dump_fun_foreach_args { + fmtfn_t to; + void *to_arg; +}; + +static void +dump_fun_foreach(ErlFunEntry *fe, struct dump_fun_foreach_args *args) +{ + erts_print(args->to, args->to_arg, "=fun\n"); + erts_print(args->to, args->to_arg, "Module: %T\n", fe->module); + erts_print(args->to, args->to_arg, "Uniq: %d\n", fe->old_uniq); + erts_print(args->to, args->to_arg, "Index: %d\n",fe->old_index); + erts_print(args->to, args->to_arg, "Address: %p\n", fe->address); +#ifdef HIPE + erts_print(args->to, args->to_arg, "Native_address: %p\n", fe->native_address); +#endif + erts_print(args->to, args->to_arg, "Refc: %ld\n", erts_refc_read(&fe->refc, 1)); +} + void erts_dump_fun_entries(fmtfn_t to, void *to_arg) { - int limit; - HashBucket** bucket; - int i; + struct dump_fun_foreach_args args = {to, to_arg}; int lock = !ERTS_IS_CRASH_DUMPING; - if (lock) erts_fun_read_lock(); - limit = erts_fun_table.size; - bucket = erts_fun_table.bucket; - for (i = 0; i < limit; i++) { - HashBucket* b = bucket[i]; - - while (b) { - ErlFunEntry* fe = (ErlFunEntry *) b; - erts_print(to, to_arg, "=fun\n"); - erts_print(to, to_arg, "Module: %T\n", fe->module); - erts_print(to, to_arg, "Uniq: %d\n", fe->old_uniq); - erts_print(to, to_arg, "Index: %d\n",fe->old_index); - erts_print(to, to_arg, "Address: %p\n", fe->address); -#ifdef HIPE - erts_print(to, to_arg, "Native_address: %p\n", fe->native_address); -#endif - erts_print(to, to_arg, "Refc: %ld\n", erts_refc_read(&fe->refc, 1)); - b = b->next; - } - } + hash_foreach(&erts_fun_table, (HFOREACH_FUN)dump_fun_foreach, &args); if (lock) erts_fun_read_unlock(); } diff --git a/erts/emulator/beam/erl_gc.c b/erts/emulator/beam/erl_gc.c index 7ab8034606..4a6f204cb5 100644 --- a/erts/emulator/beam/erl_gc.c +++ b/erts/emulator/beam/erl_gc.c @@ -65,6 +65,8 @@ # define HARDDEBUG 1 #endif +extern BeamInstr beam_apply[2]; + /* * Returns number of elements in an array. */ @@ -934,13 +936,15 @@ garbage_collect_hibernate(Process* p, int check_long_gc) */ erts_atomic32_read_bor_nob(&p->state, ERTS_PSFLG_GC); ErtsGcQuickSanityCheck(p); - ASSERT(p->stop == p->hend); /* Stack must be empty. */ + ASSERT(p->stop == p->hend - 1); /* Only allow one continuation pointer. */ + ASSERT(p->stop[0] == make_cp(beam_apply+1)); /* * Do it. */ heap_size = p->heap_sz + (p->old_htop - p->old_heap) + p->mbuf_sz; + heap_size += 1; /* Reserve place for continuation pointer */ heap = (Eterm*) ERTS_HEAP_ALLOC(ERTS_ALC_T_TMP_HEAP, sizeof(Eterm)*heap_size); @@ -966,13 +970,11 @@ garbage_collect_hibernate(Process* p, int check_long_gc) p->high_water = htop; p->htop = htop; p->hend = p->heap + heap_size; - p->stop = p->hend; + p->stop = p->hend - 1; p->heap_sz = heap_size; heap_size = actual_size = p->htop - p->heap; - if (heap_size == 0) { - heap_size = 1; /* We want a heap... */ - } + heap_size += 1; /* Reserve place for continuation pointer */ FLAGS(p) &= ~F_FORCE_GC; p->live_hf_end = ERTS_INVALID_HFRAG_PTR; @@ -988,14 +990,15 @@ garbage_collect_hibernate(Process* p, int check_long_gc) * hibernated. */ - ASSERT(p->hend - p->stop == 0); /* Empty stack */ ASSERT(actual_size < p->heap_sz); heap = ERTS_HEAP_ALLOC(ERTS_ALC_T_HEAP, sizeof(Eterm)*heap_size); sys_memcpy((void *) heap, (void *) p->heap, actual_size*sizeof(Eterm)); ERTS_HEAP_FREE(ERTS_ALC_T_TMP_HEAP, p->heap, p->heap_sz*sizeof(Eterm)); - p->stop = p->hend = heap + heap_size; + p->hend = heap + heap_size; + p->stop = p->hend - 1; + p->stop[0] = make_cp(beam_apply+1); offs = heap - p->heap; area = (char *) p->heap; @@ -2585,7 +2588,7 @@ setup_rootset(Process *p, Eterm *objv, int nobj, Rootset *rootset) /* * If a NIF or BIF has saved arguments, they need to be added */ - if (erts_setup_nif_export_rootset(p, &roots[n].v, &roots[n].sz)) + if (erts_setup_nfunc_rootset(p, &roots[n].v, &roots[n].sz)) n++; ASSERT(n <= rootset->size); @@ -2887,7 +2890,7 @@ sweep_off_heap(Process *p, int fullsweep) if (is_external_header(((struct erl_off_heap_header*) boxed_val(ptr->thing_word))->thing_word)) erts_node_bookkeep(((ExternalThing*)ptr)->node, make_boxed(&ptr->thing_word), - ERL_NODE_DEC); + ERL_NODE_DEC, __FILE__, __LINE__); *prev = ptr = (struct erl_off_heap_header*) boxed_val(ptr->thing_word); ASSERT(!IS_MOVED_BOXED(ptr->thing_word)); switch (ptr->thing_word) { @@ -2918,7 +2921,7 @@ sweep_off_heap(Process *p, int fullsweep) if (is_external_header(ptr->thing_word)) { erts_node_bookkeep(((ExternalThing*)ptr)->node, make_boxed(&ptr->thing_word), - ERL_NODE_INC); + ERL_NODE_INC, __FILE__, __LINE__); } prev = &ptr->next; ptr = ptr->next; @@ -3089,9 +3092,11 @@ offset_heap(Eterm* hp, Uint sz, Sint offs, char* area, Uint area_size) if (is_external_header(oh->thing_word)) { erts_node_bookkeep(((ExternalThing*)oh)->node, - make_boxed(((Eterm*)oh)-offs), ERL_NODE_DEC); + make_boxed(((Eterm*)oh)-offs), + ERL_NODE_DEC, __FILE__, __LINE__); erts_node_bookkeep(((ExternalThing*)oh)->node, - make_boxed((Eterm*)oh), ERL_NODE_INC); + make_boxed((Eterm*)oh), ERL_NODE_INC, + __FILE__, __LINE__); } if (ErtsInArea(oh->next, area, area_size)) { @@ -3231,7 +3236,7 @@ offset_one_rootset(Process *p, Sint offs, char* area, Uint area_size, offset_heap_ptr(objv, nobj, offs, area, area_size); } offset_off_heap(p, offs, area, area_size); - if (erts_setup_nif_export_rootset(p, &v, &sz)) + if (erts_setup_nfunc_rootset(p, &v, &sz)) offset_heap_ptr(v, sz, offs, area, area_size); } diff --git a/erts/emulator/beam/erl_init.c b/erts/emulator/beam/erl_init.c index 547e4064a2..4d0ebbd1ed 100644 --- a/erts/emulator/beam/erl_init.c +++ b/erts/emulator/beam/erl_init.c @@ -354,6 +354,7 @@ erl_init(int ncpu, erts_init_bif_chksum(); erts_init_bif_binary(); erts_init_bif_guard(); + erts_init_bif_lists(); erts_init_bif_persistent_term(); erts_init_bif_re(); erts_init_unicode(); /* after RE to get access to PCRE unicode */ diff --git a/erts/emulator/beam/erl_monitor_link.c b/erts/emulator/beam/erl_monitor_link.c index 1c6b4afaa3..43028be39d 100644 --- a/erts/emulator/beam/erl_monitor_link.c +++ b/erts/emulator/beam/erl_monitor_link.c @@ -671,6 +671,24 @@ erts_monitor_tree_foreach(ErtsMonitor *root, arg); } +void +erts_debug_monitor_tree_destroying_foreach(ErtsMonitor *root, + ErtsMonitorFunc func, + void *arg, + void *vysp) +{ + void *tmp_vysp = erts_alloc(ERTS_ALC_T_ML_YIELD_STATE, + sizeof(ErtsMonLnkYieldState)); + Sint reds; + sys_memcpy(tmp_vysp, tmp_vysp, sizeof(ErtsMonLnkYieldState)); + do { + reds = ml_rbt_foreach_yielding((ErtsMonLnkNode *) root, + (ErtsMonLnkNodeFunc) func, + arg, &tmp_vysp, (Sint) INT_MAX); + } while (reds <= 0); + ERTS_ML_ASSERT(!tmp_vysp); +} + int erts_monitor_tree_foreach_yielding(ErtsMonitor *root, ErtsMonitorFunc func, @@ -716,6 +734,19 @@ erts_monitor_list_foreach(ErtsMonitor *list, arg, &ystate, (Sint) INT_MAX)); } +void +erts_debug_monitor_list_destroying_foreach(ErtsMonitor *list, + ErtsMonitorFunc func, + void *arg, + void *vysp) +{ + void *tmp_vysp = vysp; + while (!ml_dl_list_foreach_yielding((ErtsMonLnkNode *) list, + (int (*)(ErtsMonLnkNode *, void *, Sint)) func, + arg, &tmp_vysp, (Sint) INT_MAX)); + ERTS_ML_ASSERT(!tmp_vysp); +} + int erts_monitor_list_foreach_yielding(ErtsMonitor *list, ErtsMonitorFunc func, @@ -1080,6 +1111,24 @@ erts_link_tree_foreach(ErtsLink *root, } +void +erts_debug_link_tree_destroying_foreach(ErtsLink *root, + ErtsLinkFunc func, + void *arg, + void *vysp) +{ + void *tmp_vysp = erts_alloc(ERTS_ALC_T_ML_YIELD_STATE, + sizeof(ErtsMonLnkYieldState)); + Sint reds; + sys_memcpy(tmp_vysp, vysp, sizeof(ErtsMonLnkYieldState)); + do { + reds = ml_rbt_foreach_yielding((ErtsMonLnkNode *) root, + (ErtsMonLnkNodeFunc) func, + arg, &tmp_vysp, (Sint) INT_MAX); + } while (reds <= 0); + ERTS_ML_ASSERT(!tmp_vysp); +} + int erts_link_tree_foreach_yielding(ErtsLink *root, ErtsLinkFunc func, diff --git a/erts/emulator/beam/erl_monitor_link.h b/erts/emulator/beam/erl_monitor_link.h index eff861fce8..86be400c09 100644 --- a/erts/emulator/beam/erl_monitor_link.h +++ b/erts/emulator/beam/erl_monitor_link.h @@ -1509,6 +1509,17 @@ ERTS_GLB_INLINE ErtsMonitorSuspend *erts_monitor_suspend(ErtsMonitor *mon) #endif +void +erts_debug_monitor_tree_destroying_foreach(ErtsMonitor *root, + ErtsMonitorFunc func, + void *arg, + void *vysp); +void +erts_debug_monitor_list_destroying_foreach(ErtsMonitor *list, + ErtsMonitorFunc func, + void *arg, + void *vysp); + /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\ * Link Operations * \* */ @@ -2365,4 +2376,10 @@ erts_link_dist_delete(ErtsLink *lnk) #endif /* ERTS_GLB_INLINE_INCL_FUNC_DEF */ +void +erts_debug_link_tree_destroying_foreach(ErtsLink *root, + ErtsLinkFunc func, + void *arg, + void *vysp); + #endif /* ERL_MONITOR_LINK_H__ */ diff --git a/erts/emulator/beam/erl_nfunc_sched.c b/erts/emulator/beam/erl_nfunc_sched.c index b8cf2bee0e..8263a6e9b7 100644 --- a/erts/emulator/beam/erl_nfunc_sched.c +++ b/erts/emulator/beam/erl_nfunc_sched.c @@ -30,77 +30,37 @@ #include "erl_nfunc_sched.h" #include "erl_trace.h" -NifExport * -erts_new_proc_nif_export(Process *c_p, int argc) +ErtsNativeFunc * +erts_new_proc_nfunc(Process *c_p, int argc) { + ErtsNativeFunc *nep, *old_nep; size_t size; - int i; - NifExport *nep, *old_nep; - - size = sizeof(NifExport) + (argc-1)*sizeof(Eterm); - nep = erts_alloc(ERTS_ALC_T_NIF_TRAP_EXPORT, size); - for (i = 0; i < ERTS_NUM_CODE_IX; i++) - nep->exp.addressv[i] = &nep->exp.beam[0]; + size = sizeof(ErtsNativeFunc) + (argc-1)*sizeof(Eterm); + nep = erts_alloc(ERTS_ALC_T_NFUNC_TRAP_WRAPPER, size); nep->argc = -1; /* unused marker */ nep->argv_size = argc; - nep->trace = NULL; - old_nep = ERTS_PROC_SET_NIF_TRAP_EXPORT(c_p, nep); + old_nep = ERTS_PROC_SET_NFUNC_TRAP_WRAPPER(c_p, nep); if (old_nep) { - ASSERT(!nep->trace); - erts_free(ERTS_ALC_T_NIF_TRAP_EXPORT, old_nep); + erts_free(ERTS_ALC_T_NFUNC_TRAP_WRAPPER, old_nep); } return nep; } void -erts_destroy_nif_export(Process *p) +erts_destroy_nfunc(Process *p) { - NifExport *nep = ERTS_PROC_SET_NIF_TRAP_EXPORT(p, NULL); + ErtsNativeFunc *nep = ERTS_PROC_SET_NFUNC_TRAP_WRAPPER(p, NULL); if (nep) { if (nep->m) - erts_nif_export_cleanup_nif_mod(nep); - erts_free(ERTS_ALC_T_NIF_TRAP_EXPORT, nep); + erts_nfunc_cleanup_nif_mod(nep); + erts_free(ERTS_ALC_T_NFUNC_TRAP_WRAPPER, nep); } } -void -erts_nif_export_save_trace(Process *c_p, NifExport *nep, int applying, - Export* ep, BeamInstr *cp, Uint32 flags, - Uint32 flags_meta, BeamInstr* I, - ErtsTracer meta_tracer) -{ - NifExportTrace *netp; - ASSERT(nep && nep->argc >= 0); - ASSERT(!nep->trace); - netp = erts_alloc(ERTS_ALC_T_NIF_EXP_TRACE, - sizeof(NifExportTrace)); - netp->applying = applying; - netp->ep = ep; - netp->cp = cp; - netp->flags = flags; - netp->flags_meta = flags_meta; - netp->I = I; - netp->meta_tracer = NIL; - erts_tracer_update(&netp->meta_tracer, meta_tracer); - nep->trace = netp; -} - -void -erts_nif_export_restore_trace(Process *c_p, Eterm result, NifExport *nep) -{ - NifExportTrace *netp = nep->trace; - nep->trace = NULL; - erts_bif_trace_epilogue(c_p, result, netp->applying, netp->ep, - netp->cp, netp->flags, netp->flags_meta, - netp->I, netp->meta_tracer); - erts_tracer_update(&netp->meta_tracer, NIL); - erts_free(ERTS_ALC_T_NIF_EXP_TRACE, netp); -} - -NifExport * -erts_nif_export_schedule(Process *c_p, Process *dirty_shadow_proc, +ErtsNativeFunc * +erts_nfunc_schedule(Process *c_p, Process *dirty_shadow_proc, ErtsCodeMFA *mfa, BeamInstr *pc, BeamInstr instr, void *dfunc, void *ifunc, @@ -110,7 +70,7 @@ erts_nif_export_schedule(Process *c_p, Process *dirty_shadow_proc, Process *used_proc; ErtsSchedulerData *esdp; Eterm* reg; - NifExport* nep; + ErtsNativeFunc* nep; int i; ERTS_LC_ASSERT(erts_proc_lc_my_proc_locks(c_p) @@ -133,10 +93,10 @@ erts_nif_export_schedule(Process *c_p, Process *dirty_shadow_proc, reg = esdp->x_reg_array; if (mfa) - nep = erts_get_proc_nif_export(c_p, (int) mfa->arity); + nep = erts_get_proc_nfunc(c_p, (int) mfa->arity); else { /* If no mfa, this is not the first schedule... */ - nep = ERTS_PROC_GET_NIF_TRAP_EXPORT(c_p); + nep = ERTS_PROC_GET_NFUNC_TRAP_WRAPPER(c_p); ASSERT(nep && nep->argc >= 0); } @@ -148,16 +108,15 @@ erts_nif_export_schedule(Process *c_p, Process *dirty_shadow_proc, for (i = 0; i < (int) mfa->arity; i++) nep->argv[i] = reg[i]; nep->pc = pc; - nep->cp = c_p->cp; nep->mfa = mfa; nep->current = c_p->current; ASSERT(argc >= 0); nep->argc = (int) mfa->arity; nep->m = NULL; - ASSERT(!erts_check_nif_export_in_area(c_p, + ASSERT(!erts_check_nfunc_in_area(c_p, (char *) nep, - (sizeof(NifExport) + (sizeof(ErtsNativeFunc) + (sizeof(Eterm) *(nep->argc-1))))); } @@ -167,14 +126,14 @@ erts_nif_export_schedule(Process *c_p, Process *dirty_shadow_proc, reg[i] = argv[i]; } ASSERT(is_atom(mod) && is_atom(func)); - nep->exp.info.mfa.module = mod; - nep->exp.info.mfa.function = func; - nep->exp.info.mfa.arity = (Uint) argc; - nep->exp.beam[0] = (BeamInstr) instr; /* call_nif || apply_bif */ - nep->exp.beam[1] = (BeamInstr) dfunc; + nep->trampoline.info.mfa.module = mod; + nep->trampoline.info.mfa.function = func; + nep->trampoline.info.mfa.arity = (Uint) argc; + nep->trampoline.call_op = (BeamInstr) instr; /* call_bif || call_nif */ + nep->trampoline.dfunc = (BeamInstr) dfunc; nep->func = ifunc; used_proc->arity = argc; used_proc->freason = TRAP; - used_proc->i = (BeamInstr*) nep->exp.addressv[0]; + used_proc->i = (BeamInstr*)&nep->trampoline.call_op; return nep; } diff --git a/erts/emulator/beam/erl_nfunc_sched.h b/erts/emulator/beam/erl_nfunc_sched.h index 1cb252eba5..4dae242d4f 100644 --- a/erts/emulator/beam/erl_nfunc_sched.h +++ b/erts/emulator/beam/erl_nfunc_sched.h @@ -25,92 +25,78 @@ #include "bif.h" #include "error.h" -typedef struct { - int applying; - Export* ep; - BeamInstr *cp; - Uint32 flags; - Uint32 flags_meta; - BeamInstr* I; - ErtsTracer meta_tracer; -} NifExportTrace; - /* - * NIF exports need a few more items than the Export struct provides, - * including the erl_module_nif* and a NIF function pointer, so the - * NifExport below adds those. The Export member must be first in the - * struct. A number of values are stored for error handling purposes - * only. + * Native function wrappers are used to schedule native functions on both + * normal and dirty schedulers. + * + * A number of values are only stored for error handling, and the fields + * following `current` can be omitted when a wrapper is statically "scheduled" + * through placement in a function stub. * - * 'argc' is >= 0 when NifExport is in use, and < 0 when not. + * 'argc' is >= 0 when ErtsNativeFunc is in use, and < 0 when not. */ typedef struct { - Export exp; + struct { + ErtsCodeInfo info; + BeamInstr call_op; /* call_bif || call_nif */ + BeamInstr dfunc; + } trampoline; + struct erl_module_nif* m; /* NIF module, or NULL if BIF */ void *func; /* Indirect NIF or BIF to execute (may be unused) */ ErtsCodeMFA *current;/* Current as set when originally called */ - NifExportTrace *trace; /* --- The following is only used on error --- */ BeamInstr *pc; /* Program counter */ - BeamInstr *cp; /* Continuation pointer */ ErtsCodeMFA *mfa; /* MFA of original call */ int argc; /* Number of arguments in original call */ int argv_size; /* Allocated size of argv */ Eterm argv[1]; /* Saved arguments from the original call */ -} NifExport; - -NifExport *erts_new_proc_nif_export(Process *c_p, int argc); -void erts_nif_export_save_trace(Process *c_p, NifExport *nep, int applying, - Export* ep, BeamInstr *cp, Uint32 flags, - Uint32 flags_meta, BeamInstr* I, - ErtsTracer meta_tracer); -void erts_nif_export_restore_trace(Process *c_p, Eterm result, NifExport *nep); -void erts_destroy_nif_export(Process *p); -NifExport *erts_nif_export_schedule(Process *c_p, Process *dirty_shadow_proc, - ErtsCodeMFA *mfa, BeamInstr *pc, - BeamInstr instr, - void *dfunc, void *ifunc, - Eterm mod, Eterm func, - int argc, const Eterm *argv); -void erts_nif_export_cleanup_nif_mod(NifExport *ep); /* erl_nif.c */ -ERTS_GLB_INLINE NifExport *erts_get_proc_nif_export(Process *c_p, int extra); -ERTS_GLB_INLINE int erts_setup_nif_export_rootset(Process* proc, Eterm** objv, - Uint* nobj); -ERTS_GLB_INLINE int erts_check_nif_export_in_area(Process *p, - char *start, Uint size); -ERTS_GLB_INLINE void erts_nif_export_restore(Process *c_p, NifExport *ep, - Eterm result); -ERTS_GLB_INLINE void erts_nif_export_restore_error(Process* c_p, BeamInstr **pc, - Eterm *reg, ErtsCodeMFA **nif_mfa); -ERTS_GLB_INLINE int erts_nif_export_check_save_trace(Process *c_p, Eterm result, - int applying, Export* ep, - BeamInstr *cp, Uint32 flags, - Uint32 flags_meta, BeamInstr* I, - ErtsTracer meta_tracer); +} ErtsNativeFunc; + +ErtsNativeFunc *erts_new_proc_nfunc(Process *c_p, int argc); +void erts_destroy_nfunc(Process *p); +ErtsNativeFunc *erts_nfunc_schedule(Process *c_p, Process *dirty_shadow_proc, + ErtsCodeMFA *mfa, BeamInstr *pc, + BeamInstr instr, + void *dfunc, void *ifunc, + Eterm mod, Eterm func, + int argc, const Eterm *argv); +void erts_nfunc_cleanup_nif_mod(ErtsNativeFunc *ep); /* erl_nif.c */ +ERTS_GLB_INLINE ErtsNativeFunc *erts_get_proc_nfunc(Process *c_p, int extra); +ERTS_GLB_INLINE int erts_setup_nfunc_rootset(Process* proc, Eterm** objv, + Uint* nobj); +ERTS_GLB_INLINE int erts_check_nfunc_in_area(Process *p, + char *start, Uint size); +ERTS_GLB_INLINE void erts_nfunc_restore(Process *c_p, ErtsNativeFunc *ep, + Eterm result); +ERTS_GLB_INLINE void erts_nfunc_restore_error(Process* c_p, + BeamInstr **pc, + Eterm *reg, + ErtsCodeMFA **nif_mfa); ERTS_GLB_INLINE Process *erts_proc_shadow2real(Process *c_p); #if ERTS_GLB_INLINE_INCL_FUNC_DEF -ERTS_GLB_INLINE NifExport * -erts_get_proc_nif_export(Process *c_p, int argc) +ERTS_GLB_INLINE ErtsNativeFunc * +erts_get_proc_nfunc(Process *c_p, int argc) { - NifExport *nep = ERTS_PROC_GET_NIF_TRAP_EXPORT(c_p); + ErtsNativeFunc *nep = ERTS_PROC_GET_NFUNC_TRAP_WRAPPER(c_p); if (!nep || (nep->argc < 0 && nep->argv_size < argc)) - return erts_new_proc_nif_export(c_p, argc); + return erts_new_proc_nfunc(c_p, argc); return nep; } /* * If a process has saved arguments, they need to be part of the GC * rootset. The function below is called from setup_rootset() in - * erl_gc.c. Any exception term saved in the NifExport is also made + * erl_gc.c. Any exception term saved in the ErtsNativeFunc is also made * part of the GC rootset here; it always resides in rootset[0]. */ ERTS_GLB_INLINE int -erts_setup_nif_export_rootset(Process* proc, Eterm** objv, Uint* nobj) +erts_setup_nfunc_rootset(Process* proc, Eterm** objv, Uint* nobj) { - NifExport* ep = (NifExport*) ERTS_PROC_GET_NIF_TRAP_EXPORT(proc); + ErtsNativeFunc* ep = (ErtsNativeFunc*) ERTS_PROC_GET_NFUNC_TRAP_WRAPPER(proc); if (!ep || ep->argc <= 0) return 0; @@ -121,18 +107,16 @@ erts_setup_nif_export_rootset(Process* proc, Eterm** objv, Uint* nobj) } /* - * Check if nif export points into code area... + * Check if native func wrapper points into code area... */ ERTS_GLB_INLINE int -erts_check_nif_export_in_area(Process *p, char *start, Uint size) +erts_check_nfunc_in_area(Process *p, char *start, Uint size) { - NifExport *nep = ERTS_PROC_GET_NIF_TRAP_EXPORT(p); + ErtsNativeFunc *nep = ERTS_PROC_GET_NFUNC_TRAP_WRAPPER(p); if (!nep || nep->argc < 0) return 0; if (ErtsInArea(nep->pc, start, size)) return 1; - if (ErtsInArea(nep->cp, start, size)) - return 1; if (ErtsInArea(nep->mfa, start, size)) return 1; if (ErtsInArea(nep->current, start, size)) @@ -141,7 +125,7 @@ erts_check_nif_export_in_area(Process *p, char *start, Uint size) } ERTS_GLB_INLINE void -erts_nif_export_restore(Process *c_p, NifExport *ep, Eterm result) +erts_nfunc_restore(Process *c_p, ErtsNativeFunc *ep, Eterm result) { ASSERT(!ERTS_SCHEDULER_IS_DIRTY(erts_get_scheduler_data())); ERTS_LC_ASSERT(!(c_p->static_flags @@ -151,43 +135,21 @@ erts_nif_export_restore(Process *c_p, NifExport *ep, Eterm result) c_p->current = ep->current; ep->argc = -1; /* Unused nif-export marker... */ - if (ep->trace) - erts_nif_export_restore_trace(c_p, result, ep); } ERTS_GLB_INLINE void -erts_nif_export_restore_error(Process* c_p, BeamInstr **pc, +erts_nfunc_restore_error(Process* c_p, BeamInstr **pc, Eterm *reg, ErtsCodeMFA **nif_mfa) { - NifExport *nep = (NifExport *) ERTS_PROC_GET_NIF_TRAP_EXPORT(c_p); + ErtsNativeFunc *nep = (ErtsNativeFunc *) ERTS_PROC_GET_NFUNC_TRAP_WRAPPER(c_p); int ix; ASSERT(nep); *pc = nep->pc; - c_p->cp = nep->cp; *nif_mfa = nep->mfa; for (ix = 0; ix < nep->argc; ix++) reg[ix] = nep->argv[ix]; - erts_nif_export_restore(c_p, nep, THE_NON_VALUE); -} - -ERTS_GLB_INLINE int -erts_nif_export_check_save_trace(Process *c_p, Eterm result, - int applying, Export* ep, - BeamInstr *cp, Uint32 flags, - Uint32 flags_meta, BeamInstr* I, - ErtsTracer meta_tracer) -{ - if (is_non_value(result) && c_p->freason == TRAP) { - NifExport *nep = ERTS_PROC_GET_NIF_TRAP_EXPORT(c_p); - if (nep && nep->argc >= 0) { - erts_nif_export_save_trace(c_p, nep, applying, ep, - cp, flags, flags_meta, - I, meta_tracer); - return 1; - } - } - return 0; + erts_nfunc_restore(c_p, nep, THE_NON_VALUE); } ERTS_GLB_INLINE Process * @@ -210,10 +172,10 @@ erts_proc_shadow2real(Process *c_p) #if defined(ERTS_WANT_NFUNC_SCHED_INTERNALS__) && !defined(ERTS_NFUNC_SCHED_INTERNALS__) #define ERTS_NFUNC_SCHED_INTERNALS__ -#define ERTS_I_BEAM_OP_TO_NIF_EXPORT(I) \ - (ASSERT(BeamIsOpCode(*(I), op_apply_bif) || \ - BeamIsOpCode(*(I), op_call_nif)), \ - ((NifExport *) (((char *) (I)) - offsetof(NifExport, exp.beam[0])))) +#define ERTS_I_BEAM_OP_TO_NFUNC(I) \ + (ASSERT(BeamIsOpCode(*(I), op_call_bif_W) || \ + BeamIsOpCode(*(I), op_call_nif_WWW)), \ + ((ErtsNativeFunc *) (((char *) (I)) - offsetof(ErtsNativeFunc, trampoline.call_op)))) #include "erl_message.h" diff --git a/erts/emulator/beam/erl_nif.c b/erts/emulator/beam/erl_nif.c index ce43cb9e71..6e27b4b7cb 100644 --- a/erts/emulator/beam/erl_nif.c +++ b/erts/emulator/beam/erl_nif.c @@ -309,10 +309,10 @@ void erts_post_nif(ErlNifEnv* env) /* - * Initialize a NifExport struct. Create it if needed and store it in the + * Initialize a ErtsNativeFunc struct. Create it if needed and store it in the * proc. The direct_fp function is what will be invoked by op_call_nif, and * the indirect_fp function, if not NULL, is what the direct_fp function - * will call. If the allocated NifExport isn't enough to hold all of argv, + * will call. If the allocated ErtsNativeFunc isn't enough to hold all of argv, * allocate a larger one. Save 'current' and registers if first time this * call is scheduled. */ @@ -321,7 +321,7 @@ static ERTS_INLINE ERL_NIF_TERM schedule(ErlNifEnv* env, NativeFunPtr direct_fp, NativeFunPtr indirect_fp, Eterm mod, Eterm func_name, int argc, const ERL_NIF_TERM argv[]) { - NifExport *ep; + ErtsNativeFunc *ep; Process *c_p, *dirty_shadow_proc; execution_state(env, &c_p, NULL); @@ -332,10 +332,10 @@ schedule(ErlNifEnv* env, NativeFunPtr direct_fp, NativeFunPtr indirect_fp, ERTS_LC_ASSERT(ERTS_PROC_LOCK_MAIN & erts_proc_lc_my_proc_locks(c_p)); - ep = erts_nif_export_schedule(c_p, dirty_shadow_proc, + ep = erts_nfunc_schedule(c_p, dirty_shadow_proc, c_p->current, - c_p->cp, - BeamOpCodeAddr(op_call_nif), + cp_val(c_p->stop[0]), + BeamOpCodeAddr(op_call_nif_WWW), direct_fp, indirect_fp, mod, func_name, argc, (const Eterm *) argv); @@ -356,7 +356,7 @@ erts_call_dirty_nif(ErtsSchedulerData *esdp, Process *c_p, BeamInstr *I, Eterm * { int exiting; ERL_NIF_TERM *argv = (ERL_NIF_TERM *) reg; - NifExport *nep = ERTS_I_BEAM_OP_TO_NIF_EXPORT(I); + ErtsNativeFunc *nep = ERTS_I_BEAM_OP_TO_NFUNC(I); ErtsCodeMFA *codemfa = erts_code_to_codemfa(I); NativeFunPtr dirty_nif = (NativeFunPtr) I[1]; ErlNifEnv env; @@ -364,7 +364,7 @@ erts_call_dirty_nif(ErtsSchedulerData *esdp, Process *c_p, BeamInstr *I, Eterm * #ifdef DEBUG erts_aint32_t state = erts_atomic32_read_nob(&c_p->state); - ASSERT(nep == ERTS_PROC_GET_NIF_TRAP_EXPORT(c_p)); + ASSERT(nep == ERTS_PROC_GET_NFUNC_TRAP_WRAPPER(c_p)); ASSERT(!c_p->scheduler_data); ASSERT((state & ERTS_PSFLG_DIRTY_RUNNING) @@ -2823,7 +2823,7 @@ int enif_consume_timeslice(ErlNifEnv* env, int percent) } static ERTS_INLINE void -nif_export_cleanup_nif_mod(NifExport *ep) +nfunc_cleanup_nif_mod(ErtsNativeFunc *ep) { if (erts_refc_dectest(&ep->m->rt_dtor_cnt, 0) == 0 && ep->m->mod == NULL) close_lib(ep->m); @@ -2831,17 +2831,17 @@ nif_export_cleanup_nif_mod(NifExport *ep) } void -erts_nif_export_cleanup_nif_mod(NifExport *ep) +erts_nfunc_cleanup_nif_mod(ErtsNativeFunc *ep) { - nif_export_cleanup_nif_mod(ep); + nfunc_cleanup_nif_mod(ep); } static ERTS_INLINE void -nif_export_restore(Process *c_p, NifExport *ep, Eterm res) +nfunc_restore(Process *c_p, ErtsNativeFunc *ep, Eterm res) { - erts_nif_export_restore(c_p, ep, res); + erts_nfunc_restore(c_p, ep, res); ASSERT(ep->m); - nif_export_cleanup_nif_mod(ep); + nfunc_cleanup_nif_mod(ep); } @@ -2858,15 +2858,15 @@ static ERL_NIF_TERM dirty_nif_finalizer(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) { Process* proc; - NifExport* ep; + ErtsNativeFunc* ep; execution_state(env, &proc, NULL); ASSERT(argc == 1); ASSERT(!ERTS_SCHEDULER_IS_DIRTY(erts_proc_sched_data(proc))); - ep = (NifExport*) ERTS_PROC_GET_NIF_TRAP_EXPORT(proc); + ep = (ErtsNativeFunc*) ERTS_PROC_GET_NFUNC_TRAP_WRAPPER(proc); ASSERT(ep); - nif_export_restore(proc, ep, argv[0]); + nfunc_restore(proc, ep, argv[0]); return argv[0]; } @@ -2878,21 +2878,22 @@ dirty_nif_exception(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) { ERL_NIF_TERM ret; Process* proc; - NifExport* ep; + ErtsNativeFunc* ep; Eterm exception; execution_state(env, &proc, NULL); ASSERT(argc == 1); ASSERT(!ERTS_SCHEDULER_IS_DIRTY(erts_proc_sched_data(proc))); - ep = (NifExport*) ERTS_PROC_GET_NIF_TRAP_EXPORT(proc); + ep = (ErtsNativeFunc*) ERTS_PROC_GET_NFUNC_TRAP_WRAPPER(proc); ASSERT(ep); exception = argv[0]; /* argv overwritten by restore below... */ - nif_export_cleanup_nif_mod(ep); + nfunc_cleanup_nif_mod(ep); ret = enif_raise_exception(env, exception); - /* Restore orig info for error and clear nif export in handle_error() */ - proc->freason |= EXF_RESTORE_NIF; + /* Restore orig info for error and clear native func wrapper in + * handle_error() */ + proc->freason |= EXF_RESTORE_NFUNC; return ret; } @@ -2929,7 +2930,7 @@ static_schedule_dirty_nif(ErlNifEnv* env, erts_aint32_t dirty_psflg, int argc, const ERL_NIF_TERM argv[]) { Process *proc; - NifExport *ep; + ErtsNativeFunc *ep; Eterm mod, func; NativeFunPtr fp; @@ -2939,12 +2940,11 @@ static_schedule_dirty_nif(ErlNifEnv* env, erts_aint32_t dirty_psflg, * Called in order to schedule statically determined * dirty NIF calls... * - * Note that 'current' does not point into a NifExport - * structure; only a structure with similar - * parts (located in code). + * Note that 'current' does not point into a ErtsNativeFunc + * structure; only a structure with similar parts (located in code). */ - ep = ErtsContainerStruct(proc->current, NifExport, exp.info.mfa); + ep = ErtsContainerStruct(proc->current, ErtsNativeFunc, trampoline.info.mfa); mod = proc->current->module; func = proc->current->function; fp = (NativeFunPtr) ep->func; @@ -2983,12 +2983,12 @@ execute_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) { Process* proc; NativeFunPtr fp; - NifExport* ep; + ErtsNativeFunc* ep; ERL_NIF_TERM result; execution_state(env, &proc, NULL); - ep = ErtsContainerStruct(proc->current, NifExport, exp.info.mfa); + ep = ErtsContainerStruct(proc->current, ErtsNativeFunc, trampoline.info.mfa); fp = ep->func; ASSERT(ep); ASSERT(!env->exception_thrown); @@ -3001,20 +3001,20 @@ execute_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) result = (*fp)(env, argc, argv); - ASSERT(ep == ERTS_PROC_GET_NIF_TRAP_EXPORT(proc)); + ASSERT(ep == ERTS_PROC_GET_NFUNC_TRAP_WRAPPER(proc)); if (is_value(result) || proc->freason != TRAP) { /* Done (not rescheduled)... */ ASSERT(ep->func == ERTS_DBG_NIF_NOT_SCHED_MARKER); if (!env->exception_thrown) - nif_export_restore(proc, ep, result); + nfunc_restore(proc, ep, result); else { - nif_export_cleanup_nif_mod(ep); + nfunc_cleanup_nif_mod(ep); /* * Restore orig info for error and clear nif * export in handle_error() */ - proc->freason |= EXF_RESTORE_NIF; + proc->freason |= EXF_RESTORE_NFUNC; } } @@ -4117,8 +4117,23 @@ static struct erl_module_nif* create_lib(const ErlNifEntry* src) return lib; }; +/* load_nif/2 is implemented as an instruction as it needs to know where it + * was called from, and it's a pain to get that information in a BIF. + * + * This is a small stub that rejects apply(erlang, load_nif, [Path, Args]). */ +BIF_RETTYPE load_nif_2(BIF_ALIST_2) { + if (BIF_P->flags & F_HIPE_MODE) { + BIF_RET(load_nif_error(BIF_P, "notsup", + "Calling load_nif from HiPE compiled modules " + "not supported")); + } + + BIF_RET(load_nif_error(BIF_P, "bad_lib", + "load_nif/2 must be explicitly called from the NIF " + "module. It cannot be called through apply/3.")); +} -BIF_RETTYPE load_nif_2(BIF_ALIST_2) +Eterm erts_load_nif(Process *c_p, BeamInstr *I, Eterm filename, Eterm args) { static const char bad_lib[] = "bad_lib"; static const char upgrade[] = "upgrade"; @@ -4141,41 +4156,25 @@ BIF_RETTYPE load_nif_2(BIF_ALIST_2) struct erl_module_instance* this_mi; struct erl_module_instance* prev_mi; - if (BIF_P->flags & F_HIPE_MODE) { - ret = load_nif_error(BIF_P, "notsup", "Calling load_nif from HiPE compiled " - "modules not supported"); - BIF_RET(ret); - } - encoding = erts_get_native_filename_encoding(); if (encoding == ERL_FILENAME_WIN_WCHAR) { /* Do not convert the lib name to utf-16le yet, do that in win32 specific code */ /* since lib_name is used in error messages */ encoding = ERL_FILENAME_UTF8; } - lib_name = erts_convert_filename_to_encoding(BIF_ARG_1, NULL, 0, + lib_name = erts_convert_filename_to_encoding(filename, NULL, 0, ERTS_ALC_T_TMP, 1, 0, encoding, NULL, 0); if (!lib_name) { - BIF_ERROR(BIF_P, BADARG); - } - - if (!erts_try_seize_code_write_permission(BIF_P)) { - erts_free(ERTS_ALC_T_TMP, lib_name); - ERTS_BIF_YIELD2(bif_export[BIF_load_nif_2], - BIF_P, BIF_ARG_1, BIF_ARG_2); + return THE_NON_VALUE; } /* Block system (is this the right place to do it?) */ - erts_proc_unlock(BIF_P, ERTS_PROC_LOCK_MAIN); + erts_proc_unlock(c_p, ERTS_PROC_LOCK_MAIN); erts_thr_progress_block(); /* Find calling module */ - ASSERT(BIF_P->current != NULL); - ASSERT(BIF_P->current->module == am_erlang - && BIF_P->current->function == am_load_nif - && BIF_P->current->arity == 2); - caller = find_function_from_pc(BIF_P->cp); + caller = find_function_from_pc(I); ASSERT(caller != NULL); mod_atom = caller->module; ASSERT(is_atom(mod_atom)); @@ -4195,7 +4194,7 @@ BIF_RETTYPE load_nif_2(BIF_ALIST_2) this_mi = &module_p->curr; prev_mi = &module_p->old; if (in_area(caller, module_p->old.code_hdr, module_p->old.code_length)) { - ret = load_nif_error(BIF_P, "old_code", "Calling load_nif from old " + ret = load_nif_error(c_p, "old_code", "Calling load_nif from old " "module '%T' not allowed", mod_atom); goto error; } else if (module_p->on_load) { @@ -4209,52 +4208,52 @@ BIF_RETTYPE load_nif_2(BIF_ALIST_2) } if (this_mi->nif != NULL) { - ret = load_nif_error(BIF_P,"reload","NIF library already loaded" + ret = load_nif_error(c_p,"reload","NIF library already loaded" " (reload disallowed since OTP 20)."); } else if (init_func == NULL && (err=erts_sys_ddll_open(lib_name, &handle, &errdesc)) != ERL_DE_NO_ERROR) { const char slogan[] = "Failed to load NIF library"; if (strstr(errdesc.str, lib_name) != NULL) { - ret = load_nif_error(BIF_P, "load_failed", "%s: '%s'", slogan, errdesc.str); + ret = load_nif_error(c_p, "load_failed", "%s: '%s'", slogan, errdesc.str); } else { - ret = load_nif_error(BIF_P, "load_failed", "%s %s: '%s'", slogan, lib_name, errdesc.str); + ret = load_nif_error(c_p, "load_failed", "%s %s: '%s'", slogan, lib_name, errdesc.str); } } else if (init_func == NULL && erts_sys_ddll_load_nif_init(handle, &init_func, &errdesc) != ERL_DE_NO_ERROR) { - ret = load_nif_error(BIF_P, bad_lib, "Failed to find library init" + ret = load_nif_error(c_p, bad_lib, "Failed to find library init" " function: '%s'", errdesc.str); } else if ((taint ? erts_add_taint(mod_atom) : 0, (entry = erts_sys_ddll_call_nif_init(init_func)) == NULL)) { - ret = load_nif_error(BIF_P, bad_lib, "Library init-call unsuccessful"); + ret = load_nif_error(c_p, bad_lib, "Library init-call unsuccessful"); } else if (entry->major > ERL_NIF_MAJOR_VERSION || (entry->major == ERL_NIF_MAJOR_VERSION && entry->minor > ERL_NIF_MINOR_VERSION)) { char* fmt = "That '%T' NIF library needs %s or newer. Either try to" " recompile the NIF lib or use a newer erts runtime."; - ret = load_nif_error(BIF_P, bad_lib, fmt, mod_atom, entry->min_erts); + ret = load_nif_error(c_p, bad_lib, fmt, mod_atom, entry->min_erts); } else if (entry->major < ERL_NIF_MIN_REQUIRED_MAJOR_VERSION_ON_LOAD || (entry->major==2 && entry->minor == 5)) { /* experimental maps */ char* fmt = "That old NIF library (%d.%d) is not compatible with this " "erts runtime (%d.%d). Try recompile the NIF lib."; - ret = load_nif_error(BIF_P, bad_lib, fmt, entry->major, entry->minor, + ret = load_nif_error(c_p, bad_lib, fmt, entry->major, entry->minor, ERL_NIF_MAJOR_VERSION, ERL_NIF_MINOR_VERSION); } else if (AT_LEAST_VERSION(entry, 2, 1) && sys_strcmp(entry->vm_variant, ERL_NIF_VM_VARIANT) != 0) { - ret = load_nif_error(BIF_P, bad_lib, "Library (%s) not compiled for " + ret = load_nif_error(c_p, bad_lib, "Library (%s) not compiled for " "this vm variant (%s).", entry->vm_variant, ERL_NIF_VM_VARIANT); } else if (!erts_is_atom_str((char*)entry->name, mod_atom, 1)) { - ret = load_nif_error(BIF_P, bad_lib, "Library module name '%s' does not" + ret = load_nif_error(c_p, bad_lib, "Library module name '%s' does not" " match calling module '%T'", entry->name, mod_atom); } else { @@ -4273,7 +4272,7 @@ BIF_RETTYPE load_nif_2(BIF_ALIST_2) if (!erts_atom_get(f->name, sys_strlen(f->name), &f_atom, ERTS_ATOM_ENC_LATIN1) || (ci_pp = get_func_pp(this_mi->code_hdr, f_atom, f->arity))==NULL) { - ret = load_nif_error(BIF_P,bad_lib,"Function not found %T:%s/%u", + ret = load_nif_error(c_p,bad_lib,"Function not found %T:%s/%u", mod_atom, f->name, f->arity); } else if (f->flags) { @@ -4285,16 +4284,13 @@ BIF_RETTYPE load_nif_2(BIF_ALIST_2) * a load error. */ if (f->flags != ERL_NIF_DIRTY_JOB_IO_BOUND && f->flags != ERL_NIF_DIRTY_JOB_CPU_BOUND) - ret = load_nif_error(BIF_P, bad_lib, "Illegal flags field value %d for NIF %T:%s/%u", + ret = load_nif_error(c_p, bad_lib, "Illegal flags field value %d for NIF %T:%s/%u", f->flags, mod_atom, f->name, f->arity); } - else if (erts_codeinfo_to_code(ci_pp[1]) - erts_codeinfo_to_code(ci_pp[0]) - < BEAM_NIF_MIN_FUNC_SZ) - { - ret = load_nif_error(BIF_P,bad_lib,"No explicit call to load_nif" - " in module (%T:%s/%u too small)", - mod_atom, f->name, f->arity); - } + + ASSERT(erts_codeinfo_to_code(ci_pp[1]) - erts_codeinfo_to_code(ci_pp[0]) + >= BEAM_NATIVE_MIN_FUNC_SZ); + /*erts_fprintf(stderr, "Found NIF %T:%s/%u\r\n", mod_atom, f->name, f->arity);*/ } @@ -4313,23 +4309,23 @@ BIF_RETTYPE load_nif_2(BIF_ALIST_2) if (prev_mi->nif != NULL) { /**************** Upgrade ***************/ void* prev_old_data = prev_mi->nif->priv_data; if (entry->upgrade == NULL) { - ret = load_nif_error(BIF_P, upgrade, "Upgrade not supported by this NIF library."); + ret = load_nif_error(c_p, upgrade, "Upgrade not supported by this NIF library."); goto error; } - erts_pre_nif(&env, BIF_P, lib, NULL); - veto = entry->upgrade(&env, &lib->priv_data, &prev_mi->nif->priv_data, BIF_ARG_2); + erts_pre_nif(&env, c_p, lib, NULL); + veto = entry->upgrade(&env, &lib->priv_data, &prev_mi->nif->priv_data, args); erts_post_nif(&env); if (veto) { prev_mi->nif->priv_data = prev_old_data; - ret = load_nif_error(BIF_P, upgrade, "Library upgrade-call unsuccessful (%d).", veto); + ret = load_nif_error(c_p, upgrade, "Library upgrade-call unsuccessful (%d).", veto); } } else if (entry->load != NULL) { /********* Initial load ***********/ - erts_pre_nif(&env, BIF_P, lib, NULL); - veto = entry->load(&env, &lib->priv_data, BIF_ARG_2); + erts_pre_nif(&env, c_p, lib, NULL); + veto = entry->load(&env, &lib->priv_data, args); erts_post_nif(&env); if (veto) { - ret = load_nif_error(BIF_P, "load", "Library load-call unsuccessful (%d).", veto); + ret = load_nif_error(c_p, "load", "Library load-call unsuccessful (%d).", veto); } } if (ret == am_ok) { @@ -4351,12 +4347,12 @@ BIF_RETTYPE load_nif_2(BIF_ALIST_2) code_ptr = erts_codeinfo_to_code(ci); if (ci->u.gen_bp == NULL) { - code_ptr[0] = BeamOpCodeAddr(op_call_nif); + code_ptr[0] = BeamOpCodeAddr(op_call_nif_WWW); } else { /* Function traced, patch the original instruction word */ GenericBp* g = ci->u.gen_bp; ASSERT(BeamIsOpCode(code_ptr[0], op_i_generic_breakpoint)); - g->orig_instr = BeamOpCodeAddr(op_call_nif); + g->orig_instr = BeamOpCodeAddr(op_call_nif_WWW); } if (f->flags) { code_ptr[3] = (BeamInstr) f->fptr; @@ -4383,8 +4379,7 @@ BIF_RETTYPE load_nif_2(BIF_ALIST_2) } erts_thr_progress_unblock(); - erts_proc_lock(BIF_P, ERTS_PROC_LOCK_MAIN); - erts_release_code_write_permission(); + erts_proc_lock(c_p, ERTS_PROC_LOCK_MAIN); erts_free(ERTS_ALC_T_TMP, lib_name); BIF_RET(ret); diff --git a/erts/emulator/beam/erl_node_tables.c b/erts/emulator/beam/erl_node_tables.c index 11df871763..ae3193be81 100644 --- a/erts/emulator/beam/erl_node_tables.c +++ b/erts/emulator/beam/erl_node_tables.c @@ -932,7 +932,8 @@ static void try_delete_node(void *venp) * * If refc > 0, the entry is in use. Keep the entry. */ - erts_node_bookkeep(enp, THE_NON_VALUE, ERL_NODE_DEC); + erts_node_bookkeep(enp, THE_NON_VALUE, ERL_NODE_DEC, + __FILE__, __LINE__); refc = erts_refc_dectest(&enp->refc, -1); if (refc == -1) (void) hash_erase(&erts_node_table, (void *) enp); @@ -1164,6 +1165,12 @@ void erts_lcnt_update_distribution_locks(int enable) { * can damage the real-time properties of the system. * \* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ +#ifdef ERL_NODE_BOOKKEEP +#define ERTS_DBG_NC_ALLOC_TYPE ERTS_ALC_T_NC_STD +#else +#define ERTS_DBG_NC_ALLOC_TYPE ERTS_ALC_T_NC_TMP +#endif + #include "erl_db.h" #undef INIT_AM @@ -1188,10 +1195,12 @@ static Eterm AM_delayed_delete_timer; static Eterm AM_thread_progress_delete_timer; static Eterm AM_sequence; static Eterm AM_signal; +static Eterm AM_persistent_term; static void setup_reference_table(void); static Eterm reference_table_term(Uint **hpp, ErlOffHeap *ohp, Uint *szp); static void delete_reference_table(void); +static void clear_system(void); #undef ERTS_MAX__ #define ERTS_MAX__(A, B) ((A) > (B) ? (A) : (B)) @@ -1244,11 +1253,11 @@ typedef struct inserted_bin_ { Binary *bin_val; } InsertedBin; -static ReferredNode *referred_nodes; +static ReferredNode *referred_nodes = NULL; static int no_referred_nodes; -static ReferredDist *referred_dists; +static ReferredDist *referred_dists = NULL; static int no_referred_dists; -static InsertedBin *inserted_bins; +static InsertedBin *inserted_bins = NULL; Eterm erts_get_node_and_dist_references(struct process *proc) @@ -1284,9 +1293,15 @@ erts_get_node_and_dist_references(struct process *proc) INIT_AM(thread_progress_delete_timer); INIT_AM(signal); INIT_AM(sequence); + INIT_AM(persistent_term); references_atoms_need_init = 0; } +#ifdef ERL_NODE_BOOKKEEP + if (referred_nodes || referred_dists || inserted_bins) + delete_reference_table(); +#endif + setup_reference_table(); /* Get term size */ @@ -1304,7 +1319,11 @@ erts_get_node_and_dist_references(struct process *proc) ASSERT(endp == hp); +#ifndef ERL_NODE_BOOKKEEP delete_reference_table(); +#endif + + clear_system(); erts_thr_progress_unblock(); erts_proc_lock(proc, ERTS_PROC_LOCK_MAIN); @@ -1339,7 +1358,7 @@ insert_dist_referrer(ReferredDist *referred_dist, break; if(!drp) { - drp = (DistReferrer *) erts_alloc(ERTS_ALC_T_NC_TMP, + drp = (DistReferrer *) erts_alloc(ERTS_DBG_NC_ALLOC_TYPE, sizeof(DistReferrer)); drp->next = referred_dist->referrers; referred_dist->referrers = drp; @@ -1402,7 +1421,7 @@ insert_node_referrer(ReferredNode *referred_node, int type, Eterm id) break; if(!nrp) { - nrp = (NodeReferrer *) erts_alloc(ERTS_ALC_T_NC_TMP, + nrp = (NodeReferrer *) erts_alloc(ERTS_DBG_NC_ALLOC_TYPE, sizeof(NodeReferrer)); nrp->next = referred_node->referrers; ERTS_INIT_OFF_HEAP(&nrp->off_heap); @@ -1490,10 +1509,12 @@ static void insert_offheap(ErlOffHeap *oh, int type, Eterm id) { union erl_off_heap_ptr u; + struct erts_tmp_aligned_offheap tmp; struct insert_offheap2_arg a; a.type = BIN_REF; for (u.hdr = oh->first; u.hdr; u.hdr = u.hdr->next) { + erts_align_offheap(&u, &tmp); switch (thing_subtag(u.hdr->thing_word)) { case REF_SUBTAG: if (ErtsIsDistEntryBinary(u.mref->mb)) @@ -1516,7 +1537,8 @@ insert_offheap(ErlOffHeap *oh, int type, Eterm id) erts_match_prog_foreach_offheap((Binary *) u.mref->mb, insert_offheap2, (void *) &a); - nib = erts_alloc(ERTS_ALC_T_NC_TMP, sizeof(InsertedBin)); + nib = erts_alloc(ERTS_DBG_NC_ALLOC_TYPE, + sizeof(InsertedBin)); nib->bin_val = (Binary *) u.mref->mb; nib->next = inserted_bins; inserted_bins = nib; @@ -1574,18 +1596,6 @@ static int clear_visited_monitor(ErtsMonitor *mon, void *p, Sint reds) } static void -insert_p_monitors(ErtsPTabElementCommon *p) -{ - Eterm id = p->id; - erts_monitor_tree_foreach(p->u.alive.monitors, - insert_monitor, - (void *) &id); - erts_monitor_list_foreach(p->u.alive.lt_monitors, - insert_monitor, - (void *) &id); -} - -static void insert_dist_monitors(DistEntry *dep) { if (dep->mld) { @@ -1600,8 +1610,10 @@ insert_dist_monitors(DistEntry *dep) static int -insert_sequence(ErtsDistExternal *edep, void *arg, Sint reds) +insert_sequence(DistSeqNode *seq, void *arg, Sint reds) { + ErtsDistExternal *edep = erts_get_dist_ext(&seq->hfrag); + insert_offheap(&seq->hfrag.off_heap, SEQUENCE_REF, *(Eterm*)arg); insert_dist_entry(edep->dep, SEQUENCE_REF, *(Eterm*)arg, 0); return 1; } @@ -1609,18 +1621,7 @@ insert_sequence(ErtsDistExternal *edep, void *arg, Sint reds) static void insert_dist_sequences(DistEntry *dep) { - erts_dist_seq_tree_foreach(dep, insert_sequence, (void *) &dep->sysname); -} - -static void -clear_visited_p_monitors(ErtsPTabElementCommon *p) -{ - erts_monitor_tree_foreach(p->u.alive.monitors, - clear_visited_monitor, - NULL); - erts_monitor_list_foreach(p->u.alive.lt_monitors, - clear_visited_monitor, - NULL); + erts_debug_dist_seq_tree_foreach(dep, insert_sequence, (void *) &dep->sysname); } static void @@ -1667,13 +1668,6 @@ static int clear_visited_link(ErtsLink *lnk, void *p, Sint reds) } static void -insert_p_links(ErtsPTabElementCommon *p) -{ - Eterm id = p->id; - erts_link_tree_foreach(p->u.alive.links, insert_link, (void *) &id); -} - -static void insert_dist_links(DistEntry *dep) { if (dep->mld) @@ -1683,14 +1677,6 @@ insert_dist_links(DistEntry *dep) } static void -clear_visited_p_links(ErtsPTabElementCommon *p) -{ - erts_link_tree_foreach(p->u.alive.links, - clear_visited_link, - NULL); -} - -static void clear_visited_dist_links(DistEntry *dep) { if (dep->mld) @@ -1885,15 +1871,11 @@ insert_process(Process *proc) insert_sig_ext, (void *) proc); - /* If the process is FREE, the proc->common field has been - re-used by the ptab delete, so we cannot trust it. */ - if (!(erts_atomic32_read_nob(&proc->state) & ERTS_PSFLG_FREE)) { - /* Insert links */ - insert_p_links(&proc->common); - - /* Insert monitors */ - insert_p_monitors(&proc->common); - } + /* Insert monitors and links... */ + erts_debug_proc_monitor_link_foreach(proc, + insert_monitor, + insert_link, + (void *) &proc->common.id); { DistEntry *dep = ERTS_PROC_GET_DIST_ENTRY(proc); @@ -1906,6 +1888,12 @@ insert_process(Process *proc) } static void +insert_process2(Process *proc, void *arg) +{ + insert_process(proc); +} + +static void insert_dist_suspended_procs(DistEntry *dep) { ErtsProcList *plist = erts_proclist_peek_first(dep->suspended); @@ -1916,16 +1904,47 @@ insert_dist_suspended_procs(DistEntry *dep) } } +static void clear_process(Process *proc); + +static void +clear_dist_suspended_procs(DistEntry *dep) +{ + ErtsProcList *plist = erts_proclist_peek_first(dep->suspended); + while (plist) { + if (is_not_immed(plist->u.pid)) + clear_process(plist->u.p); + plist = erts_proclist_peek_next(dep->suspended, plist); + } +} + +static void +insert_persistent_term(ErlOffHeap *ohp, void *arg) +{ + Eterm heap[3]; + insert_offheap(ohp, SYSTEM_REF, + TUPLE2(&heap[0], AM_system, AM_persistent_term)); +} + +static void +insert_ets_offheap_thr_prgr(ErlOffHeap *ohp, void *arg) +{ + Eterm heap[3]; + insert_offheap(ohp, ETS_REF, + TUPLE2(&heap[0], AM_system, AM_ets)); +} + #ifdef ERL_NODE_BOOKKEEP void -erts_node_bookkeep(ErlNode *np, Eterm term, int what) +erts_node_bookkeep(ErlNode *np, Eterm term, int what, char *f, int l) { - erts_aint_t slot = (erts_atomic_inc_read_nob(&np->slot) - 1) % 1024; + erts_aint_t slot = (erts_atomic_inc_read_nob(&np->slot) - 1) % ERTS_BOOKKEEP_SIZE; ErtsSchedulerData *esdp = erts_get_scheduler_data(); Eterm who = THE_NON_VALUE; ASSERT(np); np->books[slot].what = what; np->books[slot].term = term; + np->books[slot].file = f; + np->books[slot].line = l; if (esdp->current_process) { who = esdp->current_process->common.id; } else if (esdp->current_port) { @@ -1946,14 +1965,14 @@ setup_reference_table(void) inserted_bins = NULL; hash_get_info(&hi, &erts_node_table); - referred_nodes = erts_alloc(ERTS_ALC_T_NC_TMP, + referred_nodes = erts_alloc(ERTS_DBG_NC_ALLOC_TYPE, hi.objs*sizeof(ReferredNode)); no_referred_nodes = 0; hash_foreach(&erts_node_table, init_referred_node, NULL); ASSERT(no_referred_nodes == hi.objs); hash_get_info(&hi, &erts_dist_table); - referred_dists = erts_alloc(ERTS_ALC_T_NC_TMP, + referred_dists = erts_alloc(ERTS_DBG_NC_ALLOC_TYPE, hi.objs*sizeof(ReferredDist)); no_referred_dists = 0; hash_foreach(&erts_dist_table, init_referred_dist, NULL); @@ -1990,8 +2009,9 @@ setup_reference_table(void) if (proc) insert_process(proc); } + erts_debug_free_process_foreach(insert_process2, NULL); - erts_foreach_sys_msg_in_q(insert_sys_msg); + erts_debug_foreach_sys_msg_in_q(insert_sys_msg); /* Insert all ports */ max = erts_ptab_max(&erts_port); @@ -2008,10 +2028,18 @@ setup_reference_table(void) if (state & ERTS_PORT_SFLGS_DEAD) continue; - /* Insert links */ - insert_p_links(&prt->common); - /* Insert monitors */ - insert_p_monitors(&prt->common); + /* Insert links */ + erts_link_tree_foreach(ERTS_P_LINKS(prt), + insert_link, + (void *) &prt->common.id); + /* Insert monitors */ + erts_monitor_tree_foreach(ERTS_P_MONITORS(prt), + insert_monitor, + (void *) &prt->common.id); + /* Insert local target monitors */ + erts_monitor_list_foreach(ERTS_P_LT_MONITORS(prt), + insert_monitor, + (void *) &prt->common.id); /* Insert port data */ ohp = erts_port_data_offheap(prt); if (ohp) @@ -2091,11 +2119,16 @@ setup_reference_table(void) } /* Insert all ets tables */ - erts_db_foreach_table(insert_ets_table, NULL); + erts_db_foreach_table(insert_ets_table, NULL, 0); + erts_db_foreach_thr_prgr_offheap(insert_ets_offheap_thr_prgr, NULL); /* Insert all bif timers */ erts_debug_bif_timer_foreach(insert_bif_timer, NULL); + /* Insert persistent term storage */ + erts_debug_foreach_persistent_term_off_heap(insert_persistent_term, + NULL); + /* Insert node table (references to dist) */ hash_foreach(&erts_node_table, insert_erl_node, NULL); } @@ -2348,8 +2381,7 @@ static void noop_sig_ext(ErtsDistExternal *ext, void *arg) static void delete_reference_table(void) { - DistEntry *dep; - int i, max; + int i; for(i = 0; i < no_referred_nodes; i++) { NodeReferrer *nrp; NodeReferrer *tnrp; @@ -2358,11 +2390,13 @@ delete_reference_table(void) erts_cleanup_offheap(&nrp->off_heap); tnrp = nrp; nrp = nrp->next; - erts_free(ERTS_ALC_T_NC_TMP, (void *) tnrp); + erts_free(ERTS_DBG_NC_ALLOC_TYPE, (void *) tnrp); } } - if (referred_nodes) - erts_free(ERTS_ALC_T_NC_TMP, (void *) referred_nodes); + if (referred_nodes) { + erts_free(ERTS_DBG_NC_ALLOC_TYPE, (void *) referred_nodes); + referred_nodes = NULL; + } for(i = 0; i < no_referred_dists; i++) { DistReferrer *drp; @@ -2371,34 +2405,57 @@ delete_reference_table(void) while(drp) { tdrp = drp; drp = drp->next; - erts_free(ERTS_ALC_T_NC_TMP, (void *) tdrp); + erts_free(ERTS_DBG_NC_ALLOC_TYPE, (void *) tdrp); } } - if (referred_dists) - erts_free(ERTS_ALC_T_NC_TMP, (void *) referred_dists); + if (referred_dists) { + erts_free(ERTS_DBG_NC_ALLOC_TYPE, (void *) referred_dists); + referred_dists = NULL; + } while(inserted_bins) { InsertedBin *ib = inserted_bins; inserted_bins = inserted_bins->next; - erts_free(ERTS_ALC_T_NC_TMP, (void *)ib); + erts_free(ERTS_DBG_NC_ALLOC_TYPE, (void *)ib); } +} + +static void clear_process(Process *proc) +{ + erts_proc_sig_debug_foreach_sig(proc, + noop_sig_msg, + noop_sig_offheap, + clear_visited_monitor, + clear_visited_link, + noop_sig_ext, + (void *) proc); + + + /* Clear monitors and links... */ + erts_debug_proc_monitor_link_foreach(proc, + clear_visited_monitor, + clear_visited_link, + (void *) &proc->common.id); +} + +static void clear_process2(Process *proc, void *arg) +{ + clear_process(proc); +} - /* Cleanup... */ +static void +clear_system(void) +{ + DistEntry *dep; + int i, max; + /* Clear... */ max = erts_ptab_max(&erts_proc); for (i = 0; i < max; i++) { Process *proc = erts_pix2proc(i); - if (proc) { - clear_visited_p_links(&proc->common); - clear_visited_p_monitors(&proc->common); - erts_proc_sig_debug_foreach_sig(proc, - noop_sig_msg, - noop_sig_offheap, - clear_visited_monitor, - clear_visited_link, - noop_sig_ext, - (void *) proc); - } + if (proc) + clear_process(proc); } + erts_debug_free_process_foreach(clear_process2, NULL); max = erts_ptab_max(&erts_port); for (i = 0; i < max; i++) { @@ -2413,28 +2470,42 @@ delete_reference_table(void) if (state & ERTS_PORT_SFLGS_DEAD) continue; - clear_visited_p_links(&prt->common); - clear_visited_p_monitors(&prt->common); + /* Clear links */ + erts_link_tree_foreach(ERTS_P_LINKS(prt), + clear_visited_link, + (void *) &prt->common.id); + /* Clear monitors */ + erts_monitor_tree_foreach(ERTS_P_MONITORS(prt), + clear_visited_monitor, + (void *) &prt->common.id); + /* Clear local target monitors */ + erts_monitor_list_foreach(ERTS_P_LT_MONITORS(prt), + clear_visited_monitor, + (void *) &prt->common.id); } for(dep = erts_visible_dist_entries; dep; dep = dep->next) { clear_visited_dist_links(dep); clear_visited_dist_monitors(dep); + clear_dist_suspended_procs(dep); } for(dep = erts_hidden_dist_entries; dep; dep = dep->next) { clear_visited_dist_links(dep); clear_visited_dist_monitors(dep); + clear_dist_suspended_procs(dep); } for(dep = erts_pending_dist_entries; dep; dep = dep->next) { clear_visited_dist_links(dep); clear_visited_dist_monitors(dep); + clear_dist_suspended_procs(dep); } for(dep = erts_not_connected_dist_entries; dep; dep = dep->next) { clear_visited_dist_links(dep); clear_visited_dist_monitors(dep); + clear_dist_suspended_procs(dep); } } diff --git a/erts/emulator/beam/erl_node_tables.h b/erts/emulator/beam/erl_node_tables.h index fc3e117463..beae2df75f 100644 --- a/erts/emulator/beam/erl_node_tables.h +++ b/erts/emulator/beam/erl_node_tables.h @@ -187,6 +187,7 @@ set pagination off set $i = 0 set $node = referred_nodes[$node_ix].node while $i < $node->slot.counter + printf "%s:%d ", $node->books[$i].file, $node->books[$i].line printf "%p: ", $node->books[$i].term etp-1 $node->books[$i].who printf " " @@ -211,8 +212,12 @@ lists:usort(lists:filter(fun({V,N}) -> N /= 0 end, maps:to_list(Accs))). struct erl_node_bookkeeping { Eterm who; Eterm term; + char *file; + int line; enum { ERL_NODE_INC, ERL_NODE_DEC } what; }; + +#define ERTS_BOOKKEEP_SIZE (1024) #endif typedef struct erl_node_ { @@ -222,7 +227,7 @@ typedef struct erl_node_ { Uint32 creation; /* Creation */ DistEntry *dist_entry; /* Corresponding dist entry */ #ifdef ERL_NODE_BOOKKEEP - struct erl_node_bookkeeping books[1024]; + struct erl_node_bookkeeping books[ERTS_BOOKKEEP_SIZE]; erts_atomic_t slot; #endif } ErlNode; @@ -276,14 +281,21 @@ Eterm erts_build_dhandle(Eterm **hpp, ErlOffHeap*, DistEntry*, Uint32 conn_id); Eterm erts_make_dhandle(Process *c_p, DistEntry*, Uint32 conn_id); ERTS_GLB_INLINE void erts_init_node_entry(ErlNode *np, erts_aint_t val); +#ifdef ERL_NODE_BOOKKEEP +#define erts_ref_node_entry(NP, MIN, T) erts_ref_node_entry__((NP), (MIN), (T), __FILE__, __LINE__) +#define erts_deref_node_entry(NP, T) erts_deref_node_entry__((NP), (T), __FILE__, __LINE__) +ERTS_GLB_INLINE erts_aint_t erts_ref_node_entry__(ErlNode *np, int min_val, Eterm term, char *file, int line); +ERTS_GLB_INLINE void erts_deref_node_entry__(ErlNode *np, Eterm term, char *file, int line); +#else ERTS_GLB_INLINE erts_aint_t erts_ref_node_entry(ErlNode *np, int min_val, Eterm term); ERTS_GLB_INLINE void erts_deref_node_entry(ErlNode *np, Eterm term); +#endif ERTS_GLB_INLINE void erts_de_rlock(DistEntry *dep); ERTS_GLB_INLINE void erts_de_runlock(DistEntry *dep); ERTS_GLB_INLINE void erts_de_rwlock(DistEntry *dep); ERTS_GLB_INLINE void erts_de_rwunlock(DistEntry *dep); #ifdef ERL_NODE_BOOKKEEP -void erts_node_bookkeep(ErlNode *, Eterm , int); +void erts_node_bookkeep(ErlNode *, Eterm , int, char *file, int line); #else #define erts_node_bookkeep(...) #endif @@ -296,21 +308,40 @@ erts_init_node_entry(ErlNode *np, erts_aint_t val) erts_refc_init(&np->refc, val); } +#ifdef ERL_NODE_BOOKKEEP + +ERTS_GLB_INLINE erts_aint_t +erts_ref_node_entry__(ErlNode *np, int min_val, Eterm term, char *file, int line) +{ + erts_node_bookkeep(np, term, ERL_NODE_INC, file, line); + return erts_refc_inctest(&np->refc, min_val); +} + +ERTS_GLB_INLINE void +erts_deref_node_entry__(ErlNode *np, Eterm term, char *file, int line) +{ + erts_node_bookkeep(np, term, ERL_NODE_DEC, file, line); + if (erts_refc_dectest(&np->refc, 0) == 0) + erts_schedule_delete_node(np); +} + +#else + ERTS_GLB_INLINE erts_aint_t erts_ref_node_entry(ErlNode *np, int min_val, Eterm term) { - erts_node_bookkeep(np, term, ERL_NODE_INC); return erts_refc_inctest(&np->refc, min_val); } ERTS_GLB_INLINE void erts_deref_node_entry(ErlNode *np, Eterm term) { - erts_node_bookkeep(np, term, ERL_NODE_DEC); if (erts_refc_dectest(&np->refc, 0) == 0) erts_schedule_delete_node(np); } +#endif + ERTS_GLB_INLINE void erts_de_rlock(DistEntry *dep) { diff --git a/erts/emulator/beam/erl_printf_term.c b/erts/emulator/beam/erl_printf_term.c index 2e33a8a782..67c486a0db 100644 --- a/erts/emulator/beam/erl_printf_term.c +++ b/erts/emulator/beam/erl_printf_term.c @@ -533,13 +533,34 @@ print_term(fmtfn_t fn, void* arg, Eterm obj, long *dcount) { case EXPORT_DEF: { Export* ep = *((Export **) (export_val(wobj) + 1)); - Atom* module = atom_tab(atom_val(ep->info.mfa.module)); - Atom* name = atom_tab(atom_val(ep->info.mfa.function)); + long tdcount; + int tres; PRINT_STRING(res, fn, arg, "fun "); - PRINT_BUF(res, fn, arg, module->name, module->len); + + /* We pass a temporary 'dcount' and adjust the real one later to ensure + * that the fun doesn't get split up between the module and function + * name. */ + tdcount = MAX_ATOM_SZ_LIMIT; + tres = print_atom_name(fn, arg, ep->info.mfa.module, &tdcount); + if (tres < 0) { + res = tres; + goto L_done; + } + *dcount -= (MAX_ATOM_SZ_LIMIT - tdcount); + res += tres; + PRINT_CHAR(res, fn, arg, ':'); - PRINT_BUF(res, fn, arg, name->name, name->len); + + tdcount = MAX_ATOM_SZ_LIMIT; + tres = print_atom_name(fn, arg, ep->info.mfa.function, &tdcount); + if (tres < 0) { + res = tres; + goto L_done; + } + *dcount -= (MAX_ATOM_SZ_LIMIT - tdcount); + res += tres; + PRINT_CHAR(res, fn, arg, '/'); PRINT_SWORD(res, fn, arg, 'd', 0, 1, (ErlPfSWord) ep->info.mfa.arity); diff --git a/erts/emulator/beam/erl_proc_sig_queue.c b/erts/emulator/beam/erl_proc_sig_queue.c index 6bbd59e8e3..b60fb64342 100644 --- a/erts/emulator/beam/erl_proc_sig_queue.c +++ b/erts/emulator/beam/erl_proc_sig_queue.c @@ -4689,10 +4689,12 @@ erts_proc_sig_debug_foreach_sig(Process *c_p, case ERTS_SIG_Q_OP_MONITOR_DOWN: switch (type) { case ERTS_SIG_Q_TYPE_GEN_EXIT: - if (ERTS_SIG_IS_GEN_EXIT_EXTERNAL(sig)) - debug_foreach_sig_external(sig, ext_func, arg); - else + if (!ERTS_SIG_IS_GEN_EXIT_EXTERNAL(sig)) debug_foreach_sig_heap_frags(&sig->hfrag, oh_func, arg); + else { + oh_func(&sig->hfrag.off_heap, arg); + debug_foreach_sig_external(sig, ext_func, arg); + } break; case ERTS_LNK_TYPE_PORT: case ERTS_LNK_TYPE_PROC: diff --git a/erts/emulator/beam/erl_process.c b/erts/emulator/beam/erl_process.c index 9e385310a8..b62ec77d65 100644 --- a/erts/emulator/beam/erl_process.c +++ b/erts/emulator/beam/erl_process.c @@ -708,10 +708,10 @@ erts_pre_init_process(void) erts_psd_required_locks[ERTS_PSD_DELAYED_GC_TASK_QS].set_locks = ERTS_PSD_DELAYED_GC_TASK_QS_SET_LOCKS; - erts_psd_required_locks[ERTS_PSD_NIF_TRAP_EXPORT].get_locks - = ERTS_PSD_NIF_TRAP_EXPORT_GET_LOCKS; - erts_psd_required_locks[ERTS_PSD_NIF_TRAP_EXPORT].set_locks - = ERTS_PSD_NIF_TRAP_EXPORT_SET_LOCKS; + erts_psd_required_locks[ERTS_PSD_NFUNC_TRAP_WRAPPER].get_locks + = ERTS_PSD_NFUNC_TRAP_WRAPPER_GET_LOCKS; + erts_psd_required_locks[ERTS_PSD_NFUNC_TRAP_WRAPPER].set_locks + = ERTS_PSD_NFUNC_TRAP_WRAPPER_SET_LOCKS; erts_psd_required_locks[ERTS_PSD_ETS_OWNED_TABLES].get_locks = ERTS_PSD_ETS_OWNED_TABLES_GET_LOCKS; @@ -6478,8 +6478,8 @@ schedule_out_process(ErtsRunQueue *c_rq, erts_aint32_t state, Process *p, ASSERT(!(state & (ERTS_PSFLG_DIRTY_IO_PROC |ERTS_PSFLG_DIRTY_CPU_PROC)) - || (BeamIsOpCode(*p->i, op_call_nif) - || BeamIsOpCode(*p->i, op_apply_bif))); + || (BeamIsOpCode(*p->i, op_call_nif_WWW) + || BeamIsOpCode(*p->i, op_call_bif_W))); a = state; @@ -11458,7 +11458,7 @@ erl_create_process(Process* parent, /* Parent of process (default group leader). #else arg_size = size_object_litopt(args, &litarea); #endif - heap_need = arg_size; + heap_need = arg_size + 1; /* Reserve place for continuation pointer */ p->flags = flags; @@ -11507,7 +11507,8 @@ erl_create_process(Process* parent, /* Parent of process (default group leader). p->old_hend = p->old_htop = p->old_heap = NULL; p->high_water = p->heap; p->gen_gcs = 0; - p->stop = p->hend = p->heap + sz; + p->hend = p->heap + sz; + p->stop = p->hend - 1; /* Reserve place for continuation pointer */ p->htop = p->heap; p->heap_sz = sz; p->abandoned_heap = NULL; @@ -11525,7 +11526,7 @@ erl_create_process(Process* parent, /* Parent of process (default group leader). p->current = &p->u.initial; p->i = (BeamInstr *) beam_apply; - p->cp = (BeamInstr *) beam_apply+1; + p->stop[0] = make_cp(beam_apply + 1); p->arg_reg = p->def_arg_reg; p->max_arg_reg = sizeof(p->def_arg_reg)/sizeof(p->def_arg_reg[0]); @@ -11839,7 +11840,6 @@ void erts_init_empty_process(Process *p) p->u.initial.function = 0; p->u.initial.arity = 0; p->catches = 0; - p->cp = NULL; p->i = NULL; p->current = NULL; @@ -11917,7 +11917,6 @@ erts_debug_verify_clean_empty_process(Process* p) ASSERT(p->bif_timers == NULL); ASSERT(p->dictionary == NULL); ASSERT(p->catches == 0); - ASSERT(p->cp == NULL); ASSERT(p->i == NULL); ASSERT(p->current == NULL); @@ -11977,7 +11976,7 @@ delete_process(Process* p) if (pbt) erts_free(ERTS_ALC_T_BPD, (void *) pbt); - erts_destroy_nif_export(p); + erts_destroy_nfunc(p); /* Cleanup psd */ @@ -12118,6 +12117,8 @@ erts_proc_exit_handle_dist_monitor(ErtsMonitor *mon, void *vctxt, Sint reds) ASSERT(c_p->flags & F_DISABLE_GC); ASSERT(erts_monitor_is_target(mon) && mon->type == ERTS_MON_TYPE_DIST_PROC); + ASSERT(ctxt->dist_state == NIL); + ASSERT(!ctxt->yield); mdp = erts_monitor_to_data(mon); @@ -12162,10 +12163,14 @@ erts_proc_exit_handle_dist_monitor(ErtsMonitor *mon, void *vctxt, Sint reds) reason); reds_consumed = reds - (ctx.reds / TERM_TO_BINARY_LOOP_FACTOR); switch (code) { - case ERTS_DSIG_SEND_CONTINUE: case ERTS_DSIG_SEND_YIELD: + reds_consumed = reds; /* force yield */ + ctxt->yield = 1; + break; + case ERTS_DSIG_SEND_CONTINUE: ctxt->dist_state = erts_dsend_export_trap_context(c_p, &ctx); reds_consumed = reds; /* force yield */ + ctxt->yield = 1; break; case ERTS_DSIG_SEND_OK: break; @@ -12376,6 +12381,9 @@ erts_proc_exit_handle_dist_link(ErtsLink *lnk, void *vctxt, Sint reds) ASSERT(c_p->flags & F_DISABLE_GC); ASSERT(lnk->type == ERTS_LNK_TYPE_DIST_PROC); + ASSERT(ctxt->dist_state == NIL); + ASSERT(!ctxt->yield); + dlnk = erts_link_to_other(lnk, &ldp); dist = ((ErtsLinkDataExtended *) ldp)->dist; @@ -12413,9 +12421,13 @@ erts_proc_exit_handle_dist_link(ErtsLink *lnk, void *vctxt, Sint reds) reds_consumed = reds - (ctx.reds / TERM_TO_BINARY_LOOP_FACTOR); switch (code) { case ERTS_DSIG_SEND_YIELD: + reds_consumed = reds; /* force yield */ + ctxt->yield = 1; + break; case ERTS_DSIG_SEND_CONTINUE: ctxt->dist_state = erts_dsend_export_trap_context(c_p, &ctx); reds_consumed = reds; /* force yield */ + ctxt->yield = 1; break; case ERTS_DSIG_SEND_OK: break; @@ -12838,6 +12850,7 @@ restart: trap_state->pectxt.dist_links = NULL; trap_state->pectxt.dist_monitors = NULL; trap_state->pectxt.dist_state = NIL; + trap_state->pectxt.yield = 0; erts_proc_lock(p, ERTS_PROC_LOCK_MSGQ); @@ -12921,6 +12934,8 @@ restart: erts_kill_dist_connection(ctx->dep, ctx->connection_id); break; case ERTS_DSIG_SEND_YIELD: /*SEND_YIELD_RETURN*/ + trap_state->pectxt.dist_state = NIL; + goto yield; case ERTS_DSIG_SEND_CONTINUE: { /*SEND_YIELD_CONTINUE*/ goto yield; } @@ -12938,7 +12953,7 @@ restart: (void *) &trap_state->pectxt, &trap_state->yield_state, reds); - if (reds <= 0 || is_not_nil(trap_state->pectxt.dist_state)) + if (reds <= 0 || trap_state->pectxt.yield) goto yield; trap_state->phase = ERTS_CONTINUE_EXIT_DIST_MONITORS; } @@ -12953,7 +12968,7 @@ restart: (void *) &trap_state->pectxt, &trap_state->yield_state, reds); - if (reds <= 0 || is_not_nil(trap_state->pectxt.dist_state)) + if (reds <= 0 || trap_state->pectxt.yield) goto yield; trap_state->phase = ERTS_CONTINUE_EXIT_DONE; @@ -13038,6 +13053,7 @@ restart: sys_memcpy(trap_state, &static_state, sizeof(*trap_state)); p->u.terminate = trap_state; } + trap_state->pectxt.yield = 0; ASSERT(p->scheduler_data); ASSERT(p->scheduler_data->current_process == p); @@ -13146,9 +13162,6 @@ erts_program_counter_info(fmtfn_t to, void *to_arg, Process *p) erts_print(to, to_arg, "Program counter: %p (", p->i); print_function_from_pc(to, to_arg, p->i); erts_print(to, to_arg, ")\n"); - erts_print(to, to_arg, "CP: %p (", p->cp); - print_function_from_pc(to, to_arg, p->cp); - erts_print(to, to_arg, ")\n"); state = erts_atomic32_read_acqb(&p->state); if (!(state & (ERTS_PSFLG_RUNNING | ERTS_PSFLG_RUNNING_SYS @@ -13425,9 +13438,6 @@ static void print_current_process_info(fmtfn_t to, void *to_arg, erts_print(to, to_arg, "Current Process Program counter: %p (", p->i); print_function_from_pc(to, to_arg, p->i); erts_print(to, to_arg, ")\n"); - erts_print(to, to_arg, "Current Process CP: %p (", p->cp); - print_function_from_pc(to, to_arg, p->cp); - erts_print(to, to_arg, ")\n"); /* Getting this stacktrace can segfault if we are very very unlucky if called while a process is being garbage collected. @@ -13514,3 +13524,79 @@ erts_debug_later_op_foreach(void (*callback)(void*), } } } + +void +erts_debug_free_process_foreach(void (*func)(Process *, void *), void *arg) +{ + ErtsRunQueue *rq; + int ix, prio; + for (ix = 0; ix < erts_no_run_queues; ix++) { + rq = ERTS_RUNQ_IX(ix); + for (prio = PRIORITY_MAX; prio < PRIORITY_LOW; prio++) { + Process *p = rq->procs.prio[prio].first; + for (; p; p = p->next) { + if (ERTS_PSFLG_FREE & erts_atomic32_read_nob(&p->state)) + (*func)(p, arg); + } + } + } +} + +void +erts_debug_proc_monitor_link_foreach(Process *proc, + int (*monitor_func)(ErtsMonitor *, void *, Sint ), + int (*link_func)(ErtsLink *, void *, Sint ), + void *arg) +{ + if (!(erts_atomic32_read_nob(&proc->state) & ERTS_PSFLG_FREE)) { + /* For all links */ + erts_link_tree_foreach(ERTS_P_LINKS(proc), + link_func, + arg); + /* For all monitors */ + erts_monitor_tree_foreach(ERTS_P_MONITORS(proc), + monitor_func, + arg); + /* For all local target monitors */ + erts_monitor_list_foreach(ERTS_P_LT_MONITORS(proc), + monitor_func, + arg); + } + else { + struct continue_exit_state *ce_state = proc->u.terminate; + + /* For all links */ + if (ce_state->phase == ERTS_CONTINUE_EXIT_LINKS) + erts_debug_link_tree_destroying_foreach(ce_state->links, + link_func, + arg, + ce_state->yield_state); + else + erts_link_tree_foreach(ce_state->links, + link_func, + arg); + + /* For all monitors */ + if (ce_state->phase == ERTS_CONTINUE_EXIT_MONITORS) + erts_debug_monitor_tree_destroying_foreach(ce_state->monitors, + monitor_func, + arg, + ce_state->yield_state); + else + erts_monitor_tree_foreach(ce_state->monitors, + monitor_func, + arg); + + /* For all local target monitors */ + if (ce_state->phase == ERTS_CONTINUE_EXIT_LT_MONITORS) + erts_debug_monitor_list_destroying_foreach(ce_state->lt_monitors, + monitor_func, + arg, + ce_state->yield_state); + else + erts_monitor_list_foreach(ce_state->lt_monitors, + monitor_func, + arg); + + } +} diff --git a/erts/emulator/beam/erl_process.h b/erts/emulator/beam/erl_process.h index 2e2ab01d86..09a6c0e961 100644 --- a/erts/emulator/beam/erl_process.h +++ b/erts/emulator/beam/erl_process.h @@ -701,6 +701,13 @@ void erts_debug_later_op_foreach(void (*callback)(void*), void (*func)(void *, ErtsThrPrgrVal, void *), void *arg); +void +erts_debug_free_process_foreach(void (*func)(Process *, void *), void *arg); +void +erts_debug_proc_monitor_link_foreach(Process *proc, + int (*monitor_func)(ErtsMonitor *, void *, Sint ), + int (*link_func)(ErtsLink *, void *, Sint ), + void *arg); #ifdef ERTS_INCLUDE_SCHEDULER_INTERNALS @@ -805,7 +812,7 @@ erts_reset_max_len(ErtsRunQueue *rq, ErtsRunQueueInfo *rqi) #define ERTS_PSD_SCHED_ID 2 #define ERTS_PSD_CALL_TIME_BP 3 #define ERTS_PSD_DELAYED_GC_TASK_QS 4 -#define ERTS_PSD_NIF_TRAP_EXPORT 5 +#define ERTS_PSD_NFUNC_TRAP_WRAPPER 5 #define ERTS_PSD_ETS_OWNED_TABLES 6 #define ERTS_PSD_ETS_FIXED_TABLES 7 #define ERTS_PSD_DIST_ENTRY 8 @@ -842,8 +849,8 @@ typedef struct { #define ERTS_PSD_DELAYED_GC_TASK_QS_GET_LOCKS ERTS_PROC_LOCK_MAIN #define ERTS_PSD_DELAYED_GC_TASK_QS_SET_LOCKS ERTS_PROC_LOCK_MAIN -#define ERTS_PSD_NIF_TRAP_EXPORT_GET_LOCKS ERTS_PROC_LOCK_MAIN -#define ERTS_PSD_NIF_TRAP_EXPORT_SET_LOCKS ERTS_PROC_LOCK_MAIN +#define ERTS_PSD_NFUNC_TRAP_WRAPPER_GET_LOCKS ERTS_PROC_LOCK_MAIN +#define ERTS_PSD_NFUNC_TRAP_WRAPPER_SET_LOCKS ERTS_PROC_LOCK_MAIN #define ERTS_PSD_ETS_OWNED_TABLES_GET_LOCKS ERTS_PROC_LOCK_STATUS #define ERTS_PSD_ETS_OWNED_TABLES_SET_LOCKS ERTS_PROC_LOCK_STATUS @@ -968,7 +975,6 @@ struct process { unsigned max_arg_reg; /* Maximum number of argument registers available. */ Eterm def_arg_reg[6]; /* Default array for argument registers. */ - BeamInstr* cp; /* (untagged) Continuation pointer (for threaded code). */ BeamInstr* i; /* Program counter for threaded code. */ Sint catches; /* Number of catches on stack */ Sint fcalls; /* @@ -1364,7 +1370,7 @@ extern int erts_system_profile_ts_type; #define F_DISTRIBUTION (1 << 6) /* Process used in distribution */ #define F_USING_DDLL (1 << 7) /* Process has used the DDLL interface */ #define F_HAVE_BLCKD_MSCHED (1 << 8) /* Process has blocked multi-scheduling */ -#define F_UNUSED (1 << 9) +#define F_ETS_SUPER_USER (1 << 9) /* Process is ETS super user */ #define F_FORCE_GC (1 << 10) /* Force gc at process in-scheduling */ #define F_DISABLE_GC (1 << 11) /* Disable GC (see below) */ #define F_OFF_HEAP_MSGQ (1 << 12) /* Off heap msg queue */ @@ -1826,6 +1832,7 @@ typedef struct { ErtsLink *dist_links; ErtsMonitor *dist_monitors; Eterm dist_state; + int yield; } ErtsProcExitContext; int erts_proc_exit_handle_monitor(ErtsMonitor *mon, void *vctxt, Sint reds); int erts_proc_exit_handle_link(ErtsLink *lnk, void *vctxt, Sint reds); @@ -2031,10 +2038,10 @@ erts_psd_set(Process *p, int ix, void *data) #define ERTS_PROC_SET_DELAYED_GC_TASK_QS(P, PBT) \ ((ErtsProcSysTaskQs *) erts_psd_set((P), ERTS_PSD_DELAYED_GC_TASK_QS, (void *) (PBT))) -#define ERTS_PROC_GET_NIF_TRAP_EXPORT(P) \ - erts_psd_get((P), ERTS_PSD_NIF_TRAP_EXPORT) -#define ERTS_PROC_SET_NIF_TRAP_EXPORT(P, NTE) \ - erts_psd_set((P), ERTS_PSD_NIF_TRAP_EXPORT, (void *) (NTE)) +#define ERTS_PROC_GET_NFUNC_TRAP_WRAPPER(P) \ + erts_psd_get((P), ERTS_PSD_NFUNC_TRAP_WRAPPER) +#define ERTS_PROC_SET_NFUNC_TRAP_WRAPPER(P, NTE) \ + erts_psd_set((P), ERTS_PSD_NFUNC_TRAP_WRAPPER, (void *) (NTE)) #define ERTS_PROC_GET_DIST_ENTRY(P) \ ((DistEntry *) erts_psd_get((P), ERTS_PSD_DIST_ENTRY)) diff --git a/erts/emulator/beam/erl_trace.c b/erts/emulator/beam/erl_trace.c index ffe0752b46..5c46a10d64 100644 --- a/erts/emulator/beam/erl_trace.c +++ b/erts/emulator/beam/erl_trace.c @@ -2195,11 +2195,12 @@ sys_msg_dispatcher_wait(void *vwait_p) erts_mtx_unlock(&smq_mtx); } +static ErtsSysMsgQ *local_sys_message_queue = NULL; + static void * sys_msg_dispatcher_func(void *unused) { ErtsThrPrgrCallbacks callbacks; - ErtsSysMsgQ *local_sys_message_queue = NULL; ErtsThrPrgrData *tpd; int wait = 0; @@ -2207,6 +2208,8 @@ sys_msg_dispatcher_func(void *unused) erts_lc_set_thread_name("system message dispatcher"); #endif + local_sys_message_queue = NULL; + callbacks.arg = (void *) &wait; callbacks.wakeup = sys_msg_dispatcher_wakeup; callbacks.prepare_wait = sys_msg_dispatcher_prep_wait; @@ -2263,6 +2266,8 @@ sys_msg_dispatcher_func(void *unused) Process *proc = NULL; Port *port = NULL; + ASSERT(is_value(smqp->msg)); + if (erts_thr_progress_update(tpd)) erts_thr_progress_leader_update(tpd); @@ -2375,6 +2380,7 @@ sys_msg_dispatcher_func(void *unused) erts_fprintf(stderr, "dropped\n"); #endif } + smqp->msg = THE_NON_VALUE; } } @@ -2382,32 +2388,38 @@ sys_msg_dispatcher_func(void *unused) } void -erts_foreach_sys_msg_in_q(void (*func)(Eterm, - Eterm, - Eterm, - ErlHeapFragment *)) +erts_debug_foreach_sys_msg_in_q(void (*func)(Eterm, + Eterm, + Eterm, + ErlHeapFragment *)) { - ErtsSysMsgQ *sm; - erts_mtx_lock(&smq_mtx); - for (sm = sys_message_queue; sm; sm = sm->next) { - Eterm to; - switch (sm->type) { - case SYS_MSG_TYPE_SYSMON: - to = erts_get_system_monitor(); - break; - case SYS_MSG_TYPE_SYSPROF: - to = erts_get_system_profile(); - break; - case SYS_MSG_TYPE_ERRLGR: - to = erts_get_system_logger(); - break; - default: - to = NIL; - break; - } - (*func)(sm->from, to, sm->msg, sm->bp); + ErtsSysMsgQ *smq[] = {sys_message_queue, local_sys_message_queue}; + int i; + + ERTS_LC_ASSERT(erts_thr_progress_is_blocking()); + + for (i = 0; i < sizeof(smq)/sizeof(smq[0]); i++) { + ErtsSysMsgQ *sm; + for (sm = smq[i]; sm; sm = sm->next) { + Eterm to; + switch (sm->type) { + case SYS_MSG_TYPE_SYSMON: + to = erts_get_system_monitor(); + break; + case SYS_MSG_TYPE_SYSPROF: + to = erts_get_system_profile(); + break; + case SYS_MSG_TYPE_ERRLGR: + to = erts_get_system_logger(); + break; + default: + to = NIL; + break; + } + if (is_value(sm->msg)) + (*func)(sm->from, to, sm->msg, sm->bp); + } } - erts_mtx_unlock(&smq_mtx); } diff --git a/erts/emulator/beam/erl_trace.h b/erts/emulator/beam/erl_trace.h index bb5c9ac276..c0f31e0cb6 100644 --- a/erts/emulator/beam/erl_trace.h +++ b/erts/emulator/beam/erl_trace.h @@ -90,10 +90,10 @@ int erts_is_tracer_valid(Process* p); void erts_check_my_tracer_proc(Process *); void erts_block_sys_msg_dispatcher(void); void erts_release_sys_msg_dispatcher(void); -void erts_foreach_sys_msg_in_q(void (*func)(Eterm, - Eterm, - Eterm, - ErlHeapFragment *)); +void erts_debug_foreach_sys_msg_in_q(void (*func)(Eterm, + Eterm, + Eterm, + ErlHeapFragment *)); Eterm erts_set_system_logger(Eterm); Eterm erts_get_system_logger(void); void erts_queue_error_logger_message(Eterm, Eterm, ErlHeapFragment *); @@ -142,12 +142,6 @@ void monitor_generic(Process *p, Eterm type, Eterm spec); Uint erts_trace_flag2bit(Eterm flag); int erts_trace_flags(Eterm List, Uint *pMask, ErtsTracer *pTracer, int *pCpuTimestamp); -Eterm erts_bif_trace(int bif_index, Process* p, Eterm* args, BeamInstr *I); -Eterm -erts_bif_trace_epilogue(Process *p, Eterm result, int applying, - Export* ep, BeamInstr *cp, Uint32 flags, - Uint32 flags_meta, BeamInstr* I, - ErtsTracer meta_tracer); void erts_send_pending_trace_msgs(ErtsSchedulerData *esdp); #define ERTS_CHK_PEND_TRACE_MSGS(ESDP) \ diff --git a/erts/emulator/beam/erl_unicode.c b/erts/emulator/beam/erl_unicode.c index 1d6869a7cd..9fd3012888 100644 --- a/erts/emulator/beam/erl_unicode.c +++ b/erts/emulator/beam/erl_unicode.c @@ -800,7 +800,29 @@ static int check_leftovers(byte *source, int size) } return -1; } - + + +static Eterm +mk_utf8_result_bin(Process *p, Eterm bin) +{ + /* + * Don't let small refc-binaries escape out in the system + * when done. That is, convert such to heap binaries. + */ + Uint size = binary_size(bin); + + ASSERT(*binary_val(bin) == HEADER_PROC_BIN); + + if (size <= ERL_ONHEAP_BIN_LIMIT) { + ErlHeapBin* hb = (ErlHeapBin *) HAlloc(p, heap_bin_size(size)); + hb->thing_word = header_heap_bin(size); + hb->size = size; + sys_memcpy(hb->data, binary_bytes(bin), size); + return make_binary(hb); + } + + return bin; +} static BIF_RETTYPE build_utf8_return(Process *p,Eterm bin,Uint pos, @@ -822,15 +844,15 @@ static BIF_RETTYPE build_utf8_return(Process *p,Eterm bin,Uint pos, } else { hp = HAlloc(p,4); } - ret = TUPLE3(hp,am_error,bin,rest_term); + ret = TUPLE3(hp,am_error,mk_utf8_result_bin(p,bin),rest_term); } else if (rest_term == NIL && num_leftovers != 0) { Eterm leftover_bin = new_binary(p, leftover, num_leftovers); if (check_leftovers(leftover,num_leftovers) != 0) { hp = HAlloc(p,4); - ret = TUPLE3(hp,am_error,bin,leftover_bin); + ret = TUPLE3(hp,am_error,mk_utf8_result_bin(p,bin),leftover_bin); } else { hp = HAlloc(p,4); - ret = TUPLE3(hp,am_incomplete,bin,leftover_bin); + ret = TUPLE3(hp,am_incomplete,mk_utf8_result_bin(p,bin),leftover_bin); } } else { /* All OK */ if (rest_term != NIL) { /* Trap */ @@ -843,8 +865,8 @@ static BIF_RETTYPE build_utf8_return(Process *p,Eterm bin,Uint pos, BIF_TRAP3(&characters_to_utf8_trap_exp, p, bin, rest_term, latin1); } else { /* Success */ /*hp = HAlloc(p,5); - ret = TUPLE4(hp,bin,rest_term,make_small(pos),make_small(err));*/ - ret = bin; + ret = TUPLE4(hp,mk_utf8_result_bin(p,bin),rest_term,make_small(pos),make_small(err));*/ + ret = mk_utf8_result_bin(p,bin); } } BIF_RET(ret); diff --git a/erts/emulator/beam/error.h b/erts/emulator/beam/error.h index 64c08b1570..44a9809a18 100644 --- a/erts/emulator/beam/error.h +++ b/erts/emulator/beam/error.h @@ -66,13 +66,13 @@ #define EXF_OFFSET EXTAG_BITS #define EXF_BITS 7 -#define EXF_PANIC (1<<(0+EXF_OFFSET)) /* ignore catches */ -#define EXF_THROWN (1<<(1+EXF_OFFSET)) /* nonlocal return */ -#define EXF_LOG (1<<(2+EXF_OFFSET)) /* write to logger on termination */ -#define EXF_NATIVE (1<<(3+EXF_OFFSET)) /* occurred in native code */ -#define EXF_SAVETRACE (1<<(4+EXF_OFFSET)) /* save stack trace in internal form */ -#define EXF_ARGLIST (1<<(5+EXF_OFFSET)) /* has arglist for top of trace */ -#define EXF_RESTORE_NIF (1<<(6+EXF_OFFSET)) /* restore original bif/nif */ +#define EXF_PANIC (1<<(0+EXF_OFFSET)) /* ignore catches */ +#define EXF_THROWN (1<<(1+EXF_OFFSET)) /* nonlocal return */ +#define EXF_LOG (1<<(2+EXF_OFFSET)) /* write to logger on termination */ +#define EXF_NATIVE (1<<(3+EXF_OFFSET)) /* occurred in native code */ +#define EXF_SAVETRACE (1<<(4+EXF_OFFSET)) /* save stack trace in internal form */ +#define EXF_ARGLIST (1<<(5+EXF_OFFSET)) /* has arglist for top of trace */ +#define EXF_RESTORE_NFUNC (1<<(6+EXF_OFFSET)) /* restore original bif/nif */ #define EXC_FLAGBITS (((1<<(EXF_BITS+EXF_OFFSET))-1) \ & ~((1<<(EXF_OFFSET))-1)) diff --git a/erts/emulator/beam/export.c b/erts/emulator/beam/export.c index 946ffeffb8..ca16bfd20e 100644 --- a/erts/emulator/beam/export.c +++ b/erts/emulator/beam/export.c @@ -129,14 +129,17 @@ export_alloc(struct export_entry* tmpl_e) obj->info.mfa.module = tmpl->info.mfa.module; obj->info.mfa.function = tmpl->info.mfa.function; obj->info.mfa.arity = tmpl->info.mfa.arity; - obj->beam[0] = 0; + obj->bif_table_index = -1; + obj->is_bif_traced = 0; + + memset(&obj->trampoline, 0, sizeof(obj->trampoline)); + if (BeamOpsAreInitialized()) { - obj->beam[0] = BeamOpCodeAddr(op_call_error_handler); + obj->trampoline.op = BeamOpCodeAddr(op_call_error_handler); } - obj->beam[1] = 0; for (ix=0; ix<ERTS_NUM_CODE_IX; ix++) { - obj->addressv[ix] = obj->beam; + obj->addressv[ix] = obj->trampoline.raw; blob->entryv[ix].slot.index = -1; blob->entryv[ix].ep = &blob->exp; @@ -196,6 +199,19 @@ init_export_table(void) } } +static struct export_entry* init_template(struct export_templ* templ, + Eterm m, Eterm f, unsigned a) +{ + templ->entry.ep = &templ->exp; + templ->entry.slot.index = -1; + templ->exp.info.mfa.module = m; + templ->exp.info.mfa.function = f; + templ->exp.info.mfa.arity = a; + templ->exp.bif_table_index = -1; + templ->exp.is_bif_traced = 0; + return &templ->entry; +} + /* * Return a pointer to the export entry for the given function, * or NULL otherwise. Notes: @@ -214,41 +230,15 @@ erts_find_export_entry(Eterm m, Eterm f, unsigned int a,ErtsCodeIndex code_ix); Export* erts_find_export_entry(Eterm m, Eterm f, unsigned int a, ErtsCodeIndex code_ix) { - HashValue hval = EXPORT_HASH((BeamInstr) m, (BeamInstr) f, (BeamInstr) a); - int ix; - HashBucket* b; - - ix = hval % export_tables[code_ix].htable.size; - b = export_tables[code_ix].htable.bucket[ix]; - - /* - * Note: We have inlined the code from hash.c for speed. - */ - - while (b != (HashBucket*) 0) { - Export* ep = ((struct export_entry*) b)->ep; - if (ep->info.mfa.module == m && - ep->info.mfa.function == f && - ep->info.mfa.arity == a) { - return ep; - } - b = b->next; - } + struct export_templ templ; + struct export_entry *ee = + hash_fetch(&export_tables[code_ix].htable, + init_template(&templ, m, f, a), + (H_FUN)export_hash, (HCMP_FUN)export_cmp); + if (ee) return ee->ep; return NULL; } -static struct export_entry* init_template(struct export_templ* templ, - Eterm m, Eterm f, unsigned a) -{ - templ->entry.ep = &templ->exp; - templ->entry.slot.index = -1; - templ->exp.info.mfa.module = m; - templ->exp.info.mfa.function = f; - templ->exp.info.mfa.arity = a; - return &templ->entry; -} - - /* * Find the export entry for a loaded function. * Returns a NULL pointer if the given function is not loaded, or @@ -268,8 +258,8 @@ erts_find_function(Eterm m, Eterm f, unsigned int a, ErtsCodeIndex code_ix) ee = hash_get(&export_tables[code_ix].htable, init_template(&templ, m, f, a)); if (ee == NULL || - (ee->ep->addressv[code_ix] == ee->ep->beam && - ! BeamIsOpCode(ee->ep->beam[0], op_i_generic_breakpoint))) { + (ee->ep->addressv[code_ix] == ee->ep->trampoline.raw && + ! BeamIsOpCode(ee->ep->trampoline.op, op_i_generic_breakpoint))) { return NULL; } return ee->ep; diff --git a/erts/emulator/beam/export.h b/erts/emulator/beam/export.h index ae8dfa4cf8..0190624f79 100644 --- a/erts/emulator/beam/export.h +++ b/erts/emulator/beam/export.h @@ -31,24 +31,72 @@ typedef struct export { - void* addressv[ERTS_NUM_CODE_IX]; /* Pointer to code for function. */ - - ErtsCodeInfo info; /* MUST be just before beam[] */ - - /* - * beam[0]: This entry is 0 unless the 'addressv' field points to it. - * Threaded code instruction to load function - * (em_call_error_handler), execute BIF (em_apply_bif), - * or a breakpoint instruction (op_i_generic_breakpoint). - * beam[1]: Function pointer to BIF function (for BIFs only), - * or pointer to threaded code if the module has an - * on_load function that has not been run yet, or pointer - * to code if function beam[0] is a breakpoint instruction. - * Otherwise: 0. - */ - BeamInstr beam[2]; + /* Pointer to code for function. */ + void* addressv[ERTS_NUM_CODE_IX]; + + /* Index into bif_table[], or -1 if not a BIF. */ + int bif_table_index; + /* Non-zero if this is a BIF that's traced. */ + int is_bif_traced; + + /* This is a small trampoline function that can be used for lazy code + * loading, global call tracing, and so on. It's only valid when + * addressv points to it and should otherwise be left zeroed. + * + * Needless to say, the order of the fields below is significant. */ + ErtsCodeInfo info; + union { + BeamInstr op; /* Union discriminant. */ + + struct { + BeamInstr op; /* op_i_generic_breakpoint */ + BeamInstr address; /* Address of the original function */ + } breakpoint; + + /* This is used when a module refers to (imports) a function that + * hasn't been loaded yet. Upon loading we create an export entry which + * redirects to the error_handler so that the appropriate module will + * be loaded when called (or crash). + * + * This is also used when a module has an on_load callback as we need + * to defer all calls until the callback returns. `deferred` contains + * the address of the original function in this case, and there's an + * awkward condiditon where `deferred` may be set while op is zero. See + * erlang:finish_after_on_load/2 for details. */ + struct { + BeamInstr op; /* op_call_error_handler, or 0 during the last + * phase of code loading when on_load is + * present. See above. */ + BeamInstr deferred; + } not_loaded; + + struct { + BeamInstr op; /* op_trace_jump_W */ + BeamInstr address; /* Address of the traced function */ + } trace; + + BeamInstr raw[2]; /* For use in address comparisons, should not + * be tampered directly. */ + } trampoline; } Export; +#ifdef DEBUG +#define DBG_CHECK_EXPORT(EP, CX) \ + do { \ + if((EP)->addressv[CX] == (EP)->trampoline.raw) { \ + /* The entry currently points at the trampoline, so the + * instructions must be valid. */ \ + ASSERT(((BeamIsOpCode((EP)->trampoline.op, op_i_generic_breakpoint)) && \ + (EP)->trampoline.breakpoint.address != 0) || \ + ((BeamIsOpCode((EP)->trampoline.op, op_trace_jump_W)) && \ + (EP)->trampoline.trace.address != 0) || \ + /* (EP)->trampoline.not_loaded.deferred may be zero. */ \ + (BeamIsOpCode((EP)->trampoline.op, op_call_error_handler))); \ + } \ + } while(0) +#else +#define DBG_CHECK_EXPORT(EP, CX) ((void)(EP), (void)(CX)) +#endif void init_export_table(void); void export_info(fmtfn_t, void *); @@ -71,9 +119,6 @@ extern erts_mtx_t export_staging_lock; #define export_staging_unlock() erts_mtx_unlock(&export_staging_lock) #include "beam_load.h" /* For em_* extern declarations */ -#define ExportIsBuiltIn(EntryPtr) \ -(((EntryPtr)->addressv[erts_active_code_ix()] == (EntryPtr)->beam) && \ - (BeamIsOpCode((EntryPtr)->beam[0], op_apply_bif))) #if ERTS_GLB_INLINE_INCL_FUNC_DEF diff --git a/erts/emulator/beam/external.c b/erts/emulator/beam/external.c index 5cea253ebe..a575e1d743 100644 --- a/erts/emulator/beam/external.c +++ b/erts/emulator/beam/external.c @@ -1413,7 +1413,7 @@ enum B2TState { /* order is somewhat significant */ }; typedef struct { - int heap_size; + Sint heap_size; int terms; byte* ep; int atom_extra_skip; @@ -4536,7 +4536,7 @@ encode_size_struct_int(TTBSizeContext* ctx, ErtsAtomCacheMap *acmp, Eterm obj, static Sint decoded_size(byte *ep, byte* endp, int internal_tags, B2TContext* ctx) { - int heap_size; + Sint heap_size; int terms; int atom_extra_skip; Uint n; diff --git a/erts/emulator/beam/global.h b/erts/emulator/beam/global.h index 4c8d3d3dbe..b86709b093 100644 --- a/erts/emulator/beam/global.h +++ b/erts/emulator/beam/global.h @@ -122,6 +122,10 @@ void erts_nif_demonitored(ErtsResource* resource); extern void erts_add_taint(Eterm mod_atom); extern Eterm erts_nif_taints(Process* p); extern void erts_print_nif_taints(fmtfn_t to, void* to_arg); + +/* Loads the specified NIF. The caller must have code write permission. */ +Eterm erts_load_nif(Process *c_p, BeamInstr *I, Eterm filename, Eterm args); + void erts_unload_nif(struct erl_module_nif* nif); extern void erl_nif_init(void); extern int erts_nif_get_funcs(struct erl_module_nif*, @@ -878,11 +882,15 @@ erts_bld_port_info(Eterm **hpp, Uint *szp, Port *prt, Eterm item); +Eterm erts_bld_bin_list(Uint **hpp, Uint *szp, ErlOffHeap* oh, Eterm tail); + void erts_bif_info_init(void); /* bif.c */ +void erts_write_bif_wrapper(Export *export, BeamInstr *address); + void erts_queue_monitor_message(Process *, ErtsProcLocks*, Eterm, @@ -904,10 +912,14 @@ Eterm erts_trapping_length_1(Process* p, Eterm* args); Eterm erl_is_function(Process* p, Eterm arg1, Eterm arg2); +/* beam_bif_lists.c */ +void erts_init_bif_lists(void); + /* beam_bif_load.c */ Eterm erts_check_process_code(Process *c_p, Eterm module, int *redsp, int fcalls); Eterm erts_proc_copy_literal_area(Process *c_p, int *redsp, int fcalls, int gc_allowed); - +void erts_debug_foreach_release_literal_area_off_heap(void (*func)(ErlOffHeap *, void *), + void *arg); typedef struct ErtsLiteralArea_ { struct erl_off_heap_header *off_heap; Eterm *end; @@ -1072,17 +1084,46 @@ Uint size_object_x(Eterm, erts_literal_area_t*); #define size_object_litopt(Term,LitArea) size_object_x(Term,LitArea) Uint copy_shared_calculate(Eterm, erts_shcopy_t*); -Eterm copy_shared_perform(Eterm, Uint, erts_shcopy_t*, Eterm**, ErlOffHeap*); - Uint size_shared(Eterm); +/* #define ERTS_COPY_REGISTER_LOCATION */ + +#ifdef ERTS_COPY_REGISTER_LOCATION + +#define copy_shared_perform(U, V, X, Y, Z) \ + copy_shared_perform_x((U), (V), (X), (Y), (Z), __FILE__, __LINE__) +Eterm copy_shared_perform_x(Eterm, Uint, erts_shcopy_t*, Eterm**, ErlOffHeap*, + char *file, int line); + +Eterm copy_struct_x(Eterm, Uint, Eterm**, ErlOffHeap*, Uint*, erts_literal_area_t*, + char *file, int line); +#define copy_struct(Obj,Sz,HPP,OH) \ + copy_struct_x(Obj,Sz,HPP,OH,NULL,NULL,__FILE__,__LINE__) +#define copy_struct_litopt(Obj,Sz,HPP,OH,LitArea) \ + copy_struct_x(Obj,Sz,HPP,OH,NULL,LitArea,__FILE__,__LINE__) + +#define copy_shallow(R, SZ, HPP, OH) \ + copy_shallow_x((R), (SZ), (HPP), (OH), __FILE__, __LINE__) +Eterm copy_shallow_x(Eterm* ERTS_RESTRICT, Uint, Eterm**, ErlOffHeap*, + char *file, int line); + +#else + +#define copy_shared_perform(U, V, X, Y, Z) \ + copy_shared_perform_x((U), (V), (X), (Y), (Z)) +Eterm copy_shared_perform_x(Eterm, Uint, erts_shcopy_t*, Eterm**, ErlOffHeap*); + Eterm copy_struct_x(Eterm, Uint, Eterm**, ErlOffHeap*, Uint*, erts_literal_area_t*); #define copy_struct(Obj,Sz,HPP,OH) \ copy_struct_x(Obj,Sz,HPP,OH,NULL,NULL) #define copy_struct_litopt(Obj,Sz,HPP,OH,LitArea) \ copy_struct_x(Obj,Sz,HPP,OH,NULL,LitArea) -Eterm copy_shallow(Eterm* ERTS_RESTRICT, Uint, Eterm**, ErlOffHeap*); +#define copy_shallow(R, SZ, HPP, OH) \ + copy_shallow_x((R), (SZ), (HPP), (OH)) +Eterm copy_shallow_x(Eterm* ERTS_RESTRICT, Uint, Eterm**, ErlOffHeap*); + +#endif void erts_move_multi_frags(Eterm** hpp, ErlOffHeap*, ErlHeapFragment* first, Eterm* refs, unsigned nrefs, int literals); @@ -1115,6 +1156,7 @@ void erts_dirty_process_main(ErtsSchedulerData *); Eterm build_stacktrace(Process* c_p, Eterm exc); Eterm expand_error_value(Process* c_p, Uint freason, Eterm Value); void erts_save_stacktrace(Process* p, struct StackTrace* s, int depth); +BeamInstr *erts_printable_return_address(Process* p, Eterm *E) ERTS_NOINLINE; /* erl_init.c */ @@ -1257,6 +1299,10 @@ Uint erts_persistent_term_count(void); void erts_init_persistent_dumping(void); extern ErtsLiteralArea** erts_persistent_areas; extern Uint erts_num_persistent_areas; +void erts_debug_foreach_persistent_term_off_heap(void (*func)(ErlOffHeap *, void *), + void *arg); +int erts_debug_have_accessed_literal_area(ErtsLiteralArea *lap); +void erts_debug_save_accessed_literal_area(ErtsLiteralArea *lap); /* external.c */ void erts_init_external(void); diff --git a/erts/emulator/beam/hash.c b/erts/emulator/beam/hash.c index 8954dbb06c..177b7cc3d1 100644 --- a/erts/emulator/beam/hash.c +++ b/erts/emulator/beam/hash.c @@ -30,37 +30,19 @@ #include "hash.h" /* -** List of sizes (all are primes) -*/ -static const int h_size_table[] = { - 2, 5, 11, 23, 47, 97, 197, 397, 797, /* double upto here */ - 1201, 1597, - 2411, 3203, - 4813, 6421, - 9643, 12853, - 19289, 25717, - 51437, - 102877, - 205759, - 411527, - 823117, - 1646237, - 3292489, - 6584983, - 13169977, - 26339969, - 52679969, - -1 -}; - -/* ** Get info about hash ** */ +#define MAX_SHIFT (ERTS_SIZEOF_TERM * 8) + +static int hash_get_slots(Hash *h) { + return UWORD_CONSTANT(1) << (MAX_SHIFT - h->shift); +} + void hash_get_info(HashInfo *hi, Hash *h) { - int size = h->size; + int size = hash_get_slots(h); int i; int max_depth = 0; int objects = 0; @@ -84,7 +66,7 @@ void hash_get_info(HashInfo *hi, Hash *h) ASSERT(objects == h->nobjs); hi->name = h->name; - hi->size = h->size; + hi->size = hash_get_slots(h); hi->used = used; hi->objs = h->nobjs; hi->depth = max_depth; @@ -118,15 +100,15 @@ hash_table_sz(Hash *h) int i; for(i=0;h->name[i];i++); i++; - return sizeof(Hash) + h->size*sizeof(HashBucket*) + i; + return sizeof(Hash) + hash_get_slots(h)*sizeof(HashBucket*) + i; } static ERTS_INLINE void set_thresholds(Hash* h) { - h->grow_threshold = (8*h->size)/5; /* grow at 160% load */ - if (h->size_ix > h->min_size_ix) - h->shrink_threshold = h->size / 5; /* shrink at 20% load */ + h->grow_threshold = (8*hash_get_slots(h))/5; /* grow at 160% load */ + if (h->shift < h->max_shift) + h->shrink_threshold = hash_get_slots(h) / 5; /* shrink at 20% load */ else h->shrink_threshold = -1; /* never shrink below inital size */ } @@ -138,29 +120,27 @@ static ERTS_INLINE void set_thresholds(Hash* h) Hash* hash_init(int type, Hash* h, char* name, int size, HashFunctions fun) { int sz; - int ix = 0; + int shift = 1; h->meta_alloc_type = type; - while (h_size_table[ix] != -1 && h_size_table[ix] < size) - ix++; - if (h_size_table[ix] == -1) - return NULL; - - size = h_size_table[ix]; - sz = size*sizeof(HashBucket*); + while ((UWORD_CONSTANT(1) << shift) < size) + shift++; - h->bucket = (HashBucket**) fun.meta_alloc(h->meta_alloc_type, sz); - - memzero(h->bucket, sz); h->is_allocated = 0; h->name = name; h->fun = fun; - h->size = size; - h->size_ix = ix; - h->min_size_ix = ix; + h->shift = MAX_SHIFT - shift; + h->max_shift = h->shift; h->nobjs = 0; set_thresholds(h); + + sz = hash_get_slots(h) * sizeof(HashBucket*); + h->bucket = (HashBucket**) fun.meta_alloc(h->meta_alloc_type, sz); + memzero(h->bucket, sz); + + ASSERT(h->shift > 0 && h->shift < 64); + return h; } @@ -183,7 +163,7 @@ Hash* hash_new(int type, char* name, int size, HashFunctions fun) */ void hash_delete(Hash* h) { - int old_size = h->size; + int old_size = hash_get_slots(h); int i; for (i = 0; i < old_size; i++) { @@ -206,22 +186,20 @@ void hash_delete(Hash* h) static void rehash(Hash* h, int grow) { int sz; - int old_size = h->size; + int old_size = hash_get_slots(h); HashBucket** new_bucket; int i; if (grow) { - if ((h_size_table[h->size_ix+1]) == -1) - return; - h->size_ix++; + h->shift--; } else { - if (h->size_ix == 0) + if (h->shift == h->max_shift) return; - h->size_ix--; + h->shift++; } - h->size = h_size_table[h->size_ix]; - sz = h->size*sizeof(HashBucket*); + + sz = hash_get_slots(h)*sizeof(HashBucket*); new_bucket = (HashBucket **) h->fun.meta_alloc(h->meta_alloc_type, sz); memzero(new_bucket, sz); @@ -230,7 +208,7 @@ static void rehash(Hash* h, int grow) HashBucket* b = h->bucket[i]; while (b != (HashBucket*) 0) { HashBucket* b_next = b->next; - int ix = b->hvalue % h->size; + Uint ix = hash_get_slot(h, b->hvalue); b->next = new_bucket[ix]; new_bucket[ix] = b; b = b_next; @@ -247,16 +225,7 @@ static void rehash(Hash* h, int grow) */ void* hash_get(Hash* h, void* tmpl) { - HashValue hval = h->fun.hash(tmpl); - int ix = hval % h->size; - HashBucket* b = h->bucket[ix]; - - while(b != (HashBucket*) 0) { - if ((b->hvalue == hval) && (h->fun.cmp(tmpl, (void*)b) == 0)) - return (void*) b; - b = b->next; - } - return (void*) 0; + return hash_fetch(h, tmpl, h->fun.hash, h->fun.cmp); } /* @@ -265,7 +234,7 @@ void* hash_get(Hash* h, void* tmpl) void* hash_put(Hash* h, void* tmpl) { HashValue hval = h->fun.hash(tmpl); - int ix = hval % h->size; + Uint ix = hash_get_slot(h, hval); HashBucket* b = h->bucket[ix]; while(b != (HashBucket*) 0) { @@ -291,7 +260,7 @@ void* hash_put(Hash* h, void* tmpl) void* hash_erase(Hash* h, void* tmpl) { HashValue hval = h->fun.hash(tmpl); - int ix = hval % h->size; + Uint ix = hash_get_slot(h, hval); HashBucket* b = h->bucket[ix]; HashBucket* prev = 0; @@ -323,7 +292,7 @@ void * hash_remove(Hash *h, void *tmpl) { HashValue hval = h->fun.hash(tmpl); - int ix = hval % h->size; + Uint ix = hash_get_slot(h, hval); HashBucket *b = h->bucket[ix]; HashBucket *prev = NULL; @@ -343,11 +312,11 @@ hash_remove(Hash *h, void *tmpl) return NULL; } -void hash_foreach(Hash* h, void (*func)(void *, void *), void *func_arg2) +void hash_foreach(Hash* h, HFOREACH_FUN func, void *func_arg2) { int i; - for (i = 0; i < h->size; i++) { + for (i = 0; i < hash_get_slots(h); i++) { HashBucket* b = h->bucket[i]; while(b != (HashBucket*) 0) { (*func)((void *) b, func_arg2); diff --git a/erts/emulator/beam/hash.h b/erts/emulator/beam/hash.h index d319aaca83..4e8eb6594b 100644 --- a/erts/emulator/beam/hash.h +++ b/erts/emulator/beam/hash.h @@ -18,16 +18,16 @@ * %CopyrightEnd% */ -/* -** General hash functions -** -*/ +/** + * General hash functions + * + **/ #ifndef __HASH_H__ #define __HASH_H__ #include "sys.h" -typedef unsigned long HashValue; +typedef UWord HashValue; typedef struct hash Hash; typedef int (*HCMP_FUN)(void*, void*); @@ -38,6 +38,7 @@ typedef void (*HFREE_FUN)(void*); typedef void* (*HMALLOC_FUN)(int,size_t); typedef void (*HMFREE_FUN)(int,void*); typedef int (*HMPRINT_FUN)(fmtfn_t,void*,char*, ...); +typedef void (*HFOREACH_FUN)(void *, void *); /* ** This bucket must be placed in top of @@ -75,11 +76,10 @@ struct hash int is_allocated; /* 0 iff hash structure is on stack or is static */ int meta_alloc_type; /* argument to pass to meta_alloc and meta_free */ char* name; /* Table name (static string, for debugging) */ - int size; /* Number of slots */ + int shift; /* How much to shift the hash value */ + int max_shift; /* Never shift more than this value */ int shrink_threshold; int grow_threshold; - int size_ix; /* Size index in size table */ - int min_size_ix; /* Never shrink table smaller than this */ int nobjs; /* Number of objects in table */ HashBucket** bucket; /* Vector of bucket pointers (objects) */ }; @@ -96,6 +96,54 @@ void* hash_get(Hash*, void*); void* hash_put(Hash*, void*); void* hash_erase(Hash*, void*); void* hash_remove(Hash*, void*); -void hash_foreach(Hash*, void (*func)(void *, void *), void *); +void hash_foreach(Hash*, HFOREACH_FUN, void *); + +ERTS_GLB_INLINE Uint hash_get_slot(Hash *h, HashValue hv); +ERTS_GLB_INLINE void* hash_fetch(Hash *, void*, H_FUN, HCMP_FUN); + +#if ERTS_GLB_INLINE_INCL_FUNC_DEF + +ERTS_GLB_INLINE Uint +hash_get_slot(Hash *h, HashValue hv) +{ + /* This slot mapping function uses fibonacci hashing in order to + * protect itself against a very bad hash function. This is not + * a hash function, so the user of hash.h should still spend time + * to figure out a good hash function for its data. + * + * See https://probablydance.com/2018/06/16/fibonacci-hashing-the-optimization-that-the-world-forgot-or-a-better-alternative-to-integer-modulo/ + * for some thoughts and ideas about fibonacci hashing. + */ + + /* This is not strictly part of the fibonacci hashing algorithm + * but it does help to spread the values of the mapping function better. + */ + hv ^= hv >> h->shift; +#ifdef ARCH_64 + /* 2^64 / 1.61803398875 = 11400714819323198485.... */ + return (UWORD_CONSTANT(11400714819323198485) * hv) >> h->shift; +#else + /* 2^32 / 1.61803398875 = 2654435769.... */ + return (UWORD_CONSTANT(2654435769) * hv) >> h->shift; +#endif +} + +ERTS_GLB_INLINE void* hash_fetch(Hash *h, void* tmpl, H_FUN hash, HCMP_FUN cmp) +{ + HashValue hval = hash(tmpl); + Uint ix = hash_get_slot(h, hval); + HashBucket* b = h->bucket[ix]; + ASSERT(h->fun.hash == hash); + ASSERT(h->fun.cmp == cmp); + + while(b != (HashBucket*) 0) { + if ((b->hvalue == hval) && (cmp(tmpl, (void*)b) == 0)) + return (void*) b; + b = b->next; + } + return (void*) 0; +} + +#endif /* ERTS_GLB_INLINE_INCL_FUNC_DEF */ #endif diff --git a/erts/emulator/beam/index.c b/erts/emulator/beam/index.c index be1771b037..09d3c24424 100644 --- a/erts/emulator/beam/index.c +++ b/erts/emulator/beam/index.c @@ -114,35 +114,26 @@ int index_get(IndexTable* t, void* tmpl) return -1; } -void erts_index_merge(Hash* src, IndexTable* dst) +static void index_merge_foreach(IndexSlot *p, IndexTable *dst) { - int limit = src->size; - HashBucket** bucket = src->bucket; - int i; - - for (i = 0; i < limit; i++) { - HashBucket* b = bucket[i]; - IndexSlot* p; - int ix; - - while (b) { - Uint sz; - ix = dst->entries++; - if (ix >= dst->size) { - if (ix >= dst->limit) { - erts_exit(ERTS_ERROR_EXIT, "no more index entries in %s (max=%d)\n", - dst->htable.name, dst->limit); - } - sz = INDEX_PAGE_SIZE*sizeof(IndexSlot*); - dst->seg_table[ix>>INDEX_PAGE_SHIFT] = erts_alloc(dst->type, sz); - dst->size += INDEX_PAGE_SIZE; - } - p = (IndexSlot*) b; - p->index = ix; - dst->seg_table[ix>>INDEX_PAGE_SHIFT][ix&INDEX_PAGE_MASK] = p; - b = b->next; - } + Uint sz; + int ix = dst->entries++; + if (ix >= dst->size) { + if (ix >= dst->limit) { + erts_exit(ERTS_ERROR_EXIT, "no more index entries in %s (max=%d)\n", + dst->htable.name, dst->limit); + } + sz = INDEX_PAGE_SIZE*sizeof(IndexSlot*); + dst->seg_table[ix>>INDEX_PAGE_SHIFT] = erts_alloc(dst->type, sz); + dst->size += INDEX_PAGE_SIZE; } + p->index = ix; + dst->seg_table[ix>>INDEX_PAGE_SHIFT][ix&INDEX_PAGE_MASK] = p; +} + +void erts_index_merge(Hash* src, IndexTable* dst) +{ + hash_foreach(src, (HFOREACH_FUN)index_merge_foreach, dst); } void index_erase_latest_from(IndexTable* t, Uint from_ix) diff --git a/erts/emulator/beam/instrs.tab b/erts/emulator/beam/instrs.tab index bc8c1189a8..9396c09182 100644 --- a/erts/emulator/beam/instrs.tab +++ b/erts/emulator/beam/instrs.tab @@ -19,7 +19,12 @@ // %CopyrightEnd% // -// Stack manipulation instructions +// +// Stack manipulation instructions follow. +// +// See the comment for AH() in macros.tab for information about +// the layout of stack frames. +// allocate(NeedStack, Live) { $AH($NeedStack, 0, $Live); @@ -58,105 +63,169 @@ allocate_heap_zero(NeedStack, NeedHeap, Live) { deallocate(Deallocate) { //| -no_prefetch - SET_CP(c_p, (BeamInstr *) cp_val(*E)); E = ADD_BYTE_OFFSET(E, $Deallocate); } -deallocate_return(Deallocate) { - //| -no_next - int words_to_pop = $Deallocate; - SET_I((BeamInstr *) cp_val(*E)); - E = ADD_BYTE_OFFSET(E, words_to_pop); - CHECK_TERM(x(0)); - DispatchReturn; +// +// Micro-benchmarks showed that the deallocate_return instruction +// became slower when the continuation pointer was moved from +// the process struct to the stack. The reason seems to be read +// dependencies, i.e. that the CPU cannot figure out beforehand +// from which position on the stack the continuation pointer +// should be fetched. +// +// Initializing num_bytes with a constant value seems to restore +// the lost speed, so we've specialized the instruction for the +// most common values. +// + +deallocate_return0 := dealloc_ret.n0.execute; +deallocate_return1 := dealloc_ret.n1.execute; +deallocate_return2 := dealloc_ret.n2.execute; +deallocate_return3 := dealloc_ret.n3.execute; +deallocate_return4 := dealloc_ret.n4.execute; +deallocate_return := dealloc_ret.var.execute; + +dealloc_ret.head() { + Uint num_bytes; } -move_deallocate_return(Src, Deallocate) { - x(0) = $Src; - $deallocate_return($Deallocate); +dealloc_ret.n0() { + num_bytes = (0+1) * sizeof(Eterm); } -// Call instructions +dealloc_ret.n1() { + num_bytes = (1+1) * sizeof(Eterm); +} + +dealloc_ret.n2() { + num_bytes = (2+1) * sizeof(Eterm); +} + +dealloc_ret.n3() { + num_bytes = (3+1) * sizeof(Eterm); +} + +dealloc_ret.n4() { + num_bytes = (4+1) * sizeof(Eterm); +} + +dealloc_ret.var(Deallocate) { + num_bytes = $Deallocate; +} -DISPATCH_REL(CallDest) { +dealloc_ret.execute() { //| -no_next - $SET_I_REL($CallDest); - DTRACE_LOCAL_CALL(c_p, erts_code_to_codemfa(I)); - Dispatch(); + + E = ADD_BYTE_OFFSET(E, num_bytes); + $RETURN(); + CHECK_TERM(x(0)); + $DISPATCH_RETURN(); } -DISPATCH_ABS(CallDest) { +move_deallocate_return(Src, Deallocate) { //| -no_next - SET_I((BeamInstr *) $CallDest); - DTRACE_LOCAL_CALL(c_p, erts_code_to_codemfa(I)); - Dispatch(); + + /* + * Explicitly do reads first to mitigate the impact of read + * dependencies. + */ + + Uint bytes_to_pop = $Deallocate; + Eterm src = $Src; + E = ADD_BYTE_OFFSET(E, bytes_to_pop); + x(0) = src; + $RETURN(); + CHECK_TERM(x(0)); + $DISPATCH_RETURN(); } +// Call instructions + i_call(CallDest) { - SET_CP(c_p, $NEXT_INSTRUCTION); + //| -no_next + $SAVE_CONTINUATION_POINTER($NEXT_INSTRUCTION); $DISPATCH_REL($CallDest); } move_call(Src, CallDest) { - x(0) = $Src; - SET_CP(c_p, $NEXT_INSTRUCTION); - $DISPATCH_REL($CallDest); + //| -no_next + Eterm call_dest = $CallDest; + Eterm src = $Src; + $SAVE_CONTINUATION_POINTER($NEXT_INSTRUCTION); + x(0) = src; + $DISPATCH_REL(call_dest); } i_call_last(CallDest, Deallocate) { + //| -no_next $deallocate($Deallocate); $DISPATCH_REL($CallDest); } move_call_last(Src, CallDest, Deallocate) { - x(0) = $Src; - $i_call_last($CallDest, $Deallocate); + //| -no_next + Eterm call_dest = $CallDest; + Eterm src = $Src; + $deallocate($Deallocate); + x(0) = src; + $DISPATCH_REL(call_dest); } i_call_only(CallDest) { + //| -no_next $DISPATCH_REL($CallDest); } move_call_only(Src, CallDest) { - x(0) = $Src; - $i_call_only($CallDest); -} - -DISPATCHX(Dest) { //| -no_next - DTRACE_GLOBAL_CALL_FROM_EXPORT(c_p, $Dest); - // Dispatchx assumes the Export* is in Arg(0) - I = (&$Dest) - 1; - Dispatchx(); + Eterm call_dest = $CallDest; + Eterm src = $Src; + x(0) = src; + $DISPATCH_REL(call_dest); } i_call_ext(Dest) { - SET_CP(c_p, $NEXT_INSTRUCTION); - $DISPATCHX($Dest); + //| -no_next + $SAVE_CONTINUATION_POINTER($NEXT_INSTRUCTION); + $DISPATCH_EXPORT($Dest); } -i_move_call_ext(Src, Dest) { - x(0) = $Src; - $i_call_ext($Dest); +i_move_call_ext(Src, CallDest) { + //| -no_next + Eterm call_dest = $CallDest; + Eterm src = $Src; + $SAVE_CONTINUATION_POINTER($NEXT_INSTRUCTION); + x(0) = src; + $DISPATCH_EXPORT(call_dest); } i_call_ext_only(Dest) { - $DISPATCHX($Dest); + //| -no_next + $DISPATCH_EXPORT($Dest); } -i_move_call_ext_only(Dest, Src) { - x(0) = $Src; - $i_call_ext_only($Dest); +i_move_call_ext_only(CallDest, Src) { + //| -no_next + Eterm call_dest = $CallDest; + Eterm src = $Src; + x(0) = src; + $DISPATCH_EXPORT(call_dest); } i_call_ext_last(Dest, Deallocate) { + //| -no_next $deallocate($Deallocate); - $DISPATCHX($Dest); + $DISPATCH_EXPORT($Dest); } -i_move_call_ext_last(Dest, StackOffset, Src) { - x(0) = $Src; - $i_call_ext_last($Dest, $StackOffset); +i_move_call_ext_last(CallDest, Deallocate, Src) { + //| -no_next + Eterm call_dest = $CallDest; + Eterm src = $Src; + $deallocate($Deallocate); + x(0) = src; + $DISPATCH_EXPORT(call_dest); } APPLY(I, Deallocate, Next) { @@ -172,16 +241,18 @@ HANDLE_APPLY_ERROR() { } i_apply() { + //| -no_next BeamInstr *next; $APPLY(NULL, 0, next); if (ERTS_LIKELY(next != NULL)) { - SET_CP(c_p, $NEXT_INSTRUCTION); + $SAVE_CONTINUATION_POINTER($NEXT_INSTRUCTION); $DISPATCH_ABS(next); } $HANDLE_APPLY_ERROR(); } i_apply_last(Deallocate) { + //| -no_next BeamInstr *next; $APPLY(I, $Deallocate, next); if (ERTS_LIKELY(next != NULL)) { @@ -192,6 +263,7 @@ i_apply_last(Deallocate) { } i_apply_only() { + //| -no_next BeamInstr *next; $APPLY(I, 0, next); if (ERTS_LIKELY(next != NULL)) { @@ -208,16 +280,18 @@ FIXED_APPLY(Arity, I, Deallocate, Next) { } apply(Arity) { + //| -no_next BeamInstr *next; $FIXED_APPLY($Arity, NULL, 0, next); if (ERTS_LIKELY(next != NULL)) { - SET_CP(c_p, $NEXT_INSTRUCTION); + $SAVE_CONTINUATION_POINTER($NEXT_INSTRUCTION); $DISPATCH_ABS(next); } $HANDLE_APPLY_ERROR(); } apply_last(Arity, Deallocate) { + //| -no_next BeamInstr *next; $FIXED_APPLY($Arity, I, $Deallocate, next); if (ERTS_LIKELY(next != NULL)) { @@ -237,23 +311,19 @@ HANDLE_APPLY_FUN_ERROR() { goto find_func_info; } -DISPATCH_FUN(I) { - //| -no_next - SET_I($I); - Dispatchfun(); -} - i_apply_fun() { + //| -no_next BeamInstr *next; $APPLY_FUN(next); if (ERTS_LIKELY(next != NULL)) { - SET_CP(c_p, $NEXT_INSTRUCTION); + $SAVE_CONTINUATION_POINTER($NEXT_INSTRUCTION); $DISPATCH_FUN(next); } $HANDLE_APPLY_FUN_ERROR(); } i_apply_fun_last(Deallocate) { + //| -no_next BeamInstr *next; $APPLY_FUN(next); if (ERTS_LIKELY(next != NULL)) { @@ -264,6 +334,7 @@ i_apply_fun_last(Deallocate) { } i_apply_fun_only() { + //| -no_next BeamInstr *next; $APPLY_FUN(next); if (ERTS_LIKELY(next != NULL)) { @@ -280,16 +351,18 @@ CALL_FUN(Fun, Next) { } i_call_fun(Fun) { + //| -no_next BeamInstr *next; $CALL_FUN($Fun, next); if (ERTS_LIKELY(next != NULL)) { - SET_CP(c_p, $NEXT_INSTRUCTION); + $SAVE_CONTINUATION_POINTER($NEXT_INSTRUCTION); $DISPATCH_FUN(next); } $HANDLE_APPLY_FUN_ERROR(); } i_call_fun_last(Fun, Deallocate) { + //| -no_next BeamInstr *next; $CALL_FUN($Fun, next); if (ERTS_LIKELY(next != NULL)) { @@ -301,18 +374,13 @@ i_call_fun_last(Fun, Deallocate) { return() { //| -no_next - SET_I(c_p->cp); - DTRACE_RETURN_FROM_PC(c_p); + $RETURN(); - /* - * We must clear the CP to make sure that a stale value do not - * create a false module dependcy preventing code upgrading. - * It also means that we can use the CP in stack backtraces. - */ - c_p->cp = 0; + DTRACE_RETURN_FROM_PC(c_p); CHECK_TERM(r(0)); HEAP_SPACE_VERIFIED(0); - DispatchReturn; + + $DISPATCH_RETURN(); } get_list(Src, Hd, Tl) { @@ -478,16 +546,21 @@ i_make_fun(FunP, NumFree) { } move_trim(Src, Dst, Words) { - Uint cp = E[0]; $Dst = $Src; - E += $Words; - E[0] = cp; + $i_trim($Words); } i_trim(Words) { - Uint cp = E[0]; E += $Words; - E[0] = cp; + + /* + * Clear the reserved location for the continuation pointer at + * E[0]. This is not strictly necessary for correctness, but if a + * GC is triggered before E[0] is overwritten by another + * continuation pointer the now dead term at E[0] would be + * retained by the GC. + */ + E[0] = NIL; } move(Src, Dst) { @@ -599,9 +672,8 @@ move_window5(S1, S2, S3, S4, S5, D) { move_return(Src) { //| -no_next x(0) = $Src; - SET_I(c_p->cp); - c_p->cp = 0; - DispatchReturn; + $RETURN(); + $DISPATCH_RETURN(); } move_x1(Src) { diff --git a/erts/emulator/beam/io.c b/erts/emulator/beam/io.c index 45fef0c0e5..1622330aab 100644 --- a/erts/emulator/beam/io.c +++ b/erts/emulator/beam/io.c @@ -3243,7 +3243,10 @@ static void deliver_read_message(Port* prt, erts_aint32_t state, Eterm to, need += 3; } if ((state & ERTS_PORT_SFLG_BINARY_IO) && buf != NULL) { - need += PROC_BIN_SIZE; + if (len <= ERL_ONHEAP_BIN_LIMIT) + need += heap_bin_size(len); + else + need += PROC_BIN_SIZE; } else { need += 2*len; } @@ -3261,11 +3264,21 @@ static void deliver_read_message(Port* prt, erts_aint32_t state, Eterm to, if ((state & ERTS_PORT_SFLG_BINARY_IO) == 0) { listp = buf_to_intlist(&hp, buf, len, listp); } else if (buf != NULL) { - Binary* bptr = erts_bin_nrml_alloc(len); - sys_memcpy(bptr->orig_bytes, buf, len); + if (len <= ERL_ONHEAP_BIN_LIMIT) { + ErlHeapBin *hbin = (ErlHeapBin *) hp; + hbin->thing_word = header_heap_bin(len); + hbin->size = (Uint) len; + sys_memcpy(hbin->data, buf, len); + listp = make_binary(hp); + hp += heap_bin_size(len); + } + else { + Binary* bptr = erts_bin_nrml_alloc(len); + sys_memcpy(bptr->orig_bytes, buf, len); - listp = erts_build_proc_bin(ohp, hp, bptr); - hp += PROC_BIN_SIZE; + listp = erts_build_proc_bin(ohp, hp, bptr); + hp += PROC_BIN_SIZE; + } } /* Prepend the header */ @@ -3388,7 +3401,14 @@ deliver_vec_message(Port* prt, /* Port */ need = 3 + 3; /* Heap space for two tuples */ if (state & ERTS_PORT_SFLG_BINARY_IO) { - need += (2+PROC_BIN_SIZE)*vsize - 2 + hlen*2; + Sint i; + for (i = 0; i < vsize; i++) { + if (iov[i].iov_len <= ERL_ONHEAP_BIN_LIMIT) + need += heap_bin_size(iov[i].iov_len); + else + need += PROC_BIN_SIZE; + } + need += (vsize - 1)*2 + hlen*2; } else { need += (hlen+csize)*2; } @@ -3408,36 +3428,52 @@ deliver_vec_message(Port* prt, /* Port */ } else { binv += vsize; while (vsize--) { - ErlDrvBinary* b; - ProcBin* pb = (ProcBin*) hp; - byte* base; - - iov--; - binv--; - if ((b = *binv) == NULL) { - b = driver_alloc_binary(iov->iov_len); - sys_memcpy(b->orig_bytes, iov->iov_base, iov->iov_len); - base = (byte*) b->orig_bytes; - } else { - /* Must increment reference count, caller calls free */ - driver_binary_inc_refc(b); - base = iov->iov_base; - } - pb->thing_word = HEADER_PROC_BIN; - pb->size = iov->iov_len; - pb->next = ohp->first; - ohp->first = (struct erl_off_heap_header*)pb; - pb->val = ErlDrvBinary2Binary(b); - pb->bytes = base; - pb->flags = 0; - hp += PROC_BIN_SIZE; + Eterm bin; + Uint bin_size; + iov--; + binv--; + bin_size = (Uint) iov->iov_len; + + if (bin_size <= ERL_ONHEAP_BIN_LIMIT) { + ErlHeapBin *hbin = (ErlHeapBin *) hp; + hbin->thing_word = header_heap_bin(bin_size); + hbin->size = bin_size; + sys_memcpy(hbin->data, iov->iov_base, bin_size); + bin = make_binary(hp); + hp += heap_bin_size(bin_size); + } + else { + ErlDrvBinary* b; + ProcBin* pb = (ProcBin*) hp; + byte* base; + + if ((b = *binv) == NULL) { + b = driver_alloc_binary(bin_size); + sys_memcpy(b->orig_bytes, iov->iov_base, bin_size); + base = (byte*) b->orig_bytes; + } else { + /* Must increment reference count, caller calls free */ + driver_binary_inc_refc(b); + base = iov->iov_base; + } + pb->thing_word = HEADER_PROC_BIN; + pb->size = bin_size; + pb->next = ohp->first; + ohp->first = (struct erl_off_heap_header*)pb; + pb->val = ErlDrvBinary2Binary(b); + pb->bytes = base; + pb->flags = 0; + hp += PROC_BIN_SIZE; - OH_OVERHEAD(ohp, iov->iov_len / sizeof(Eterm)); + OH_OVERHEAD(ohp, bin_size / sizeof(Eterm)); + + bin = make_binary(pb); + } if (listp == NIL) { /* compatible with deliver_bin_message */ - listp = make_binary(pb); + listp = bin; } else { - listp = CONS(hp, make_binary(pb), listp); + listp = CONS(hp, bin, listp); hp += 2; } } diff --git a/erts/emulator/beam/macros.tab b/erts/emulator/beam/macros.tab index 1b5e5f66b0..848e35d45c 100644 --- a/erts/emulator/beam/macros.tab +++ b/erts/emulator/beam/macros.tab @@ -104,14 +104,136 @@ GC_TEST_PRESERVE(NeedHeap, Live, PreserveTerm) { // Make sure that there are NeedStack + NeedHeap + 1 words available -// on the combined heap/stack segment, then allocates NeedHeap + 1 -// words on the stack and saves CP. +// on the combined heap/stack segment, then decrement the stack +// pointer by (NeedStack + 1) words. Finally clear the word reserved +// for the continuation pointer at the top of the stack. +// +// Stack frame layout: +// +// +-----------+ +// y(N) | Term | +// +-----------+ +// . +// . +// . +// +-----------+ +// y(0) | Term | +// +-----------+ +// E ==> | NIL or CP | +// +-----------+ +// +// When the function owning the stack frame is the currently executing +// function, the word at the top of the stack is NIL. When calling +// another function, the continuation pointer will be stored in the +// word at the top of the stack. When returning to the function +// owning the stack frame, the word at the stack top will again be set +// to NIL. + AH(NeedStack, NeedHeap, Live) { unsigned needed = $NeedStack + 1; $GC_TEST(needed, $NeedHeap, $Live); E -= needed; - *E = make_cp(c_p->cp); - c_p->cp = 0; + *E = NIL; +} + + +// +// Helpers for call instructions +// + +DISPATCH() { + BeamInstr dis_next; + + dis_next = *I; + CHECK_ARGS(I); + + if (FCALLS > 0 || FCALLS > neg_o_reds) { + FCALLS--; + Goto(dis_next); + } else { + goto context_switch; + } +} + +DISPATCH_ABS(CallDest) { + SET_I((BeamInstr *) $CallDest); + DTRACE_LOCAL_CALL(c_p, erts_code_to_codemfa(I)); + + $DISPATCH(); +} + +DISPATCH_EXPORT(Export) { + BeamInstr dis_next; + Export *ep; + + ep = (Export*)($Export); + + DTRACE_GLOBAL_CALL_FROM_EXPORT(c_p, ep); + + SET_I(ep->addressv[erts_active_code_ix()]); + CHECK_ARGS(I); + dis_next = *I; + + if (ERTS_UNLIKELY(FCALLS <= 0)) { + if (ERTS_PROC_GET_SAVED_CALLS_BUF(c_p) && FCALLS > neg_o_reds) { + save_calls(c_p, ep); + } else { + goto context_switch; + } + } + + FCALLS--; + Goto(dis_next); +} + +DISPATCH_FUN(I) { + BeamInstr dis_next; + + SET_I($I); + + dis_next = *I; + CHECK_ARGS(I); + + if (FCALLS > 0 || FCALLS > neg_o_reds) { + FCALLS--; + Goto(dis_next); + } else { + goto context_switch_fun; + } +} + +DISPATCH_REL(CallDest) { + $SET_I_REL($CallDest); + DTRACE_LOCAL_CALL(c_p, erts_code_to_codemfa(I)); + + $DISPATCH(); +} + +DISPATCH_RETURN() { + if (FCALLS > 0 || FCALLS > neg_o_reds) { + FCALLS--; + Goto(*I); + } else { + c_p->current = NULL; + c_p->arity = 1; + goto context_switch3; + } +} + +// Save the continuation pointer in the reserved slot at the +// top of the stack as preparation for doing a function call. + +SAVE_CONTINUATION_POINTER(IP) { + ASSERT(VALID_INSTR(*($IP))); + *E = (BeamInstr) ($IP); +} + +// Return to the function whose continuation pointer is stored +// at the top of the stack and set that word to NIL. + +RETURN() { + SET_I(cp_val(*E)); + *E = NIL; } NEXT0() { diff --git a/erts/emulator/beam/ops.tab b/erts/emulator/beam/ops.tab index f525d126e7..1d336e4b7b 100644 --- a/erts/emulator/beam/ops.tab +++ b/erts/emulator/beam/ops.tab @@ -77,19 +77,32 @@ return # To ensure that a "move Src x(0)" instruction can be combined with # the following call instruction, we need to make sure that there is # no line/1 instruction between the move and the call. -# -# A tail-recursive call to an external function (BIF or non-BIF) will -# never be saved on the stack, so there is no reason to keep the line -# instruction. + +move S X0=x==0 | line Loc | call Ar Func => \ + line Loc | move S X0 | call Ar Func move S X0=x==0 | line Loc | call_ext Ar Func => \ line Loc | move S X0 | call_ext Ar Func + +# +# A tail call will not refer to the current function on error unless it's a +# BIF, so we can omit the line instruction for non-BIFs. +# + +move S X0=x==0 | line Loc | call_ext_last Ar Func=u$is_bif D => \ + line Loc | move S X0 | call_ext_last Ar Func D +move S X0=x==0 | line Loc | call_ext_only Ar Func=u$is_bif => \ + line Loc | move S X0 | call_ext_only Ar Func + move S X0=x==0 | line Loc | call_ext_last Ar Func D => \ move S X0 | call_ext_last Ar Func D move S X0=x==0 | line Loc | call_ext_only Ar Func => \ move S X0 | call_ext_only Ar Func -move S X0=x==0 | line Loc | call Ar Func => \ - line Loc | move S X0 | call Ar Func + +move S X0=x==0 | line Loc | call_last Ar Func D => \ + move S X0 | call_last Ar Func D +move S X0=x==0 | line Loc | call_only Ar Func => \ + move S X0 | call_only Ar Func line Loc | func_info M F A => func_info M F A | line Loc @@ -574,8 +587,8 @@ put_list s s d %cold normal_exit continue_exit -apply_bif -call_nif +call_bif W +call_nif W W W call_error_handler error_action_code return_trace @@ -596,8 +609,20 @@ move S x==0 | deallocate D | return => move_deallocate_return S D move_deallocate_return xycn Q +deallocate u==0 | return => deallocate_return0 +deallocate u==1 | return => deallocate_return1 +deallocate u==2 | return => deallocate_return2 +deallocate u==3 | return => deallocate_return3 +deallocate u==4 | return => deallocate_return4 + deallocate D | return => deallocate_return D +deallocate_return0 +deallocate_return1 +deallocate_return2 +deallocate_return3 +deallocate_return4 + deallocate_return Q test_heap Need u==1 | put_list Y=y x==0 x==0 => test_heap_1_put_list Need Y @@ -775,62 +800,22 @@ allocate_init t t? y # External function and bif calls. ################################################################# -# -# The BIFs erts_internal:check_process_code/1 must be called like a function, -# to ensure that c_p->i (program counter) is set correctly (an ordinary -# BIF call doesn't set it). -# - -call_ext u==1 Bif=u$bif:erts_internal:check_process_code/1 => i_call_ext Bif -call_ext_last u==1 Bif=u$bif:erts_internal:check_process_code/1 D => i_call_ext_last Bif D -call_ext_only u==1 Bif=u$bif:erts_internal:check_process_code/1 => i_call_ext_only Bif - -# -# The BIFs erts_internal:garbage_collect/1 must be called like a function, -# to allow them to invoke the garbage collector. (The stack pointer must -# be saved and p->arity must be zeroed, which is not done on ordinary BIF calls.) -# -call_ext u==1 Bif=u$bif:erts_internal:garbage_collect/1 => i_call_ext Bif -call_ext_last u==1 Bif=u$bif:erts_internal:garbage_collect/1 D => i_call_ext_last Bif D -call_ext_only u==1 Bif=u$bif:erts_internal:garbage_collect/1 => i_call_ext_only Bif - -# -# put/2 and erase/1 must be able to do garbage collection, so we must call -# them like functions. -# - -call_ext u==2 Bif=u$bif:erlang:put/2 => i_call_ext Bif -call_ext_last u==2 Bif=u$bif:erlang:put/2 D => i_call_ext_last Bif D -call_ext_only u==2 Bif=u$bif:erlang:put/2 => i_call_ext_only Bif - -call_ext u==1 Bif=u$bif:erlang:erase/1 => i_call_ext Bif -call_ext_last u==1 Bif=u$bif:erlang:erase/1 D => i_call_ext_last Bif D -call_ext_only u==1 Bif=u$bif:erlang:erase/1 => i_call_ext_only Bif +# Expands into call_light_bif(_only)/2 +call_light_bif/1 +call_light_bif_only/1 +call_light_bif_last/2 # -# The process_info/1,2 BIF should be called like a function, to force -# the emulator to set c_p->current before calling it (a BIF call doesn't -# set it). +# The load_nif/2 BIF is an instruction. # -# In addition, we force the use of a non-tail-recursive call. This will ensure -# that c_p->cp points into the function making the call. -# - -call_ext u==1 Bif=u$bif:erlang:process_info/1 => i_call_ext Bif -call_ext_last u==1 Bif=u$bif:erlang:process_info/1 D => i_call_ext Bif | deallocate_return D -call_ext_only Ar=u==1 Bif=u$bif:erlang:process_info/1 => allocate u Ar | i_call_ext Bif | deallocate_return u -call_ext u==2 Bif=u$bif:erlang:process_info/2 => i_call_ext Bif -call_ext_last u==2 Bif=u$bif:erlang:process_info/2 D => i_call_ext Bif | deallocate_return D -call_ext_only Ar=u==2 Bif=u$bif:erlang:process_info/2 => allocate u Ar | i_call_ext Bif | deallocate_return u - -# -# load_nif/2 also needs to know calling function like process_info -# -call_ext u==2 Bif=u$bif:erlang:load_nif/2 => i_call_ext Bif -call_ext_last u==2 Bif=u$bif:erlang:load_nif/2 D => i_call_ext Bif | deallocate_return D -call_ext_only Ar=u==2 Bif=u$bif:erlang:load_nif/2 => allocate u Ar | i_call_ext Bif | deallocate_return u +call_ext u==2 u$func:erlang:load_nif/2 => i_load_nif +call_ext_last u==2 u$func:erlang:load_nif/2 D => i_load_nif | deallocate_return D +call_ext_only u==2 u$func:erlang:load_nif/2 => i_load_nif | return +%cold +i_load_nif +%hot # # apply/2 is an instruction, not a BIF. @@ -849,33 +834,6 @@ call_ext_last u==3 u$bif:erlang:apply/3 D => i_apply_last D call_ext_only u==3 u$bif:erlang:apply/3 => i_apply_only # -# The exit/1 and throw/1 BIFs never execute the instruction following them; -# thus there is no need to generate any return instruction. -# - -call_ext_last u==1 Bif=u$bif:erlang:exit/1 D => call_bif Bif -call_ext_last u==1 Bif=u$bif:erlang:throw/1 D => call_bif Bif - -call_ext_only u==1 Bif=u$bif:erlang:exit/1 => call_bif Bif -call_ext_only u==1 Bif=u$bif:erlang:throw/1 => call_bif Bif - -# -# The error/1 and error/2 BIFs never execute the instruction following them; -# thus there is no need to generate any return instruction. -# However, they generate stack backtraces, so if the call instruction -# is call_ext_only/2 instruction, we explicitly do an allocate/2 to store -# the continuation pointer on the stack. -# - -call_ext_last u==1 Bif=u$bif:erlang:error/1 D => call_bif Bif -call_ext_last u==2 Bif=u$bif:erlang:error/2 D => call_bif Bif - -call_ext_only Ar=u==1 Bif=u$bif:erlang:error/1 => \ - allocate u Ar | call_bif Bif -call_ext_only Ar=u==2 Bif=u$bif:erlang:error/2 => \ - allocate u Ar | call_bif Bif - -# # The yield/0 BIF is an instruction # @@ -987,17 +945,24 @@ call_ext_only u==0 u$func:os:perf_counter/0 => \ i_perf_counter | return # -# The general case for BIFs that have no special instructions. -# A BIF used in the tail must be followed by a return instruction. +# BIFs like process_info/1,2 require up-to-date information about the current +# emulator state, which the ordinary call_light_bif instruction doesn't save. # -# To make trapping and stack backtraces work correctly, we make sure that -# the continuation pointer is always stored on the stack. -call_ext u Bif=u$is_bif => call_bif Bif +call_ext u Bif=u$is_bif | is_heavy_bif(Bif) => \ + i_call_ext Bif +call_ext_last u Bif=u$is_bif D | is_heavy_bif(Bif) => \ + i_call_ext Bif | deallocate_return D +call_ext_only Ar=u Bif=u$is_bif | is_heavy_bif(Bif) => \ + allocate u Ar | i_call_ext Bif | deallocate_return u -call_ext_last u Bif=u$is_bif D => deallocate D | call_bif_only Bif +# +# The general case for BIFs that have no special requirements. +# -call_ext_only Ar=u Bif=u$is_bif => call_bif_only Bif +call_ext u Bif=u$is_bif => call_light_bif Bif +call_ext_last u Bif=u$is_bif D => call_light_bif_last Bif D +call_ext_only Ar=u Bif=u$is_bif => call_light_bif_only Bif # # Any remaining calls are calls to Erlang functions, not BIFs. @@ -1022,14 +987,32 @@ i_apply_fun i_apply_fun_last Q i_apply_fun_only +# +# When a BIF is traced, these instructions make a body call through the export +# entry instead of calling the BIF directly (setting up a temporary stack frame +# if needed). We therefore retain the stack frame in call_light_bif_last, and +# add a deallocate_return after call_light_bif_only to remove the temporary +# stack frame before returning. +# + +call_light_bif Bif=u$is_bif => \ + call_light_bif Bif Bif + +call_light_bif_last Bif=u$is_bif D => \ + call_light_bif Bif Bif | deallocate_return D + +call_light_bif_only Bif=u$is_bif => \ + call_light_bif_only Bif Bif | deallocate_return u + +call_light_bif b e +call_light_bif_only b e + %cold -i_hibernate +i_hibernate i_perf_counter -%hot -call_bif e -call_bif_only e +%hot # # Calls to non-building and guard BIFs. diff --git a/erts/emulator/beam/register.c b/erts/emulator/beam/register.c index c7e02c6d48..8e44b527a2 100644 --- a/erts/emulator/beam/register.c +++ b/erts/emulator/beam/register.c @@ -265,10 +265,8 @@ Eterm erts_whereis_name_to_id(Process *c_p, Eterm name) { Eterm res = am_undefined; - HashValue hval; - int ix; - HashBucket* b; ErtsProcLocks c_p_locks = 0; + RegProc *rp, tmpl; if (c_p) { c_p_locks = ERTS_PROC_LOCK_MAIN; ERTS_CHK_HAVE_ONLY_MAIN_PROC_LOCK(c_p); @@ -278,29 +276,14 @@ erts_whereis_name_to_id(Process *c_p, Eterm name) if (c_p && !c_p_locks) erts_proc_lock(c_p, ERTS_PROC_LOCK_MAIN); - hval = REG_HASH(name); - ix = hval % process_reg.size; - b = process_reg.bucket[ix]; + tmpl.name = name; + rp = hash_fetch(&process_reg, &tmpl, (H_FUN)reg_hash, (HCMP_FUN)reg_cmp); - /* - * Note: We have inlined the code from hash.c for speed. - */ - - while (b) { - RegProc* rp = (RegProc *) b; - if (rp->name == name) { - /* - * SMP NOTE: No need to lock registered entity since it cannot - * be removed without acquiring write reg lock and id on entity - * is read only. - */ - if (rp->p) - res = rp->p->common.id; - else if (rp->pt) - res = rp->pt->common.id; - break; - } - b = b->next; + if (rp) { + if (rp->p) + res = rp->p->common.id; + else if (rp->pt) + res = rp->pt->common.id; } reg_read_unlock(); @@ -321,10 +304,7 @@ erts_whereis_name(Process *c_p, Port** port, int lock_port) { - RegProc* rp = NULL; - HashValue hval; - int ix; - HashBucket* b; + RegProc* rp = NULL, tmpl; ErtsProcLocks current_c_p_locks; Port *pending_port = NULL; @@ -342,21 +322,8 @@ erts_whereis_name(Process *c_p, * - current_c_p_locks (either c_p_locks or 0) on c_p */ - hval = REG_HASH(name); - ix = hval % process_reg.size; - b = process_reg.bucket[ix]; - - /* - * Note: We have inlined the code from hash.c for speed. - */ - - while (b) { - if (((RegProc *) b)->name == name) { - rp = (RegProc *) b; - break; - } - b = b->next; - } + tmpl.name = name; + rp = hash_fetch(&process_reg, &tmpl, (H_FUN)reg_hash, (HCMP_FUN)reg_cmp); if (proc) { if (!rp) @@ -564,18 +531,6 @@ int erts_unregister_name(Process *c_p, return res; } -int process_reg_size(void) -{ - int size; - int lock = !ERTS_IS_CRASH_DUMPING; - if (lock) - reg_read_lock(); - size = process_reg.size; - if (lock) - reg_read_unlock(); - return size; -} - int process_reg_sz(void) { int sz; @@ -592,15 +547,24 @@ int process_reg_sz(void) #include "bif.h" +struct registered_foreach_arg { + Eterm res; + Eterm *hp; +}; + +static void +registered_foreach(RegProc *reg, struct registered_foreach_arg *arg) +{ + arg->res = CONS(arg->hp, reg->name, arg->res); + arg->hp += 2; +} + /* return a list of the registered processes */ BIF_RETTYPE registered_0(BIF_ALIST_0) { - int i; - Eterm res; + struct registered_foreach_arg arg; Uint need; - Eterm* hp; - HashBucket **bucket; ErtsProcLocks proc_locks = ERTS_PROC_LOCK_MAIN; ERTS_CHK_HAVE_ONLY_MAIN_PROC_LOCK(BIF_P); @@ -608,41 +572,21 @@ BIF_RETTYPE registered_0(BIF_ALIST_0) if (!proc_locks) erts_proc_lock(BIF_P, ERTS_PROC_LOCK_MAIN); - bucket = process_reg.bucket; - - /* work out how much heap we need & maybe garb, by scanning through - the registered process table */ - need = 0; - for (i = 0; i < process_reg.size; i++) { - HashBucket *b = bucket[i]; - while (b != NULL) { - need += 2; - b = b->next; - } - } + /* work out how much heap we need */ + need = process_reg.nobjs * 2; if (need == 0) { reg_read_unlock(); BIF_RET(NIL); } - hp = HAlloc(BIF_P, need); - - /* scan through again and make the list */ - res = NIL; + /* scan through again and make the list */ + arg.hp = HAlloc(BIF_P, need); + arg.res = NIL; - for (i = 0; i < process_reg.size; i++) { - HashBucket *b = bucket[i]; - while (b != NULL) { - RegProc *reg = (RegProc *) b; - - res = CONS(hp, reg->name, res); - hp += 2; - b = b->next; - } - } + hash_foreach(&process_reg, (HFOREACH_FUN)registered_foreach, &arg); reg_read_unlock(); - BIF_RET(res); + BIF_RET(arg.res); } diff --git a/erts/emulator/beam/register.h b/erts/emulator/beam/register.h index 27a314ca78..c77bd03653 100644 --- a/erts/emulator/beam/register.h +++ b/erts/emulator/beam/register.h @@ -41,7 +41,6 @@ typedef struct reg_proc Eterm name; /* Atom name */ } RegProc; -int process_reg_size(void); int process_reg_sz(void); void init_register_table(void); void register_info(fmtfn_t, void *); diff --git a/erts/emulator/beam/sys.h b/erts/emulator/beam/sys.h index db07512cf7..8a59b61b63 100644 --- a/erts/emulator/beam/sys.h +++ b/erts/emulator/beam/sys.h @@ -673,7 +673,16 @@ typedef struct preload { */ typedef Eterm ErtsTracer; -#include "erl_osenv.h" + +/* + * This structure contains the rb tree for the erlang osenv copy + * see erl_osenv.h for more details. + */ +typedef struct __erts_osenv_t { + struct __env_rbtnode_t *tree; + int variable_count; + int content_size; +} erts_osenv_t; /* * This structure contains options to all built in drivers. diff --git a/erts/emulator/beam/trace_instrs.tab b/erts/emulator/beam/trace_instrs.tab index 3eee81c053..9f22587f96 100644 --- a/erts/emulator/beam/trace_instrs.tab +++ b/erts/emulator/beam/trace_instrs.tab @@ -20,16 +20,15 @@ // return_trace() { - ErtsCodeMFA* mfa = (ErtsCodeMFA *)(E[0]); + ErtsCodeMFA* mfa = (ErtsCodeMFA *)(E[1]); SWAPOUT; /* Needed for shared heap */ ERTS_UNREQ_PROC_MAIN_LOCK(c_p); - erts_trace_return(c_p, mfa, r(0), ERTS_TRACER_FROM_ETERM(E+1)/* tracer */); + erts_trace_return(c_p, mfa, r(0), ERTS_TRACER_FROM_ETERM(E+2)/* tracer */); ERTS_REQ_PROC_MAIN_LOCK(c_p); SWAPIN; - c_p->cp = NULL; - SET_I((BeamInstr *) cp_val(E[2])); E += 3; + $RETURN(); Goto(*I); //| -no_next } @@ -45,13 +44,12 @@ i_generic_breakpoint() { } i_return_time_trace() { - BeamInstr *pc = (BeamInstr *) (UWord) E[0]; + BeamInstr *pc = (BeamInstr *) (UWord) E[1]; SWAPOUT; erts_trace_time_return(c_p, erts_code_to_codeinfo(pc)); SWAPIN; - c_p->cp = NULL; - SET_I((BeamInstr *) cp_val(E[1])); E += 2; + $RETURN(); Goto(*I); //| -no_next } @@ -59,8 +57,10 @@ i_return_time_trace() { i_return_to_trace() { if (IS_TRACED_FL(c_p, F_TRACE_RETURN_TO)) { Uint *cpp = (Uint*) E; + while (is_not_CP(*cpp)) { + cpp++; + } for(;;) { - ASSERT(is_CP(*cpp)); if (IsOpCode(*cp_val(*cpp), return_trace)) { do ++cpp; @@ -80,9 +80,8 @@ i_return_to_trace() { ERTS_REQ_PROC_MAIN_LOCK(c_p); SWAPIN; } - c_p->cp = NULL; - SET_I((BeamInstr *) cp_val(E[0])); E += 1; + $RETURN(); Goto(*I); //| -no_next } diff --git a/erts/emulator/hipe/hipe_debug.c b/erts/emulator/hipe/hipe_debug.c index 138e4f7da3..2e34cfac59 100644 --- a/erts/emulator/hipe/hipe_debug.c +++ b/erts/emulator/hipe/hipe_debug.c @@ -232,7 +232,6 @@ void hipe_print_pcb(Process *p) U("intial.fun ", u.initial.function); U("intial.ari ", u.initial.arity); U("current ", current); - P("cp ", cp); P("i ", i); U("catches ", catches); U("arity ", arity); diff --git a/erts/emulator/hipe/hipe_instrs.tab b/erts/emulator/hipe/hipe_instrs.tab index a01baebddf..8aa8544b2a 100644 --- a/erts/emulator/hipe/hipe_instrs.tab +++ b/erts/emulator/hipe/hipe_instrs.tab @@ -86,15 +86,14 @@ hipe_trap.post() { switch( c_p->def_arg_reg[3] ) { case HIPE_MODE_SWITCH_RES_RETURN: ASSERT(is_value(reg[0])); - SET_I(c_p->cp); - c_p->cp = 0; + $RETURN(); Goto(*I); case HIPE_MODE_SWITCH_RES_CALL_EXPORTED: c_p->i = c_p->hipe.u.callee_exp->addressv[erts_active_code_ix()]; /*fall through*/ case HIPE_MODE_SWITCH_RES_CALL_BEAM: SET_I(c_p->i); - Dispatch(); + $DISPATCH(); case HIPE_MODE_SWITCH_RES_CALL_CLOSURE: /* This can be used to call any function value, but currently it's only used to call closures referring to unloaded @@ -105,13 +104,11 @@ hipe_trap.post() { next = call_fun(c_p, c_p->arity - 1, reg, THE_NON_VALUE); HEAVY_SWAPIN; if (next != NULL) { - SET_I(next); - Dispatchfun(); + $DISPATCH_FUN(next); } goto find_func_info; } case HIPE_MODE_SWITCH_RES_THROW: - c_p->cp = NULL; I = handle_error(c_p, I, reg, NULL); goto post_error_handling; default: diff --git a/erts/emulator/hipe/hipe_mode_switch.c b/erts/emulator/hipe/hipe_mode_switch.c index 052cf9c263..863c5e6d44 100644 --- a/erts/emulator/hipe/hipe_mode_switch.c +++ b/erts/emulator/hipe/hipe_mode_switch.c @@ -202,15 +202,13 @@ hipe_push_beam_trap_frame(Process *p, Eterm reg[], unsigned arity) p->stop -= 2; p->stop[1] = hipe_beam_catch_throw; } - p->stop[0] = make_cp(p->cp); + p->stop[0] = (BeamInstr) hipe_beam_pc_return; ++p->catches; - p->cp = hipe_beam_pc_return; } static __inline__ void hipe_pop_beam_trap_frame(Process *p) { ASSERT(p->stop[1] == hipe_beam_catch_throw); - p->cp = cp_val(p->stop[0]); --p->catches; p->stop += 2; } @@ -263,7 +261,7 @@ Process *hipe_mode_switch(Process *p, unsigned cmd, Eterm reg[]) unsigned arity = cmd >> 8; /* p->hipe.u.ncallee set in beam_emu */ - if (p->cp == hipe_beam_pc_return) { + if (cp_val(p->stop[0]) == hipe_beam_pc_return) { /* Native called BEAM, which now tailcalls native. */ hipe_pop_beam_trap_frame(p); result = hipe_tailcall_to_native(p, arity, reg); @@ -292,7 +290,7 @@ Process *hipe_mode_switch(Process *p, unsigned cmd, Eterm reg[]) /* just like a normal call from now on */ /* p->hipe.u.ncallee set in beam_emu */ - if (p->cp == hipe_beam_pc_return) { + if (cp_val(p->stop[0]) == hipe_beam_pc_return) { /* Native called BEAM, which now tailcalls native. */ hipe_pop_beam_trap_frame(p); result = hipe_tailcall_to_native(p, arity, reg); diff --git a/erts/emulator/hipe/hipe_x86_signal.c b/erts/emulator/hipe/hipe_x86_signal.c index d3b6933155..df8e1825bc 100644 --- a/erts/emulator/hipe/hipe_x86_signal.c +++ b/erts/emulator/hipe/hipe_x86_signal.c @@ -159,19 +159,9 @@ #if !(defined(__GLIBC__) || defined(__DARWIN__) || defined(__NetBSD__) || defined(__FreeBSD__) || defined(__sun__)) /* - * Unknown libc -- assume musl. Note: musl deliberately does not provide a musl-specific - * feature test macro, so we cannot check for it. - * - * sigaction is a weak alias for __sigaction, which is a wrapper for __libc_sigaction. - * There are libc-internal calls to __libc_sigaction which install handlers, so we must - * override __libc_sigaction rather than __sigaction. + * Unknown libc -- assume musl, which does not allow safe signals */ -#define NEXT_SIGACTION "__libc_sigaction" -#define LIBC_SIGACTION __libc_sigaction -#define OVERRIDE_SIGACTION -#ifndef _NSIG -#define _NSIG NSIG -#endif +#error "HiPE does not work without a libc that can guarantee that sigaltstack works" #endif /* !(__GLIBC__ || __DARWIN__ || __NetBSD__ || __FreeBSD__ || __sun__) */ #if defined(NEXT_SIGACTION) diff --git a/erts/emulator/internal_doc/beam_makeops.md b/erts/emulator/internal_doc/beam_makeops.md index 2880099b70..267af78412 100644 --- a/erts/emulator/internal_doc/beam_makeops.md +++ b/erts/emulator/internal_doc/beam_makeops.md @@ -1457,26 +1457,26 @@ all instructions. It expands to the address of the next instruction. Here is an example: i_call(CallDest) { - SET_CP(c_p, $NEXT_INSTRUCTION); + //| -no_next + $SAVE_CONTINUATION_POINTER($NEXT_INSTRUCTION); $DISPATCH_REL($CallDest); } -When calling a function, the return address is first stored in `c_p->cp` -(using the `SET_CP()` macro defined in `beam_emu.c`), and then control is +When calling a function, the return address is first stored in `E[0]` +(using the `$SAVE_CONTINUATION_POINTER()` macro), and then control is transferred to the callee. Here is the generated code: OpCase(i_call_f): { - SET_CP(c_p, I+1); - ASSERT(VALID_INSTR(*(I + (fb(BeamExtraData(I[0]))) + 0))); - I += fb(BeamExtraData(I[0])) + 0;; - DTRACE_LOCAL_CALL(c_p, erts_code_to_codemfa(I)); - Dispatch();; + ASSERT(VALID_INSTR(*(I+2))); + *E = (BeamInstr) (I+2);; + + /* ... dispatch code intentionally left out ... */ } -We can see that that `$NEXT_INSTRUCTION` has been expanded to `I+1`. +We can see that that `$NEXT_INSTRUCTION` has been expanded to `I+2`. That makes sense since the size of the `i_call_f/1` instruction is -one word. +two words. ##### The IP_ADJUSTMENT pre-bound variable ##### diff --git a/erts/emulator/nifs/common/prim_file_nif.c b/erts/emulator/nifs/common/prim_file_nif.c index 9e9a14844e..5c5e9a2d30 100644 --- a/erts/emulator/nifs/common/prim_file_nif.c +++ b/erts/emulator/nifs/common/prim_file_nif.c @@ -162,6 +162,7 @@ WRAP_FILE_HANDLE_EXPORT(allocate_nif) WRAP_FILE_HANDLE_EXPORT(advise_nif) WRAP_FILE_HANDLE_EXPORT(get_handle_nif) WRAP_FILE_HANDLE_EXPORT(ipread_s32bu_p32bu_nif) +WRAP_FILE_HANDLE_EXPORT(read_handle_info_nif) static ErlNifFunc nif_funcs[] = { /* File handle ops */ @@ -176,6 +177,7 @@ static ErlNifFunc nif_funcs[] = { {"truncate_nif", 1, truncate_nif, ERL_NIF_DIRTY_JOB_IO_BOUND}, {"allocate_nif", 3, allocate_nif, ERL_NIF_DIRTY_JOB_IO_BOUND}, {"advise_nif", 4, advise_nif, ERL_NIF_DIRTY_JOB_IO_BOUND}, + {"read_handle_info_nif", 1, read_handle_info_nif, ERL_NIF_DIRTY_JOB_IO_BOUND}, /* Filesystem ops */ {"make_hard_link_nif", 2, make_hard_link_nif, ERL_NIF_DIRTY_JOB_IO_BOUND}, @@ -896,6 +898,26 @@ static ERL_NIF_TERM get_handle_nif_impl(efile_data_t *d, ErlNifEnv *env, int arg return efile_get_handle(env, d); } +static ERL_NIF_TERM build_file_info(ErlNifEnv *env, efile_fileinfo_t *info) { + /* #file_info as declared in file.hrl */ + return enif_make_tuple(env, 14, + am_file_info, + enif_make_uint64(env, info->size), + efile_filetype_to_atom(info->type), + efile_access_to_atom(info->access), + enif_make_int64(env, MAX(EFILE_MIN_FILETIME, info->a_time)), + enif_make_int64(env, MAX(EFILE_MIN_FILETIME, info->m_time)), + enif_make_int64(env, MAX(EFILE_MIN_FILETIME, info->c_time)), + enif_make_uint(env, info->mode), + enif_make_uint(env, info->links), + enif_make_uint(env, info->major_device), + enif_make_uint(env, info->minor_device), + enif_make_uint(env, info->inode), + enif_make_uint(env, info->uid), + enif_make_uint(env, info->gid) + ); +} + static ERL_NIF_TERM read_info_nif(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]) { posix_errno_t posix_errno; @@ -914,23 +936,20 @@ static ERL_NIF_TERM read_info_nif(ErlNifEnv *env, int argc, const ERL_NIF_TERM a return posix_error_to_tuple(env, posix_errno); } - /* #file_info as declared in file.hrl */ - return enif_make_tuple(env, 14, - am_file_info, - enif_make_uint64(env, info.size), - efile_filetype_to_atom(info.type), - efile_access_to_atom(info.access), - enif_make_int64(env, MAX(EFILE_MIN_FILETIME, info.a_time)), - enif_make_int64(env, MAX(EFILE_MIN_FILETIME, info.m_time)), - enif_make_int64(env, MAX(EFILE_MIN_FILETIME, info.c_time)), - enif_make_uint(env, info.mode), - enif_make_uint(env, info.links), - enif_make_uint(env, info.major_device), - enif_make_uint(env, info.minor_device), - enif_make_uint(env, info.inode), - enif_make_uint(env, info.uid), - enif_make_uint(env, info.gid) - ); + return build_file_info(env, &info); +} + +static ERL_NIF_TERM read_handle_info_nif_impl(efile_data_t *d, ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]) { + posix_errno_t posix_errno; + efile_fileinfo_t info = {0}; + + ASSERT(argc == 0); + + if((posix_errno = efile_read_handle_info(d, &info))) { + return posix_error_to_tuple(env, posix_errno); + } + + return build_file_info(env, &info); } static ERL_NIF_TERM set_permissions_nif(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]) { diff --git a/erts/emulator/nifs/common/prim_file_nif.h b/erts/emulator/nifs/common/prim_file_nif.h index 020714a03b..28c1ea9d00 100644 --- a/erts/emulator/nifs/common/prim_file_nif.h +++ b/erts/emulator/nifs/common/prim_file_nif.h @@ -170,6 +170,7 @@ int efile_close(efile_data_t *d, posix_errno_t *error); /* **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** */ posix_errno_t efile_read_info(const efile_path_t *path, int follow_link, efile_fileinfo_t *result); +posix_errno_t efile_read_handle_info(efile_data_t *d, efile_fileinfo_t *result); /** @brief Sets the file times to the given values. Refer to efile_fileinfo_t * for a description of each. */ diff --git a/erts/emulator/nifs/common/socket_nif.c b/erts/emulator/nifs/common/socket_nif.c index 7ab712530c..881a9c7ccd 100644 --- a/erts/emulator/nifs/common/socket_nif.c +++ b/erts/emulator/nifs/common/socket_nif.c @@ -24,7 +24,7 @@ * The first function is called 'nif_<something>', e.g. nif_open. * This does the initial validation and argument processing and then * calls the function that does the actual work. This is called - * 'n<something>'. + * 'esock_<something>'. * ---------------------------------------------------------------------- * * @@ -354,11 +354,11 @@ static void (*esock_sctp_freepaddrs)(struct sockaddr *addrs) = NULL; /* Debug stuff... */ -#define SOCKET_GLOBAL_DEBUG_DEFAULT FALSE -#define SOCKET_DEBUG_DEFAULT FALSE +#define ESOCK_GLOBAL_DEBUG_DEFAULT FALSE +#define ESOCK_DEBUG_DEFAULT FALSE /* Counters and stuff (Don't know where to sent this stuff anyway) */ -#define SOCKET_NIF_IOW_DEFAULT FALSE +#define ESOCK_NIF_IOW_DEFAULT FALSE @@ -398,10 +398,10 @@ static void (*esock_sctp_freepaddrs)(struct sockaddr *addrs) = NULL; #if defined(TCP_CA_NAME_MAX) -#define SOCKET_OPT_TCP_CONGESTION_NAME_MAX TCP_CA_NAME_MAX +#define ESOCK_OPT_TCP_CONGESTION_NAME_MAX TCP_CA_NAME_MAX #else /* This is really excessive, but just in case... */ -#define SOCKET_OPT_TCP_CONGESTION_NAME_MAX 256 +#define ESOCK_OPT_TCP_CONGESTION_NAME_MAX 256 #endif @@ -414,25 +414,25 @@ static void (*esock_sctp_freepaddrs)(struct sockaddr *addrs) = NULL; /* *** Socket state defs *** */ -#define SOCKET_FLAG_OPEN 0x0001 -#define SOCKET_FLAG_ACTIVE 0x0004 -#define SOCKET_FLAG_LISTEN 0x0008 -#define SOCKET_FLAG_CON 0x0010 -#define SOCKET_FLAG_ACC 0x0020 -#define SOCKET_FLAG_BUSY 0x0040 -#define SOCKET_FLAG_CLOSE 0x0080 - -#define SOCKET_STATE_CLOSED (0) -#define SOCKET_STATE_OPEN (SOCKET_FLAG_OPEN) -#define SOCKET_STATE_CONNECTED (SOCKET_STATE_OPEN | SOCKET_FLAG_ACTIVE) -#define SOCKET_STATE_LISTENING (SOCKET_STATE_OPEN | SOCKET_FLAG_LISTEN) -#define SOCKET_STATE_CONNECTING (SOCKET_STATE_OPEN | SOCKET_FLAG_CON) -#define SOCKET_STATE_ACCEPTING (SOCKET_STATE_LISTENING | SOCKET_FLAG_ACC) -#define SOCKET_STATE_CLOSING (SOCKET_FLAG_CLOSE) -#define SOCKET_STATE_DTOR (0xFFFF) +#define ESOCK_FLAG_OPEN 0x0001 +#define ESOCK_FLAG_ACTIVE 0x0004 +#define ESOCK_FLAG_LISTEN 0x0008 +#define ESOCK_FLAG_CON 0x0010 +#define ESOCK_FLAG_ACC 0x0020 +#define ESOCK_FLAG_BUSY 0x0040 +#define ESOCK_FLAG_CLOSE 0x0080 + +#define ESOCK_STATE_CLOSED (0) +#define ESOCK_STATE_OPEN (ESOCK_FLAG_OPEN) +#define ESOCK_STATE_CONNECTED (ESOCK_STATE_OPEN | ESOCK_FLAG_ACTIVE) +#define ESOCK_STATE_LISTENING (ESOCK_STATE_OPEN | ESOCK_FLAG_LISTEN) +#define ESOCK_STATE_CONNECTING (ESOCK_STATE_OPEN | ESOCK_FLAG_CON) +#define ESOCK_STATE_ACCEPTING (ESOCK_STATE_LISTENING | ESOCK_FLAG_ACC) +#define ESOCK_STATE_CLOSING (ESOCK_FLAG_CLOSE) +#define ESOCK_STATE_DTOR (0xFFFF) #define IS_CLOSED(d) \ - ((d)->state == SOCKET_STATE_CLOSED) + ((d)->state == ESOCK_STATE_CLOSED) /* #define IS_STATE(d, f) \ @@ -440,55 +440,59 @@ static void (*esock_sctp_freepaddrs)(struct sockaddr *addrs) = NULL; */ #define IS_CLOSING(d) \ - (((d)->state & SOCKET_STATE_CLOSING) == SOCKET_STATE_CLOSING) + (((d)->state & ESOCK_STATE_CLOSING) == ESOCK_STATE_CLOSING) #define IS_OPEN(d) \ - (((d)->state & SOCKET_FLAG_OPEN) == SOCKET_FLAG_OPEN) + (((d)->state & ESOCK_FLAG_OPEN) == ESOCK_FLAG_OPEN) #define IS_CONNECTED(d) \ - (((d)->state & SOCKET_STATE_CONNECTED) == SOCKET_STATE_CONNECTED) + (((d)->state & ESOCK_STATE_CONNECTED) == ESOCK_STATE_CONNECTED) #define IS_CONNECTING(d) \ - (((d)->state & SOCKET_FLAG_CON) == SOCKET_FLAG_CON) + (((d)->state & ESOCK_FLAG_CON) == ESOCK_FLAG_CON) /* #define IS_BUSY(d) \ - (((d)->state & SOCKET_FLAG_BUSY) == SOCKET_FLAG_BUSY) + (((d)->state & ESOCK_FLAG_BUSY) == ESOCK_FLAG_BUSY) */ -#define SOCKET_SEND_FLAG_CONFIRM 0 -#define SOCKET_SEND_FLAG_DONTROUTE 1 -#define SOCKET_SEND_FLAG_EOR 2 -#define SOCKET_SEND_FLAG_MORE 3 -#define SOCKET_SEND_FLAG_NOSIGNAL 4 -#define SOCKET_SEND_FLAG_OOB 5 -#define SOCKET_SEND_FLAG_LOW SOCKET_SEND_FLAG_CONFIRM -#define SOCKET_SEND_FLAG_HIGH SOCKET_SEND_FLAG_OOB - -#define SOCKET_RECV_FLAG_CMSG_CLOEXEC 0 -#define SOCKET_RECV_FLAG_ERRQUEUE 1 -#define SOCKET_RECV_FLAG_OOB 2 -#define SOCKET_RECV_FLAG_PEEK 3 -#define SOCKET_RECV_FLAG_TRUNC 4 -#define SOCKET_RECV_FLAG_LOW SOCKET_RECV_FLAG_CMSG_CLOEXEC -#define SOCKET_RECV_FLAG_HIGH SOCKET_RECV_FLAG_TRUNC - -#define SOCKET_RECV_BUFFER_SIZE_DEFAULT 8192 -#define SOCKET_RECV_CTRL_BUFFER_SIZE_DEFAULT 1024 -#define SOCKET_SEND_CTRL_BUFFER_SIZE_DEFAULT 1024 - -#define VT2S(__VT__) (((__VT__) == SOCKET_OPT_VALUE_TYPE_UNSPEC) ? "unspec" : \ - (((__VT__) == SOCKET_OPT_VALUE_TYPE_INT) ? "int" : \ - ((__VT__) == SOCKET_OPT_VALUE_TYPE_BOOL) ? "bool" : \ +#define ESOCK_GET_RESOURCE(ENV, REF, RES) \ + enif_get_resource((ENV), (REF), esocks, (RES)) + +#define ESOCK_SEND_FLAG_CONFIRM 0 +#define ESOCK_SEND_FLAG_DONTROUTE 1 +#define ESOCK_SEND_FLAG_EOR 2 +#define ESOCK_SEND_FLAG_MORE 3 +#define ESOCK_SEND_FLAG_NOSIGNAL 4 +#define ESOCK_SEND_FLAG_OOB 5 +#define ESOCK_SEND_FLAG_LOW ESOCK_SEND_FLAG_CONFIRM +#define ESOCK_SEND_FLAG_HIGH ESOCK_SEND_FLAG_OOB + +#define ESOCK_RECV_FLAG_CMSG_CLOEXEC 0 +#define ESOCK_RECV_FLAG_ERRQUEUE 1 +#define ESOCK_RECV_FLAG_OOB 2 +#define ESOCK_RECV_FLAG_PEEK 3 +#define ESOCK_RECV_FLAG_TRUNC 4 +#define ESOCK_RECV_FLAG_LOW ESOCK_RECV_FLAG_CMSG_CLOEXEC +#define ESOCK_RECV_FLAG_HIGH ESOCK_RECV_FLAG_TRUNC + +#define ESOCK_RECV_BUFFER_SIZE_DEFAULT 8192 +#define ESOCK_RECV_CTRL_BUFFER_SIZE_DEFAULT 1024 +#define ESOCK_SEND_CTRL_BUFFER_SIZE_DEFAULT 1024 + +#define VT2S(__VT__) (((__VT__) == ESOCK_OPT_VALUE_TYPE_UNSPEC) ? "unspec" : \ + (((__VT__) == ESOCK_OPT_VALUE_TYPE_INT) ? "int" : \ + ((__VT__) == ESOCK_OPT_VALUE_TYPE_BOOL) ? "bool" : \ "undef")) -#define SOCKET_OPT_VALUE_TYPE_UNSPEC 0 -#define SOCKET_OPT_VALUE_TYPE_INT 1 -#define SOCKET_OPT_VALUE_TYPE_BOOL 2 +#define ESOCK_OPT_VALUE_TYPE_UNSPEC 0 +#define ESOCK_OPT_VALUE_TYPE_INT 1 +#define ESOCK_OPT_VALUE_TYPE_BOOL 2 #define ESOCK_DESC_PATTERN_CREATED 0x03030303 #define ESOCK_DESC_PATTERN_DTOR 0xC0C0C0C0 +/* typedef union { struct { // 0 = not open, 1 = open @@ -501,15 +505,16 @@ typedef union { unsigned int listen:2; // unsigned int listening:1; // unsigned int accepting:1; - /* Room for more... */ + / * Room for more... * / } flags; unsigned int field; // Make it easy to reset all flags... } SocketState; +*/ /* #define IS_OPEN(d) ((d)->state.flags.open) -#define IS_CONNECTED(d) ((d)->state.flags.connect == SOCKET_STATE_CONNECTED) -#define IS_CONNECTING(d) ((d)->state.flags.connect == SOCKET_STATE_CONNECTING) +#define IS_CONNECTED(d) ((d)->state.flags.connect == ESOCK_STATE_CONNECTED) +#define IS_CONNECTING(d) ((d)->state.flags.connect == ESOCK_STATE_CONNECTING) */ @@ -520,151 +525,151 @@ typedef union { */ /* domain */ -#define SOCKET_DOMAIN_LOCAL 1 -#define SOCKET_DOMAIN_INET 2 -#define SOCKET_DOMAIN_INET6 3 +#define ESOCK_DOMAIN_LOCAL 1 +#define ESOCK_DOMAIN_INET 2 +#define ESOCK_DOMAIN_INET6 3 /* type */ -#define SOCKET_TYPE_STREAM 1 -#define SOCKET_TYPE_DGRAM 2 -#define SOCKET_TYPE_RAW 3 -// #define SOCKET_TYPE_RDM 4 -#define SOCKET_TYPE_SEQPACKET 5 +#define ESOCK_TYPE_STREAM 1 +#define ESOCK_TYPE_DGRAM 2 +#define ESOCK_TYPE_RAW 3 +// #define ESOCK_TYPE_RDM 4 +#define ESOCK_TYPE_SEQPACKET 5 /* protocol */ -#define SOCKET_PROTOCOL_DEFAULT 0 -#define SOCKET_PROTOCOL_IP 1 -#define SOCKET_PROTOCOL_TCP 2 -#define SOCKET_PROTOCOL_UDP 3 -#define SOCKET_PROTOCOL_SCTP 4 -#define SOCKET_PROTOCOL_ICMP 5 -#define SOCKET_PROTOCOL_IGMP 6 +#define ESOCK_PROTOCOL_DEFAULT 0 +#define ESOCK_PROTOCOL_IP 1 +#define ESOCK_PROTOCOL_TCP 2 +#define ESOCK_PROTOCOL_UDP 3 +#define ESOCK_PROTOCOL_SCTP 4 +#define ESOCK_PROTOCOL_ICMP 5 +#define ESOCK_PROTOCOL_IGMP 6 /* shutdown how */ -#define SOCKET_SHUTDOWN_HOW_RD 0 -#define SOCKET_SHUTDOWN_HOW_WR 1 -#define SOCKET_SHUTDOWN_HOW_RDWR 2 - - -#define SOCKET_OPT_LEVEL_OTP 0 -#define SOCKET_OPT_LEVEL_SOCKET 1 -#define SOCKET_OPT_LEVEL_IP 2 -#define SOCKET_OPT_LEVEL_IPV6 3 -#define SOCKET_OPT_LEVEL_TCP 4 -#define SOCKET_OPT_LEVEL_UDP 5 -#define SOCKET_OPT_LEVEL_SCTP 6 - -#define SOCKET_OPT_OTP_DEBUG 1 -#define SOCKET_OPT_OTP_IOW 2 -#define SOCKET_OPT_OTP_CTRL_PROC 3 -#define SOCKET_OPT_OTP_RCVBUF 4 -#define SOCKET_OPT_OTP_RCVCTRLBUF 6 -#define SOCKET_OPT_OTP_SNDCTRLBUF 7 -#define SOCKET_OPT_OTP_FD 8 -#define SOCKET_OPT_OTP_DOMAIN 0xFF01 // INTERNAL AND ONLY GET -#define SOCKET_OPT_OTP_TYPE 0xFF02 // INTERNAL AND ONLY GET -#define SOCKET_OPT_OTP_PROTOCOL 0xFF03 // INTERNAL AND ONLY GET - -#define SOCKET_OPT_SOCK_ACCEPTCONN 1 -#define SOCKET_OPT_SOCK_BINDTODEVICE 3 -#define SOCKET_OPT_SOCK_BROADCAST 4 -#define SOCKET_OPT_SOCK_DEBUG 6 -#define SOCKET_OPT_SOCK_DOMAIN 7 -#define SOCKET_OPT_SOCK_DONTROUTE 8 -#define SOCKET_OPT_SOCK_KEEPALIVE 10 -#define SOCKET_OPT_SOCK_LINGER 11 -#define SOCKET_OPT_SOCK_OOBINLINE 13 -#define SOCKET_OPT_SOCK_PEEK_OFF 15 -#define SOCKET_OPT_SOCK_PRIORITY 17 -#define SOCKET_OPT_SOCK_PROTOCOL 18 -#define SOCKET_OPT_SOCK_RCVBUF 19 -#define SOCKET_OPT_SOCK_RCVLOWAT 21 -#define SOCKET_OPT_SOCK_RCVTIMEO 22 -#define SOCKET_OPT_SOCK_REUSEADDR 23 -#define SOCKET_OPT_SOCK_REUSEPORT 24 -#define SOCKET_OPT_SOCK_SNDBUF 27 -#define SOCKET_OPT_SOCK_SNDLOWAT 29 -#define SOCKET_OPT_SOCK_SNDTIMEO 30 -#define SOCKET_OPT_SOCK_TIMESTAMP 31 -#define SOCKET_OPT_SOCK_TYPE 32 - -#define SOCKET_OPT_IP_ADD_MEMBERSHIP 1 -#define SOCKET_OPT_IP_ADD_SOURCE_MEMBERSHIP 2 -#define SOCKET_OPT_IP_BLOCK_SOURCE 3 -#define SOCKET_OPT_IP_DROP_MEMBERSHIP 5 -#define SOCKET_OPT_IP_DROP_SOURCE_MEMBERSHIP 6 -#define SOCKET_OPT_IP_FREEBIND 7 -#define SOCKET_OPT_IP_HDRINCL 8 -#define SOCKET_OPT_IP_MINTTL 9 -#define SOCKET_OPT_IP_MSFILTER 10 -#define SOCKET_OPT_IP_MTU 11 -#define SOCKET_OPT_IP_MTU_DISCOVER 12 -#define SOCKET_OPT_IP_MULTICAST_ALL 13 -#define SOCKET_OPT_IP_MULTICAST_IF 14 -#define SOCKET_OPT_IP_MULTICAST_LOOP 15 -#define SOCKET_OPT_IP_MULTICAST_TTL 16 -#define SOCKET_OPT_IP_NODEFRAG 17 -#define SOCKET_OPT_IP_PKTINFO 19 -#define SOCKET_OPT_IP_RECVDSTADDR 20 -#define SOCKET_OPT_IP_RECVERR 21 -#define SOCKET_OPT_IP_RECVIF 22 -#define SOCKET_OPT_IP_RECVOPTS 23 -#define SOCKET_OPT_IP_RECVORIGDSTADDR 24 -#define SOCKET_OPT_IP_RECVTOS 25 -#define SOCKET_OPT_IP_RECVTTL 26 -#define SOCKET_OPT_IP_RETOPTS 27 -#define SOCKET_OPT_IP_ROUTER_ALERT 28 -#define SOCKET_OPT_IP_SENDSRCADDR 29 // Same as IP_RECVDSTADDR? -#define SOCKET_OPT_IP_TOS 30 -#define SOCKET_OPT_IP_TRANSPARENT 31 -#define SOCKET_OPT_IP_TTL 32 -#define SOCKET_OPT_IP_UNBLOCK_SOURCE 33 - -#define SOCKET_OPT_IPV6_ADDRFORM 1 -#define SOCKET_OPT_IPV6_ADD_MEMBERSHIP 2 -#define SOCKET_OPT_IPV6_AUTHHDR 3 -#define SOCKET_OPT_IPV6_DROP_MEMBERSHIP 6 -#define SOCKET_OPT_IPV6_DSTOPTS 7 -#define SOCKET_OPT_IPV6_FLOWINFO 11 -#define SOCKET_OPT_IPV6_HOPLIMIT 12 -#define SOCKET_OPT_IPV6_HOPOPTS 13 -#define SOCKET_OPT_IPV6_MTU 17 -#define SOCKET_OPT_IPV6_MTU_DISCOVER 18 -#define SOCKET_OPT_IPV6_MULTICAST_HOPS 19 -#define SOCKET_OPT_IPV6_MULTICAST_IF 20 -#define SOCKET_OPT_IPV6_MULTICAST_LOOP 21 -#define SOCKET_OPT_IPV6_RECVERR 24 -#define SOCKET_OPT_IPV6_RECVPKTINFO 25 // PKTINFO on FreeBSD -#define SOCKET_OPT_IPV6_ROUTER_ALERT 27 -#define SOCKET_OPT_IPV6_RTHDR 28 -#define SOCKET_OPT_IPV6_UNICAST_HOPS 30 -#define SOCKET_OPT_IPV6_V6ONLY 32 - -#define SOCKET_OPT_TCP_CONGESTION 1 -#define SOCKET_OPT_TCP_CORK 2 -#define SOCKET_OPT_TCP_MAXSEG 7 -#define SOCKET_OPT_TCP_NODELAY 9 - -#define SOCKET_OPT_UDP_CORK 1 - -#define SOCKET_OPT_SCTP_ASSOCINFO 2 -#define SOCKET_OPT_SCTP_AUTOCLOSE 8 -#define SOCKET_OPT_SCTP_DISABLE_FRAGMENTS 12 -#define SOCKET_OPT_SCTP_EVENTS 14 -#define SOCKET_OPT_SCTP_INITMSG 18 -#define SOCKET_OPT_SCTP_MAXSEG 21 -#define SOCKET_OPT_SCTP_NODELAY 23 -#define SOCKET_OPT_SCTP_RTOINFO 29 +#define ESOCK_SHUTDOWN_HOW_RD 0 +#define ESOCK_SHUTDOWN_HOW_WR 1 +#define ESOCK_SHUTDOWN_HOW_RDWR 2 + + +#define ESOCK_OPT_LEVEL_OTP 0 +#define ESOCK_OPT_LEVEL_SOCKET 1 +#define ESOCK_OPT_LEVEL_IP 2 +#define ESOCK_OPT_LEVEL_IPV6 3 +#define ESOCK_OPT_LEVEL_TCP 4 +#define ESOCK_OPT_LEVEL_UDP 5 +#define ESOCK_OPT_LEVEL_SCTP 6 + +#define ESOCK_OPT_OTP_DEBUG 1 +#define ESOCK_OPT_OTP_IOW 2 +#define ESOCK_OPT_OTP_CTRL_PROC 3 +#define ESOCK_OPT_OTP_RCVBUF 4 +#define ESOCK_OPT_OTP_RCVCTRLBUF 6 +#define ESOCK_OPT_OTP_SNDCTRLBUF 7 +#define ESOCK_OPT_OTP_FD 8 +#define ESOCK_OPT_OTP_DOMAIN 0xFF01 // INTERNAL AND ONLY GET +#define ESOCK_OPT_OTP_TYPE 0xFF02 // INTERNAL AND ONLY GET +#define ESOCK_OPT_OTP_PROTOCOL 0xFF03 // INTERNAL AND ONLY GET + +#define ESOCK_OPT_SOCK_ACCEPTCONN 1 +#define ESOCK_OPT_SOCK_BINDTODEVICE 3 +#define ESOCK_OPT_SOCK_BROADCAST 4 +#define ESOCK_OPT_SOCK_DEBUG 6 +#define ESOCK_OPT_SOCK_DOMAIN 7 +#define ESOCK_OPT_SOCK_DONTROUTE 8 +#define ESOCK_OPT_SOCK_KEEPALIVE 10 +#define ESOCK_OPT_SOCK_LINGER 11 +#define ESOCK_OPT_SOCK_OOBINLINE 13 +#define ESOCK_OPT_SOCK_PEEK_OFF 15 +#define ESOCK_OPT_SOCK_PRIORITY 17 +#define ESOCK_OPT_SOCK_PROTOCOL 18 +#define ESOCK_OPT_SOCK_RCVBUF 19 +#define ESOCK_OPT_SOCK_RCVLOWAT 21 +#define ESOCK_OPT_SOCK_RCVTIMEO 22 +#define ESOCK_OPT_SOCK_REUSEADDR 23 +#define ESOCK_OPT_SOCK_REUSEPORT 24 +#define ESOCK_OPT_SOCK_SNDBUF 27 +#define ESOCK_OPT_SOCK_SNDLOWAT 29 +#define ESOCK_OPT_SOCK_SNDTIMEO 30 +#define ESOCK_OPT_SOCK_TIMESTAMP 31 +#define ESOCK_OPT_SOCK_TYPE 32 + +#define ESOCK_OPT_IP_ADD_MEMBERSHIP 1 +#define ESOCK_OPT_IP_ADD_SOURCE_MEMBERSHIP 2 +#define ESOCK_OPT_IP_BLOCK_SOURCE 3 +#define ESOCK_OPT_IP_DROP_MEMBERSHIP 5 +#define ESOCK_OPT_IP_DROP_SOURCE_MEMBERSHIP 6 +#define ESOCK_OPT_IP_FREEBIND 7 +#define ESOCK_OPT_IP_HDRINCL 8 +#define ESOCK_OPT_IP_MINTTL 9 +#define ESOCK_OPT_IP_MSFILTER 10 +#define ESOCK_OPT_IP_MTU 11 +#define ESOCK_OPT_IP_MTU_DISCOVER 12 +#define ESOCK_OPT_IP_MULTICAST_ALL 13 +#define ESOCK_OPT_IP_MULTICAST_IF 14 +#define ESOCK_OPT_IP_MULTICAST_LOOP 15 +#define ESOCK_OPT_IP_MULTICAST_TTL 16 +#define ESOCK_OPT_IP_NODEFRAG 17 +#define ESOCK_OPT_IP_PKTINFO 19 +#define ESOCK_OPT_IP_RECVDSTADDR 20 +#define ESOCK_OPT_IP_RECVERR 21 +#define ESOCK_OPT_IP_RECVIF 22 +#define ESOCK_OPT_IP_RECVOPTS 23 +#define ESOCK_OPT_IP_RECVORIGDSTADDR 24 +#define ESOCK_OPT_IP_RECVTOS 25 +#define ESOCK_OPT_IP_RECVTTL 26 +#define ESOCK_OPT_IP_RETOPTS 27 +#define ESOCK_OPT_IP_ROUTER_ALERT 28 +#define ESOCK_OPT_IP_SENDSRCADDR 29 // Same as IP_RECVDSTADDR? +#define ESOCK_OPT_IP_TOS 30 +#define ESOCK_OPT_IP_TRANSPARENT 31 +#define ESOCK_OPT_IP_TTL 32 +#define ESOCK_OPT_IP_UNBLOCK_SOURCE 33 + +#define ESOCK_OPT_IPV6_ADDRFORM 1 +#define ESOCK_OPT_IPV6_ADD_MEMBERSHIP 2 +#define ESOCK_OPT_IPV6_AUTHHDR 3 +#define ESOCK_OPT_IPV6_DROP_MEMBERSHIP 6 +#define ESOCK_OPT_IPV6_DSTOPTS 7 +#define ESOCK_OPT_IPV6_FLOWINFO 11 +#define ESOCK_OPT_IPV6_HOPLIMIT 12 +#define ESOCK_OPT_IPV6_HOPOPTS 13 +#define ESOCK_OPT_IPV6_MTU 17 +#define ESOCK_OPT_IPV6_MTU_DISCOVER 18 +#define ESOCK_OPT_IPV6_MULTICAST_HOPS 19 +#define ESOCK_OPT_IPV6_MULTICAST_IF 20 +#define ESOCK_OPT_IPV6_MULTICAST_LOOP 21 +#define ESOCK_OPT_IPV6_RECVERR 24 +#define ESOCK_OPT_IPV6_RECVPKTINFO 25 // PKTINFO on FreeBSD +#define ESOCK_OPT_IPV6_ROUTER_ALERT 27 +#define ESOCK_OPT_IPV6_RTHDR 28 +#define ESOCK_OPT_IPV6_UNICAST_HOPS 30 +#define ESOCK_OPT_IPV6_V6ONLY 32 + +#define ESOCK_OPT_TCP_CONGESTION 1 +#define ESOCK_OPT_TCP_CORK 2 +#define ESOCK_OPT_TCP_MAXSEG 7 +#define ESOCK_OPT_TCP_NODELAY 9 + +#define ESOCK_OPT_UDP_CORK 1 + +#define ESOCK_OPT_SCTP_ASSOCINFO 2 +#define ESOCK_OPT_SCTP_AUTOCLOSE 8 +#define ESOCK_OPT_SCTP_DISABLE_FRAGMENTS 12 +#define ESOCK_OPT_SCTP_EVENTS 14 +#define ESOCK_OPT_SCTP_INITMSG 18 +#define ESOCK_OPT_SCTP_MAXSEG 21 +#define ESOCK_OPT_SCTP_NODELAY 23 +#define ESOCK_OPT_SCTP_RTOINFO 29 /* We should *eventually* use this instead of hard-coding the size (to 1) */ #define ESOCK_RECVMSG_IOVEC_SZ 1 -#define SOCKET_CMD_DEBUG 0x0001 +#define ESOCK_CMD_DEBUG 0x0001 -#define SOCKET_SUPPORTS_OPTIONS 0x0001 -#define SOCKET_SUPPORTS_SCTP 0x0002 -#define SOCKET_SUPPORTS_IPV6 0x0003 -#define SOCKET_SUPPORTS_LOCAL 0x0004 +#define ESOCK_SUPPORTS_OPTIONS 0x0001 +#define ESOCK_SUPPORTS_SCTP 0x0002 +#define ESOCK_SUPPORTS_IPV6 0x0003 +#define ESOCK_SUPPORTS_LOCAL 0x0004 #define ESOCK_WHICH_PROTO_ERROR -1 #define ESOCK_WHICH_PROTO_UNSUP -2 @@ -1021,10 +1026,10 @@ static BOOLEAN_T ecommand2command(ErlNifEnv* env, ERL_NIF_TERM ecommand, Uint16* command, ERL_NIF_TERM* edata); -static ERL_NIF_TERM ncommand(ErlNifEnv* env, - Uint16 cmd, - ERL_NIF_TERM ecdata); -static ERL_NIF_TERM ncommand_debug(ErlNifEnv* env, ERL_NIF_TERM ecdata); +static ERL_NIF_TERM esock_command(ErlNifEnv* env, + Uint16 cmd, + ERL_NIF_TERM ecdata); +static ERL_NIF_TERM esock_command_debug(ErlNifEnv* env, ERL_NIF_TERM ecdata); static ERL_NIF_TERM esock_global_info(ErlNifEnv* env); static ERL_NIF_TERM esock_socket_info(ErlNifEnv* env, @@ -1048,1109 +1053,1109 @@ static ERL_NIF_TERM socket_info_reqs(ErlNifEnv* env, ESockRequestor* crp, ESockRequestQueue* q); -static ERL_NIF_TERM nsupports(ErlNifEnv* env, int key); -static ERL_NIF_TERM nsupports_options(ErlNifEnv* env); -static ERL_NIF_TERM nsupports_options_socket(ErlNifEnv* env); -static ERL_NIF_TERM nsupports_options_ip(ErlNifEnv* env); -static ERL_NIF_TERM nsupports_options_ipv6(ErlNifEnv* env); -static ERL_NIF_TERM nsupports_options_tcp(ErlNifEnv* env); -static ERL_NIF_TERM nsupports_options_udp(ErlNifEnv* env); -static ERL_NIF_TERM nsupports_options_sctp(ErlNifEnv* env); -static ERL_NIF_TERM nsupports_sctp(ErlNifEnv* env); -static ERL_NIF_TERM nsupports_ipv6(ErlNifEnv* env); -static ERL_NIF_TERM nsupports_local(ErlNifEnv* env); - -static ERL_NIF_TERM nopen(ErlNifEnv* env, +static ERL_NIF_TERM esock_supports(ErlNifEnv* env, int key); +static ERL_NIF_TERM esock_supports_options(ErlNifEnv* env); +static ERL_NIF_TERM esock_supports_options_socket(ErlNifEnv* env); +static ERL_NIF_TERM esock_supports_options_ip(ErlNifEnv* env); +static ERL_NIF_TERM esock_supports_options_ipv6(ErlNifEnv* env); +static ERL_NIF_TERM esock_supports_options_tcp(ErlNifEnv* env); +static ERL_NIF_TERM esock_supports_options_udp(ErlNifEnv* env); +static ERL_NIF_TERM esock_supports_options_sctp(ErlNifEnv* env); +static ERL_NIF_TERM esock_supports_sctp(ErlNifEnv* env); +static ERL_NIF_TERM esock_supports_ipv6(ErlNifEnv* env); +static ERL_NIF_TERM esock_supports_local(ErlNifEnv* env); + +static ERL_NIF_TERM esock_open(ErlNifEnv* env, int domain, int type, int protocol, char* netns); -static BOOLEAN_T nopen_which_protocol(SOCKET sock, int* proto); +static BOOLEAN_T esock_open_which_protocol(SOCKET sock, int* proto); -static ERL_NIF_TERM nbind(ErlNifEnv* env, - ESockDescriptor* descP, - ESockAddress* sockAddrP, - unsigned int addrLen); -static ERL_NIF_TERM nconnect(ErlNifEnv* env, - ESockDescriptor* descP, - ERL_NIF_TERM sockRef); -static ERL_NIF_TERM nlisten(ErlNifEnv* env, - ESockDescriptor* descP, - int backlog); -static ERL_NIF_TERM naccept_erts(ErlNifEnv* env, +static ERL_NIF_TERM esock_bind(ErlNifEnv* env, + ESockDescriptor* descP, + ESockAddress* sockAddrP, + unsigned int addrLen); +static ERL_NIF_TERM esock_connect(ErlNifEnv* env, + ESockDescriptor* descP, + ERL_NIF_TERM sockRef); +static ERL_NIF_TERM esock_listen(ErlNifEnv* env, + ESockDescriptor* descP, + int backlog); +static ERL_NIF_TERM esock_accept(ErlNifEnv* env, ESockDescriptor* descP, ERL_NIF_TERM sockRef, ERL_NIF_TERM ref); -static ERL_NIF_TERM naccept_listening(ErlNifEnv* env, - ESockDescriptor* descP, - ERL_NIF_TERM sockRef, - ERL_NIF_TERM ref); -static ERL_NIF_TERM naccept_listening_error(ErlNifEnv* env, +static ERL_NIF_TERM esock_accept_listening(ErlNifEnv* env, + ESockDescriptor* descP, + ERL_NIF_TERM sockRef, + ERL_NIF_TERM ref); +static ERL_NIF_TERM esock_accept_listening_error(ErlNifEnv* env, + ESockDescriptor* descP, + ERL_NIF_TERM sockRef, + ERL_NIF_TERM accRef, + ErlNifPid caller, + int save_errno); +static ERL_NIF_TERM esock_accept_listening_accept(ErlNifEnv* env, + ESockDescriptor* descP, + SOCKET accSock, + ErlNifPid caller, + ESockAddress* remote); +static ERL_NIF_TERM esock_accept_accepting(ErlNifEnv* env, + ESockDescriptor* descP, + ERL_NIF_TERM sockRef, + ERL_NIF_TERM ref); +static ERL_NIF_TERM esock_accept_accepting_current(ErlNifEnv* env, + ESockDescriptor* descP, + ERL_NIF_TERM sockRef, + ERL_NIF_TERM ref); +static ERL_NIF_TERM esock_accept_accepting_current_accept(ErlNifEnv* env, + ESockDescriptor* descP, + ERL_NIF_TERM sockRef, + SOCKET accSock, + ESockAddress* remote); +static ERL_NIF_TERM esock_accept_accepting_current_error(ErlNifEnv* env, + ESockDescriptor* descP, + ERL_NIF_TERM sockRef, + ERL_NIF_TERM opRef, + int save_errno); +static ERL_NIF_TERM esock_accept_accepting_other(ErlNifEnv* env, + ESockDescriptor* descP, + ERL_NIF_TERM ref, + ErlNifPid caller); +static ERL_NIF_TERM esock_accept_busy_retry(ErlNifEnv* env, ESockDescriptor* descP, ERL_NIF_TERM sockRef, ERL_NIF_TERM accRef, - ErlNifPid caller, - int save_errno); -static ERL_NIF_TERM naccept_listening_accept(ErlNifEnv* env, - ESockDescriptor* descP, - SOCKET accSock, - ErlNifPid caller, - ESockAddress* remote); -static ERL_NIF_TERM naccept_accepting(ErlNifEnv* env, - ESockDescriptor* descP, - ERL_NIF_TERM sockRef, - ERL_NIF_TERM ref); -static ERL_NIF_TERM naccept_accepting_current(ErlNifEnv* env, - ESockDescriptor* descP, - ERL_NIF_TERM sockRef, - ERL_NIF_TERM ref); -static ERL_NIF_TERM naccept_accepting_current_accept(ErlNifEnv* env, - ESockDescriptor* descP, - ERL_NIF_TERM sockRef, - SOCKET accSock, - ESockAddress* remote); -static ERL_NIF_TERM naccept_accepting_current_error(ErlNifEnv* env, - ESockDescriptor* descP, - ERL_NIF_TERM sockRef, - ERL_NIF_TERM opRef, - int save_errno); -static ERL_NIF_TERM naccept_accepting_other(ErlNifEnv* env, - ESockDescriptor* descP, - ERL_NIF_TERM ref, - ErlNifPid caller); -static ERL_NIF_TERM naccept_busy_retry(ErlNifEnv* env, + ErlNifPid* pid, + unsigned int nextState); +static BOOLEAN_T esock_accept_accepted(ErlNifEnv* env, ESockDescriptor* descP, - ERL_NIF_TERM sockRef, - ERL_NIF_TERM accRef, - ErlNifPid* pid, - unsigned int nextState); -static BOOLEAN_T naccept_accepted(ErlNifEnv* env, - ESockDescriptor* descP, - SOCKET accSock, - ErlNifPid pid, - ESockAddress* remote, - ERL_NIF_TERM* result); -static ERL_NIF_TERM nsend(ErlNifEnv* env, - ESockDescriptor* descP, - ERL_NIF_TERM sockRef, - ERL_NIF_TERM sendRef, - ErlNifBinary* dataP, - int flags); -static ERL_NIF_TERM nsendto(ErlNifEnv* env, - ESockDescriptor* descP, - ERL_NIF_TERM sockRef, - ERL_NIF_TERM sendRef, - ErlNifBinary* dataP, - int flags, - ESockAddress* toAddrP, - unsigned int toAddrLen); -static ERL_NIF_TERM nsendmsg_erts(ErlNifEnv* env, + SOCKET accSock, + ErlNifPid pid, + ESockAddress* remote, + ERL_NIF_TERM* result); +static ERL_NIF_TERM esock_send(ErlNifEnv* env, + ESockDescriptor* descP, + ERL_NIF_TERM sockRef, + ERL_NIF_TERM sendRef, + ErlNifBinary* dataP, + int flags); +static ERL_NIF_TERM esock_sendto(ErlNifEnv* env, + ESockDescriptor* descP, + ERL_NIF_TERM sockRef, + ERL_NIF_TERM sendRef, + ErlNifBinary* dataP, + int flags, + ESockAddress* toAddrP, + unsigned int toAddrLen); +static ERL_NIF_TERM esock_sendmsg(ErlNifEnv* env, ESockDescriptor* descP, ERL_NIF_TERM sockRef, ERL_NIF_TERM sendRef, ERL_NIF_TERM eMsgHdr, int flags); -static ERL_NIF_TERM nrecv(ErlNifEnv* env, - ESockDescriptor* descP, - ERL_NIF_TERM sendRef, - ERL_NIF_TERM recvRef, - int len, - int flags); -static ERL_NIF_TERM nrecvfrom_erts(ErlNifEnv* env, +static ERL_NIF_TERM esock_recv(ErlNifEnv* env, + ESockDescriptor* descP, + ERL_NIF_TERM sendRef, + ERL_NIF_TERM recvRef, + int len, + int flags); +static ERL_NIF_TERM esock_recvfrom(ErlNifEnv* env, ESockDescriptor* descP, ERL_NIF_TERM sockRef, ERL_NIF_TERM recvRef, Uint16 bufSz, int flags); -static ERL_NIF_TERM nrecvmsg_erts(ErlNifEnv* env, +static ERL_NIF_TERM esock_recvmsg(ErlNifEnv* env, ESockDescriptor* descP, ERL_NIF_TERM sockRef, ERL_NIF_TERM recvRef, Uint16 bufLen, Uint16 ctrlLen, int flags); -static ERL_NIF_TERM nclose(ErlNifEnv* env, - ESockDescriptor* descP); -static BOOLEAN_T nclose_check(ErlNifEnv* env, - ESockDescriptor* descP, - ERL_NIF_TERM* reason); -static ERL_NIF_TERM nclose_do(ErlNifEnv* env, - ESockDescriptor* descP); -static ERL_NIF_TERM nshutdown(ErlNifEnv* env, - ESockDescriptor* descP, - int how); -static ERL_NIF_TERM nsetopt(ErlNifEnv* env, - ESockDescriptor* descP, - BOOLEAN_T isEncoded, - BOOLEAN_T isOTP, - int level, - int eOpt, - ERL_NIF_TERM eVal); +static ERL_NIF_TERM esock_close(ErlNifEnv* env, + ESockDescriptor* descP); +static BOOLEAN_T esock_close_check(ErlNifEnv* env, + ESockDescriptor* descP, + ERL_NIF_TERM* reason); +static ERL_NIF_TERM esock_close_do(ErlNifEnv* env, + ESockDescriptor* descP); +static ERL_NIF_TERM esock_shutdown(ErlNifEnv* env, + ESockDescriptor* descP, + int how); +static ERL_NIF_TERM esock_setopt(ErlNifEnv* env, + ESockDescriptor* descP, + BOOLEAN_T isEncoded, + BOOLEAN_T isOTP, + int level, + int eOpt, + ERL_NIF_TERM eVal); /* Set OTP level options */ -static ERL_NIF_TERM nsetopt_otp(ErlNifEnv* env, - ESockDescriptor* descP, - int eOpt, - ERL_NIF_TERM eVal); -/* *** nsetopt_otp_debug *** - * *** nsetopt_otp_iow *** - * *** nsetopt_otp_ctrl_proc *** - * *** nsetopt_otp_rcvbuf *** - * *** nsetopt_otp_rcvctrlbuf *** - * *** nsetopt_otp_sndctrlbuf *** - */ -#define NSETOPT_OTP_FUNCS \ - NSETOPT_OTP_FUNC_DEF(debug); \ - NSETOPT_OTP_FUNC_DEF(iow); \ - NSETOPT_OTP_FUNC_DEF(ctrl_proc); \ - NSETOPT_OTP_FUNC_DEF(rcvbuf); \ - NSETOPT_OTP_FUNC_DEF(rcvctrlbuf); \ - NSETOPT_OTP_FUNC_DEF(sndctrlbuf); -#define NSETOPT_OTP_FUNC_DEF(F) \ - static ERL_NIF_TERM nsetopt_otp_##F(ErlNifEnv* env, \ - ESockDescriptor* descP, \ - ERL_NIF_TERM eVal) -NSETOPT_OTP_FUNCS -#undef NSETOPT_OTP_FUNC_DEF +static ERL_NIF_TERM esock_setopt_otp(ErlNifEnv* env, + ESockDescriptor* descP, + int eOpt, + ERL_NIF_TERM eVal); +/* *** esock_setopt_otp_debug *** + * *** esock_setopt_otp_iow *** + * *** esock_setopt_otp_ctrl_proc *** + * *** esock_setopt_otp_rcvbuf *** + * *** esock_setopt_otp_rcvctrlbuf *** + * *** esock_setopt_otp_sndctrlbuf *** + */ +#define ESOCK_SETOPT_OTP_FUNCS \ + ESOCK_SETOPT_OTP_FUNC_DEF(debug); \ + ESOCK_SETOPT_OTP_FUNC_DEF(iow); \ + ESOCK_SETOPT_OTP_FUNC_DEF(ctrl_proc); \ + ESOCK_SETOPT_OTP_FUNC_DEF(rcvbuf); \ + ESOCK_SETOPT_OTP_FUNC_DEF(rcvctrlbuf); \ + ESOCK_SETOPT_OTP_FUNC_DEF(sndctrlbuf); +#define ESOCK_SETOPT_OTP_FUNC_DEF(F) \ + static ERL_NIF_TERM esock_setopt_otp_##F(ErlNifEnv* env, \ + ESockDescriptor* descP, \ + ERL_NIF_TERM eVal) +ESOCK_SETOPT_OTP_FUNCS +#undef ESOCK_SETOPT_OTP_FUNC_DEF /* Set native options */ -static ERL_NIF_TERM nsetopt_native(ErlNifEnv* env, - ESockDescriptor* descP, - int level, - int eOpt, - ERL_NIF_TERM eVal); -static ERL_NIF_TERM nsetopt_level(ErlNifEnv* env, - ESockDescriptor* descP, - int level, - int eOpt, - ERL_NIF_TERM eVal); -static ERL_NIF_TERM nsetopt_lvl_socket(ErlNifEnv* env, +static ERL_NIF_TERM esock_setopt_native(ErlNifEnv* env, + ESockDescriptor* descP, + int level, + int eOpt, + ERL_NIF_TERM eVal); +static ERL_NIF_TERM esock_setopt_level(ErlNifEnv* env, ESockDescriptor* descP, + int level, int eOpt, ERL_NIF_TERM eVal); +static ERL_NIF_TERM esock_setopt_lvl_socket(ErlNifEnv* env, + ESockDescriptor* descP, + int eOpt, + ERL_NIF_TERM eVal); /* *** Handling set of socket options for level = socket *** */ #if defined(SO_BINDTODEVICE) -static ERL_NIF_TERM nsetopt_lvl_sock_bindtodevice(ErlNifEnv* env, - ESockDescriptor* descP, - ERL_NIF_TERM eVal); +static ERL_NIF_TERM esock_setopt_lvl_sock_bindtodevice(ErlNifEnv* env, + ESockDescriptor* descP, + ERL_NIF_TERM eVal); #endif #if defined(SO_BROADCAST) -static ERL_NIF_TERM nsetopt_lvl_sock_broadcast(ErlNifEnv* env, - ESockDescriptor* descP, - ERL_NIF_TERM eVal); +static ERL_NIF_TERM esock_setopt_lvl_sock_broadcast(ErlNifEnv* env, + ESockDescriptor* descP, + ERL_NIF_TERM eVal); #endif #if defined(SO_DEBUG) -static ERL_NIF_TERM nsetopt_lvl_sock_debug(ErlNifEnv* env, - ESockDescriptor* descP, - ERL_NIF_TERM eVal); +static ERL_NIF_TERM esock_setopt_lvl_sock_debug(ErlNifEnv* env, + ESockDescriptor* descP, + ERL_NIF_TERM eVal); #endif #if defined(SO_DONTROUTE) -static ERL_NIF_TERM nsetopt_lvl_sock_dontroute(ErlNifEnv* env, - ESockDescriptor* descP, - ERL_NIF_TERM eVal); +static ERL_NIF_TERM esock_setopt_lvl_sock_dontroute(ErlNifEnv* env, + ESockDescriptor* descP, + ERL_NIF_TERM eVal); #endif #if defined(SO_KEEPALIVE) -static ERL_NIF_TERM nsetopt_lvl_sock_keepalive(ErlNifEnv* env, - ESockDescriptor* descP, - ERL_NIF_TERM eVal); +static ERL_NIF_TERM esock_setopt_lvl_sock_keepalive(ErlNifEnv* env, + ESockDescriptor* descP, + ERL_NIF_TERM eVal); #endif #if defined(SO_LINGER) -static ERL_NIF_TERM nsetopt_lvl_sock_linger(ErlNifEnv* env, - ESockDescriptor* descP, - ERL_NIF_TERM eVal); +static ERL_NIF_TERM esock_setopt_lvl_sock_linger(ErlNifEnv* env, + ESockDescriptor* descP, + ERL_NIF_TERM eVal); #endif #if defined(SO_OOBINLINE) -static ERL_NIF_TERM nsetopt_lvl_sock_oobinline(ErlNifEnv* env, - ESockDescriptor* descP, - ERL_NIF_TERM eVal); +static ERL_NIF_TERM esock_setopt_lvl_sock_oobinline(ErlNifEnv* env, + ESockDescriptor* descP, + ERL_NIF_TERM eVal); #endif #if defined(SO_PEEK_OFF) -static ERL_NIF_TERM nsetopt_lvl_sock_peek_off(ErlNifEnv* env, - ESockDescriptor* descP, - ERL_NIF_TERM eVal); +static ERL_NIF_TERM esock_setopt_lvl_sock_peek_off(ErlNifEnv* env, + ESockDescriptor* descP, + ERL_NIF_TERM eVal); #endif #if defined(SO_PRIORITY) -static ERL_NIF_TERM nsetopt_lvl_sock_priority(ErlNifEnv* env, - ESockDescriptor* descP, - ERL_NIF_TERM eVal); +static ERL_NIF_TERM esock_setopt_lvl_sock_priority(ErlNifEnv* env, + ESockDescriptor* descP, + ERL_NIF_TERM eVal); #endif #if defined(SO_RCVBUF) -static ERL_NIF_TERM nsetopt_lvl_sock_rcvbuf(ErlNifEnv* env, - ESockDescriptor* descP, - ERL_NIF_TERM eVal); +static ERL_NIF_TERM esock_setopt_lvl_sock_rcvbuf(ErlNifEnv* env, + ESockDescriptor* descP, + ERL_NIF_TERM eVal); #endif #if defined(SO_RCVLOWAT) -static ERL_NIF_TERM nsetopt_lvl_sock_rcvlowat(ErlNifEnv* env, - ESockDescriptor* descP, - ERL_NIF_TERM eVal); +static ERL_NIF_TERM esock_setopt_lvl_sock_rcvlowat(ErlNifEnv* env, + ESockDescriptor* descP, + ERL_NIF_TERM eVal); #endif #if defined(SO_RCVTIMEO) -static ERL_NIF_TERM nsetopt_lvl_sock_rcvtimeo(ErlNifEnv* env, - ESockDescriptor* descP, - ERL_NIF_TERM eVal); +static ERL_NIF_TERM esock_setopt_lvl_sock_rcvtimeo(ErlNifEnv* env, + ESockDescriptor* descP, + ERL_NIF_TERM eVal); #endif #if defined(SO_REUSEADDR) -static ERL_NIF_TERM nsetopt_lvl_sock_reuseaddr(ErlNifEnv* env, - ESockDescriptor* descP, - ERL_NIF_TERM eVal); +static ERL_NIF_TERM esock_setopt_lvl_sock_reuseaddr(ErlNifEnv* env, + ESockDescriptor* descP, + ERL_NIF_TERM eVal); #endif #if defined(SO_REUSEPORT) -static ERL_NIF_TERM nsetopt_lvl_sock_reuseport(ErlNifEnv* env, - ESockDescriptor* descP, - ERL_NIF_TERM eVal); +static ERL_NIF_TERM esock_setopt_lvl_sock_reuseport(ErlNifEnv* env, + ESockDescriptor* descP, + ERL_NIF_TERM eVal); #endif #if defined(SO_SNDBUF) -static ERL_NIF_TERM nsetopt_lvl_sock_sndbuf(ErlNifEnv* env, - ESockDescriptor* descP, - ERL_NIF_TERM eVal); +static ERL_NIF_TERM esock_setopt_lvl_sock_sndbuf(ErlNifEnv* env, + ESockDescriptor* descP, + ERL_NIF_TERM eVal); #endif #if defined(SO_SNDLOWAT) -static ERL_NIF_TERM nsetopt_lvl_sock_sndlowat(ErlNifEnv* env, - ESockDescriptor* descP, - ERL_NIF_TERM eVal); +static ERL_NIF_TERM esock_setopt_lvl_sock_sndlowat(ErlNifEnv* env, + ESockDescriptor* descP, + ERL_NIF_TERM eVal); #endif #if defined(SO_SNDTIMEO) -static ERL_NIF_TERM nsetopt_lvl_sock_sndtimeo(ErlNifEnv* env, - ESockDescriptor* descP, - ERL_NIF_TERM eVal); +static ERL_NIF_TERM esock_setopt_lvl_sock_sndtimeo(ErlNifEnv* env, + ESockDescriptor* descP, + ERL_NIF_TERM eVal); #endif #if defined(SO_TIMESTAMP) -static ERL_NIF_TERM nsetopt_lvl_sock_timestamp(ErlNifEnv* env, - ESockDescriptor* descP, - ERL_NIF_TERM eVal); +static ERL_NIF_TERM esock_setopt_lvl_sock_timestamp(ErlNifEnv* env, + ESockDescriptor* descP, + ERL_NIF_TERM eVal); #endif -static ERL_NIF_TERM nsetopt_lvl_ip(ErlNifEnv* env, - ESockDescriptor* descP, - int eOpt, - ERL_NIF_TERM eVal); +static ERL_NIF_TERM esock_setopt_lvl_ip(ErlNifEnv* env, + ESockDescriptor* descP, + int eOpt, + ERL_NIF_TERM eVal); /* *** Handling set of socket options for level = ip *** */ #if defined(IP_ADD_MEMBERSHIP) -static ERL_NIF_TERM nsetopt_lvl_ip_add_membership(ErlNifEnv* env, - ESockDescriptor* descP, - ERL_NIF_TERM eVal); +static ERL_NIF_TERM esock_setopt_lvl_ip_add_membership(ErlNifEnv* env, + ESockDescriptor* descP, + ERL_NIF_TERM eVal); #endif #if defined(IP_ADD_SOURCE_MEMBERSHIP) -static ERL_NIF_TERM nsetopt_lvl_ip_add_source_membership(ErlNifEnv* env, - ESockDescriptor* descP, - ERL_NIF_TERM eVal); +static ERL_NIF_TERM esock_setopt_lvl_ip_add_source_membership(ErlNifEnv* env, + ESockDescriptor* descP, + ERL_NIF_TERM eVal); #endif #if defined(IP_BLOCK_SOURCE) -static ERL_NIF_TERM nsetopt_lvl_ip_block_source(ErlNifEnv* env, - ESockDescriptor* descP, - ERL_NIF_TERM eVal); +static ERL_NIF_TERM esock_setopt_lvl_ip_block_source(ErlNifEnv* env, + ESockDescriptor* descP, + ERL_NIF_TERM eVal); #endif #if defined(IP_DROP_MEMBERSHIP) -static ERL_NIF_TERM nsetopt_lvl_ip_drop_membership(ErlNifEnv* env, - ESockDescriptor* descP, - ERL_NIF_TERM eVal); +static ERL_NIF_TERM esock_setopt_lvl_ip_drop_membership(ErlNifEnv* env, + ESockDescriptor* descP, + ERL_NIF_TERM eVal); #endif #if defined(IP_DROP_SOURCE_MEMBERSHIP) -static ERL_NIF_TERM nsetopt_lvl_ip_drop_source_membership(ErlNifEnv* env, - ESockDescriptor* descP, - ERL_NIF_TERM eVal); +static ERL_NIF_TERM esock_setopt_lvl_ip_drop_source_membership(ErlNifEnv* env, + ESockDescriptor* descP, + ERL_NIF_TERM eVal); #endif #if defined(IP_FREEBIND) -static ERL_NIF_TERM nsetopt_lvl_ip_freebind(ErlNifEnv* env, - ESockDescriptor* descP, - ERL_NIF_TERM eVal); +static ERL_NIF_TERM esock_setopt_lvl_ip_freebind(ErlNifEnv* env, + ESockDescriptor* descP, + ERL_NIF_TERM eVal); #endif #if defined(IP_HDRINCL) -static ERL_NIF_TERM nsetopt_lvl_ip_hdrincl(ErlNifEnv* env, - ESockDescriptor* descP, - ERL_NIF_TERM eVal); +static ERL_NIF_TERM esock_setopt_lvl_ip_hdrincl(ErlNifEnv* env, + ESockDescriptor* descP, + ERL_NIF_TERM eVal); #endif #if defined(IP_MINTTL) -static ERL_NIF_TERM nsetopt_lvl_ip_minttl(ErlNifEnv* env, - ESockDescriptor* descP, - ERL_NIF_TERM eVal); +static ERL_NIF_TERM esock_setopt_lvl_ip_minttl(ErlNifEnv* env, + ESockDescriptor* descP, + ERL_NIF_TERM eVal); #endif #if defined(IP_MSFILTER) && defined(IP_MSFILTER_SIZE) -static ERL_NIF_TERM nsetopt_lvl_ip_msfilter(ErlNifEnv* env, - ESockDescriptor* descP, - ERL_NIF_TERM eVal); +static ERL_NIF_TERM esock_setopt_lvl_ip_msfilter(ErlNifEnv* env, + ESockDescriptor* descP, + ERL_NIF_TERM eVal); static BOOLEAN_T decode_ip_msfilter_mode(ErlNifEnv* env, ERL_NIF_TERM eVal, Uint32* mode); -static ERL_NIF_TERM nsetopt_lvl_ip_msfilter_set(ErlNifEnv* env, - SOCKET sock, - struct ip_msfilter* msfP, - SOCKLEN_T optLen); +static ERL_NIF_TERM esock_setopt_lvl_ip_msfilter_set(ErlNifEnv* env, + SOCKET sock, + struct ip_msfilter* msfP, + SOCKLEN_T optLen); #endif #if defined(IP_MTU_DISCOVER) -static ERL_NIF_TERM nsetopt_lvl_ip_mtu_discover(ErlNifEnv* env, - ESockDescriptor* descP, - ERL_NIF_TERM eVal); +static ERL_NIF_TERM esock_setopt_lvl_ip_mtu_discover(ErlNifEnv* env, + ESockDescriptor* descP, + ERL_NIF_TERM eVal); #endif #if defined(IP_MULTICAST_ALL) -static ERL_NIF_TERM nsetopt_lvl_ip_multicast_all(ErlNifEnv* env, - ESockDescriptor* descP, - ERL_NIF_TERM eVal); +static ERL_NIF_TERM esock_setopt_lvl_ip_multicast_all(ErlNifEnv* env, + ESockDescriptor* descP, + ERL_NIF_TERM eVal); #endif #if defined(IP_MULTICAST_IF) -static ERL_NIF_TERM nsetopt_lvl_ip_multicast_if(ErlNifEnv* env, - ESockDescriptor* descP, - ERL_NIF_TERM eVal); +static ERL_NIF_TERM esock_setopt_lvl_ip_multicast_if(ErlNifEnv* env, + ESockDescriptor* descP, + ERL_NIF_TERM eVal); #endif #if defined(IP_MULTICAST_LOOP) -static ERL_NIF_TERM nsetopt_lvl_ip_multicast_loop(ErlNifEnv* env, - ESockDescriptor* descP, - ERL_NIF_TERM eVal); +static ERL_NIF_TERM esock_setopt_lvl_ip_multicast_loop(ErlNifEnv* env, + ESockDescriptor* descP, + ERL_NIF_TERM eVal); #endif #if defined(IP_MULTICAST_TTL) -static ERL_NIF_TERM nsetopt_lvl_ip_multicast_ttl(ErlNifEnv* env, - ESockDescriptor* descP, - ERL_NIF_TERM eVal); +static ERL_NIF_TERM esock_setopt_lvl_ip_multicast_ttl(ErlNifEnv* env, + ESockDescriptor* descP, + ERL_NIF_TERM eVal); #endif #if defined(IP_NODEFRAG) -static ERL_NIF_TERM nsetopt_lvl_ip_nodefrag(ErlNifEnv* env, - ESockDescriptor* descP, - ERL_NIF_TERM eVal); +static ERL_NIF_TERM esock_setopt_lvl_ip_nodefrag(ErlNifEnv* env, + ESockDescriptor* descP, + ERL_NIF_TERM eVal); #endif #if defined(IP_PKTINFO) -static ERL_NIF_TERM nsetopt_lvl_ip_pktinfo(ErlNifEnv* env, - ESockDescriptor* descP, - ERL_NIF_TERM eVal); +static ERL_NIF_TERM esock_setopt_lvl_ip_pktinfo(ErlNifEnv* env, + ESockDescriptor* descP, + ERL_NIF_TERM eVal); #endif #if defined(IP_RECVDSTADDR) -static ERL_NIF_TERM nsetopt_lvl_ip_recvdstaddr(ErlNifEnv* env, - ESockDescriptor* descP, - ERL_NIF_TERM eVal); +static ERL_NIF_TERM esock_setopt_lvl_ip_recvdstaddr(ErlNifEnv* env, + ESockDescriptor* descP, + ERL_NIF_TERM eVal); #endif #if defined(IP_RECVERR) -static ERL_NIF_TERM nsetopt_lvl_ip_recverr(ErlNifEnv* env, - ESockDescriptor* descP, - ERL_NIF_TERM eVal); +static ERL_NIF_TERM esock_setopt_lvl_ip_recverr(ErlNifEnv* env, + ESockDescriptor* descP, + ERL_NIF_TERM eVal); #endif #if defined(IP_RECVIF) -static ERL_NIF_TERM nsetopt_lvl_ip_recvif(ErlNifEnv* env, - ESockDescriptor* descP, - ERL_NIF_TERM eVal); +static ERL_NIF_TERM esock_setopt_lvl_ip_recvif(ErlNifEnv* env, + ESockDescriptor* descP, + ERL_NIF_TERM eVal); #endif #if defined(IP_RECVOPTS) -static ERL_NIF_TERM nsetopt_lvl_ip_recvopts(ErlNifEnv* env, - ESockDescriptor* descP, - ERL_NIF_TERM eVal); +static ERL_NIF_TERM esock_setopt_lvl_ip_recvopts(ErlNifEnv* env, + ESockDescriptor* descP, + ERL_NIF_TERM eVal); #endif #if defined(IP_RECVORIGDSTADDR) -static ERL_NIF_TERM nsetopt_lvl_ip_recvorigdstaddr(ErlNifEnv* env, - ESockDescriptor* descP, - ERL_NIF_TERM eVal); +static ERL_NIF_TERM esock_setopt_lvl_ip_recvorigdstaddr(ErlNifEnv* env, + ESockDescriptor* descP, + ERL_NIF_TERM eVal); #endif #if defined(IP_RECVTOS) -static ERL_NIF_TERM nsetopt_lvl_ip_recvtos(ErlNifEnv* env, - ESockDescriptor* descP, - ERL_NIF_TERM eVal); +static ERL_NIF_TERM esock_setopt_lvl_ip_recvtos(ErlNifEnv* env, + ESockDescriptor* descP, + ERL_NIF_TERM eVal); #endif #if defined(IP_RECVTTL) -static ERL_NIF_TERM nsetopt_lvl_ip_recvttl(ErlNifEnv* env, - ESockDescriptor* descP, - ERL_NIF_TERM eVal); +static ERL_NIF_TERM esock_setopt_lvl_ip_recvttl(ErlNifEnv* env, + ESockDescriptor* descP, + ERL_NIF_TERM eVal); #endif #if defined(IP_RETOPTS) -static ERL_NIF_TERM nsetopt_lvl_ip_retopts(ErlNifEnv* env, - ESockDescriptor* descP, - ERL_NIF_TERM eVal); -#endif -#if defined(IP_ROUTER_ALERT) -static ERL_NIF_TERM nsetopt_lvl_ip_router_alert(ErlNifEnv* env, +static ERL_NIF_TERM esock_setopt_lvl_ip_retopts(ErlNifEnv* env, ESockDescriptor* descP, ERL_NIF_TERM eVal); #endif +#if defined(IP_ROUTER_ALERT) +static ERL_NIF_TERM esock_setopt_lvl_ip_router_alert(ErlNifEnv* env, + ESockDescriptor* descP, + ERL_NIF_TERM eVal); +#endif #if defined(IP_SENDSRCADDR) -static ERL_NIF_TERM nsetopt_lvl_ip_sendsrcaddr(ErlNifEnv* env, - ESockDescriptor* descP, - ERL_NIF_TERM eVal); +static ERL_NIF_TERM esock_setopt_lvl_ip_sendsrcaddr(ErlNifEnv* env, + ESockDescriptor* descP, + ERL_NIF_TERM eVal); #endif #if defined(IP_TOS) -static ERL_NIF_TERM nsetopt_lvl_ip_tos(ErlNifEnv* env, - ESockDescriptor* descP, - ERL_NIF_TERM eVal); +static ERL_NIF_TERM esock_setopt_lvl_ip_tos(ErlNifEnv* env, + ESockDescriptor* descP, + ERL_NIF_TERM eVal); #endif #if defined(IP_TRANSPARENT) -static ERL_NIF_TERM nsetopt_lvl_ip_transparent(ErlNifEnv* env, - ESockDescriptor* descP, - ERL_NIF_TERM eVal); +static ERL_NIF_TERM esock_setopt_lvl_ip_transparent(ErlNifEnv* env, + ESockDescriptor* descP, + ERL_NIF_TERM eVal); #endif #if defined(IP_TTL) -static ERL_NIF_TERM nsetopt_lvl_ip_ttl(ErlNifEnv* env, - ESockDescriptor* descP, - ERL_NIF_TERM eVal); +static ERL_NIF_TERM esock_setopt_lvl_ip_ttl(ErlNifEnv* env, + ESockDescriptor* descP, + ERL_NIF_TERM eVal); #endif #if defined(IP_UNBLOCK_SOURCE) -static ERL_NIF_TERM nsetopt_lvl_ip_unblock_source(ErlNifEnv* env, - ESockDescriptor* descP, - ERL_NIF_TERM eVal); +static ERL_NIF_TERM esock_setopt_lvl_ip_unblock_source(ErlNifEnv* env, + ESockDescriptor* descP, + ERL_NIF_TERM eVal); #endif #if defined(IP_DROP_MEMBERSHIP) || defined(IP_ADD_MEMBERSHIP) static -ERL_NIF_TERM nsetopt_lvl_ip_update_membership(ErlNifEnv* env, - ESockDescriptor* descP, - ERL_NIF_TERM eVal, - int opt); +ERL_NIF_TERM esock_setopt_lvl_ip_update_membership(ErlNifEnv* env, + ESockDescriptor* descP, + ERL_NIF_TERM eVal, + int opt); #endif #if defined(IP_ADD_SOURCE_MEMBERSHIP) || defined(IP_DROP_SOURCE_MEMBERSHIP) || defined(IP_BLOCK_SOURCE) || defined(IP_UNBLOCK_SOURCE) static -ERL_NIF_TERM nsetopt_lvl_ip_update_source(ErlNifEnv* env, - ESockDescriptor* descP, - ERL_NIF_TERM eVal, - int opt); +ERL_NIF_TERM esock_setopt_lvl_ip_update_source(ErlNifEnv* env, + ESockDescriptor* descP, + ERL_NIF_TERM eVal, + int opt); #endif /* *** Handling set of socket options for level = ipv6 *** */ #if defined(HAVE_IPV6) -static ERL_NIF_TERM nsetopt_lvl_ipv6(ErlNifEnv* env, - ESockDescriptor* descP, - int eOpt, - ERL_NIF_TERM eVal); +static ERL_NIF_TERM esock_setopt_lvl_ipv6(ErlNifEnv* env, + ESockDescriptor* descP, + int eOpt, + ERL_NIF_TERM eVal); #if defined(IPV6_ADDRFORM) -static ERL_NIF_TERM nsetopt_lvl_ipv6_addrform(ErlNifEnv* env, - ESockDescriptor* descP, - ERL_NIF_TERM eVal); +static ERL_NIF_TERM esock_setopt_lvl_ipv6_addrform(ErlNifEnv* env, + ESockDescriptor* descP, + ERL_NIF_TERM eVal); #endif #if defined(IPV6_ADD_MEMBERSHIP) -static ERL_NIF_TERM nsetopt_lvl_ipv6_add_membership(ErlNifEnv* env, - ESockDescriptor* descP, - ERL_NIF_TERM eVal); +static ERL_NIF_TERM esock_setopt_lvl_ipv6_add_membership(ErlNifEnv* env, + ESockDescriptor* descP, + ERL_NIF_TERM eVal); #endif #if defined(IPV6_AUTHHDR) -static ERL_NIF_TERM nsetopt_lvl_ipv6_authhdr(ErlNifEnv* env, - ESockDescriptor* descP, - ERL_NIF_TERM eVal); +static ERL_NIF_TERM esock_setopt_lvl_ipv6_authhdr(ErlNifEnv* env, + ESockDescriptor* descP, + ERL_NIF_TERM eVal); #endif #if defined(IPV6_DROP_MEMBERSHIP) -static ERL_NIF_TERM nsetopt_lvl_ipv6_drop_membership(ErlNifEnv* env, - ESockDescriptor* descP, - ERL_NIF_TERM eVal); +static ERL_NIF_TERM esock_setopt_lvl_ipv6_drop_membership(ErlNifEnv* env, + ESockDescriptor* descP, + ERL_NIF_TERM eVal); #endif #if defined(IPV6_DSTOPTS) -static ERL_NIF_TERM nsetopt_lvl_ipv6_dstopts(ErlNifEnv* env, - ESockDescriptor* descP, - ERL_NIF_TERM eVal); +static ERL_NIF_TERM esock_setopt_lvl_ipv6_dstopts(ErlNifEnv* env, + ESockDescriptor* descP, + ERL_NIF_TERM eVal); #endif #if defined(IPV6_FLOWINFO) -static ERL_NIF_TERM nsetopt_lvl_ipv6_flowinfo(ErlNifEnv* env, - ESockDescriptor* descP, - ERL_NIF_TERM eVal); +static ERL_NIF_TERM esock_setopt_lvl_ipv6_flowinfo(ErlNifEnv* env, + ESockDescriptor* descP, + ERL_NIF_TERM eVal); #endif #if defined(IPV6_HOPLIMIT) -static ERL_NIF_TERM nsetopt_lvl_ipv6_hoplimit(ErlNifEnv* env, - ESockDescriptor* descP, - ERL_NIF_TERM eVal); +static ERL_NIF_TERM esock_setopt_lvl_ipv6_hoplimit(ErlNifEnv* env, + ESockDescriptor* descP, + ERL_NIF_TERM eVal); #endif #if defined(IPV6_HOPOPTS) -static ERL_NIF_TERM nsetopt_lvl_ipv6_hopopts(ErlNifEnv* env, - ESockDescriptor* descP, - ERL_NIF_TERM eVal); +static ERL_NIF_TERM esock_setopt_lvl_ipv6_hopopts(ErlNifEnv* env, + ESockDescriptor* descP, + ERL_NIF_TERM eVal); #endif #if defined(IPV6_MTU) -static ERL_NIF_TERM nsetopt_lvl_ipv6_mtu(ErlNifEnv* env, - ESockDescriptor* descP, - ERL_NIF_TERM eVal); +static ERL_NIF_TERM esock_setopt_lvl_ipv6_mtu(ErlNifEnv* env, + ESockDescriptor* descP, + ERL_NIF_TERM eVal); #endif #if defined(IPV6_MTU_DISCOVER) -static ERL_NIF_TERM nsetopt_lvl_ipv6_mtu_discover(ErlNifEnv* env, - ESockDescriptor* descP, - ERL_NIF_TERM eVal); +static ERL_NIF_TERM esock_setopt_lvl_ipv6_mtu_discover(ErlNifEnv* env, + ESockDescriptor* descP, + ERL_NIF_TERM eVal); #endif #if defined(IPV6_MULTICAST_HOPS) -static ERL_NIF_TERM nsetopt_lvl_ipv6_multicast_hops(ErlNifEnv* env, - ESockDescriptor* descP, - ERL_NIF_TERM eVal); +static ERL_NIF_TERM esock_setopt_lvl_ipv6_multicast_hops(ErlNifEnv* env, + ESockDescriptor* descP, + ERL_NIF_TERM eVal); #endif #if defined(IPV6_MULTICAST_IF) -static ERL_NIF_TERM nsetopt_lvl_ipv6_multicast_if(ErlNifEnv* env, - ESockDescriptor* descP, - ERL_NIF_TERM eVal); +static ERL_NIF_TERM esock_setopt_lvl_ipv6_multicast_if(ErlNifEnv* env, + ESockDescriptor* descP, + ERL_NIF_TERM eVal); #endif #if defined(IPV6_MULTICAST_LOOP) -static ERL_NIF_TERM nsetopt_lvl_ipv6_multicast_loop(ErlNifEnv* env, - ESockDescriptor* descP, - ERL_NIF_TERM eVal); +static ERL_NIF_TERM esock_setopt_lvl_ipv6_multicast_loop(ErlNifEnv* env, + ESockDescriptor* descP, + ERL_NIF_TERM eVal); #endif #if defined(IPV6_RECVERR) -static ERL_NIF_TERM nsetopt_lvl_ipv6_recverr(ErlNifEnv* env, - ESockDescriptor* descP, - ERL_NIF_TERM eVal); +static ERL_NIF_TERM esock_setopt_lvl_ipv6_recverr(ErlNifEnv* env, + ESockDescriptor* descP, + ERL_NIF_TERM eVal); #endif #if defined(IPV6_RECVPKTINFO) || defined(IPV6_PKTINFO) -static ERL_NIF_TERM nsetopt_lvl_ipv6_recvpktinfo(ErlNifEnv* env, - ESockDescriptor* descP, - ERL_NIF_TERM eVal); +static ERL_NIF_TERM esock_setopt_lvl_ipv6_recvpktinfo(ErlNifEnv* env, + ESockDescriptor* descP, + ERL_NIF_TERM eVal); #endif #if defined(IPV6_ROUTER_ALERT) -static ERL_NIF_TERM nsetopt_lvl_ipv6_router_alert(ErlNifEnv* env, - ESockDescriptor* descP, - ERL_NIF_TERM eVal); +static ERL_NIF_TERM esock_setopt_lvl_ipv6_router_alert(ErlNifEnv* env, + ESockDescriptor* descP, + ERL_NIF_TERM eVal); #endif #if defined(IPV6_RTHDR) -static ERL_NIF_TERM nsetopt_lvl_ipv6_rthdr(ErlNifEnv* env, - ESockDescriptor* descP, - ERL_NIF_TERM eVal); +static ERL_NIF_TERM esock_setopt_lvl_ipv6_rthdr(ErlNifEnv* env, + ESockDescriptor* descP, + ERL_NIF_TERM eVal); #endif #if defined(IPV6_UNICAST_HOPS) -static ERL_NIF_TERM nsetopt_lvl_ipv6_unicast_hops(ErlNifEnv* env, - ESockDescriptor* descP, - ERL_NIF_TERM eVal); +static ERL_NIF_TERM esock_setopt_lvl_ipv6_unicast_hops(ErlNifEnv* env, + ESockDescriptor* descP, + ERL_NIF_TERM eVal); #endif #if defined(IPV6_V6ONLY) -static ERL_NIF_TERM nsetopt_lvl_ipv6_v6only(ErlNifEnv* env, - ESockDescriptor* descP, - ERL_NIF_TERM eVal); +static ERL_NIF_TERM esock_setopt_lvl_ipv6_v6only(ErlNifEnv* env, + ESockDescriptor* descP, + ERL_NIF_TERM eVal); #endif #if defined(IPV6_ADD_MEMBERSHIP) || defined(IPV6_DROP_MEMBERSHIP) -static ERL_NIF_TERM nsetopt_lvl_ipv6_update_membership(ErlNifEnv* env, - ESockDescriptor* descP, - ERL_NIF_TERM eVal, - int opt); +static ERL_NIF_TERM esock_setopt_lvl_ipv6_update_membership(ErlNifEnv* env, + ESockDescriptor* descP, + ERL_NIF_TERM eVal, + int opt); #endif #endif // defined(HAVE_IPV6) -static ERL_NIF_TERM nsetopt_lvl_tcp(ErlNifEnv* env, - ESockDescriptor* descP, - int eOpt, - ERL_NIF_TERM eVal); +static ERL_NIF_TERM esock_setopt_lvl_tcp(ErlNifEnv* env, + ESockDescriptor* descP, + int eOpt, + ERL_NIF_TERM eVal); #if defined(TCP_CONGESTION) -static ERL_NIF_TERM nsetopt_lvl_tcp_congestion(ErlNifEnv* env, - ESockDescriptor* descP, - ERL_NIF_TERM eVal); +static ERL_NIF_TERM esock_setopt_lvl_tcp_congestion(ErlNifEnv* env, + ESockDescriptor* descP, + ERL_NIF_TERM eVal); #endif #if defined(TCP_MAXSEG) -static ERL_NIF_TERM nsetopt_lvl_tcp_maxseg(ErlNifEnv* env, - ESockDescriptor* descP, - ERL_NIF_TERM eVal); +static ERL_NIF_TERM esock_setopt_lvl_tcp_maxseg(ErlNifEnv* env, + ESockDescriptor* descP, + ERL_NIF_TERM eVal); #endif #if defined(TCP_NODELAY) -static ERL_NIF_TERM nsetopt_lvl_tcp_nodelay(ErlNifEnv* env, - ESockDescriptor* descP, - ERL_NIF_TERM eVal); +static ERL_NIF_TERM esock_setopt_lvl_tcp_nodelay(ErlNifEnv* env, + ESockDescriptor* descP, + ERL_NIF_TERM eVal); #endif -static ERL_NIF_TERM nsetopt_lvl_udp(ErlNifEnv* env, - ESockDescriptor* descP, - int eOpt, - ERL_NIF_TERM eVal); -#if defined(UDP_CORK) -static ERL_NIF_TERM nsetopt_lvl_udp_cork(ErlNifEnv* env, +static ERL_NIF_TERM esock_setopt_lvl_udp(ErlNifEnv* env, ESockDescriptor* descP, + int eOpt, ERL_NIF_TERM eVal); +#if defined(UDP_CORK) +static ERL_NIF_TERM esock_setopt_lvl_udp_cork(ErlNifEnv* env, + ESockDescriptor* descP, + ERL_NIF_TERM eVal); #endif #if defined(HAVE_SCTP) -static ERL_NIF_TERM nsetopt_lvl_sctp(ErlNifEnv* env, - ESockDescriptor* descP, - int eOpt, - ERL_NIF_TERM eVal); +static ERL_NIF_TERM esock_setopt_lvl_sctp(ErlNifEnv* env, + ESockDescriptor* descP, + int eOpt, + ERL_NIF_TERM eVal); #if defined(SCTP_ASSOCINFO) -static ERL_NIF_TERM nsetopt_lvl_sctp_associnfo(ErlNifEnv* env, - ESockDescriptor* descP, - ERL_NIF_TERM eVal); +static ERL_NIF_TERM esock_setopt_lvl_sctp_associnfo(ErlNifEnv* env, + ESockDescriptor* descP, + ERL_NIF_TERM eVal); #endif #if defined(SCTP_AUTOCLOSE) -static ERL_NIF_TERM nsetopt_lvl_sctp_autoclose(ErlNifEnv* env, - ESockDescriptor* descP, - ERL_NIF_TERM eVal); +static ERL_NIF_TERM esock_setopt_lvl_sctp_autoclose(ErlNifEnv* env, + ESockDescriptor* descP, + ERL_NIF_TERM eVal); #endif #if defined(SCTP_DISABLE_FRAGMENTS) -static ERL_NIF_TERM nsetopt_lvl_sctp_disable_fragments(ErlNifEnv* env, - ESockDescriptor* descP, - ERL_NIF_TERM eVal); +static ERL_NIF_TERM esock_setopt_lvl_sctp_disable_fragments(ErlNifEnv* env, + ESockDescriptor* descP, + ERL_NIF_TERM eVal); #endif #if defined(SCTP_EVENTS) -static ERL_NIF_TERM nsetopt_lvl_sctp_events(ErlNifEnv* env, - ESockDescriptor* descP, - ERL_NIF_TERM eVal); +static ERL_NIF_TERM esock_setopt_lvl_sctp_events(ErlNifEnv* env, + ESockDescriptor* descP, + ERL_NIF_TERM eVal); #endif #if defined(SCTP_INITMSG) -static ERL_NIF_TERM nsetopt_lvl_sctp_initmsg(ErlNifEnv* env, - ESockDescriptor* descP, - ERL_NIF_TERM eVal); +static ERL_NIF_TERM esock_setopt_lvl_sctp_initmsg(ErlNifEnv* env, + ESockDescriptor* descP, + ERL_NIF_TERM eVal); #endif #if defined(SCTP_MAXSEG) -static ERL_NIF_TERM nsetopt_lvl_sctp_maxseg(ErlNifEnv* env, - ESockDescriptor* descP, - ERL_NIF_TERM eVal); +static ERL_NIF_TERM esock_setopt_lvl_sctp_maxseg(ErlNifEnv* env, + ESockDescriptor* descP, + ERL_NIF_TERM eVal); #endif #if defined(SCTP_NODELAY) -static ERL_NIF_TERM nsetopt_lvl_sctp_nodelay(ErlNifEnv* env, - ESockDescriptor* descP, - ERL_NIF_TERM eVal); +static ERL_NIF_TERM esock_setopt_lvl_sctp_nodelay(ErlNifEnv* env, + ESockDescriptor* descP, + ERL_NIF_TERM eVal); #endif #if defined(SCTP_RTOINFO) -static ERL_NIF_TERM nsetopt_lvl_sctp_rtoinfo(ErlNifEnv* env, - ESockDescriptor* descP, - ERL_NIF_TERM eVal); +static ERL_NIF_TERM esock_setopt_lvl_sctp_rtoinfo(ErlNifEnv* env, + ESockDescriptor* descP, + ERL_NIF_TERM eVal); #endif #endif // defined(HAVE_SCTP) -static ERL_NIF_TERM ngetopt(ErlNifEnv* env, - ESockDescriptor* descP, - BOOLEAN_T isEncoded, - BOOLEAN_T isOTP, - int level, - ERL_NIF_TERM eOpt); +static ERL_NIF_TERM esock_getopt(ErlNifEnv* env, + ESockDescriptor* descP, + BOOLEAN_T isEncoded, + BOOLEAN_T isOTP, + int level, + ERL_NIF_TERM eOpt); -static ERL_NIF_TERM ngetopt_otp(ErlNifEnv* env, - ESockDescriptor* descP, - int eOpt); -/* *** ngetopt_otp_debug *** - * *** ngetopt_otp_iow *** - * *** ngetopt_otp_ctrl_proc *** - * *** ngetopt_otp_rcvbuf *** - * *** ngetopt_otp_rcvctrlbuf *** - * *** ngetopt_otp_sndctrlbuf *** - * *** ngetopt_otp_fd *** - * *** ngetopt_otp_domain *** - * *** ngetopt_otp_type *** - * *** ngetopt_otp_protocol *** - */ -#define NGETOPT_OTP_FUNCS \ - NGETOPT_OTP_FUNC_DEF(debug); \ - NGETOPT_OTP_FUNC_DEF(iow); \ - NGETOPT_OTP_FUNC_DEF(ctrl_proc); \ - NGETOPT_OTP_FUNC_DEF(rcvbuf); \ - NGETOPT_OTP_FUNC_DEF(rcvctrlbuf); \ - NGETOPT_OTP_FUNC_DEF(sndctrlbuf); \ - NGETOPT_OTP_FUNC_DEF(fd); \ - NGETOPT_OTP_FUNC_DEF(domain); \ - NGETOPT_OTP_FUNC_DEF(type); \ - NGETOPT_OTP_FUNC_DEF(protocol); -#define NGETOPT_OTP_FUNC_DEF(F) \ - static ERL_NIF_TERM ngetopt_otp_##F(ErlNifEnv* env, \ - ESockDescriptor* descP) -NGETOPT_OTP_FUNCS -#undef NGETOPT_OTP_FUNC_DEF +static ERL_NIF_TERM esock_getopt_otp(ErlNifEnv* env, + ESockDescriptor* descP, + int eOpt); +/* *** esock_getopt_otp_debug *** + * *** esock_getopt_otp_iow *** + * *** esock_getopt_otp_ctrl_proc *** + * *** esock_getopt_otp_rcvbuf *** + * *** esock_getopt_otp_rcvctrlbuf *** + * *** esock_getopt_otp_sndctrlbuf *** + * *** esock_getopt_otp_fd *** + * *** esock_getopt_otp_domain *** + * *** esock_getopt_otp_type *** + * *** esock_getopt_otp_protocol *** + */ +#define ESOCK_GETOPT_OTP_FUNCS \ + ESOCK_GETOPT_OTP_FUNC_DEF(debug); \ + ESOCK_GETOPT_OTP_FUNC_DEF(iow); \ + ESOCK_GETOPT_OTP_FUNC_DEF(ctrl_proc); \ + ESOCK_GETOPT_OTP_FUNC_DEF(rcvbuf); \ + ESOCK_GETOPT_OTP_FUNC_DEF(rcvctrlbuf); \ + ESOCK_GETOPT_OTP_FUNC_DEF(sndctrlbuf); \ + ESOCK_GETOPT_OTP_FUNC_DEF(fd); \ + ESOCK_GETOPT_OTP_FUNC_DEF(domain); \ + ESOCK_GETOPT_OTP_FUNC_DEF(type); \ + ESOCK_GETOPT_OTP_FUNC_DEF(protocol); +#define ESOCK_GETOPT_OTP_FUNC_DEF(F) \ + static ERL_NIF_TERM esock_getopt_otp_##F(ErlNifEnv* env, \ + ESockDescriptor* descP) +ESOCK_GETOPT_OTP_FUNCS +#undef ESOCK_GETOPT_OTP_FUNC_DEF -static ERL_NIF_TERM ngetopt_native(ErlNifEnv* env, - ESockDescriptor* descP, - int level, - ERL_NIF_TERM eOpt); -static ERL_NIF_TERM ngetopt_native_unspec(ErlNifEnv* env, - ESockDescriptor* descP, - int level, - int opt, - SOCKOPTLEN_T valueSz); -static ERL_NIF_TERM ngetopt_level(ErlNifEnv* env, - ESockDescriptor* descP, - int level, - int eOpt); -static ERL_NIF_TERM ngetopt_lvl_socket(ErlNifEnv* env, +static ERL_NIF_TERM esock_getopt_native(ErlNifEnv* env, + ESockDescriptor* descP, + int level, + ERL_NIF_TERM eOpt); +static ERL_NIF_TERM esock_getopt_native_unspec(ErlNifEnv* env, + ESockDescriptor* descP, + int level, + int opt, + SOCKOPTLEN_T valueSz); +static ERL_NIF_TERM esock_getopt_level(ErlNifEnv* env, ESockDescriptor* descP, + int level, int eOpt); +static ERL_NIF_TERM esock_getopt_lvl_socket(ErlNifEnv* env, + ESockDescriptor* descP, + int eOpt); #if defined(SO_ACCEPTCONN) -static ERL_NIF_TERM ngetopt_lvl_sock_acceptconn(ErlNifEnv* env, - ESockDescriptor* descP); +static ERL_NIF_TERM esock_getopt_lvl_sock_acceptconn(ErlNifEnv* env, + ESockDescriptor* descP); #endif #if defined(SO_BINDTODEVICE) -static ERL_NIF_TERM ngetopt_lvl_sock_bindtodevice(ErlNifEnv* env, - ESockDescriptor* descP); +static ERL_NIF_TERM esock_getopt_lvl_sock_bindtodevice(ErlNifEnv* env, + ESockDescriptor* descP); #endif #if defined(SO_BROADCAST) -static ERL_NIF_TERM ngetopt_lvl_sock_broadcast(ErlNifEnv* env, - ESockDescriptor* descP); +static ERL_NIF_TERM esock_getopt_lvl_sock_broadcast(ErlNifEnv* env, + ESockDescriptor* descP); #endif #if defined(SO_DEBUG) -static ERL_NIF_TERM ngetopt_lvl_sock_debug(ErlNifEnv* env, - ESockDescriptor* descP); +static ERL_NIF_TERM esock_getopt_lvl_sock_debug(ErlNifEnv* env, + ESockDescriptor* descP); #endif #if defined(SO_DOMAIN) -static ERL_NIF_TERM ngetopt_lvl_sock_domain(ErlNifEnv* env, - ESockDescriptor* descP); +static ERL_NIF_TERM esock_getopt_lvl_sock_domain(ErlNifEnv* env, + ESockDescriptor* descP); #endif #if defined(SO_DONTROUTE) -static ERL_NIF_TERM ngetopt_lvl_sock_dontroute(ErlNifEnv* env, - ESockDescriptor* descP); +static ERL_NIF_TERM esock_getopt_lvl_sock_dontroute(ErlNifEnv* env, + ESockDescriptor* descP); #endif #if defined(SO_KEEPALIVE) -static ERL_NIF_TERM ngetopt_lvl_sock_keepalive(ErlNifEnv* env, - ESockDescriptor* descP); +static ERL_NIF_TERM esock_getopt_lvl_sock_keepalive(ErlNifEnv* env, + ESockDescriptor* descP); #endif #if defined(SO_LINGER) -static ERL_NIF_TERM ngetopt_lvl_sock_linger(ErlNifEnv* env, - ESockDescriptor* descP); +static ERL_NIF_TERM esock_getopt_lvl_sock_linger(ErlNifEnv* env, + ESockDescriptor* descP); #endif #if defined(SO_OOBINLINE) -static ERL_NIF_TERM ngetopt_lvl_sock_oobinline(ErlNifEnv* env, - ESockDescriptor* descP); +static ERL_NIF_TERM esock_getopt_lvl_sock_oobinline(ErlNifEnv* env, + ESockDescriptor* descP); #endif #if defined(SO_PEEK_OFF) -static ERL_NIF_TERM ngetopt_lvl_sock_peek_off(ErlNifEnv* env, - ESockDescriptor* descP); +static ERL_NIF_TERM esock_getopt_lvl_sock_peek_off(ErlNifEnv* env, + ESockDescriptor* descP); #endif #if defined(SO_PRIORITY) -static ERL_NIF_TERM ngetopt_lvl_sock_priority(ErlNifEnv* env, - ESockDescriptor* descP); +static ERL_NIF_TERM esock_getopt_lvl_sock_priority(ErlNifEnv* env, + ESockDescriptor* descP); #endif #if defined(SO_PROTOCOL) -static ERL_NIF_TERM ngetopt_lvl_sock_protocol(ErlNifEnv* env, - ESockDescriptor* descP); +static ERL_NIF_TERM esock_getopt_lvl_sock_protocol(ErlNifEnv* env, + ESockDescriptor* descP); #endif #if defined(SO_RCVBUF) -static ERL_NIF_TERM ngetopt_lvl_sock_rcvbuf(ErlNifEnv* env, - ESockDescriptor* descP); +static ERL_NIF_TERM esock_getopt_lvl_sock_rcvbuf(ErlNifEnv* env, + ESockDescriptor* descP); #endif #if defined(SO_RCVLOWAT) -static ERL_NIF_TERM ngetopt_lvl_sock_rcvlowat(ErlNifEnv* env, - ESockDescriptor* descP); +static ERL_NIF_TERM esock_getopt_lvl_sock_rcvlowat(ErlNifEnv* env, + ESockDescriptor* descP); #endif #if defined(SO_RCVTIMEO) -static ERL_NIF_TERM ngetopt_lvl_sock_rcvtimeo(ErlNifEnv* env, - ESockDescriptor* descP); +static ERL_NIF_TERM esock_getopt_lvl_sock_rcvtimeo(ErlNifEnv* env, + ESockDescriptor* descP); #endif #if defined(SO_REUSEADDR) -static ERL_NIF_TERM ngetopt_lvl_sock_reuseaddr(ErlNifEnv* env, - ESockDescriptor* descP); +static ERL_NIF_TERM esock_getopt_lvl_sock_reuseaddr(ErlNifEnv* env, + ESockDescriptor* descP); #endif #if defined(SO_REUSEPORT) -static ERL_NIF_TERM ngetopt_lvl_sock_reuseport(ErlNifEnv* env, - ESockDescriptor* descP); +static ERL_NIF_TERM esock_getopt_lvl_sock_reuseport(ErlNifEnv* env, + ESockDescriptor* descP); #endif #if defined(SO_SNDBUF) -static ERL_NIF_TERM ngetopt_lvl_sock_sndbuf(ErlNifEnv* env, - ESockDescriptor* descP); +static ERL_NIF_TERM esock_getopt_lvl_sock_sndbuf(ErlNifEnv* env, + ESockDescriptor* descP); #endif #if defined(SO_SNDLOWAT) -static ERL_NIF_TERM ngetopt_lvl_sock_sndlowat(ErlNifEnv* env, - ESockDescriptor* descP); +static ERL_NIF_TERM esock_getopt_lvl_sock_sndlowat(ErlNifEnv* env, + ESockDescriptor* descP); #endif #if defined(SO_SNDTIMEO) -static ERL_NIF_TERM ngetopt_lvl_sock_sndtimeo(ErlNifEnv* env, - ESockDescriptor* descP); +static ERL_NIF_TERM esock_getopt_lvl_sock_sndtimeo(ErlNifEnv* env, + ESockDescriptor* descP); #endif #if defined(SO_TIMESTAMP) -static ERL_NIF_TERM ngetopt_lvl_sock_timestamp(ErlNifEnv* env, - ESockDescriptor* descP); +static ERL_NIF_TERM esock_getopt_lvl_sock_timestamp(ErlNifEnv* env, + ESockDescriptor* descP); #endif #if defined(SO_TYPE) -static ERL_NIF_TERM ngetopt_lvl_sock_type(ErlNifEnv* env, - ESockDescriptor* descP); +static ERL_NIF_TERM esock_getopt_lvl_sock_type(ErlNifEnv* env, + ESockDescriptor* descP); #endif -static ERL_NIF_TERM ngetopt_lvl_ip(ErlNifEnv* env, - ESockDescriptor* descP, - int eOpt); +static ERL_NIF_TERM esock_getopt_lvl_ip(ErlNifEnv* env, + ESockDescriptor* descP, + int eOpt); #if defined(IP_FREEBIND) -static ERL_NIF_TERM ngetopt_lvl_ip_freebind(ErlNifEnv* env, - ESockDescriptor* descP); +static ERL_NIF_TERM esock_getopt_lvl_ip_freebind(ErlNifEnv* env, + ESockDescriptor* descP); #endif #if defined(IP_HDRINCL) -static ERL_NIF_TERM ngetopt_lvl_ip_hdrincl(ErlNifEnv* env, - ESockDescriptor* descP); +static ERL_NIF_TERM esock_getopt_lvl_ip_hdrincl(ErlNifEnv* env, + ESockDescriptor* descP); #endif #if defined(IP_MINTTL) -static ERL_NIF_TERM ngetopt_lvl_ip_minttl(ErlNifEnv* env, - ESockDescriptor* descP); +static ERL_NIF_TERM esock_getopt_lvl_ip_minttl(ErlNifEnv* env, + ESockDescriptor* descP); #endif #if defined(IP_MTU) -static ERL_NIF_TERM ngetopt_lvl_ip_mtu(ErlNifEnv* env, - ESockDescriptor* descP); +static ERL_NIF_TERM esock_getopt_lvl_ip_mtu(ErlNifEnv* env, + ESockDescriptor* descP); #endif #if defined(IP_MTU_DISCOVER) -static ERL_NIF_TERM ngetopt_lvl_ip_mtu_discover(ErlNifEnv* env, - ESockDescriptor* descP); +static ERL_NIF_TERM esock_getopt_lvl_ip_mtu_discover(ErlNifEnv* env, + ESockDescriptor* descP); #endif #if defined(IP_MULTICAST_ALL) -static ERL_NIF_TERM ngetopt_lvl_ip_multicast_all(ErlNifEnv* env, - ESockDescriptor* descP); +static ERL_NIF_TERM esock_getopt_lvl_ip_multicast_all(ErlNifEnv* env, + ESockDescriptor* descP); #endif #if defined(IP_MULTICAST_IF) -static ERL_NIF_TERM ngetopt_lvl_ip_multicast_if(ErlNifEnv* env, - ESockDescriptor* descP); +static ERL_NIF_TERM esock_getopt_lvl_ip_multicast_if(ErlNifEnv* env, + ESockDescriptor* descP); #endif #if defined(IP_MULTICAST_LOOP) -static ERL_NIF_TERM ngetopt_lvl_ip_multicast_loop(ErlNifEnv* env, - ESockDescriptor* descP); +static ERL_NIF_TERM esock_getopt_lvl_ip_multicast_loop(ErlNifEnv* env, + ESockDescriptor* descP); #endif #if defined(IP_MULTICAST_TTL) -static ERL_NIF_TERM ngetopt_lvl_ip_multicast_ttl(ErlNifEnv* env, - ESockDescriptor* descP); +static ERL_NIF_TERM esock_getopt_lvl_ip_multicast_ttl(ErlNifEnv* env, + ESockDescriptor* descP); #endif #if defined(IP_NODEFRAG) -static ERL_NIF_TERM ngetopt_lvl_ip_nodefrag(ErlNifEnv* env, - ESockDescriptor* descP); +static ERL_NIF_TERM esock_getopt_lvl_ip_nodefrag(ErlNifEnv* env, + ESockDescriptor* descP); #endif #if defined(IP_PKTINFO) -static ERL_NIF_TERM ngetopt_lvl_ip_pktinfo(ErlNifEnv* env, - ESockDescriptor* descP); +static ERL_NIF_TERM esock_getopt_lvl_ip_pktinfo(ErlNifEnv* env, + ESockDescriptor* descP); #endif #if defined(IP_RECVDSTADDR) -static ERL_NIF_TERM ngetopt_lvl_ip_recvdstaddr(ErlNifEnv* env, - ESockDescriptor* descP); +static ERL_NIF_TERM esock_getopt_lvl_ip_recvdstaddr(ErlNifEnv* env, + ESockDescriptor* descP); #endif #if defined(IP_RECVERR) -static ERL_NIF_TERM ngetopt_lvl_ip_recverr(ErlNifEnv* env, - ESockDescriptor* descP); +static ERL_NIF_TERM esock_getopt_lvl_ip_recverr(ErlNifEnv* env, + ESockDescriptor* descP); #endif #if defined(IP_RECVIF) -static ERL_NIF_TERM ngetopt_lvl_ip_recvif(ErlNifEnv* env, - ESockDescriptor* descP); +static ERL_NIF_TERM esock_getopt_lvl_ip_recvif(ErlNifEnv* env, + ESockDescriptor* descP); #endif #if defined(IP_RECVOPTS) -static ERL_NIF_TERM ngetopt_lvl_ip_recvopts(ErlNifEnv* env, - ESockDescriptor* descP); +static ERL_NIF_TERM esock_getopt_lvl_ip_recvopts(ErlNifEnv* env, + ESockDescriptor* descP); #endif #if defined(IP_RECVORIGDSTADDR) -static ERL_NIF_TERM ngetopt_lvl_ip_recvorigdstaddr(ErlNifEnv* env, - ESockDescriptor* descP); +static ERL_NIF_TERM esock_getopt_lvl_ip_recvorigdstaddr(ErlNifEnv* env, + ESockDescriptor* descP); #endif #if defined(IP_RECVTOS) -static ERL_NIF_TERM ngetopt_lvl_ip_recvtos(ErlNifEnv* env, - ESockDescriptor* descP); +static ERL_NIF_TERM esock_getopt_lvl_ip_recvtos(ErlNifEnv* env, + ESockDescriptor* descP); #endif #if defined(IP_RECVTTL) -static ERL_NIF_TERM ngetopt_lvl_ip_recvttl(ErlNifEnv* env, - ESockDescriptor* descP); +static ERL_NIF_TERM esock_getopt_lvl_ip_recvttl(ErlNifEnv* env, + ESockDescriptor* descP); #endif #if defined(IP_RETOPTS) -static ERL_NIF_TERM ngetopt_lvl_ip_retopts(ErlNifEnv* env, - ESockDescriptor* descP); +static ERL_NIF_TERM esock_getopt_lvl_ip_retopts(ErlNifEnv* env, + ESockDescriptor* descP); #endif #if defined(IP_ROUTER_ALERT) -static ERL_NIF_TERM ngetopt_lvl_ip_router_alert(ErlNifEnv* env, - ESockDescriptor* descP); +static ERL_NIF_TERM esock_getopt_lvl_ip_router_alert(ErlNifEnv* env, + ESockDescriptor* descP); #endif #if defined(IP_SENDSRCADDR) -static ERL_NIF_TERM ngetopt_lvl_ip_sendsrcaddr(ErlNifEnv* env, - ESockDescriptor* descP); +static ERL_NIF_TERM esock_getopt_lvl_ip_sendsrcaddr(ErlNifEnv* env, + ESockDescriptor* descP); #endif #if defined(IP_TOS) -static ERL_NIF_TERM ngetopt_lvl_ip_tos(ErlNifEnv* env, - ESockDescriptor* descP); +static ERL_NIF_TERM esock_getopt_lvl_ip_tos(ErlNifEnv* env, + ESockDescriptor* descP); #endif #if defined(IP_TRANSPARENT) -static ERL_NIF_TERM ngetopt_lvl_ip_transparent(ErlNifEnv* env, - ESockDescriptor* descP); +static ERL_NIF_TERM esock_getopt_lvl_ip_transparent(ErlNifEnv* env, + ESockDescriptor* descP); #endif #if defined(IP_TTL) -static ERL_NIF_TERM ngetopt_lvl_ip_ttl(ErlNifEnv* env, - ESockDescriptor* descP); +static ERL_NIF_TERM esock_getopt_lvl_ip_ttl(ErlNifEnv* env, + ESockDescriptor* descP); #endif #if defined(HAVE_IPV6) -static ERL_NIF_TERM ngetopt_lvl_ipv6(ErlNifEnv* env, - ESockDescriptor* descP, - int eOpt); +static ERL_NIF_TERM esock_getopt_lvl_ipv6(ErlNifEnv* env, + ESockDescriptor* descP, + int eOpt); #if defined(IPV6_AUTHHDR) -static ERL_NIF_TERM ngetopt_lvl_ipv6_authhdr(ErlNifEnv* env, - ESockDescriptor* descP); +static ERL_NIF_TERM esock_getopt_lvl_ipv6_authhdr(ErlNifEnv* env, + ESockDescriptor* descP); #endif #if defined(IPV6_DSTOPTS) -static ERL_NIF_TERM ngetopt_lvl_ipv6_dstopts(ErlNifEnv* env, - ESockDescriptor* descP); +static ERL_NIF_TERM esock_getopt_lvl_ipv6_dstopts(ErlNifEnv* env, + ESockDescriptor* descP); #endif #if defined(IPV6_FLOWINFO) -static ERL_NIF_TERM ngetopt_lvl_ipv6_flowinfo(ErlNifEnv* env, - ESockDescriptor* descP); +static ERL_NIF_TERM esock_getopt_lvl_ipv6_flowinfo(ErlNifEnv* env, + ESockDescriptor* descP); #endif #if defined(IPV6_HOPLIMIT) -static ERL_NIF_TERM ngetopt_lvl_ipv6_hoplimit(ErlNifEnv* env, - ESockDescriptor* descP); +static ERL_NIF_TERM esock_getopt_lvl_ipv6_hoplimit(ErlNifEnv* env, + ESockDescriptor* descP); #endif #if defined(IPV6_HOPOPTS) -static ERL_NIF_TERM ngetopt_lvl_ipv6_hopopts(ErlNifEnv* env, - ESockDescriptor* descP); +static ERL_NIF_TERM esock_getopt_lvl_ipv6_hopopts(ErlNifEnv* env, + ESockDescriptor* descP); #endif #if defined(IPV6_MTU) -static ERL_NIF_TERM ngetopt_lvl_ipv6_mtu(ErlNifEnv* env, - ESockDescriptor* descP); +static ERL_NIF_TERM esock_getopt_lvl_ipv6_mtu(ErlNifEnv* env, + ESockDescriptor* descP); #endif #if defined(IPV6_MTU_DISCOVER) -static ERL_NIF_TERM ngetopt_lvl_ipv6_mtu_discover(ErlNifEnv* env, - ESockDescriptor* descP); +static ERL_NIF_TERM esock_getopt_lvl_ipv6_mtu_discover(ErlNifEnv* env, + ESockDescriptor* descP); #endif #if defined(IPV6_MULTICAST_HOPS) -static ERL_NIF_TERM ngetopt_lvl_ipv6_multicast_hops(ErlNifEnv* env, - ESockDescriptor* descP); +static ERL_NIF_TERM esock_getopt_lvl_ipv6_multicast_hops(ErlNifEnv* env, + ESockDescriptor* descP); #endif #if defined(IPV6_MULTICAST_IF) -static ERL_NIF_TERM ngetopt_lvl_ipv6_multicast_if(ErlNifEnv* env, - ESockDescriptor* descP); +static ERL_NIF_TERM esock_getopt_lvl_ipv6_multicast_if(ErlNifEnv* env, + ESockDescriptor* descP); #endif #if defined(IPV6_MULTICAST_LOOP) -static ERL_NIF_TERM ngetopt_lvl_ipv6_multicast_loop(ErlNifEnv* env, - ESockDescriptor* descP); +static ERL_NIF_TERM esock_getopt_lvl_ipv6_multicast_loop(ErlNifEnv* env, + ESockDescriptor* descP); #endif #if defined(IPV6_RECVERR) -static ERL_NIF_TERM ngetopt_lvl_ipv6_recverr(ErlNifEnv* env, - ESockDescriptor* descP); +static ERL_NIF_TERM esock_getopt_lvl_ipv6_recverr(ErlNifEnv* env, + ESockDescriptor* descP); #endif #if defined(IPV6_RECVPKTINFO) || defined(IPV6_PKTINFO) -static ERL_NIF_TERM ngetopt_lvl_ipv6_recvpktinfo(ErlNifEnv* env, - ESockDescriptor* descP); +static ERL_NIF_TERM esock_getopt_lvl_ipv6_recvpktinfo(ErlNifEnv* env, + ESockDescriptor* descP); #endif #if defined(IPV6_ROUTER_ALERT) -static ERL_NIF_TERM ngetopt_lvl_ipv6_router_alert(ErlNifEnv* env, - ESockDescriptor* descP); +static ERL_NIF_TERM esock_getopt_lvl_ipv6_router_alert(ErlNifEnv* env, + ESockDescriptor* descP); #endif #if defined(IPV6_RTHDR) -static ERL_NIF_TERM ngetopt_lvl_ipv6_rthdr(ErlNifEnv* env, - ESockDescriptor* descP); +static ERL_NIF_TERM esock_getopt_lvl_ipv6_rthdr(ErlNifEnv* env, + ESockDescriptor* descP); #endif #if defined(IPV6_UNICAST_HOPS) -static ERL_NIF_TERM ngetopt_lvl_ipv6_unicast_hops(ErlNifEnv* env, - ESockDescriptor* descP); +static ERL_NIF_TERM esock_getopt_lvl_ipv6_unicast_hops(ErlNifEnv* env, + ESockDescriptor* descP); #endif #if defined(IPV6_V6ONLY) -static ERL_NIF_TERM ngetopt_lvl_ipv6_v6only(ErlNifEnv* env, - ESockDescriptor* descP); +static ERL_NIF_TERM esock_getopt_lvl_ipv6_v6only(ErlNifEnv* env, + ESockDescriptor* descP); #endif #endif // defined(HAVE_IPV6) -static ERL_NIF_TERM ngetopt_lvl_tcp(ErlNifEnv* env, - ESockDescriptor* descP, - int eOpt); +static ERL_NIF_TERM esock_getopt_lvl_tcp(ErlNifEnv* env, + ESockDescriptor* descP, + int eOpt); #if defined(TCP_CONGESTION) -static ERL_NIF_TERM ngetopt_lvl_tcp_congestion(ErlNifEnv* env, - ESockDescriptor* descP); +static ERL_NIF_TERM esock_getopt_lvl_tcp_congestion(ErlNifEnv* env, + ESockDescriptor* descP); #endif #if defined(TCP_MAXSEG) -static ERL_NIF_TERM ngetopt_lvl_tcp_maxseg(ErlNifEnv* env, - ESockDescriptor* descP); +static ERL_NIF_TERM esock_getopt_lvl_tcp_maxseg(ErlNifEnv* env, + ESockDescriptor* descP); #endif #if defined(TCP_NODELAY) -static ERL_NIF_TERM ngetopt_lvl_tcp_nodelay(ErlNifEnv* env, - ESockDescriptor* descP); +static ERL_NIF_TERM esock_getopt_lvl_tcp_nodelay(ErlNifEnv* env, + ESockDescriptor* descP); #endif -static ERL_NIF_TERM ngetopt_lvl_udp(ErlNifEnv* env, - ESockDescriptor* descP, - int eOpt); +static ERL_NIF_TERM esock_getopt_lvl_udp(ErlNifEnv* env, + ESockDescriptor* descP, + int eOpt); #if defined(UDP_CORK) -static ERL_NIF_TERM ngetopt_lvl_udp_cork(ErlNifEnv* env, - ESockDescriptor* descP); +static ERL_NIF_TERM esock_getopt_lvl_udp_cork(ErlNifEnv* env, + ESockDescriptor* descP); #endif #if defined(HAVE_SCTP) -static ERL_NIF_TERM ngetopt_lvl_sctp(ErlNifEnv* env, - ESockDescriptor* descP, - int eOpt); +static ERL_NIF_TERM esock_getopt_lvl_sctp(ErlNifEnv* env, + ESockDescriptor* descP, + int eOpt); #if defined(SCTP_ASSOCINFO) -static ERL_NIF_TERM ngetopt_lvl_sctp_associnfo(ErlNifEnv* env, - ESockDescriptor* descP); +static ERL_NIF_TERM esock_getopt_lvl_sctp_associnfo(ErlNifEnv* env, + ESockDescriptor* descP); #endif #if defined(SCTP_AUTOCLOSE) -static ERL_NIF_TERM ngetopt_lvl_sctp_autoclose(ErlNifEnv* env, - ESockDescriptor* descP); +static ERL_NIF_TERM esock_getopt_lvl_sctp_autoclose(ErlNifEnv* env, + ESockDescriptor* descP); #endif #if defined(SCTP_DISABLE_FRAGMENTS) -static ERL_NIF_TERM ngetopt_lvl_sctp_disable_fragments(ErlNifEnv* env, - ESockDescriptor* descP); +static ERL_NIF_TERM esock_getopt_lvl_sctp_disable_fragments(ErlNifEnv* env, + ESockDescriptor* descP); #endif #if defined(SCTP_MAXSEG) -static ERL_NIF_TERM ngetopt_lvl_sctp_maxseg(ErlNifEnv* env, - ESockDescriptor* descP); +static ERL_NIF_TERM esock_getopt_lvl_sctp_maxseg(ErlNifEnv* env, + ESockDescriptor* descP); #endif #if defined(SCTP_INITMSG) -static ERL_NIF_TERM ngetopt_lvl_sctp_initmsg(ErlNifEnv* env, - ESockDescriptor* descP); +static ERL_NIF_TERM esock_getopt_lvl_sctp_initmsg(ErlNifEnv* env, + ESockDescriptor* descP); #endif #if defined(SCTP_NODELAY) -static ERL_NIF_TERM ngetopt_lvl_sctp_nodelay(ErlNifEnv* env, - ESockDescriptor* descP); +static ERL_NIF_TERM esock_getopt_lvl_sctp_nodelay(ErlNifEnv* env, + ESockDescriptor* descP); #endif #if defined(SCTP_RTOINFO) -static ERL_NIF_TERM ngetopt_lvl_sctp_rtoinfo(ErlNifEnv* env, - ESockDescriptor* descP); +static ERL_NIF_TERM esock_getopt_lvl_sctp_rtoinfo(ErlNifEnv* env, + ESockDescriptor* descP); #endif #endif // defined(HAVE_SCTP) -static ERL_NIF_TERM nsockname(ErlNifEnv* env, - ESockDescriptor* descP); -static ERL_NIF_TERM npeername(ErlNifEnv* env, - ESockDescriptor* descP); -static ERL_NIF_TERM ncancel(ErlNifEnv* env, - ESockDescriptor* descP, - ERL_NIF_TERM op, - ERL_NIF_TERM sockRef, - ERL_NIF_TERM opRef); -static ERL_NIF_TERM ncancel_connect(ErlNifEnv* env, - ESockDescriptor* descP, - ERL_NIF_TERM opRef); -static ERL_NIF_TERM ncancel_accept(ErlNifEnv* env, - ESockDescriptor* descP, - ERL_NIF_TERM sockRef, - ERL_NIF_TERM opRef); -static ERL_NIF_TERM ncancel_accept_current(ErlNifEnv* env, - ESockDescriptor* descP, - ERL_NIF_TERM sockRef); -static ERL_NIF_TERM ncancel_accept_waiting(ErlNifEnv* env, - ESockDescriptor* descP, - ERL_NIF_TERM opRef); -static ERL_NIF_TERM ncancel_send(ErlNifEnv* env, - ESockDescriptor* descP, - ERL_NIF_TERM sockRef, - ERL_NIF_TERM opRef); -static ERL_NIF_TERM ncancel_send_current(ErlNifEnv* env, - ESockDescriptor* descP, - ERL_NIF_TERM sockRef); -static ERL_NIF_TERM ncancel_send_waiting(ErlNifEnv* env, - ESockDescriptor* descP, - ERL_NIF_TERM opRef); -static ERL_NIF_TERM ncancel_recv(ErlNifEnv* env, +static ERL_NIF_TERM esock_sockname(ErlNifEnv* env, + ESockDescriptor* descP); +static ERL_NIF_TERM esock_peername(ErlNifEnv* env, + ESockDescriptor* descP); +static ERL_NIF_TERM esock_cancel(ErlNifEnv* env, ESockDescriptor* descP, + ERL_NIF_TERM op, ERL_NIF_TERM sockRef, ERL_NIF_TERM opRef); -static ERL_NIF_TERM ncancel_recv_current(ErlNifEnv* env, - ESockDescriptor* descP, - ERL_NIF_TERM sockRef); -static ERL_NIF_TERM ncancel_recv_waiting(ErlNifEnv* env, +static ERL_NIF_TERM esock_cancel_connect(ErlNifEnv* env, ESockDescriptor* descP, ERL_NIF_TERM opRef); -static ERL_NIF_TERM ncancel_read_select(ErlNifEnv* env, +static ERL_NIF_TERM esock_cancel_accept(ErlNifEnv* env, ESockDescriptor* descP, + ERL_NIF_TERM sockRef, ERL_NIF_TERM opRef); -static ERL_NIF_TERM ncancel_write_select(ErlNifEnv* env, - ESockDescriptor* descP, - ERL_NIF_TERM opRef); -static ERL_NIF_TERM ncancel_mode_select(ErlNifEnv* env, - ESockDescriptor* descP, - ERL_NIF_TERM opRef, - int smode, - int rmode); +static ERL_NIF_TERM esock_cancel_accept_current(ErlNifEnv* env, + ESockDescriptor* descP, + ERL_NIF_TERM sockRef); +static ERL_NIF_TERM esock_cancel_accept_waiting(ErlNifEnv* env, + ESockDescriptor* descP, + ERL_NIF_TERM opRef); +static ERL_NIF_TERM esock_cancel_send(ErlNifEnv* env, + ESockDescriptor* descP, + ERL_NIF_TERM sockRef, + ERL_NIF_TERM opRef); +static ERL_NIF_TERM esock_cancel_send_current(ErlNifEnv* env, + ESockDescriptor* descP, + ERL_NIF_TERM sockRef); +static ERL_NIF_TERM esock_cancel_send_waiting(ErlNifEnv* env, + ESockDescriptor* descP, + ERL_NIF_TERM opRef); +static ERL_NIF_TERM esock_cancel_recv(ErlNifEnv* env, + ESockDescriptor* descP, + ERL_NIF_TERM sockRef, + ERL_NIF_TERM opRef); +static ERL_NIF_TERM esock_cancel_recv_current(ErlNifEnv* env, + ESockDescriptor* descP, + ERL_NIF_TERM sockRef); +static ERL_NIF_TERM esock_cancel_recv_waiting(ErlNifEnv* env, + ESockDescriptor* descP, + ERL_NIF_TERM opRef); +static ERL_NIF_TERM esock_cancel_read_select(ErlNifEnv* env, + ESockDescriptor* descP, + ERL_NIF_TERM opRef); +static ERL_NIF_TERM esock_cancel_write_select(ErlNifEnv* env, + ESockDescriptor* descP, + ERL_NIF_TERM opRef); +static ERL_NIF_TERM esock_cancel_mode_select(ErlNifEnv* env, + ESockDescriptor* descP, + ERL_NIF_TERM opRef, + int smode, + int rmode); #if defined(USE_SETOPT_STR_OPT) -static ERL_NIF_TERM nsetopt_str_opt(ErlNifEnv* env, - ESockDescriptor* descP, - int level, - int opt, - int max, - ERL_NIF_TERM eVal); +static ERL_NIF_TERM esock_setopt_str_opt(ErlNifEnv* env, + ESockDescriptor* descP, + int level, + int opt, + int max, + ERL_NIF_TERM eVal); #endif -static ERL_NIF_TERM nsetopt_bool_opt(ErlNifEnv* env, - ESockDescriptor* descP, - int level, - int opt, - ERL_NIF_TERM eVal); -static ERL_NIF_TERM nsetopt_int_opt(ErlNifEnv* env, - ESockDescriptor* descP, - int level, - int opt, - ERL_NIF_TERM eVal); -static ERL_NIF_TERM nsetopt_timeval_opt(ErlNifEnv* env, - ESockDescriptor* descP, - int level, - int opt, - ERL_NIF_TERM eVal); +static ERL_NIF_TERM esock_setopt_bool_opt(ErlNifEnv* env, + ESockDescriptor* descP, + int level, + int opt, + ERL_NIF_TERM eVal); +static ERL_NIF_TERM esock_setopt_int_opt(ErlNifEnv* env, + ESockDescriptor* descP, + int level, + int opt, + ERL_NIF_TERM eVal); +static ERL_NIF_TERM esock_setopt_timeval_opt(ErlNifEnv* env, + ESockDescriptor* descP, + int level, + int opt, + ERL_NIF_TERM eVal); #if defined(USE_GETOPT_STR_OPT) -static ERL_NIF_TERM ngetopt_str_opt(ErlNifEnv* env, - ESockDescriptor* descP, - int level, - int opt, - int max); +static ERL_NIF_TERM esock_getopt_str_opt(ErlNifEnv* env, + ESockDescriptor* descP, + int level, + int opt, + int max); #endif -static ERL_NIF_TERM ngetopt_bool_opt(ErlNifEnv* env, - ESockDescriptor* descP, - int level, - int opt); -static ERL_NIF_TERM ngetopt_int_opt(ErlNifEnv* env, - ESockDescriptor* descP, - int level, - int opt); -static ERL_NIF_TERM ngetopt_timeval_opt(ErlNifEnv* env, - ESockDescriptor* descP, - int level, - int opt); +static ERL_NIF_TERM esock_getopt_bool_opt(ErlNifEnv* env, + ESockDescriptor* descP, + int level, + int opt); +static ERL_NIF_TERM esock_getopt_int_opt(ErlNifEnv* env, + ESockDescriptor* descP, + int level, + int opt); +static ERL_NIF_TERM esock_getopt_timeval_opt(ErlNifEnv* env, + ESockDescriptor* descP, + int level, + int opt); static BOOLEAN_T send_check_writer(ErlNifEnv* env, ESockDescriptor* descP, @@ -2281,10 +2286,10 @@ static ERL_NIF_TERM recvmsg_check_msg(ErlNifEnv* env, ErlNifBinary* ctrlBufP, ERL_NIF_TERM sockRef); -static ERL_NIF_TERM nfinalize_connection(ErlNifEnv* env, +static ERL_NIF_TERM esock_finalize_connection(ErlNifEnv* env, + ESockDescriptor* descP); +static ERL_NIF_TERM esock_finalize_close(ErlNifEnv* env, ESockDescriptor* descP); -static ERL_NIF_TERM nfinalize_close(ErlNifEnv* env, - ESockDescriptor* descP); extern char* encode_msghdr(ErlNifEnv* env, ESockDescriptor* descP, @@ -2417,11 +2422,11 @@ static BOOLEAN_T decode_native_get_opt(ErlNifEnv* env, // static void encode_bool(BOOLEAN_T val, ERL_NIF_TERM* eVal); static ERL_NIF_TERM encode_ip_tos(ErlNifEnv* env, int val); -static void socket_stop_handle_current(ErlNifEnv* env, - const char* role, - ESockDescriptor* descP, - ERL_NIF_TERM sockRef, - ESockRequestor* reqP); +static void esock_stop_handle_current(ErlNifEnv* env, + const char* role, + ESockDescriptor* descP, + ERL_NIF_TERM sockRef, + ESockRequestor* reqP); static void inform_waiting_procs(ErlNifEnv* env, const char* role, ESockDescriptor* descP, @@ -2560,30 +2565,30 @@ static size_t my_strnlen(const char *s, size_t maxlen); #endif */ -static void socket_dtor(ErlNifEnv* env, void* obj); -static void socket_stop(ErlNifEnv* env, - void* obj, - int fd, - int is_direct_call); -static void socket_down(ErlNifEnv* env, - void* obj, - const ErlNifPid* pid, - const ErlNifMonitor* mon); +static void esock_dtor(ErlNifEnv* env, void* obj); +static void esock_stop(ErlNifEnv* env, + void* obj, + int fd, + int is_direct_call); +static void esock_down(ErlNifEnv* env, + void* obj, + const ErlNifPid* pid, + const ErlNifMonitor* mon); #if !defined(__WIN32__) -static void socket_down_acceptor(ErlNifEnv* env, - ESockDescriptor* descP, - ERL_NIF_TERM sockRef, - const ErlNifPid* pid); -static void socket_down_writer(ErlNifEnv* env, - ESockDescriptor* descP, - ERL_NIF_TERM sockRef, - const ErlNifPid* pid); -static void socket_down_reader(ErlNifEnv* env, - ESockDescriptor* descP, - ERL_NIF_TERM sockRef, - const ErlNifPid* pid); +static void esock_down_acceptor(ErlNifEnv* env, + ESockDescriptor* descP, + ERL_NIF_TERM sockRef, + const ErlNifPid* pid); +static void esock_down_writer(ErlNifEnv* env, + ESockDescriptor* descP, + ERL_NIF_TERM sockRef, + const ErlNifPid* pid); +static void esock_down_reader(ErlNifEnv* env, + ESockDescriptor* descP, + ERL_NIF_TERM sockRef, + const ErlNifPid* pid); static char* esock_send_wrap_msg(ErlNifEnv* env, ESockDescriptor* descP, @@ -2995,11 +3000,11 @@ LOCAL_ERROR_REASON_ATOMS /* *** Sockets *** */ -static ErlNifResourceType* sockets; -static ErlNifResourceTypeInit socketInit = { - socket_dtor, - socket_stop, - (ErlNifResourceDown*) socket_down +static ErlNifResourceType* esocks; +static ErlNifResourceTypeInit esockInit = { + esock_dtor, + esock_stop, + (ErlNifResourceDown*) esock_down }; // Initiated when the nif is loaded @@ -3100,7 +3105,7 @@ ERL_NIF_TERM nif_info(ErlNifEnv* env, { ESockDescriptor* descP; - if (!enif_get_resource(env, argv[0], sockets, (void**) &descP)) { + if (!ESOCK_GET_RESOURCE(env, argv[0], (void**) &descP)) { return enif_make_badarg(env); } SSDBG( descP, ("SOCKET", "nif_info -> get socket info\r\n") ); @@ -3297,7 +3302,7 @@ ERL_NIF_TERM nif_command(ErlNifEnv* env, "\r\n (e) command data: %T" "\r\n", cmd, ecdata) ); - result = ncommand(env, cmd, ecdata); + result = esock_command(env, cmd, ecdata); SGDBG( ("SOCKET", "nif_command -> done with result: " "\r\n %T" @@ -3311,15 +3316,15 @@ ERL_NIF_TERM nif_command(ErlNifEnv* env, #if !defined(__WIN32__) static -ERL_NIF_TERM ncommand(ErlNifEnv* env, Uint16 cmd, ERL_NIF_TERM ecdata) +ERL_NIF_TERM esock_command(ErlNifEnv* env, Uint16 cmd, ERL_NIF_TERM ecdata) { ERL_NIF_TERM result; - SGDBG( ("SOCKET", "ncommand -> entry with 0x%lX\r\n", cmd) ); + SGDBG( ("SOCKET", "esock_command -> entry with 0x%lX\r\n", cmd) ); switch (cmd) { - case SOCKET_CMD_DEBUG: - result = ncommand_debug(env, ecdata); + case ESOCK_CMD_DEBUG: + result = esock_command_debug(env, ecdata); break; default: @@ -3333,7 +3338,7 @@ ERL_NIF_TERM ncommand(ErlNifEnv* env, Uint16 cmd, ERL_NIF_TERM ecdata) static -ERL_NIF_TERM ncommand_debug(ErlNifEnv* env, ERL_NIF_TERM ecdata) +ERL_NIF_TERM esock_command_debug(ErlNifEnv* env, ERL_NIF_TERM ecdata) { ERL_NIF_TERM result; @@ -3346,7 +3351,7 @@ ERL_NIF_TERM ncommand_debug(ErlNifEnv* env, ERL_NIF_TERM ecdata) data.dbg = FALSE; result = esock_atom_ok; } else { - SGDBG( ("SOCKET", "ncommand_debug -> invalid debug value: %T\r\n", + SGDBG( ("SOCKET", "esock_command_debug -> invalid debug value: %T\r\n", ecdata) ); result = esock_make_error(env, esock_atom_einval); } @@ -3366,20 +3371,20 @@ ERL_NIF_TERM ncommand_debug(ErlNifEnv* env, ERL_NIF_TERM ecdata) */ #if !defined(__WIN32__) -#define SOCKET_INFO_REQ_FUNCS \ - SOCKET_INFO_REQ_FUNC_DECL(readers, readMtx, currentReaderP, readersQ) \ - SOCKET_INFO_REQ_FUNC_DECL(writers, writeMtx, currentWriterP, writersQ) \ - SOCKET_INFO_REQ_FUNC_DECL(acceptors, accMtx, currentAcceptorP, acceptorsQ) +#define ESOCK_INFO_REQ_FUNCS \ + ESOCK_INFO_REQ_FUNC_DECL(readers, readMtx, currentReaderP, readersQ) \ + ESOCK_INFO_REQ_FUNC_DECL(writers, writeMtx, currentWriterP, writersQ) \ + ESOCK_INFO_REQ_FUNC_DECL(acceptors, accMtx, currentAcceptorP, acceptorsQ) -#define SOCKET_INFO_REQ_FUNC_DECL(F, MTX, CRP, Q) \ +#define ESOCK_INFO_REQ_FUNC_DECL(F, MTX, CRP, Q) \ static \ ERL_NIF_TERM esock_socket_info_##F(ErlNifEnv* env, \ ESockDescriptor* descP) \ { \ return socket_info_reqs(env, descP, descP->MTX, descP->CRP, &descP->Q); \ } -SOCKET_INFO_REQ_FUNCS -#undef SOCKET_INFO_REQ_FUNC_DECL +ESOCK_INFO_REQ_FUNCS +#undef ESOCK_INFO_REQ_FUNC_DECL static @@ -3461,40 +3466,40 @@ ERL_NIF_TERM nif_supports(ErlNifEnv* env, return enif_make_badarg(env); } - return nsupports(env, key); + return esock_supports(env, key); #endif } -/* nsupports - what features do we support +/* esock_supports - what features do we support * * This is to prove information about what features actually * work on the current platform. */ #if !defined(__WIN32__) static -ERL_NIF_TERM nsupports(ErlNifEnv* env, int key) +ERL_NIF_TERM esock_supports(ErlNifEnv* env, int key) { ERL_NIF_TERM result; - SGDBG( ("SOCKET", "nsupports -> entry with 0x%lX\r\n", key) ); + SGDBG( ("SOCKET", "esock_supports -> entry with 0x%lX\r\n", key) ); switch (key) { - case SOCKET_SUPPORTS_OPTIONS: - result = nsupports_options(env); + case ESOCK_SUPPORTS_OPTIONS: + result = esock_supports_options(env); break; - case SOCKET_SUPPORTS_SCTP: - result = nsupports_sctp(env); + case ESOCK_SUPPORTS_SCTP: + result = esock_supports_sctp(env); break; - case SOCKET_SUPPORTS_IPV6: - result = nsupports_ipv6(env); + case ESOCK_SUPPORTS_IPV6: + result = esock_supports_ipv6(env); break; - case SOCKET_SUPPORTS_LOCAL: - result = nsupports_local(env); + case ESOCK_SUPPORTS_LOCAL: + result = esock_supports_local(env); break; default: @@ -3509,19 +3514,19 @@ ERL_NIF_TERM nsupports(ErlNifEnv* env, int key) #if !defined(__WIN32__) static -ERL_NIF_TERM nsupports_options(ErlNifEnv* env) +ERL_NIF_TERM esock_supports_options(ErlNifEnv* env) { - ERL_NIF_TERM sockOpts = nsupports_options_socket(env); + ERL_NIF_TERM sockOpts = esock_supports_options_socket(env); ERL_NIF_TERM sockOptsT = MKT2(env, esock_atom_socket, sockOpts); - ERL_NIF_TERM ipOpts = nsupports_options_ip(env); + ERL_NIF_TERM ipOpts = esock_supports_options_ip(env); ERL_NIF_TERM ipOptsT = MKT2(env, esock_atom_ip, ipOpts); - ERL_NIF_TERM ipv6Opts = nsupports_options_ipv6(env); + ERL_NIF_TERM ipv6Opts = esock_supports_options_ipv6(env); ERL_NIF_TERM ipv6OptsT = MKT2(env, esock_atom_ipv6, ipv6Opts); - ERL_NIF_TERM tcpOpts = nsupports_options_tcp(env); + ERL_NIF_TERM tcpOpts = esock_supports_options_tcp(env); ERL_NIF_TERM tcpOptsT = MKT2(env, esock_atom_tcp, tcpOpts); - ERL_NIF_TERM udpOpts = nsupports_options_udp(env); + ERL_NIF_TERM udpOpts = esock_supports_options_udp(env); ERL_NIF_TERM udpOptsT = MKT2(env, esock_atom_udp, udpOpts); - ERL_NIF_TERM sctpOpts = nsupports_options_sctp(env); + ERL_NIF_TERM sctpOpts = esock_supports_options_sctp(env); ERL_NIF_TERM sctpOptsT = MKT2(env, esock_atom_sctp, sctpOpts); ERL_NIF_TERM optsA[] = {sockOptsT, ipOptsT, ipv6OptsT, @@ -3537,13 +3542,13 @@ ERL_NIF_TERM nsupports_options(ErlNifEnv* env) #if !defined(__WIN32__) static -ERL_NIF_TERM nsupports_options_socket(ErlNifEnv* env) +ERL_NIF_TERM esock_supports_options_socket(ErlNifEnv* env) { SocketTArray opts = TARRAY_CREATE(128); ERL_NIF_TERM tmp, optsL; - /* *** SOCKET_OPT_SOCK_ACCEPTCONN => SO_ACCEPTCONN *** */ + /* *** ESOCK_OPT_SOCK_ACCEPTCONN => SO_ACCEPTCONN *** */ #if defined(SO_ACCEPTCONN) tmp = MKT2(env, esock_atom_acceptconn, esock_atom_true); #else @@ -3552,12 +3557,12 @@ ERL_NIF_TERM nsupports_options_socket(ErlNifEnv* env) TARRAY_ADD(opts, tmp); - /* *** SOCKET_OPT_SOCK_ACCEPTFILTER => SO_ACCEPTFILTER *** */ + /* *** ESOCK_OPT_SOCK_ACCEPTFILTER => SO_ACCEPTFILTER *** */ tmp = MKT2(env, esock_atom_acceptfilter, esock_atom_false); TARRAY_ADD(opts, tmp); - /* *** SOCKET_OPT_SOCK_BINDTODEVICE => SO_BINDTODEVICE *** */ + /* *** ESOCK_OPT_SOCK_BINDTODEVICE => SO_BINDTODEVICE *** */ #if defined(SO_BINDTODEVICE) tmp = MKT2(env, esock_atom_bindtodevice, esock_atom_true); #else @@ -3566,7 +3571,7 @@ ERL_NIF_TERM nsupports_options_socket(ErlNifEnv* env) TARRAY_ADD(opts, tmp); - /* *** SOCKET_OPT_SOCK_BROADCAST => SO_BROADCAST *** */ + /* *** ESOCK_OPT_SOCK_BROADCAST => SO_BROADCAST *** */ #if defined(SO_BROADCAST) tmp = MKT2(env, esock_atom_broadcast, esock_atom_true); #else @@ -3575,12 +3580,12 @@ ERL_NIF_TERM nsupports_options_socket(ErlNifEnv* env) TARRAY_ADD(opts, tmp); - /* *** SOCKET_OPT_SOCK_BUSY_POLL => SO_BUSY_POLL *** */ + /* *** ESOCK_OPT_SOCK_BUSY_POLL => SO_BUSY_POLL *** */ tmp = MKT2(env, esock_atom_busy_poll, esock_atom_false); TARRAY_ADD(opts, tmp); - /* *** SOCKET_OPT_SOCK_DEBUG => SO_DEBUG *** */ + /* *** ESOCK_OPT_SOCK_DEBUG => SO_DEBUG *** */ #if defined(SO_DEBUG) tmp = MKT2(env, esock_atom_debug, esock_atom_true); #else @@ -3589,7 +3594,7 @@ ERL_NIF_TERM nsupports_options_socket(ErlNifEnv* env) TARRAY_ADD(opts, tmp); - /* *** SOCKET_OPT_SOCK_DOMAIN => SO_DOMAIN *** */ + /* *** ESOCK_OPT_SOCK_DOMAIN => SO_DOMAIN *** */ #if defined(SO_DOMAIN) tmp = MKT2(env, esock_atom_domain, esock_atom_true); #else @@ -3598,7 +3603,7 @@ ERL_NIF_TERM nsupports_options_socket(ErlNifEnv* env) TARRAY_ADD(opts, tmp); - /* *** SOCKET_OPT_SOCK_DONTROUTE => SO_DONTROUTE *** */ + /* *** ESOCK_OPT_SOCK_DONTROUTE => SO_DONTROUTE *** */ #if defined(SO_DONTROUTE) tmp = MKT2(env, esock_atom_dontroute, esock_atom_true); #else @@ -3607,12 +3612,12 @@ ERL_NIF_TERM nsupports_options_socket(ErlNifEnv* env) TARRAY_ADD(opts, tmp); - /* *** SOCKET_OPT_SOCK_ERROR => SO_ERROR *** */ + /* *** ESOCK_OPT_SOCK_ERROR => SO_ERROR *** */ tmp = MKT2(env, esock_atom_error, esock_atom_false); TARRAY_ADD(opts, tmp); - /* *** SOCKET_OPT_SOCK_KEEPALIVE => SO_KEEPALIVE *** */ + /* *** ESOCK_OPT_SOCK_KEEPALIVE => SO_KEEPALIVE *** */ #if defined(SO_KEEPALIVE) tmp = MKT2(env, esock_atom_keepalive, esock_atom_true); #else @@ -3621,7 +3626,7 @@ ERL_NIF_TERM nsupports_options_socket(ErlNifEnv* env) TARRAY_ADD(opts, tmp); - /* *** SOCKET_OPT_SOCK_LINGER => SO_LINGER *** */ + /* *** ESOCK_OPT_SOCK_LINGER => SO_LINGER *** */ #if defined(SO_LINGER) tmp = MKT2(env, esock_atom_linger, esock_atom_true); #else @@ -3630,12 +3635,12 @@ ERL_NIF_TERM nsupports_options_socket(ErlNifEnv* env) TARRAY_ADD(opts, tmp); - /* *** SOCKET_OPT_SOCK_MARK => SO_MARK *** */ + /* *** ESOCK_OPT_SOCK_MARK => SO_MARK *** */ tmp = MKT2(env, esock_atom_mark, esock_atom_false); TARRAY_ADD(opts, tmp); - /* *** SOCKET_OPT_SOCK_OOBINLINE => SO_OOBINLINE *** */ + /* *** ESOCK_OPT_SOCK_OOBINLINE => SO_OOBINLINE *** */ #if defined(SO_OOBINLINE) tmp = MKT2(env, esock_atom_oobinline, esock_atom_true); #else @@ -3644,12 +3649,12 @@ ERL_NIF_TERM nsupports_options_socket(ErlNifEnv* env) TARRAY_ADD(opts, tmp); - /* *** SOCKET_OPT_PASSCRED => SO_PASSCRED *** */ + /* *** ESOCK_OPT_PASSCRED => SO_PASSCRED *** */ tmp = MKT2(env, esock_atom_passcred, esock_atom_false); TARRAY_ADD(opts, tmp); - /* *** SOCKET_OPT_SOCK_PEEK_OFF => SO_PEEK_OFF *** */ + /* *** ESOCK_OPT_SOCK_PEEK_OFF => SO_PEEK_OFF *** */ #if defined(SO_PEEK_OFF) tmp = MKT2(env, esock_atom_peek_off, esock_atom_true); #else @@ -3658,12 +3663,12 @@ ERL_NIF_TERM nsupports_options_socket(ErlNifEnv* env) TARRAY_ADD(opts, tmp); - /* *** SOCKET_OPT_SOCK_PEEKCRED => SO_PEEKCRED *** */ + /* *** ESOCK_OPT_SOCK_PEEKCRED => SO_PEEKCRED *** */ tmp = MKT2(env, esock_atom_peekcred, esock_atom_false); TARRAY_ADD(opts, tmp); - /* *** SOCKET_OPT_SOCK_PRIORITY => SO_PRIORITY *** */ + /* *** ESOCK_OPT_SOCK_PRIORITY => SO_PRIORITY *** */ #if defined(SO_PRIORITY) tmp = MKT2(env, esock_atom_priority, esock_atom_true); #else @@ -3672,7 +3677,7 @@ ERL_NIF_TERM nsupports_options_socket(ErlNifEnv* env) TARRAY_ADD(opts, tmp); - /* *** SOCKET_OPT_SOCK_PROTOCOL => SO_PROTOCOL *** */ + /* *** ESOCK_OPT_SOCK_PROTOCOL => SO_PROTOCOL *** */ #if defined(SO_PROTOCOL) tmp = MKT2(env, esock_atom_protocol, esock_atom_true); #else @@ -3681,7 +3686,7 @@ ERL_NIF_TERM nsupports_options_socket(ErlNifEnv* env) TARRAY_ADD(opts, tmp); - /* *** SOCKET_OPT_SOCK_RCVBUF => SO_RCVBUF *** */ + /* *** ESOCK_OPT_SOCK_RCVBUF => SO_RCVBUF *** */ #if defined(SO_RCVBUF) tmp = MKT2(env, esock_atom_rcvbuf, esock_atom_true); #else @@ -3690,12 +3695,12 @@ ERL_NIF_TERM nsupports_options_socket(ErlNifEnv* env) TARRAY_ADD(opts, tmp); - /* *** SOCKET_OPT_SOCK_RCVBUFFORCE => SO_RCVBUFFORCE *** */ + /* *** ESOCK_OPT_SOCK_RCVBUFFORCE => SO_RCVBUFFORCE *** */ tmp = MKT2(env, esock_atom_rcvbufforce, esock_atom_false); TARRAY_ADD(opts, tmp); - /* *** SOCKET_OPT_SOCK_RCVLOWAT => SO_RCVLOWAT *** */ + /* *** ESOCK_OPT_SOCK_RCVLOWAT => SO_RCVLOWAT *** */ #if defined(SO_RCVLOWAT) tmp = MKT2(env, esock_atom_rcvlowat, esock_atom_true); #else @@ -3704,7 +3709,7 @@ ERL_NIF_TERM nsupports_options_socket(ErlNifEnv* env) TARRAY_ADD(opts, tmp); - /* *** SOCKET_OPT_SOCK_RCVTIMEO => SO_RCVTIMEO *** */ + /* *** ESOCK_OPT_SOCK_RCVTIMEO => SO_RCVTIMEO *** */ #if defined(SO_RCVTIMEO) tmp = MKT2(env, esock_atom_rcvtimeo, esock_atom_true); #else @@ -3713,7 +3718,7 @@ ERL_NIF_TERM nsupports_options_socket(ErlNifEnv* env) TARRAY_ADD(opts, tmp); - /* *** SOCKET_OPT_SOCK_REUSEADDR => SO_REUSEADDR *** */ + /* *** ESOCK_OPT_SOCK_REUSEADDR => SO_REUSEADDR *** */ #if defined(SO_REUSEADDR) tmp = MKT2(env, esock_atom_reuseaddr, esock_atom_true); #else @@ -3722,7 +3727,7 @@ ERL_NIF_TERM nsupports_options_socket(ErlNifEnv* env) TARRAY_ADD(opts, tmp); - /* *** SOCKET_OPT_SOCK_REUSEPORT => SO_REUSEPORT *** */ + /* *** ESOCK_OPT_SOCK_REUSEPORT => SO_REUSEPORT *** */ #if defined(SO_REUSEPORT) tmp = MKT2(env, esock_atom_reuseport, esock_atom_true); #else @@ -3731,17 +3736,17 @@ ERL_NIF_TERM nsupports_options_socket(ErlNifEnv* env) TARRAY_ADD(opts, tmp); - /* *** SOCKET_OPT_SOCK_RXQ_OVFL => SO_RXQ_OVFL *** */ + /* *** ESOCK_OPT_SOCK_RXQ_OVFL => SO_RXQ_OVFL *** */ tmp = MKT2(env, esock_atom_rxq_ovfl, esock_atom_false); TARRAY_ADD(opts, tmp); - /* *** SOCKET_OPT_SOCK_SETFIB => SO_SETFIB *** */ + /* *** ESOCK_OPT_SOCK_SETFIB => SO_SETFIB *** */ tmp = MKT2(env, esock_atom_setfib, esock_atom_false); TARRAY_ADD(opts, tmp); - /* *** SOCKET_OPT_SOCK_SNDBUF => SO_SNDBUF *** */ + /* *** ESOCK_OPT_SOCK_SNDBUF => SO_SNDBUF *** */ #if defined(SO_SNDBUF) tmp = MKT2(env, esock_atom_sndbuf, esock_atom_true); #else @@ -3750,12 +3755,12 @@ ERL_NIF_TERM nsupports_options_socket(ErlNifEnv* env) TARRAY_ADD(opts, tmp); - /* *** SOCKET_OPT_SOCK_SNDBUFFORCE => SO_SNDBUFFORCE *** */ + /* *** ESOCK_OPT_SOCK_SNDBUFFORCE => SO_SNDBUFFORCE *** */ tmp = MKT2(env, esock_atom_sndbufforce, esock_atom_false); TARRAY_ADD(opts, tmp); - /* *** SOCKET_OPT_SOCK_SNDLOWAT => SO_SNDLOWAT *** */ + /* *** ESOCK_OPT_SOCK_SNDLOWAT => SO_SNDLOWAT *** */ #if defined(SO_SNDLOWAT) tmp = MKT2(env, esock_atom_sndlowat, esock_atom_true); #else @@ -3764,7 +3769,7 @@ ERL_NIF_TERM nsupports_options_socket(ErlNifEnv* env) TARRAY_ADD(opts, tmp); - /* *** SOCKET_OPT_SOCK_SNDTIMEO => SO_SNDTIMEO *** */ + /* *** ESOCK_OPT_SOCK_SNDTIMEO => SO_SNDTIMEO *** */ #if defined(SO_SNDTIMEO) tmp = MKT2(env, esock_atom_sndtimeo, esock_atom_true); #else @@ -3773,7 +3778,7 @@ ERL_NIF_TERM nsupports_options_socket(ErlNifEnv* env) TARRAY_ADD(opts, tmp); - /* *** SOCKET_OPT_SOCK_TIMESTAMP => SO_TIMESTAMP *** */ + /* *** ESOCK_OPT_SOCK_TIMESTAMP => SO_TIMESTAMP *** */ #if defined(SO_TIMESTAMP) tmp = MKT2(env, esock_atom_timestamp, esock_atom_true); #else @@ -3782,7 +3787,7 @@ ERL_NIF_TERM nsupports_options_socket(ErlNifEnv* env) TARRAY_ADD(opts, tmp); - /* *** SOCKET_OPT_SOCK_TYPE => SO_TYPE *** */ + /* *** ESOCK_OPT_SOCK_TYPE => SO_TYPE *** */ #if defined(SO_TYPE) tmp = MKT2(env, esock_atom_type, esock_atom_true); #else @@ -3801,13 +3806,13 @@ ERL_NIF_TERM nsupports_options_socket(ErlNifEnv* env) #if !defined(__WIN32__) static -ERL_NIF_TERM nsupports_options_ip(ErlNifEnv* env) +ERL_NIF_TERM esock_supports_options_ip(ErlNifEnv* env) { SocketTArray opts = TARRAY_CREATE(128); ERL_NIF_TERM tmp, optsL; - /* *** SOCKET_OPT_IP_ADD_MEMBERSHIP => IP_ADD_MEMBERSHIP *** */ + /* *** ESOCK_OPT_IP_ADD_MEMBERSHIP => IP_ADD_MEMBERSHIP *** */ #if defined(IP_ADD_MEMBERSHIP) tmp = MKT2(env, esock_atom_add_membership, esock_atom_true); #else @@ -3816,7 +3821,7 @@ ERL_NIF_TERM nsupports_options_ip(ErlNifEnv* env) TARRAY_ADD(opts, tmp); - /* *** SOCKET_OPT_IP_ADD_SOURCE_MEMBERSHIP => IP_ADD_SOURCE_MEMBERSHIP *** */ + /* *** ESOCK_OPT_IP_ADD_SOURCE_MEMBERSHIP => IP_ADD_SOURCE_MEMBERSHIP *** */ #if defined(IP_ADD_SOURCE_MEMBERSHIP) tmp = MKT2(env, esock_atom_add_source_membership, esock_atom_true); #else @@ -3825,7 +3830,7 @@ ERL_NIF_TERM nsupports_options_ip(ErlNifEnv* env) TARRAY_ADD(opts, tmp); - /* *** SOCKET_OPT_IP_BLOCK_SOURCE => IP_BLOCK_SOURCE *** */ + /* *** ESOCK_OPT_IP_BLOCK_SOURCE => IP_BLOCK_SOURCE *** */ #if defined(IP_BLOCK_SOURCE) tmp = MKT2(env, esock_atom_block_source, esock_atom_true); #else @@ -3834,12 +3839,12 @@ ERL_NIF_TERM nsupports_options_ip(ErlNifEnv* env) TARRAY_ADD(opts, tmp); - /* *** SOCKET_OPT_IP_DONTFRAG => IP_DONTFRAG *** */ + /* *** ESOCK_OPT_IP_DONTFRAG => IP_DONTFRAG *** */ tmp = MKT2(env, esock_atom_dontfrag, esock_atom_false); TARRAY_ADD(opts, tmp); - /* *** SOCKET_OPT_IP_DROP_MEMBERSHIP => IP_DROP_MEMBERSHIP *** */ + /* *** ESOCK_OPT_IP_DROP_MEMBERSHIP => IP_DROP_MEMBERSHIP *** */ #if defined(IP_DROP_MEMBERSHIP) tmp = MKT2(env, esock_atom_drop_membership, esock_atom_true); #else @@ -3848,7 +3853,7 @@ ERL_NIF_TERM nsupports_options_ip(ErlNifEnv* env) TARRAY_ADD(opts, tmp); - /* *** SOCKET_OPT_IP_DROP_SOURCE_MEMBERSHIP => IP_DROP_SOURCE_MEMBERSHIP *** */ + /* *** ESOCK_OPT_IP_DROP_SOURCE_MEMBERSHIP => IP_DROP_SOURCE_MEMBERSHIP *** */ #if defined(IP_DROP_SOURCE_MEMBERSHIP) tmp = MKT2(env, esock_atom_drop_source_membership, esock_atom_true); #else @@ -3857,7 +3862,7 @@ ERL_NIF_TERM nsupports_options_ip(ErlNifEnv* env) TARRAY_ADD(opts, tmp); - /* *** SOCKET_OPT_IP_FREEBIND => IP_FREEBIND *** */ + /* *** ESOCK_OPT_IP_FREEBIND => IP_FREEBIND *** */ #if defined(IP_FREEBIND) tmp = MKT2(env, esock_atom_freebind, esock_atom_true); #else @@ -3866,7 +3871,7 @@ ERL_NIF_TERM nsupports_options_ip(ErlNifEnv* env) TARRAY_ADD(opts, tmp); - /* *** SOCKET_OPT_IP_HDRINCL => IP_HDRINCL *** */ + /* *** ESOCK_OPT_IP_HDRINCL => IP_HDRINCL *** */ #if defined(IP_HDRINCL) tmp = MKT2(env, esock_atom_hdrincl, esock_atom_true); #else @@ -3875,7 +3880,7 @@ ERL_NIF_TERM nsupports_options_ip(ErlNifEnv* env) TARRAY_ADD(opts, tmp); - /* *** SOCKET_OPT_IP_MINTTL => IP_MINTTL *** */ + /* *** ESOCK_OPT_IP_MINTTL => IP_MINTTL *** */ #if defined(IP_MINTTL) tmp = MKT2(env, esock_atom_minttl, esock_atom_true); #else @@ -3884,7 +3889,7 @@ ERL_NIF_TERM nsupports_options_ip(ErlNifEnv* env) TARRAY_ADD(opts, tmp); - /* *** SOCKET_OPT_IP_MSFILTER => IP_MSFILTER / IP_MSFILTER_SIZE *** */ + /* *** ESOCK_OPT_IP_MSFILTER => IP_MSFILTER / IP_MSFILTER_SIZE *** */ #if defined(IP_MSFILTER) && defined(IP_MSFILTER_SIZE) tmp = MKT2(env, esock_atom_msfilter, esock_atom_true); #else @@ -3893,12 +3898,12 @@ ERL_NIF_TERM nsupports_options_ip(ErlNifEnv* env) TARRAY_ADD(opts, tmp); - /* *** SOCKET_OPT_IP_MTU => IP_MTU *** */ + /* *** ESOCK_OPT_IP_MTU => IP_MTU *** */ tmp = MKT2(env, esock_atom_mtu, esock_atom_false); TARRAY_ADD(opts, tmp); - /* *** SOCKET_OPT_IP_MTU_DISCOVER => IP_MTU_DISCOVER *** */ + /* *** ESOCK_OPT_IP_MTU_DISCOVER => IP_MTU_DISCOVER *** */ #if defined(IP_MTU_DISCOVER) tmp = MKT2(env, esock_atom_mtu_discover, esock_atom_true); #else @@ -3907,7 +3912,7 @@ ERL_NIF_TERM nsupports_options_ip(ErlNifEnv* env) TARRAY_ADD(opts, tmp); - /* *** SOCKET_OPT_IP_MULTICAST_ALL => IP_MULTICAST_ALL *** */ + /* *** ESOCK_OPT_IP_MULTICAST_ALL => IP_MULTICAST_ALL *** */ #if defined(IP_MULTICAST_ALL) tmp = MKT2(env, esock_atom_multicast_all, esock_atom_true); #else @@ -3916,7 +3921,7 @@ ERL_NIF_TERM nsupports_options_ip(ErlNifEnv* env) TARRAY_ADD(opts, tmp); - /* *** SOCKET_OPT_IP_MULTICAST_IF => IP_MULTICAST_IF *** */ + /* *** ESOCK_OPT_IP_MULTICAST_IF => IP_MULTICAST_IF *** */ #if defined(IP_MULTICAST_IF) tmp = MKT2(env, esock_atom_multicast_if, esock_atom_true); #else @@ -3925,7 +3930,7 @@ ERL_NIF_TERM nsupports_options_ip(ErlNifEnv* env) TARRAY_ADD(opts, tmp); - /* *** SOCKET_OPT_IP_MULTICAST_LOOP => IP_MULTICAST_LOOP *** */ + /* *** ESOCK_OPT_IP_MULTICAST_LOOP => IP_MULTICAST_LOOP *** */ #if defined(IP_MULTICAST_LOOP) tmp = MKT2(env, esock_atom_multicast_loop, esock_atom_true); #else @@ -3934,7 +3939,7 @@ ERL_NIF_TERM nsupports_options_ip(ErlNifEnv* env) TARRAY_ADD(opts, tmp); - /* *** SOCKET_OPT_IP_MULTICAST_TTL => IP_MULTICAST_TTL *** */ + /* *** ESOCK_OPT_IP_MULTICAST_TTL => IP_MULTICAST_TTL *** */ #if defined(IP_MULTICAST_TTL) tmp = MKT2(env, esock_atom_multicast_ttl, esock_atom_true); #else @@ -3943,7 +3948,7 @@ ERL_NIF_TERM nsupports_options_ip(ErlNifEnv* env) TARRAY_ADD(opts, tmp); - /* *** SOCKET_OPT_IP_NODEFRAG => IP_NODEFRAG *** */ + /* *** ESOCK_OPT_IP_NODEFRAG => IP_NODEFRAG *** */ #if defined(IP_NODEFRAG) tmp = MKT2(env, esock_atom_nodefrag, esock_atom_true); #else @@ -3952,12 +3957,12 @@ ERL_NIF_TERM nsupports_options_ip(ErlNifEnv* env) TARRAY_ADD(opts, tmp); - /* *** SOCKET_OPT_IP_OPTIONS => IP_OPTIONS *** */ + /* *** ESOCK_OPT_IP_OPTIONS => IP_OPTIONS *** */ tmp = MKT2(env, esock_atom_options, esock_atom_false); TARRAY_ADD(opts, tmp); - /* *** SOCKET_OPT_IP_PKTINFO => IP_PKTINFO *** */ + /* *** ESOCK_OPT_IP_PKTINFO => IP_PKTINFO *** */ #if defined(IP_PKTINFO) tmp = MKT2(env, esock_atom_pktinfo, esock_atom_true); #else @@ -3966,7 +3971,7 @@ ERL_NIF_TERM nsupports_options_ip(ErlNifEnv* env) TARRAY_ADD(opts, tmp); - /* *** SOCKET_OPT_IP_RECVDSTADDR => IP_RECVDSTADDR *** */ + /* *** ESOCK_OPT_IP_RECVDSTADDR => IP_RECVDSTADDR *** */ #if defined(IP_RECVDSTADDR) tmp = MKT2(env, esock_atom_recvdstaddr, esock_atom_true); #else @@ -3975,7 +3980,7 @@ ERL_NIF_TERM nsupports_options_ip(ErlNifEnv* env) TARRAY_ADD(opts, tmp); - /* *** SOCKET_OPT_IP_RECVERR => IP_RECVERR *** */ + /* *** ESOCK_OPT_IP_RECVERR => IP_RECVERR *** */ #if defined(IP_RECVERR) tmp = MKT2(env, esock_atom_recverr, esock_atom_true); #else @@ -3984,7 +3989,7 @@ ERL_NIF_TERM nsupports_options_ip(ErlNifEnv* env) TARRAY_ADD(opts, tmp); - /* *** SOCKET_OPT_IP_RECVIF => IP_RECVIF *** */ + /* *** ESOCK_OPT_IP_RECVIF => IP_RECVIF *** */ #if defined(IP_RECVIF) tmp = MKT2(env, esock_atom_recvif, esock_atom_true); #else @@ -3993,7 +3998,7 @@ ERL_NIF_TERM nsupports_options_ip(ErlNifEnv* env) TARRAY_ADD(opts, tmp); - /* *** SOCKET_OPT_IP_RECVOPTS => IP_RECVOPTS *** */ + /* *** ESOCK_OPT_IP_RECVOPTS => IP_RECVOPTS *** */ #if defined(IP_RECVOPTS) tmp = MKT2(env, esock_atom_recvopts, esock_atom_true); #else @@ -4002,7 +4007,7 @@ ERL_NIF_TERM nsupports_options_ip(ErlNifEnv* env) TARRAY_ADD(opts, tmp); - /* *** SOCKET_OPT_IP_RECVORIGDSTADDR => IP_RECVORIGDSTADDR *** */ + /* *** ESOCK_OPT_IP_RECVORIGDSTADDR => IP_RECVORIGDSTADDR *** */ #if defined(IP_RECVORIGDSTADDR) tmp = MKT2(env, esock_atom_recvorigdstaddr, esock_atom_true); #else @@ -4011,7 +4016,7 @@ ERL_NIF_TERM nsupports_options_ip(ErlNifEnv* env) TARRAY_ADD(opts, tmp); - /* *** SOCKET_OPT_IP_RECVTOS => IP_RECVTOS *** */ + /* *** ESOCK_OPT_IP_RECVTOS => IP_RECVTOS *** */ #if defined(IP_RECVTOS) tmp = MKT2(env, esock_atom_recvtos, esock_atom_true); #else @@ -4020,7 +4025,7 @@ ERL_NIF_TERM nsupports_options_ip(ErlNifEnv* env) TARRAY_ADD(opts, tmp); - /* *** SOCKET_OPT_IP_RECVTTL => IP_RECVTTL *** */ + /* *** ESOCK_OPT_IP_RECVTTL => IP_RECVTTL *** */ #if defined(IP_RECVTTL) tmp = MKT2(env, esock_atom_recvttl, esock_atom_true); #else @@ -4029,7 +4034,7 @@ ERL_NIF_TERM nsupports_options_ip(ErlNifEnv* env) TARRAY_ADD(opts, tmp); - /* *** SOCKET_OPT_IP_RETOPTS => IP_RETOPTS *** */ + /* *** ESOCK_OPT_IP_RETOPTS => IP_RETOPTS *** */ #if defined(IP_RETOPTS) tmp = MKT2(env, esock_atom_retopts, esock_atom_true); #else @@ -4038,7 +4043,7 @@ ERL_NIF_TERM nsupports_options_ip(ErlNifEnv* env) TARRAY_ADD(opts, tmp); - /* *** SOCKET_OPT_IP_ROUTER_ALERT => IP_ROUTER_ALERT *** */ + /* *** ESOCK_OPT_IP_ROUTER_ALERT => IP_ROUTER_ALERT *** */ #if defined(IP_ROUTER_ALERT) tmp = MKT2(env, esock_atom_router_alert, esock_atom_true); #else @@ -4047,7 +4052,7 @@ ERL_NIF_TERM nsupports_options_ip(ErlNifEnv* env) TARRAY_ADD(opts, tmp); - /* *** SOCKET_OPT_IP_SENDSRCADDR => IP_SENDSRCADDR *** */ + /* *** ESOCK_OPT_IP_SENDSRCADDR => IP_SENDSRCADDR *** */ #if defined(IP_SENDSRCADDR) tmp = MKT2(env, esock_atom_sendsrcaddr, esock_atom_true); #else @@ -4056,7 +4061,7 @@ ERL_NIF_TERM nsupports_options_ip(ErlNifEnv* env) TARRAY_ADD(opts, tmp); - /* *** SOCKET_OPT_IP_TOS => IP_TOS *** */ + /* *** ESOCK_OPT_IP_TOS => IP_TOS *** */ #if defined(IP_TOS) tmp = MKT2(env, esock_atom_tos, esock_atom_true); #else @@ -4065,7 +4070,7 @@ ERL_NIF_TERM nsupports_options_ip(ErlNifEnv* env) TARRAY_ADD(opts, tmp); - /* *** SOCKET_OPT_IP_TRANSPARENT => IP_TRANSPARENT *** */ + /* *** ESOCK_OPT_IP_TRANSPARENT => IP_TRANSPARENT *** */ #if defined(IP_TRANSPARENT) tmp = MKT2(env, esock_atom_transparent, esock_atom_true); #else @@ -4074,7 +4079,7 @@ ERL_NIF_TERM nsupports_options_ip(ErlNifEnv* env) TARRAY_ADD(opts, tmp); - /* *** SOCKET_OPT_IP_TTL => IP_TTL *** */ + /* *** ESOCK_OPT_IP_TTL => IP_TTL *** */ #if defined(IP_TTL) tmp = MKT2(env, esock_atom_ttl, esock_atom_true); #else @@ -4083,7 +4088,7 @@ ERL_NIF_TERM nsupports_options_ip(ErlNifEnv* env) TARRAY_ADD(opts, tmp); - /* *** SOCKET_OPT_IP_UNBLOCK_SOURCE => IP_UNBLOCK_SOURCE *** */ + /* *** ESOCK_OPT_IP_UNBLOCK_SOURCE => IP_UNBLOCK_SOURCE *** */ #if defined(IP_UNBLOCK_SOURCE) tmp = MKT2(env, esock_atom_unblock_source, esock_atom_true); #else @@ -4102,13 +4107,13 @@ ERL_NIF_TERM nsupports_options_ip(ErlNifEnv* env) #if !defined(__WIN32__) static -ERL_NIF_TERM nsupports_options_ipv6(ErlNifEnv* env) +ERL_NIF_TERM esock_supports_options_ipv6(ErlNifEnv* env) { SocketTArray opts = TARRAY_CREATE(128); ERL_NIF_TERM tmp, optsL; - /* *** SOCKET_OPT_IPV6_ADDRFORM => IPV6_ADDRFORM *** */ + /* *** ESOCK_OPT_IPV6_ADDRFORM => IPV6_ADDRFORM *** */ #if defined(IPV6_ADDRFORM) tmp = MKT2(env, esock_atom_addrform, esock_atom_true); #else @@ -4117,7 +4122,7 @@ ERL_NIF_TERM nsupports_options_ipv6(ErlNifEnv* env) TARRAY_ADD(opts, tmp); - /* *** SOCKET_OPT_IPV6_ADD_MEMBERSHIP => IPV6_ADD_MEMBERSHIP *** */ + /* *** ESOCK_OPT_IPV6_ADD_MEMBERSHIP => IPV6_ADD_MEMBERSHIP *** */ #if defined(IPV6_ADD_MEMBERSHIP) tmp = MKT2(env, esock_atom_add_membership, esock_atom_true); #else @@ -4126,7 +4131,7 @@ ERL_NIF_TERM nsupports_options_ipv6(ErlNifEnv* env) TARRAY_ADD(opts, tmp); - /* *** SOCKET_OPT_IPV6_AUTHHDR => IPV6_AUTHHDR *** */ + /* *** ESOCK_OPT_IPV6_AUTHHDR => IPV6_AUTHHDR *** */ #if defined(IPV6_AUTHHDR) tmp = MKT2(env, esock_atom_authhdr, esock_atom_true); #else @@ -4135,17 +4140,17 @@ ERL_NIF_TERM nsupports_options_ipv6(ErlNifEnv* env) TARRAY_ADD(opts, tmp); - /* *** SOCKET_OPT_IPV6_AUTH_LEVEL => IPV6_AUTH_LEVEL *** */ + /* *** ESOCK_OPT_IPV6_AUTH_LEVEL => IPV6_AUTH_LEVEL *** */ tmp = MKT2(env, esock_atom_auth_level, esock_atom_false); TARRAY_ADD(opts, tmp); - /* *** SOCKET_OPT_IPV6_CHECKSUM => IPV6_CHECKSUM *** */ + /* *** ESOCK_OPT_IPV6_CHECKSUM => IPV6_CHECKSUM *** */ tmp = MKT2(env, esock_atom_checksum, esock_atom_false); TARRAY_ADD(opts, tmp); - /* *** SOCKET_OPT_IPV6_DROP_MEMBERSHIP => IPV6_DROP_MEMBERSHIP *** */ + /* *** ESOCK_OPT_IPV6_DROP_MEMBERSHIP => IPV6_DROP_MEMBERSHIP *** */ #if defined(IPV6_DROP_MEMBERSHIP) tmp = MKT2(env, esock_atom_drop_membership, esock_atom_true); #else @@ -4154,7 +4159,7 @@ ERL_NIF_TERM nsupports_options_ipv6(ErlNifEnv* env) TARRAY_ADD(opts, tmp); - /* *** SOCKET_OPT_IPV6_DSTOPTS => IPV6_DSTOPTS *** */ + /* *** ESOCK_OPT_IPV6_DSTOPTS => IPV6_DSTOPTS *** */ #if defined(IPV6_DSTOPTS) tmp = MKT2(env, esock_atom_dstopts, esock_atom_true); #else @@ -4163,22 +4168,22 @@ ERL_NIF_TERM nsupports_options_ipv6(ErlNifEnv* env) TARRAY_ADD(opts, tmp); - /* *** SOCKET_OPT_IPV6_ESP_NETWORK_LEVEL => IPV6_ESP_NETWORK_LEVEL *** */ + /* *** ESOCK_OPT_IPV6_ESP_NETWORK_LEVEL => IPV6_ESP_NETWORK_LEVEL *** */ tmp = MKT2(env, esock_atom_esp_network_level, esock_atom_false); TARRAY_ADD(opts, tmp); - /* *** SOCKET_OPT_IPV6_ESP_TRANS_LEVEL => IPV6_ESP_TRANS_LEVEL *** */ + /* *** ESOCK_OPT_IPV6_ESP_TRANS_LEVEL => IPV6_ESP_TRANS_LEVEL *** */ tmp = MKT2(env, esock_atom_esp_trans_level, esock_atom_false); TARRAY_ADD(opts, tmp); - /* *** SOCKET_OPT_IPV6_FAITH => IPV6_FAITH *** */ + /* *** ESOCK_OPT_IPV6_FAITH => IPV6_FAITH *** */ tmp = MKT2(env, esock_atom_faith, esock_atom_false); TARRAY_ADD(opts, tmp); - /* *** SOCKET_OPT_IPV6_FLOWINFO => IPV6_FLOWINFO *** */ + /* *** ESOCK_OPT_IPV6_FLOWINFO => IPV6_FLOWINFO *** */ #if defined(IPV6_FLOWINFO) tmp = MKT2(env, esock_atom_flowinfo, esock_atom_true); #else @@ -4187,7 +4192,7 @@ ERL_NIF_TERM nsupports_options_ipv6(ErlNifEnv* env) TARRAY_ADD(opts, tmp); - /* *** SOCKET_OPT_IPV6_HOPLIMIT => IPV6_HOPLIMIT *** */ + /* *** ESOCK_OPT_IPV6_HOPLIMIT => IPV6_HOPLIMIT *** */ #if defined(IPV6_HOPLIMIT) tmp = MKT2(env, esock_atom_hoplimit, esock_atom_true); #else @@ -4196,7 +4201,7 @@ ERL_NIF_TERM nsupports_options_ipv6(ErlNifEnv* env) TARRAY_ADD(opts, tmp); - /* *** SOCKET_OPT_IPV6_HOPOPTS => IPV6_HOPOPTS *** */ + /* *** ESOCK_OPT_IPV6_HOPOPTS => IPV6_HOPOPTS *** */ #if defined(IPV6_HOPOPTS) tmp = MKT2(env, esock_atom_hopopts, esock_atom_true); #else @@ -4205,22 +4210,22 @@ ERL_NIF_TERM nsupports_options_ipv6(ErlNifEnv* env) TARRAY_ADD(opts, tmp); - /* *** SOCKET_OPT_IPV6_IPCOMP_LEVEL => IPV6_IPCOMP_LEVEL *** */ + /* *** ESOCK_OPT_IPV6_IPCOMP_LEVEL => IPV6_IPCOMP_LEVEL *** */ tmp = MKT2(env, esock_atom_ipcomp_level, esock_atom_false); TARRAY_ADD(opts, tmp); - /* *** SOCKET_OPT_IPV6_JOIN_GROUP => IPV6_JOIN_GROUP *** */ + /* *** ESOCK_OPT_IPV6_JOIN_GROUP => IPV6_JOIN_GROUP *** */ tmp = MKT2(env, esock_atom_join_group, esock_atom_false); TARRAY_ADD(opts, tmp); - /* *** SOCKET_OPT_IPV6_LEAVE_GROUP => IPV6_LEAVE_GROUP *** */ + /* *** ESOCK_OPT_IPV6_LEAVE_GROUP => IPV6_LEAVE_GROUP *** */ tmp = MKT2(env, esock_atom_leave_group, esock_atom_false); TARRAY_ADD(opts, tmp); - /* *** SOCKET_OPT_IPV6_MTU => IPV6_MTU *** */ + /* *** ESOCK_OPT_IPV6_MTU => IPV6_MTU *** */ #if defined(IPV6_MTU) tmp = MKT2(env, esock_atom_mtu, esock_atom_true); #else @@ -4229,7 +4234,7 @@ ERL_NIF_TERM nsupports_options_ipv6(ErlNifEnv* env) TARRAY_ADD(opts, tmp); - /* *** SOCKET_OPT_IPV6_MTU_DISCOVER => IPV6_MTU_DISCOVER *** */ + /* *** ESOCK_OPT_IPV6_MTU_DISCOVER => IPV6_MTU_DISCOVER *** */ #if defined(IPV6_MTU_DISCOVER) tmp = MKT2(env, esock_atom_mtu_discover, esock_atom_true); #else @@ -4238,7 +4243,7 @@ ERL_NIF_TERM nsupports_options_ipv6(ErlNifEnv* env) TARRAY_ADD(opts, tmp); - /* *** SOCKET_OPT_IPV6_MULTICAST_HOPS => IPV6_MULTICAST_HOPS *** */ + /* *** ESOCK_OPT_IPV6_MULTICAST_HOPS => IPV6_MULTICAST_HOPS *** */ #if defined(IPV6_MULTICAST_HOPS) tmp = MKT2(env, esock_atom_multicast_hops, esock_atom_true); #else @@ -4247,7 +4252,7 @@ ERL_NIF_TERM nsupports_options_ipv6(ErlNifEnv* env) TARRAY_ADD(opts, tmp); - /* *** SOCKET_OPT_IPV6_MULTICAST_IF => IPV6_MULTICAST_IF *** */ + /* *** ESOCK_OPT_IPV6_MULTICAST_IF => IPV6_MULTICAST_IF *** */ #if defined(IPV6_MULTICAST_IF) tmp = MKT2(env, esock_atom_multicast_if, esock_atom_true); #else @@ -4256,7 +4261,7 @@ ERL_NIF_TERM nsupports_options_ipv6(ErlNifEnv* env) TARRAY_ADD(opts, tmp); - /* *** SOCKET_OPT_IPV6_MULTICAST_LOOP => IPV6_MULTICAST_LOOP *** */ + /* *** ESOCK_OPT_IPV6_MULTICAST_LOOP => IPV6_MULTICAST_LOOP *** */ #if defined(IPV6_MULTICAST_LOOP) tmp = MKT2(env, esock_atom_multicast_loop, esock_atom_true); #else @@ -4265,17 +4270,17 @@ ERL_NIF_TERM nsupports_options_ipv6(ErlNifEnv* env) TARRAY_ADD(opts, tmp); - /* *** SOCKET_OPT_IPV6_PORTRANGE => IPV6_PORTRANGE *** */ + /* *** ESOCK_OPT_IPV6_PORTRANGE => IPV6_PORTRANGE *** */ tmp = MKT2(env, esock_atom_portrange, esock_atom_false); TARRAY_ADD(opts, tmp); - /* *** SOCKET_OPT_IPV6_PKTOPTIONS => IPV6_PKTOPTIONS *** */ + /* *** ESOCK_OPT_IPV6_PKTOPTIONS => IPV6_PKTOPTIONS *** */ tmp = MKT2(env, esock_atom_pktoptions, esock_atom_false); TARRAY_ADD(opts, tmp); - /* *** SOCKET_OPT_IPV6_RECVERR => IPV6_RECVERR *** */ + /* *** ESOCK_OPT_IPV6_RECVERR => IPV6_RECVERR *** */ #if defined(IPV6_RECVERR) tmp = MKT2(env, esock_atom_recverr, esock_atom_true); #else @@ -4284,7 +4289,7 @@ ERL_NIF_TERM nsupports_options_ipv6(ErlNifEnv* env) TARRAY_ADD(opts, tmp); - /* *** SOCKET_OPT_IPV6_RECVPKTINFO => IPV6_RECVPKTINFO *** */ + /* *** ESOCK_OPT_IPV6_RECVPKTINFO => IPV6_RECVPKTINFO *** */ #if defined(IPV6_RECVPKTINFO) tmp = MKT2(env, esock_atom_recvpktinfo, esock_atom_true); #else @@ -4293,12 +4298,12 @@ ERL_NIF_TERM nsupports_options_ipv6(ErlNifEnv* env) TARRAY_ADD(opts, tmp); - /* *** SOCKET_OPT_IPV6_RECVTCLASS => IPV6_RECVTCLASS *** */ + /* *** ESOCK_OPT_IPV6_RECVTCLASS => IPV6_RECVTCLASS *** */ tmp = MKT2(env, esock_atom_recvtclass, esock_atom_false); TARRAY_ADD(opts, tmp); - /* *** SOCKET_OPT_IPV6_ROUTER_ALERT => IPV6_ROUTER_ALERT *** */ + /* *** ESOCK_OPT_IPV6_ROUTER_ALERT => IPV6_ROUTER_ALERT *** */ #if defined(IPV6_ROUTER_ALERT) tmp = MKT2(env, esock_atom_router_alert, esock_atom_true); #else @@ -4307,7 +4312,7 @@ ERL_NIF_TERM nsupports_options_ipv6(ErlNifEnv* env) TARRAY_ADD(opts, tmp); - /* *** SOCKET_OPT_IPV6_RTHDR => IPV6_RTHDR *** */ + /* *** ESOCK_OPT_IPV6_RTHDR => IPV6_RTHDR *** */ #if defined(IPV6_RTHDR) tmp = MKT2(env, esock_atom_rthdr, esock_atom_true); #else @@ -4316,12 +4321,12 @@ ERL_NIF_TERM nsupports_options_ipv6(ErlNifEnv* env) TARRAY_ADD(opts, tmp); - /* *** SOCKET_OPT_IPV6_TCLASS => IPV6_TCLASS *** */ + /* *** ESOCK_OPT_IPV6_TCLASS => IPV6_TCLASS *** */ tmp = MKT2(env, esock_atom_tclass, esock_atom_false); TARRAY_ADD(opts, tmp); - /* *** SOCKET_OPT_IPV6_UNICAST_HOPS => IPV6_UNICAST_HOPS *** */ + /* *** ESOCK_OPT_IPV6_UNICAST_HOPS => IPV6_UNICAST_HOPS *** */ #if defined(IPV6_UNICAST_HOPS) tmp = MKT2(env, esock_atom_unicast_hops, esock_atom_true); #else @@ -4330,12 +4335,12 @@ ERL_NIF_TERM nsupports_options_ipv6(ErlNifEnv* env) TARRAY_ADD(opts, tmp); - /* *** SOCKET_OPT_IPV6_USE_MIN_MTU => IPV6_USE_MIN_MTU *** */ + /* *** ESOCK_OPT_IPV6_USE_MIN_MTU => IPV6_USE_MIN_MTU *** */ tmp = MKT2(env, esock_atom_use_min_mtu, esock_atom_false); TARRAY_ADD(opts, tmp); - /* *** SOCKET_OPT_IPV6_V6ONLY => IPV6_V6ONLY *** */ + /* *** ESOCK_OPT_IPV6_V6ONLY => IPV6_V6ONLY *** */ #if defined(IPV6_V6ONLY) tmp = MKT2(env, esock_atom_v6only, esock_atom_true); #else @@ -4354,13 +4359,13 @@ ERL_NIF_TERM nsupports_options_ipv6(ErlNifEnv* env) #if !defined(__WIN32__) static -ERL_NIF_TERM nsupports_options_tcp(ErlNifEnv* env) +ERL_NIF_TERM esock_supports_options_tcp(ErlNifEnv* env) { SocketTArray opts = TARRAY_CREATE(32); ERL_NIF_TERM tmp, optsL; - /* *** SOCKET_OPT_TCP_CONGESTION => TCP_CONGESTION *** */ + /* *** ESOCK_OPT_TCP_CONGESTION => TCP_CONGESTION *** */ #if defined(TCP_CONGESTION) tmp = MKT2(env, esock_atom_congestion, esock_atom_true); #else @@ -4369,7 +4374,7 @@ ERL_NIF_TERM nsupports_options_tcp(ErlNifEnv* env) TARRAY_ADD(opts, tmp); - /* *** SOCKET_OPT_TCP_CORK => TCP_CORK *** */ + /* *** ESOCK_OPT_TCP_CORK => TCP_CORK *** */ #if defined(TCP_CORK) tmp = MKT2(env, esock_atom_cork, esock_atom_true); #else @@ -4378,27 +4383,27 @@ ERL_NIF_TERM nsupports_options_tcp(ErlNifEnv* env) TARRAY_ADD(opts, tmp); - /* *** SOCKET_OPT_TCP_INFO => TCP_INFO *** */ + /* *** ESOCK_OPT_TCP_INFO => TCP_INFO *** */ tmp = MKT2(env, esock_atom_info, esock_atom_false); TARRAY_ADD(opts, tmp); - /* *** SOCKET_OPT_TCP_KEEPCNT => TCP_KEEPCNT *** */ + /* *** ESOCK_OPT_TCP_KEEPCNT => TCP_KEEPCNT *** */ tmp = MKT2(env, esock_atom_keepcnt, esock_atom_false); TARRAY_ADD(opts, tmp); - /* *** SOCKET_OPT_TCP_KEEPIDLE => TCP_KEEPIDLE *** */ + /* *** ESOCK_OPT_TCP_KEEPIDLE => TCP_KEEPIDLE *** */ tmp = MKT2(env, esock_atom_keepidle, esock_atom_false); TARRAY_ADD(opts, tmp); - /* *** SOCKET_OPT_TCP_KEEPINTVL => TCP_KEEPINTVL *** */ + /* *** ESOCK_OPT_TCP_KEEPINTVL => TCP_KEEPINTVL *** */ tmp = MKT2(env, esock_atom_keepintvl, esock_atom_false); TARRAY_ADD(opts, tmp); - /* *** SOCKET_OPT_TCP_MAXSEG => TCP_MAXSEG *** */ + /* *** ESOCK_OPT_TCP_MAXSEG => TCP_MAXSEG *** */ #if defined(TCP_MAXSEG) tmp = MKT2(env, esock_atom_maxseg, esock_atom_true); #else @@ -4407,12 +4412,12 @@ ERL_NIF_TERM nsupports_options_tcp(ErlNifEnv* env) TARRAY_ADD(opts, tmp); - /* *** SOCKET_OPT_TCP_MD5SIG => TCP_MD5SIG *** */ + /* *** ESOCK_OPT_TCP_MD5SIG => TCP_MD5SIG *** */ tmp = MKT2(env, esock_atom_md5sig, esock_atom_false); TARRAY_ADD(opts, tmp); - /* *** SOCKET_OPT_TCP_NODELAY => TCP_NODELAY *** */ + /* *** ESOCK_OPT_TCP_NODELAY => TCP_NODELAY *** */ #if defined(TCP_NODELAY) tmp = MKT2(env, esock_atom_nodelay, esock_atom_true); #else @@ -4421,22 +4426,22 @@ ERL_NIF_TERM nsupports_options_tcp(ErlNifEnv* env) TARRAY_ADD(opts, tmp); - /* *** SOCKET_OPT_TCP_NOOPT => TCP_NOOPT *** */ + /* *** ESOCK_OPT_TCP_NOOPT => TCP_NOOPT *** */ tmp = MKT2(env, esock_atom_noopt, esock_atom_false); TARRAY_ADD(opts, tmp); - /* *** SOCKET_OPT_TCP_NOPUSH => TCP_NOPUSH *** */ + /* *** ESOCK_OPT_TCP_NOPUSH => TCP_NOPUSH *** */ tmp = MKT2(env, esock_atom_nopush, esock_atom_false); TARRAY_ADD(opts, tmp); - /* *** SOCKET_OPT_TCP_SYNCNT => TCP_SYNCNT *** */ + /* *** ESOCK_OPT_TCP_SYNCNT => TCP_SYNCNT *** */ tmp = MKT2(env, esock_atom_syncnt, esock_atom_false); TARRAY_ADD(opts, tmp); - /* *** SOCKET_OPT_TCP_USER_TIMEOUT => TCP_USER_TIMEOUT *** */ + /* *** ESOCK_OPT_TCP_USER_TIMEOUT => TCP_USER_TIMEOUT *** */ tmp = MKT2(env, esock_atom_user_timeout, esock_atom_false); TARRAY_ADD(opts, tmp); @@ -4451,13 +4456,13 @@ ERL_NIF_TERM nsupports_options_tcp(ErlNifEnv* env) #if !defined(__WIN32__) static -ERL_NIF_TERM nsupports_options_udp(ErlNifEnv* env) +ERL_NIF_TERM esock_supports_options_udp(ErlNifEnv* env) { SocketTArray opts = TARRAY_CREATE(8); ERL_NIF_TERM tmp, optsL; - /* *** SOCKET_OPT_UDP_CORK => UDP_CORK *** */ + /* *** ESOCK_OPT_UDP_CORK => UDP_CORK *** */ #if defined(UDP_CORK) tmp = MKT2(env, esock_atom_cork, esock_atom_true); #else @@ -4476,18 +4481,18 @@ ERL_NIF_TERM nsupports_options_udp(ErlNifEnv* env) #if !defined(__WIN32__) static -ERL_NIF_TERM nsupports_options_sctp(ErlNifEnv* env) +ERL_NIF_TERM esock_supports_options_sctp(ErlNifEnv* env) { SocketTArray opts = TARRAY_CREATE(64); ERL_NIF_TERM tmp, optsL; - /* *** SOCKET_OPT_SCTP_ADAPTION_LAYER => SCTP_ADAPTION_LAYER *** */ + /* *** ESOCK_OPT_SCTP_ADAPTION_LAYER => SCTP_ADAPTION_LAYER *** */ tmp = MKT2(env, esock_atom_adaption_layer, esock_atom_false); TARRAY_ADD(opts, tmp); - /* *** SOCKET_OPT_SCTP_ASSOCINFO => SCTP_ASSOCINFO *** */ + /* *** ESOCK_OPT_SCTP_ASSOCINFO => SCTP_ASSOCINFO *** */ #if defined(SCTP_ASSOCINFO) tmp = MKT2(env, esock_atom_associnfo, esock_atom_true); #else @@ -4496,32 +4501,32 @@ ERL_NIF_TERM nsupports_options_sctp(ErlNifEnv* env) TARRAY_ADD(opts, tmp); - /* *** SOCKET_OPT_SCTP_AUTH_ACTIVE_KEY => SCTP_AUTH_ACTIVE_KEY *** */ + /* *** ESOCK_OPT_SCTP_AUTH_ACTIVE_KEY => SCTP_AUTH_ACTIVE_KEY *** */ tmp = MKT2(env, esock_atom_auth_active_key, esock_atom_false); TARRAY_ADD(opts, tmp); - /* *** SOCKET_OPT_SCTP_AUTH_ASCONF => SCTP_AUTH_ASCONF *** */ + /* *** ESOCK_OPT_SCTP_AUTH_ASCONF => SCTP_AUTH_ASCONF *** */ tmp = MKT2(env, esock_atom_auth_asconf, esock_atom_false); TARRAY_ADD(opts, tmp); - /* *** SOCKET_OPT_SCTP_AUTH_CHUNK => SCTP_AUTH_CHUNK *** */ + /* *** ESOCK_OPT_SCTP_AUTH_CHUNK => SCTP_AUTH_CHUNK *** */ tmp = MKT2(env, esock_atom_auth_chunk, esock_atom_false); TARRAY_ADD(opts, tmp); - /* *** SOCKET_OPT_SCTP_AUTH_DELETE_KEY => SCTP_AUTH_DELETE_KEY *** */ + /* *** ESOCK_OPT_SCTP_AUTH_DELETE_KEY => SCTP_AUTH_DELETE_KEY *** */ tmp = MKT2(env, esock_atom_auth_delete_key, esock_atom_false); TARRAY_ADD(opts, tmp); - /* *** SOCKET_OPT_SCTP_AUTH_KEY => SCTP_AUTH_KEY *** */ + /* *** ESOCK_OPT_SCTP_AUTH_KEY => SCTP_AUTH_KEY *** */ tmp = MKT2(env, esock_atom_auth_key, esock_atom_false); TARRAY_ADD(opts, tmp); - /* *** SOCKET_OPT_SCTP_AUTOCLOSE => SCTP_AUTOCLOSE *** */ + /* *** ESOCK_OPT_SCTP_AUTOCLOSE => SCTP_AUTOCLOSE *** */ #if defined(SCTP_AUTOCLOSE) tmp = MKT2(env, esock_atom_autoclose, esock_atom_true); #else @@ -4530,22 +4535,22 @@ ERL_NIF_TERM nsupports_options_sctp(ErlNifEnv* env) TARRAY_ADD(opts, tmp); - /* *** SOCKET_OPT_SCTP_CONTEXT => SCTP_CONTEXT *** */ + /* *** ESOCK_OPT_SCTP_CONTEXT => SCTP_CONTEXT *** */ tmp = MKT2(env, esock_atom_context, esock_atom_false); TARRAY_ADD(opts, tmp); - /* *** SOCKET_OPT_SCTP_DEFAULT_SEND_PARAMS => SCTP_DEFAULT_SEND_PARAMS *** */ + /* *** ESOCK_OPT_SCTP_DEFAULT_SEND_PARAMS => SCTP_DEFAULT_SEND_PARAMS *** */ tmp = MKT2(env, esock_atom_default_send_params, esock_atom_false); TARRAY_ADD(opts, tmp); - /* *** SOCKET_OPT_SCTP_DELAYED_ACK_TIME => SCTP_DELAYED_ACK_TIME *** */ + /* *** ESOCK_OPT_SCTP_DELAYED_ACK_TIME => SCTP_DELAYED_ACK_TIME *** */ tmp = MKT2(env, esock_atom_delayed_ack_time, esock_atom_false); TARRAY_ADD(opts, tmp); - /* *** SOCKET_OPT_SCTP_DISABLE_FRAGMENTS => SCTP_DISABLE_FRAGMENTS *** */ + /* *** ESOCK_OPT_SCTP_DISABLE_FRAGMENTS => SCTP_DISABLE_FRAGMENTS *** */ #if defined(SCTP_DISABLE_FRAGMENTS) tmp = MKT2(env, esock_atom_disable_fragments, esock_atom_true); #else @@ -4554,12 +4559,12 @@ ERL_NIF_TERM nsupports_options_sctp(ErlNifEnv* env) TARRAY_ADD(opts, tmp); - /* *** SOCKET_OPT_SCTP_HMAC_IDENT => SCTP_HMAC_IDENT *** */ + /* *** ESOCK_OPT_SCTP_HMAC_IDENT => SCTP_HMAC_IDENT *** */ tmp = MKT2(env, esock_atom_hmac_ident, esock_atom_false); TARRAY_ADD(opts, tmp); - /* *** SOCKET_OPT_SCTP_EVENTS => SCTP_EVENTS *** */ + /* *** ESOCK_OPT_SCTP_EVENTS => SCTP_EVENTS *** */ #if defined(SCTP_EVENTS) tmp = MKT2(env, esock_atom_events, esock_atom_true); #else @@ -4568,22 +4573,22 @@ ERL_NIF_TERM nsupports_options_sctp(ErlNifEnv* env) TARRAY_ADD(opts, tmp); - /* *** SOCKET_OPT_SCTP_EXPLICIT_EOR => SCTP_EXPLICIT_EOR *** */ + /* *** ESOCK_OPT_SCTP_EXPLICIT_EOR => SCTP_EXPLICIT_EOR *** */ tmp = MKT2(env, esock_atom_explicit_eor, esock_atom_false); TARRAY_ADD(opts, tmp); - /* *** SOCKET_OPT_SCTP_FRAGMENT_INTERLEAVE => SCTP_FRAGMENT_INTERLEAVE *** */ + /* *** ESOCK_OPT_SCTP_FRAGMENT_INTERLEAVE => SCTP_FRAGMENT_INTERLEAVE *** */ tmp = MKT2(env, esock_atom_fragment_interleave, esock_atom_false); TARRAY_ADD(opts, tmp); - /* *** SOCKET_OPT_SCTP_GET_PEER_ADDR_INFO => SCTP_GET_PEER_ADDR_INFO *** */ + /* *** ESOCK_OPT_SCTP_GET_PEER_ADDR_INFO => SCTP_GET_PEER_ADDR_INFO *** */ tmp = MKT2(env, esock_atom_get_peer_addr_info, esock_atom_false); TARRAY_ADD(opts, tmp); - /* *** SOCKET_OPT_SCTP_INITMSG => SCTP_INITMSG *** */ + /* *** ESOCK_OPT_SCTP_INITMSG => SCTP_INITMSG *** */ #if defined(SCTP_INITMSG) tmp = MKT2(env, esock_atom_initmsg, esock_atom_true); #else @@ -4592,17 +4597,17 @@ ERL_NIF_TERM nsupports_options_sctp(ErlNifEnv* env) TARRAY_ADD(opts, tmp); - /* *** SOCKET_OPT_SCTP_I_WANT_MAPPED_V4_ADDR => SCTP_I_WANT_MAPPED_V4_ADDR *** */ + /* *** ESOCK_OPT_SCTP_I_WANT_MAPPED_V4_ADDR => SCTP_I_WANT_MAPPED_V4_ADDR *** */ tmp = MKT2(env, esock_atom_i_want_mapped_v4_addr, esock_atom_false); TARRAY_ADD(opts, tmp); - /* *** SOCKET_OPT_SCTP_LOCAL_AUTH_CHUNKS => SCTP_LOCAL_AUTH_CHUNKS *** */ + /* *** ESOCK_OPT_SCTP_LOCAL_AUTH_CHUNKS => SCTP_LOCAL_AUTH_CHUNKS *** */ tmp = MKT2(env, esock_atom_local_auth_chunks, esock_atom_false); TARRAY_ADD(opts, tmp); - /* *** SOCKET_OPT_SCTP_MAXSEG => SCTP_MAXSEG *** */ + /* *** ESOCK_OPT_SCTP_MAXSEG => SCTP_MAXSEG *** */ #if defined(SCTP_MAXSEG) tmp = MKT2(env, esock_atom_maxseg, esock_atom_true); #else @@ -4611,12 +4616,12 @@ ERL_NIF_TERM nsupports_options_sctp(ErlNifEnv* env) TARRAY_ADD(opts, tmp); - /* *** SOCKET_OPT_SCTP_MAXBURST => SCTP_MAXBURST *** */ + /* *** ESOCK_OPT_SCTP_MAXBURST => SCTP_MAXBURST *** */ tmp = MKT2(env, esock_atom_maxburst, esock_atom_false); TARRAY_ADD(opts, tmp); - /* *** SOCKET_OPT_SCTP_NODELAY => SCTP_NODELAY *** */ + /* *** ESOCK_OPT_SCTP_NODELAY => SCTP_NODELAY *** */ #if defined(SCTP_NODELAY) tmp = MKT2(env, esock_atom_nodelay, esock_atom_true); #else @@ -4625,32 +4630,32 @@ ERL_NIF_TERM nsupports_options_sctp(ErlNifEnv* env) TARRAY_ADD(opts, tmp); - /* *** SOCKET_OPT_SCTP_PARTIAL_DELIVERY_POINT => SCTP_PARTIAL_DELIVERY_POINT *** */ + /* *** ESOCK_OPT_SCTP_PARTIAL_DELIVERY_POINT => SCTP_PARTIAL_DELIVERY_POINT *** */ tmp = MKT2(env, esock_atom_partial_delivery_point, esock_atom_false); TARRAY_ADD(opts, tmp); - /* *** SOCKET_OPT_SCTP_PEER_ADDR_PARAMS => SCTP_PEER_ADDR_PARAMS *** */ + /* *** ESOCK_OPT_SCTP_PEER_ADDR_PARAMS => SCTP_PEER_ADDR_PARAMS *** */ tmp = MKT2(env, esock_atom_peer_addr_params, esock_atom_false); TARRAY_ADD(opts, tmp); - /* *** SOCKET_OPT_SCTP_PEER_AUTH_CHUNKS => SCTP_PEER_AUTH_CHUNKS *** */ + /* *** ESOCK_OPT_SCTP_PEER_AUTH_CHUNKS => SCTP_PEER_AUTH_CHUNKS *** */ tmp = MKT2(env, esock_atom_peer_auth_chunks, esock_atom_false); TARRAY_ADD(opts, tmp); - /* *** SOCKET_OPT_SCTP_PRIMARY_ADDR => SCTP_PRIMARY_ADDR *** */ + /* *** ESOCK_OPT_SCTP_PRIMARY_ADDR => SCTP_PRIMARY_ADDR *** */ tmp = MKT2(env, esock_atom_primary_addr, esock_atom_false); TARRAY_ADD(opts, tmp); - /* *** SOCKET_OPT_SCTP_RESET_STREAMS => SCTP_RESET_STREAMS *** */ + /* *** ESOCK_OPT_SCTP_RESET_STREAMS => SCTP_RESET_STREAMS *** */ tmp = MKT2(env, esock_atom_reset_streams, esock_atom_false); TARRAY_ADD(opts, tmp); - /* *** SOCKET_OPT_SCTP_RTOINFO => SCTP_RTOINFO *** */ + /* *** ESOCK_OPT_SCTP_RTOINFO => SCTP_RTOINFO *** */ #if defined(SCTP_RTOINFO) tmp = MKT2(env, esock_atom_rtoinfo, esock_atom_true); #else @@ -4659,17 +4664,17 @@ ERL_NIF_TERM nsupports_options_sctp(ErlNifEnv* env) TARRAY_ADD(opts, tmp); - /* *** SOCKET_OPT_SCTP_SET_PEER_PRIMARY_ADDR => SCTP_SET_PEER_PRIMARY_ADDR *** */ + /* *** ESOCK_OPT_SCTP_SET_PEER_PRIMARY_ADDR => SCTP_SET_PEER_PRIMARY_ADDR *** */ tmp = MKT2(env, esock_atom_set_peer_primary_addr, esock_atom_false); TARRAY_ADD(opts, tmp); - /* *** SOCKET_OPT_SCTP_STATUS => SCTP_STATUS *** */ + /* *** ESOCK_OPT_SCTP_STATUS => SCTP_STATUS *** */ tmp = MKT2(env, esock_atom_status, esock_atom_false); TARRAY_ADD(opts, tmp); - /* *** SOCKET_OPT_SCTP_USE_EXT_RECVINFO => SCTP_USE_EXT_RECVINFO *** */ + /* *** ESOCK_OPT_SCTP_USE_EXT_RECVINFO => SCTP_USE_EXT_RECVINFO *** */ tmp = MKT2(env, esock_atom_use_ext_recvinfo, esock_atom_false); TARRAY_ADD(opts, tmp); @@ -4684,7 +4689,7 @@ ERL_NIF_TERM nsupports_options_sctp(ErlNifEnv* env) #if !defined(__WIN32__) static -ERL_NIF_TERM nsupports_sctp(ErlNifEnv* env) +ERL_NIF_TERM esock_supports_sctp(ErlNifEnv* env) { ERL_NIF_TERM supports; @@ -4702,7 +4707,7 @@ ERL_NIF_TERM nsupports_sctp(ErlNifEnv* env) #if !defined(__WIN32__) static -ERL_NIF_TERM nsupports_ipv6(ErlNifEnv* env) +ERL_NIF_TERM esock_supports_ipv6(ErlNifEnv* env) { ERL_NIF_TERM supports; @@ -4721,7 +4726,7 @@ ERL_NIF_TERM nsupports_ipv6(ErlNifEnv* env) #if !defined(__WIN32__) static -ERL_NIF_TERM nsupports_local(ErlNifEnv* env) +ERL_NIF_TERM esock_supports_local(ErlNifEnv* env) { ERL_NIF_TERM supports; @@ -4813,7 +4818,7 @@ ERL_NIF_TERM nif_open(ErlNifEnv* env, #endif - result = nopen(env, domain, type, proto, netns); + result = esock_open(env, domain, type, proto, netns); SGDBG( ("SOCKET", "nif_open -> done with result: " "\r\n %T" @@ -4825,7 +4830,7 @@ ERL_NIF_TERM nif_open(ErlNifEnv* env, } -/* nopen - create an endpoint for communication +/* esock_open - create an endpoint for communication * * Assumes the input has been validated. * @@ -4836,9 +4841,9 @@ ERL_NIF_TERM nif_open(ErlNifEnv* env, #if !defined(__WIN32__) static -ERL_NIF_TERM nopen(ErlNifEnv* env, - int domain, int type, int protocol, - char* netns) +ERL_NIF_TERM esock_open(ErlNifEnv* env, + int domain, int type, int protocol, + char* netns) { ESockDescriptor* descP; ERL_NIF_TERM res; @@ -4849,7 +4854,7 @@ ERL_NIF_TERM nopen(ErlNifEnv* env, int current_ns = 0; #endif - SGDBG( ("SOCKET", "nopen -> entry with" + SGDBG( ("SOCKET", "esock_open -> entry with" "\r\n domain: %d" "\r\n type: %d" "\r\n protocol: %d" @@ -4865,7 +4870,7 @@ ERL_NIF_TERM nopen(ErlNifEnv* env, if ((sock = sock_open(domain, type, proto)) == INVALID_SOCKET) return esock_make_error_errno(env, sock_errno()); - SGDBG( ("SOCKET", "nopen -> open success: %d\r\n", sock) ); + SGDBG( ("SOCKET", "esock_open -> open success: %d\r\n", sock) ); /* NOTE that if the protocol = 0 (default) and the domain is not @@ -4877,7 +4882,7 @@ ERL_NIF_TERM nopen(ErlNifEnv* env, && (domain != AF_LOCAL) #endif ) - if (!nopen_which_protocol(sock, &proto)) { + if (!esock_open_which_protocol(sock, &proto)) { if (proto == ESOCK_WHICH_PROTO_ERROR) { save_errno = sock_errno(); while ((sock_close(sock) == INVALID_SOCKET) && @@ -4907,7 +4912,7 @@ ERL_NIF_TERM nopen(ErlNifEnv* env, return esock_make_error_errno(env, save_errno); } - SGDBG( ("SOCKET", "nopen -> event success: %d\r\n", event) ); + SGDBG( ("SOCKET", "esock_open -> event success: %d\r\n", event) ); SET_NONBLOCKING(sock); @@ -4919,7 +4924,7 @@ ERL_NIF_TERM nopen(ErlNifEnv* env, return enif_make_badarg(env); } - descP->state = SOCKET_STATE_OPEN; + descP->state = ESOCK_STATE_OPEN; descP->domain = domain; descP->type = type; descP->protocol = proto; @@ -4948,7 +4953,7 @@ ERL_NIF_TERM nopen(ErlNifEnv* env, if (enif_self(env, &descP->ctrlPid) == NULL) return esock_make_error(env, atom_exself); - if (MONP("nopen -> ctrl", + if (MONP("esock_open -> ctrl", env, descP, &descP->ctrlPid, &descP->ctrlMon) != 0) @@ -4962,7 +4967,7 @@ ERL_NIF_TERM nopen(ErlNifEnv* env, static -BOOLEAN_T nopen_which_protocol(SOCKET sock, int* proto) +BOOLEAN_T esock_open_which_protocol(SOCKET sock, int* proto) { #if defined(SO_PROTOCOL) int val; @@ -5121,7 +5126,7 @@ ERL_NIF_TERM nif_bind(ErlNifEnv* env, /* Extract arguments and perform preliminary validation */ if ((argc != 2) || - !enif_get_resource(env, argv[0], sockets, (void**) &descP)) { + !ESOCK_GET_RESOURCE(env, argv[0], (void**) &descP)) { return enif_make_badarg(env); } eSockAddr = argv[1]; @@ -5138,13 +5143,13 @@ ERL_NIF_TERM nif_bind(ErlNifEnv* env, /* Make sure we are ready * Not sure how this would even happen, but... */ - if (descP->state != SOCKET_STATE_OPEN) + if (descP->state != ESOCK_STATE_OPEN) return esock_make_error(env, atom_exbadstate); if ((xres = esock_decode_sockaddr(env, eSockAddr, &sockAddr, &addrLen)) != NULL) return esock_make_error_str(env, xres); - return nbind(env, descP, &sockAddr, addrLen); + return esock_bind(env, descP, &sockAddr, addrLen); #endif // if defined(__WIN32__) } @@ -5152,24 +5157,24 @@ ERL_NIF_TERM nif_bind(ErlNifEnv* env, #if !defined(__WIN32__) static -ERL_NIF_TERM nbind(ErlNifEnv* env, - ESockDescriptor* descP, - ESockAddress* sockAddrP, - unsigned int addrLen) +ERL_NIF_TERM esock_bind(ErlNifEnv* env, + ESockDescriptor* descP, + ESockAddress* sockAddrP, + unsigned int addrLen) { int port, ntohs_port; - SSDBG( descP, ("SOCKET", "nbind -> try bind\r\n") ); + SSDBG( descP, ("SOCKET", "esock_bind -> try bind\r\n") ); if (IS_SOCKET_ERROR(sock_bind(descP->sock, (struct sockaddr*) sockAddrP, addrLen))) { return esock_make_error_errno(env, sock_errno()); } - SSDBG( descP, ("SOCKET", "nbind -> bound - get port\r\n") ); + SSDBG( descP, ("SOCKET", "esock_bind -> bound - get port\r\n") ); port = which_address_port(sockAddrP); - SSDBG( descP, ("SOCKET", "nbind -> port: %d\r\n", port) ); + SSDBG( descP, ("SOCKET", "esock_bind -> port: %d\r\n", port) ); if (port == 0) { SOCKLEN_T len = sizeof(ESockAddress); sys_memzero((char *) sockAddrP, len); @@ -5181,7 +5186,8 @@ ERL_NIF_TERM nbind(ErlNifEnv* env, ntohs_port = sock_ntohs(port); - SSDBG( descP, ("SOCKET", "nbind -> done with port = %d\r\n", ntohs_port) ); + SSDBG( descP, ("SOCKET", + "esock_bind -> done with port = %d\r\n", ntohs_port) ); return esock_make_ok2(env, MKI(env, ntohs_port)); @@ -5221,7 +5227,7 @@ ERL_NIF_TERM nif_connect(ErlNifEnv* env, sockRef = argv[0]; if ((argc != 2) || - !enif_get_resource(env, sockRef, sockets, (void**) &descP)) { + !ESOCK_GET_RESOURCE(env, sockRef, (void**) &descP)) { return enif_make_badarg(env); } eSockAddr = argv[1]; @@ -5248,7 +5254,7 @@ ERL_NIF_TERM nif_connect(ErlNifEnv* env, MLOCK(descP->writeMtx); MLOCK(descP->cfgMtx); - res = nconnect(env, descP, sockRef); + res = esock_connect(env, descP, sockRef); MUNLOCK(descP->cfgMtx); MUNLOCK(descP->writeMtx); @@ -5262,9 +5268,9 @@ ERL_NIF_TERM nif_connect(ErlNifEnv* env, #if !defined(__WIN32__) static -ERL_NIF_TERM nconnect(ErlNifEnv* env, - ESockDescriptor* descP, - ERL_NIF_TERM sockRef) +ERL_NIF_TERM esock_connect(ErlNifEnv* env, + ESockDescriptor* descP, + ERL_NIF_TERM sockRef) { ERL_NIF_TERM res, ref; int code, sres, save_errno = 0; @@ -5277,17 +5283,17 @@ ERL_NIF_TERM nconnect(ErlNifEnv* env, return esock_make_error(env, atom_closed); if (!IS_OPEN(descP)) { - SSDBG( descP, ("SOCKET", "nconnect -> not open\r\n") ); + SSDBG( descP, ("SOCKET", "esock_connect -> not open\r\n") ); return esock_make_error(env, atom_exbadstate); } if (IS_CONNECTED(descP)) { - SSDBG( descP, ("SOCKET", "nconnect -> already connected\r\n") ); + SSDBG( descP, ("SOCKET", "esock_connect -> already connected\r\n") ); return esock_make_error(env, atom_eisconn); } if (IS_CONNECTING(descP) && !is_connector(env, descP)) { - SSDBG( descP, ("SOCKET", "nconnect -> already connecting\r\n") ); + SSDBG( descP, ("SOCKET", "esock_connect -> already connecting\r\n") ); return esock_make_error(env, esock_atom_einval); } @@ -5301,14 +5307,15 @@ ERL_NIF_TERM nconnect(ErlNifEnv* env, descP->addrLen); save_errno = sock_errno(); - SSDBG( descP, ("SOCKET", "nconnect -> connect result: %d, %d\r\n", + SSDBG( descP, ("SOCKET", "esock_connect -> connect result: %d, %d\r\n", code, save_errno) ); if (IS_SOCKET_ERROR(code)) { switch (save_errno) { case ERRNO_BLOCK: /* Winsock2 */ case EINPROGRESS: /* Unix & OSE!! */ - SSDBG( descP, ("SOCKET", "nconnect -> would block => select\r\n") ); + SSDBG( descP, ("SOCKET", + "esock_connect -> would block => select\r\n") ); ref = MKREF(env); @@ -5322,13 +5329,13 @@ ERL_NIF_TERM nconnect(ErlNifEnv* env, if (enif_self(env, &descP->connPid) == NULL) return esock_make_error(env, atom_exself); - if (MONP("nconnect -> conn", + if (MONP("esock_connect -> conn", env, descP, &descP->connPid, &descP->connMon) != 0) return esock_make_error(env, atom_exmon); - descP->state = SOCKET_STATE_CONNECTING; + descP->state = ESOCK_STATE_CONNECTING; if ((sres = esock_select_write(env, descP->sock, descP, NULL, sockRef, ref)) < 0) { @@ -5343,18 +5350,19 @@ ERL_NIF_TERM nconnect(ErlNifEnv* env, break; case EISCONN: - SSDBG( descP, ("SOCKET", "nconnect -> *already* connected\r\n") ); + SSDBG( descP, ("SOCKET", + "esock_connect -> *already* connected\r\n") ); { /* This is ***strange*** so make sure */ int err = 0; if (!verify_is_connected(descP, &err)) { - descP->state = SOCKET_STATE_OPEN; /* restore state */ + descP->state = ESOCK_STATE_OPEN; /* restore state */ res = esock_make_error_errno(env, err); } else { - descP->state = SOCKET_STATE_CONNECTED; + descP->state = ESOCK_STATE_CONNECTED; /* And just to be on the safe side, reset these */ enif_set_pid_undefined(&descP->connPid); - DEMONP("nconnect -> connected", + DEMONP("esock_connect -> connected", env, descP, &descP->connMon); descP->isReadable = TRUE; descP->isWritable = TRUE; @@ -5364,7 +5372,7 @@ ERL_NIF_TERM nconnect(ErlNifEnv* env, break; default: - SSDBG( descP, ("SOCKET", "nconnect -> other error(1): %d\r\n", + SSDBG( descP, ("SOCKET", "esock_connect -> other error(1): %d\r\n", save_errno) ); res = esock_make_error_errno(env, save_errno); break; @@ -5372,11 +5380,11 @@ ERL_NIF_TERM nconnect(ErlNifEnv* env, } else if (code == 0) { /* ok we are connected */ - SSDBG( descP, ("SOCKET", "nconnect -> connected\r\n") ); + SSDBG( descP, ("SOCKET", "esock_connect -> connected\r\n") ); - descP->state = SOCKET_STATE_CONNECTED; + descP->state = ESOCK_STATE_CONNECTED; enif_set_pid_undefined(&descP->connPid); - DEMONP("nconnect -> connected", env, descP, &descP->connMon); + DEMONP("esock_connect -> connected", env, descP, &descP->connMon); descP->isReadable = TRUE; descP->isWritable = TRUE; @@ -5385,7 +5393,7 @@ ERL_NIF_TERM nconnect(ErlNifEnv* env, } else { /* Do we really need this case? */ - SSDBG( descP, ("SOCKET", "nconnect -> other error(2): %d\r\n", + SSDBG( descP, ("SOCKET", "esock_connect -> other error(2): %d\r\n", save_errno) ); res = esock_make_error_errno(env, save_errno); @@ -5422,23 +5430,23 @@ ERL_NIF_TERM nif_finalize_connection(ErlNifEnv* env, /* Extract arguments and perform preliminary validation */ if ((argc != 1) || - !enif_get_resource(env, argv[0], sockets, (void**) &descP)) { + !ESOCK_GET_RESOURCE(env, argv[0], (void**) &descP)) { return enif_make_badarg(env); } - return nfinalize_connection(env, descP); + return esock_finalize_connection(env, descP); #endif } -/* *** nfinalize_connection *** +/* *** esock_finalize_connection *** * Perform the final check to verify a connection. */ #if !defined(__WIN32__) static -ERL_NIF_TERM nfinalize_connection(ErlNifEnv* env, - ESockDescriptor* descP) +ERL_NIF_TERM esock_finalize_connection(ErlNifEnv* env, + ESockDescriptor* descP) { int error; @@ -5446,13 +5454,14 @@ ERL_NIF_TERM nfinalize_connection(ErlNifEnv* env, return esock_make_error(env, atom_enotconn); if (!verify_is_connected(descP, &error)) { - descP->state = SOCKET_STATE_OPEN; /* restore state */ + descP->state = ESOCK_STATE_OPEN; /* restore state */ return esock_make_error_errno(env, error); } - descP->state = SOCKET_STATE_CONNECTED; + descP->state = ESOCK_STATE_CONNECTED; enif_set_pid_undefined(&descP->connPid); - DEMONP("nfinalize_connection -> connected", env, descP, &descP->connMon); + DEMONP("esock_finalize_connection -> connected", + env, descP, &descP->connMon); descP->isReadable = TRUE; descP->isWritable = TRUE; @@ -5565,7 +5574,7 @@ ERL_NIF_TERM nif_listen(ErlNifEnv* env, /* Extract arguments and perform preliminary validation */ if ((argc != 2) || - !enif_get_resource(env, argv[0], sockets, (void**) &descP) || + !ESOCK_GET_RESOURCE(env, argv[0], (void**) &descP) || !GET_INT(env, argv[1], &backlog)) { return enif_make_badarg(env); } @@ -5576,7 +5585,7 @@ ERL_NIF_TERM nif_listen(ErlNifEnv* env, "\r\n backlog: %d" "\r\n", descP->sock, argv[0], backlog) ); - return nlisten(env, descP, backlog); + return esock_listen(env, descP, backlog); #endif // if defined(__WIN32__) } @@ -5585,9 +5594,9 @@ ERL_NIF_TERM nif_listen(ErlNifEnv* env, #if !defined(__WIN32__) static -ERL_NIF_TERM nlisten(ErlNifEnv* env, - ESockDescriptor* descP, - int backlog) +ERL_NIF_TERM esock_listen(ErlNifEnv* env, + ESockDescriptor* descP, + int backlog) { /* @@ -5597,7 +5606,7 @@ ERL_NIF_TERM nlisten(ErlNifEnv* env, if (IS_CLOSED(descP) || IS_CLOSING(descP)) return esock_make_error(env, atom_closed); - if (descP->state == SOCKET_STATE_CLOSED) + if (descP->state == ESOCK_STATE_CLOSED) return esock_make_error(env, atom_exbadstate); if (!IS_OPEN(descP)) @@ -5611,7 +5620,7 @@ ERL_NIF_TERM nlisten(ErlNifEnv* env, if (IS_SOCKET_ERROR(sock_listen(descP->sock, backlog))) return esock_make_error_errno(env, sock_errno()); - descP->state = SOCKET_STATE_LISTENING; + descP->state = ESOCK_STATE_LISTENING; return esock_atom_ok; @@ -5648,7 +5657,7 @@ ERL_NIF_TERM nif_accept(ErlNifEnv* env, sockRef = argv[0]; if ((argc != 2) || - !enif_get_resource(env, sockRef, sockets, (void**) &descP)) { + !ESOCK_GET_RESOURCE(env, sockRef, (void**) &descP)) { return enif_make_badarg(env); } ref = argv[1]; @@ -5669,15 +5678,15 @@ ERL_NIF_TERM nif_accept(ErlNifEnv* env, "\r\n", descP->sock, sockRef, ref, - ((descP->state == SOCKET_STATE_LISTENING) ? "listening" : - ((descP->state == SOCKET_STATE_ACCEPTING) ? "accepting" : "other")), + ((descP->state == ESOCK_STATE_LISTENING) ? "listening" : + ((descP->state == ESOCK_STATE_ACCEPTING) ? "accepting" : "other")), descP->currentAcceptorP, descP->currentAcceptor.pid, esock_make_monitor_term(env, &descP->currentAcceptor.mon), descP->currentAcceptor.env, descP->currentAcceptor.ref) ); - res = naccept_erts(env, descP, sockRef, ref); + res = esock_accept(env, descP, sockRef, ref); MUNLOCK(descP->accMtx); @@ -5689,7 +5698,7 @@ ERL_NIF_TERM nif_accept(ErlNifEnv* env, #if !defined(__WIN32__) static -ERL_NIF_TERM naccept_erts(ErlNifEnv* env, +ERL_NIF_TERM esock_accept(ErlNifEnv* env, ESockDescriptor* descP, ERL_NIF_TERM sockRef, ERL_NIF_TERM ref) @@ -5700,12 +5709,12 @@ ERL_NIF_TERM naccept_erts(ErlNifEnv* env, return esock_make_error(env, atom_closed); switch (descP->state) { - case SOCKET_STATE_LISTENING: - res = naccept_listening(env, descP, sockRef, ref); + case ESOCK_STATE_LISTENING: + res = esock_accept_listening(env, descP, sockRef, ref); break; - case SOCKET_STATE_ACCEPTING: - res = naccept_accepting(env, descP, sockRef, ref); + case ESOCK_STATE_ACCEPTING: + res = esock_accept_accepting(env, descP, sockRef, ref); break; default: @@ -5718,16 +5727,16 @@ ERL_NIF_TERM naccept_erts(ErlNifEnv* env, #endif // if !defined(__WIN32__) -/* *** naccept_listening *** +/* *** esock_accept_listening *** * * We have no active acceptor (and therefor no acceptors in queue). */ #if !defined(__WIN32__) static -ERL_NIF_TERM naccept_listening(ErlNifEnv* env, - ESockDescriptor* descP, - ERL_NIF_TERM sockRef, - ERL_NIF_TERM accRef) +ERL_NIF_TERM esock_accept_listening(ErlNifEnv* env, + ESockDescriptor* descP, + ERL_NIF_TERM sockRef, + ERL_NIF_TERM accRef) { ESockAddress remote; unsigned int n; @@ -5736,14 +5745,14 @@ ERL_NIF_TERM naccept_listening(ErlNifEnv* env, ErlNifPid caller; ERL_NIF_TERM res; - SSDBG( descP, ("SOCKET", "naccept_listening -> get caller\r\n") ); + SSDBG( descP, ("SOCKET", "esock_accept_listening -> get caller\r\n") ); if (enif_self(env, &caller) == NULL) return esock_make_error(env, atom_exself); n = sizeof(remote); sys_memzero((char *) &remote, n); - SSDBG( descP, ("SOCKET", "naccept_listening -> try accept\r\n") ); + SSDBG( descP, ("SOCKET", "esock_accept_listening -> try accept\r\n") ); accSock = sock_accept(descP->sock, (struct sockaddr*) &remote, &n); if (accSock == INVALID_SOCKET) { @@ -5751,10 +5760,11 @@ ERL_NIF_TERM naccept_listening(ErlNifEnv* env, SSDBG( descP, ("SOCKET", - "naccept_listening -> accept failed (%d)\r\n", save_errno) ); + "esock_accept_listening -> accept failed (%d)\r\n", + save_errno) ); - res = naccept_listening_error(env, descP, sockRef, accRef, - caller, save_errno); + res = esock_accept_listening_error(env, descP, sockRef, accRef, + caller, save_errno); } else { @@ -5762,9 +5772,9 @@ ERL_NIF_TERM naccept_listening(ErlNifEnv* env, * We got one */ - SSDBG( descP, ("SOCKET", "naccept_listening -> success\r\n") ); + SSDBG( descP, ("SOCKET", "esock_accept_listening -> success\r\n") ); - res = naccept_listening_accept(env, descP, accSock, caller, &remote); + res = esock_accept_listening_accept(env, descP, accSock, caller, &remote); } @@ -5772,7 +5782,7 @@ ERL_NIF_TERM naccept_listening(ErlNifEnv* env, } -/* *** naccept_listening_error *** +/* *** esock_accept_listening_error *** * * The accept call resultet in an error - handle it. * There are only two cases: @@ -5780,12 +5790,12 @@ ERL_NIF_TERM naccept_listening(ErlNifEnv* env, * 2) Other => Return the value (converted to an atom) */ static -ERL_NIF_TERM naccept_listening_error(ErlNifEnv* env, - ESockDescriptor* descP, - ERL_NIF_TERM sockRef, - ERL_NIF_TERM accRef, - ErlNifPid caller, - int save_errno) +ERL_NIF_TERM esock_accept_listening_error(ErlNifEnv* env, + ESockDescriptor* descP, + ERL_NIF_TERM sockRef, + ERL_NIF_TERM accRef, + ErlNifPid caller, + int save_errno) { ERL_NIF_TERM res; @@ -5794,10 +5804,10 @@ ERL_NIF_TERM naccept_listening_error(ErlNifEnv* env, /* *** Try again later *** */ SSDBG( descP, - ("SOCKET", "naccept_listening_error -> would block\r\n") ); + ("SOCKET", "esock_accept_listening_error -> would block\r\n") ); descP->currentAcceptor.pid = caller; - if (MONP("naccept_listening -> current acceptor", + if (MONP("esock_accept_listening -> current acceptor", env, descP, &descP->currentAcceptor.pid, &descP->currentAcceptor.mon) != 0) { @@ -5809,14 +5819,14 @@ ERL_NIF_TERM naccept_listening_error(ErlNifEnv* env, descP->currentAcceptor.ref = CP_TERM(descP->currentAcceptor.env, accRef); descP->currentAcceptorP = &descP->currentAcceptor; - res = naccept_busy_retry(env, descP, - sockRef, accRef, - NULL, SOCKET_STATE_ACCEPTING); + res = esock_accept_busy_retry(env, descP, + sockRef, accRef, + NULL, ESOCK_STATE_ACCEPTING); } } else { SSDBG( descP, ("SOCKET", - "naccept_listening -> errno: %d\r\n", save_errno) ); + "esock_accept_listening -> errno: %d\r\n", save_errno) ); res = esock_make_error_errno(env, save_errno); } @@ -5824,20 +5834,20 @@ ERL_NIF_TERM naccept_listening_error(ErlNifEnv* env, } -/* *** naccept_listening_accept *** +/* *** esock_accept_listening_accept *** * * The accept call was successful (accepted) - handle the new connection. */ static -ERL_NIF_TERM naccept_listening_accept(ErlNifEnv* env, - ESockDescriptor* descP, - SOCKET accSock, - ErlNifPid caller, - ESockAddress* remote) +ERL_NIF_TERM esock_accept_listening_accept(ErlNifEnv* env, + ESockDescriptor* descP, + SOCKET accSock, + ErlNifPid caller, + ESockAddress* remote) { ERL_NIF_TERM res; - naccept_accepted(env, descP, accSock, caller, remote, &res); + esock_accept_accepted(env, descP, accSock, caller, remote, &res); return res; } @@ -5845,7 +5855,7 @@ ERL_NIF_TERM naccept_listening_accept(ErlNifEnv* env, -/* *** naccept_accepting *** +/* *** esock_accept_accepting *** * * We have an active acceptor and possibly acceptors waiting in queue. * If the pid of the calling process is not the pid of the "current process", @@ -5853,20 +5863,20 @@ ERL_NIF_TERM naccept_listening_accept(ErlNifEnv* env, */ #if !defined(__WIN32__) static -ERL_NIF_TERM naccept_accepting(ErlNifEnv* env, - ESockDescriptor* descP, - ERL_NIF_TERM sockRef, - ERL_NIF_TERM ref) +ERL_NIF_TERM esock_accept_accepting(ErlNifEnv* env, + ESockDescriptor* descP, + ERL_NIF_TERM sockRef, + ERL_NIF_TERM ref) { ErlNifPid caller; ERL_NIF_TERM res; - SSDBG( descP, ("SOCKET", "naccept_accepting -> get caller\r\n") ); + SSDBG( descP, ("SOCKET", "esock_accept_accepting -> get caller\r\n") ); if (enif_self(env, &caller) == NULL) return esock_make_error(env, atom_exself); - SSDBG( descP, ("SOCKET", "naccept_accepting -> check: " + SSDBG( descP, ("SOCKET", "esock_accept_accepting -> check: " "are caller current acceptor:" "\r\n Caller: %T" "\r\n Current: %T" @@ -5875,18 +5885,19 @@ ERL_NIF_TERM naccept_accepting(ErlNifEnv* env, if (COMPARE_PIDS(&descP->currentAcceptor.pid, &caller) == 0) { SSDBG( descP, - ("SOCKET", "naccept_accepting -> current acceptor\r\n") ); + ("SOCKET", "esock_accept_accepting -> current acceptor\r\n") ); - res = naccept_accepting_current(env, descP, sockRef, ref); + res = esock_accept_accepting_current(env, descP, sockRef, ref); } else { /* Not the "current acceptor", so (maybe) push onto queue */ SSDBG( descP, - ("SOCKET", "naccept_accepting -> *not* current acceptor\r\n") ); + ("SOCKET", + "esock_accept_accepting -> *not* current acceptor\r\n") ); - res = naccept_accepting_other(env, descP, ref, caller); + res = esock_accept_accepting_other(env, descP, ref, caller); } @@ -5896,14 +5907,14 @@ ERL_NIF_TERM naccept_accepting(ErlNifEnv* env, -/* *** naccept_accepting_current *** +/* *** esock_accept_accepting_current *** * Handles when the current acceptor makes another attempt. */ static -ERL_NIF_TERM naccept_accepting_current(ErlNifEnv* env, - ESockDescriptor* descP, - ERL_NIF_TERM sockRef, - ERL_NIF_TERM accRef) +ERL_NIF_TERM esock_accept_accepting_current(ErlNifEnv* env, + ESockDescriptor* descP, + ERL_NIF_TERM sockRef, + ERL_NIF_TERM accRef) { ESockAddress remote; unsigned int n; @@ -5911,7 +5922,8 @@ ERL_NIF_TERM naccept_accepting_current(ErlNifEnv* env, int save_errno; ERL_NIF_TERM res; - SSDBG( descP, ("SOCKET", "naccept_accepting_current -> try accept\r\n") ); + SSDBG( descP, ("SOCKET", + "esock_accept_accepting_current -> try accept\r\n") ); n = sizeof(descP->remote); sys_memzero((char *) &remote, n); accSock = sock_accept(descP->sock, (struct sockaddr*) &remote, &n); @@ -5921,18 +5933,19 @@ ERL_NIF_TERM naccept_accepting_current(ErlNifEnv* env, SSDBG( descP, ("SOCKET", - "naccept_accepting_current -> accept failed: %d\r\n", + "esock_accept_accepting_current -> accept failed: %d\r\n", save_errno) ); - res = naccept_accepting_current_error(env, descP, sockRef, - accRef, save_errno); + res = esock_accept_accepting_current_error(env, descP, sockRef, + accRef, save_errno); } else { - SSDBG( descP, ("SOCKET", "naccept_accepting_current -> accepted\r\n") ); + SSDBG( descP, ("SOCKET", + "esock_accept_accepting_current -> accepted\r\n") ); - res = naccept_accepting_current_accept(env, descP, sockRef, - accSock, &remote); + res = esock_accept_accepting_current_accept(env, descP, sockRef, + accSock, &remote); } @@ -5940,27 +5953,27 @@ ERL_NIF_TERM naccept_accepting_current(ErlNifEnv* env, } -/* *** naccept_accepting_current_accept *** +/* *** esock_accept_accepting_current_accept *** * Handles when the current acceptor succeeded in its accept call - * handle the new connection. */ static -ERL_NIF_TERM naccept_accepting_current_accept(ErlNifEnv* env, - ESockDescriptor* descP, - ERL_NIF_TERM sockRef, - SOCKET accSock, - ESockAddress* remote) +ERL_NIF_TERM esock_accept_accepting_current_accept(ErlNifEnv* env, + ESockDescriptor* descP, + ERL_NIF_TERM sockRef, + SOCKET accSock, + ESockAddress* remote) { ERL_NIF_TERM res; - if (naccept_accepted(env, descP, accSock, - descP->currentAcceptor.pid, remote, &res)) { + if (esock_accept_accepted(env, descP, accSock, + descP->currentAcceptor.pid, remote, &res)) { /* Clean out the old cobweb's before trying to invite a new spider */ descP->currentAcceptor.ref = esock_atom_undefined; enif_set_pid_undefined(&descP->currentAcceptor.pid); - esock_free_env("naccept_accepting_current_accept - " + esock_free_env("esock_accept_accepting_current_accept - " "current-accept-env", descP->currentAcceptor.env); descP->currentAcceptor.env = NULL; @@ -5969,10 +5982,10 @@ ERL_NIF_TERM naccept_accepting_current_accept(ErlNifEnv* env, SSDBG( descP, ("SOCKET", - "naccept_accepting_current_accept -> " + "esock_accept_accepting_current_accept -> " "no more writers\r\n") ); - descP->state = SOCKET_STATE_LISTENING; + descP->state = ESOCK_STATE_LISTENING; descP->currentAcceptorP = NULL; ESOCK_ASSERT(!descP->currentAcceptor.env); @@ -5986,18 +5999,18 @@ ERL_NIF_TERM naccept_accepting_current_accept(ErlNifEnv* env, } -/* *** naccept_accepting_current_error *** +/* *** esock_accept_accepting_current_error *** * The accept call of current acceptor resultet in an error - handle it. * There are only two cases: * 1) BLOCK => Attempt a "retry" * 2) Other => Return the value (converted to an atom) */ static -ERL_NIF_TERM naccept_accepting_current_error(ErlNifEnv* env, - ESockDescriptor* descP, - ERL_NIF_TERM sockRef, - ERL_NIF_TERM opRef, - int save_errno) +ERL_NIF_TERM esock_accept_accepting_current_error(ErlNifEnv* env, + ESockDescriptor* descP, + ERL_NIF_TERM sockRef, + ERL_NIF_TERM opRef, + int save_errno) { ESockRequestor req; ERL_NIF_TERM res, reason; @@ -6011,13 +6024,13 @@ ERL_NIF_TERM naccept_accepting_current_error(ErlNifEnv* env, SSDBG( descP, ("SOCKET", - "naccept_accepting_current_error -> " + "esock_accept_accepting_current_error -> " "would block: try again\r\n") ); - res = naccept_busy_retry(env, descP, sockRef, opRef, - &descP->currentAcceptor.pid, - /* No state change */ - descP->state); + res = esock_accept_busy_retry(env, descP, sockRef, opRef, + &descP->currentAcceptor.pid, + /* No state change */ + descP->state); } else { @@ -6026,12 +6039,13 @@ ERL_NIF_TERM naccept_accepting_current_error(ErlNifEnv* env, while (acceptor_pop(env, descP, &req)) { SSDBG( descP, - ("SOCKET", "naccept_accepting_current_error -> abort %T\r\n", + ("SOCKET", + "esock_accept_accepting_current_error -> abort %T\r\n", req.pid) ); esock_send_abort_msg(env, sockRef, req.ref, req.env, reason, &req.pid); req.env = NULL; - DEMONP("naccept_accepting_current_error -> pop'ed writer", + DEMONP("esock_accept_accepting_current_error -> pop'ed writer", env, descP, &req.mon); } @@ -6041,16 +6055,16 @@ ERL_NIF_TERM naccept_accepting_current_error(ErlNifEnv* env, } -/* *** naccept_accepting_other *** +/* *** esock_accept_accepting_other *** * Handles when the another acceptor makes an attempt, which * results (maybe) in the request beeing pushed onto the * acceptor queue. */ static -ERL_NIF_TERM naccept_accepting_other(ErlNifEnv* env, - ESockDescriptor* descP, - ERL_NIF_TERM ref, - ErlNifPid caller) +ERL_NIF_TERM esock_accept_accepting_other(ErlNifEnv* env, + ESockDescriptor* descP, + ERL_NIF_TERM ref, + ErlNifPid caller) { ERL_NIF_TERM result; @@ -6065,18 +6079,18 @@ ERL_NIF_TERM naccept_accepting_other(ErlNifEnv* env, -/* *** naccept_busy_retry *** +/* *** esock_accept_busy_retry *** * * Perform a retry select. If successful, set nextState. */ #if !defined(__WIN32__) static -ERL_NIF_TERM naccept_busy_retry(ErlNifEnv* env, - ESockDescriptor* descP, - ERL_NIF_TERM sockRef, - ERL_NIF_TERM accRef, - ErlNifPid* pid, - unsigned int nextState) +ERL_NIF_TERM esock_accept_busy_retry(ErlNifEnv* env, + ESockDescriptor* descP, + ERL_NIF_TERM sockRef, + ERL_NIF_TERM accRef, + ErlNifPid* pid, + unsigned int nextState) { int sres; ERL_NIF_TERM res, reason; @@ -6095,17 +6109,17 @@ ERL_NIF_TERM naccept_busy_retry(ErlNifEnv* env, -/* *** naccept_accepted *** +/* *** esock_accept_accepted *** * * Generic function handling a successful accept. */ static -BOOLEAN_T naccept_accepted(ErlNifEnv* env, - ESockDescriptor* descP, - SOCKET accSock, - ErlNifPid pid, - ESockAddress* remote, - ERL_NIF_TERM* result) +BOOLEAN_T esock_accept_accepted(ErlNifEnv* env, + ESockDescriptor* descP, + SOCKET accSock, + ErlNifPid pid, + ESockAddress* remote, + ERL_NIF_TERM* result) { ESockDescriptor* accDescP; HANDLE accEvent; @@ -6143,7 +6157,7 @@ BOOLEAN_T naccept_accepted(ErlNifEnv* env, enif_release_resource(accDescP); accDescP->ctrlPid = pid; - if (MONP("naccept_accepted -> ctrl", + if (MONP("esock_accept_accepted -> ctrl", env, accDescP, &accDescP->ctrlPid, &accDescP->ctrlMon) != 0) { @@ -6156,7 +6170,7 @@ BOOLEAN_T naccept_accepted(ErlNifEnv* env, accDescP->remote = *remote; SET_NONBLOCKING(accDescP->sock); - accDescP->state = SOCKET_STATE_CONNECTED; + accDescP->state = ESOCK_STATE_CONNECTED; accDescP->isReadable = TRUE; accDescP->isWritable = TRUE; @@ -6209,7 +6223,7 @@ ERL_NIF_TERM nif_send(ErlNifEnv* env, sockRef = argv[0]; // We need this in case we send in case we send abort sendRef = argv[1]; - if (!enif_get_resource(env, sockRef, sockets, (void**) &descP)) { + if (!ESOCK_GET_RESOURCE(env, sockRef, (void**) &descP)) { return enif_make_badarg(env); } @@ -6234,7 +6248,7 @@ ERL_NIF_TERM nif_send(ErlNifEnv* env, * is done! */ - res = nsend(env, descP, sockRef, sendRef, &sndData, flags); + res = esock_send(env, descP, sockRef, sendRef, &sndData, flags); MUNLOCK(descP->writeMtx); @@ -6245,7 +6259,7 @@ ERL_NIF_TERM nif_send(ErlNifEnv* env, -/* *** nsend *** +/* *** esock_send *** * * Do the actual send. * Do some initial writer checks, do the actual send and then @@ -6254,12 +6268,12 @@ ERL_NIF_TERM nif_send(ErlNifEnv* env, */ #if !defined(__WIN32__) static -ERL_NIF_TERM nsend(ErlNifEnv* env, - ESockDescriptor* descP, - ERL_NIF_TERM sockRef, - ERL_NIF_TERM sendRef, - ErlNifBinary* sndDataP, - int flags) +ERL_NIF_TERM esock_send(ErlNifEnv* env, + ESockDescriptor* descP, + ERL_NIF_TERM sockRef, + ERL_NIF_TERM sendRef, + ErlNifBinary* sndDataP, + int flags) { int save_errno; ssize_t written; @@ -6331,16 +6345,15 @@ ERL_NIF_TERM nif_sendto(ErlNifEnv* env, /* Extract arguments and perform preliminary validation */ if ((argc != 5) || - !enif_get_resource(env, argv[0], sockets, (void**) &descP) || !GET_BIN(env, argv[2], &sndData) || !GET_UINT(env, argv[4], &eflags)) { return enif_make_badarg(env); } - sockRef = argv[0]; // We need this in case we send in case we send abort + sockRef = argv[0]; // We need this in case we send abort (to the caller) sendRef = argv[1]; eSockAddr = argv[3]; - if (!enif_get_resource(env, sockRef, sockets, (void**) &descP)) { + if (!ESOCK_GET_RESOURCE(env, sockRef, (void**) &descP)) { return enif_make_badarg(env); } @@ -6369,8 +6382,8 @@ ERL_NIF_TERM nif_sendto(ErlNifEnv* env, MLOCK(descP->writeMtx); - res = nsendto(env, descP, sockRef, sendRef, &sndData, flags, - &remoteAddr, remoteAddrLen); + res = esock_sendto(env, descP, sockRef, sendRef, &sndData, flags, + &remoteAddr, remoteAddrLen); MUNLOCK(descP->writeMtx); @@ -6386,14 +6399,14 @@ ERL_NIF_TERM nif_sendto(ErlNifEnv* env, #if !defined(__WIN32__) static -ERL_NIF_TERM nsendto(ErlNifEnv* env, - ESockDescriptor* descP, - ERL_NIF_TERM sockRef, - ERL_NIF_TERM sendRef, - ErlNifBinary* dataP, - int flags, - ESockAddress* toAddrP, - unsigned int toAddrLen) +ERL_NIF_TERM esock_sendto(ErlNifEnv* env, + ESockDescriptor* descP, + ERL_NIF_TERM sockRef, + ERL_NIF_TERM sendRef, + ErlNifBinary* dataP, + int flags, + ESockAddress* toAddrP, + unsigned int toAddrLen) { int save_errno; ssize_t written; @@ -6468,11 +6481,11 @@ ERL_NIF_TERM nif_sendmsg(ErlNifEnv* env, !GET_UINT(env, argv[3], &eflags)) { return enif_make_badarg(env); } - sockRef = argv[0]; // We need this in case we send in case we send abort + sockRef = argv[0]; // We need this in case we send abort (to the caller) sendRef = argv[1]; eMsgHdr = argv[2]; - if (!enif_get_resource(env, sockRef, sockets, (void**) &descP)) { + if (!ESOCK_GET_RESOURCE(env, sockRef, (void**) &descP)) { return enif_make_badarg(env); } @@ -6489,7 +6502,7 @@ ERL_NIF_TERM nif_sendmsg(ErlNifEnv* env, MLOCK(descP->writeMtx); - res = nsendmsg_erts(env, descP, sockRef, sendRef, eMsgHdr, flags); + res = esock_sendmsg(env, descP, sockRef, sendRef, eMsgHdr, flags); MUNLOCK(descP->writeMtx); @@ -6506,7 +6519,7 @@ ERL_NIF_TERM nif_sendmsg(ErlNifEnv* env, #if !defined(__WIN32__) static -ERL_NIF_TERM nsendmsg_erts(ErlNifEnv* env, +ERL_NIF_TERM esock_sendmsg(ErlNifEnv* env, ESockDescriptor* descP, ERL_NIF_TERM sockRef, ERL_NIF_TERM sendRef, @@ -6540,7 +6553,8 @@ ERL_NIF_TERM nsendmsg_erts(ErlNifEnv* env, /* We don't need the address */ - SSDBG( descP, ("SOCKET", "nsendmsg_erts -> connected: no address\r\n") ); + SSDBG( descP, ("SOCKET", + "esock_sendmsg -> connected: no address\r\n") ); msgHdr.msg_name = NULL; msgHdr.msg_namelen = 0; @@ -6555,7 +6569,7 @@ ERL_NIF_TERM nsendmsg_erts(ErlNifEnv* env, if (!GET_MAP_VAL(env, eMsgHdr, esock_atom_addr, &eAddr)) return esock_make_error(env, esock_atom_einval); - SSDBG( descP, ("SOCKET", "nsendmsg_erts -> not connected: " + SSDBG( descP, ("SOCKET", "esock_sendmsg -> not connected: " "\r\n address: %T" "\r\n", eAddr) ); @@ -6575,7 +6589,7 @@ ERL_NIF_TERM nsendmsg_erts(ErlNifEnv* env, if (!GET_LIST_LEN(env, eIOV, &iovLen) && (iovLen > 0)) return esock_make_error(env, esock_atom_einval); - SSDBG( descP, ("SOCKET", "nsendmsg_erts -> iov length: %d\r\n", iovLen) ); + SSDBG( descP, ("SOCKET", "esock_sendmsg -> iov length: %d\r\n", iovLen) ); iovBins = MALLOC(iovLen * sizeof(ErlNifBinary)); ESOCK_ASSERT( (iovBins != NULL) ); @@ -6593,7 +6607,7 @@ ERL_NIF_TERM nsendmsg_erts(ErlNifEnv* env, ctrlBufLen = 0; ctrlBuf = NULL; } - SSDBG( descP, ("SOCKET", "nsendmsg_erts -> optional ctrl: " + SSDBG( descP, ("SOCKET", "esock_sendmsg -> optional ctrl: " "\r\n ctrlBuf: 0x%lX" "\r\n ctrlBufLen: %d" "\r\n eCtrl: %T\r\n", ctrlBuf, ctrlBufLen, eCtrl) ); @@ -6611,7 +6625,8 @@ ERL_NIF_TERM nsendmsg_erts(ErlNifEnv* env, SSDBG( descP, ("SOCKET", - "nsendmsg_erts -> total (iov) data size: %d\r\n", dataSize) ); + "esock_sendmsg -> " + "total (iov) data size: %d\r\n", dataSize) ); /* Decode the ctrl and initiate that part of the msghdr. @@ -6769,10 +6784,10 @@ ERL_NIF_TERM nif_recv(ErlNifEnv* env, !GET_UINT(env, argv[3], &eflags)) { return enif_make_badarg(env); } - sockRef = argv[0]; // We need this in case we case we send abort + sockRef = argv[0]; // We need this in case we send abort (to the caller) recvRef = argv[1]; - if (!enif_get_resource(env, sockRef, sockets, (void**) &descP)) { + if (!ESOCK_GET_RESOURCE(env, sockRef, (void**) &descP)) { return enif_make_badarg(env); } @@ -6789,7 +6804,7 @@ ERL_NIF_TERM nif_recv(ErlNifEnv* env, * is done! */ - res = nrecv(env, descP, sockRef, recvRef, len, flags); + res = esock_recv(env, descP, sockRef, recvRef, len, flags); MUNLOCK(descP->readMtx); @@ -6806,12 +6821,12 @@ ERL_NIF_TERM nif_recv(ErlNifEnv* env, */ #if !defined(__WIN32__) static -ERL_NIF_TERM nrecv(ErlNifEnv* env, - ESockDescriptor* descP, - ERL_NIF_TERM sockRef, - ERL_NIF_TERM recvRef, - int len, - int flags) +ERL_NIF_TERM esock_recv(ErlNifEnv* env, + ESockDescriptor* descP, + ERL_NIF_TERM sockRef, + ERL_NIF_TERM recvRef, + int len, + int flags) { ssize_t read; ErlNifBinary buf; @@ -6819,7 +6834,7 @@ ERL_NIF_TERM nrecv(ErlNifEnv* env, int save_errno; int bufSz = (len ? len : descP->rBufSz); - SSDBG( descP, ("SOCKET", "nrecv -> entry with" + SSDBG( descP, ("SOCKET", "esock_recv -> entry with" "\r\n len: %d (%d:%d)" "\r\n flags: %d" "\r\n", len, descP->rNumCnt, bufSz, flags) ); @@ -6842,7 +6857,7 @@ ERL_NIF_TERM nrecv(ErlNifEnv* env, SOCK_CNT_INC(env, descP, sockRef, atom_read_tries, &descP->readTries, 1); // If it fails (read = -1), we need errno... - SSDBG( descP, ("SOCKET", "nrecv -> try read (%d)\r\n", buf.size) ); + SSDBG( descP, ("SOCKET", "esock_recv -> try read (%d)\r\n", buf.size) ); read = sock_recv(descP->sock, buf.data, buf.size, flags); if (IS_SOCKET_ERROR(read)) { save_errno = sock_errno(); @@ -6850,7 +6865,8 @@ ERL_NIF_TERM nrecv(ErlNifEnv* env, save_errno = -1; // The value does not actually matter in this case } - SSDBG( descP, ("SOCKET", "nrecv -> read: %d (%d)\r\n", read, save_errno) ); + SSDBG( descP, ("SOCKET", + "esock_recv -> read: %d (%d)\r\n", read, save_errno) ); return recv_check_result(env, descP, read, len, @@ -6911,10 +6927,10 @@ ERL_NIF_TERM nif_recvfrom(ErlNifEnv* env, !GET_UINT(env, argv[3], &eflags)) { return enif_make_badarg(env); } - sockRef = argv[0]; // We need this in case we send in case we send abort + sockRef = argv[0]; // We need this in case we send abort (to the caller) recvRef = argv[1]; - if (!enif_get_resource(env, sockRef, sockets, (void**) &descP)) { + if (!ESOCK_GET_RESOURCE(env, sockRef, (void**) &descP)) { return enif_make_badarg(env); } @@ -6951,7 +6967,7 @@ ERL_NIF_TERM nif_recvfrom(ErlNifEnv* env, * </KOLLA> */ - res = nrecvfrom_erts(env, descP, sockRef, recvRef, bufSz, flags); + res = esock_recvfrom(env, descP, sockRef, recvRef, bufSz, flags); MUNLOCK(descP->readMtx); @@ -6967,7 +6983,7 @@ ERL_NIF_TERM nif_recvfrom(ErlNifEnv* env, */ #if !defined(__WIN32__) static -ERL_NIF_TERM nrecvfrom_erts(ErlNifEnv* env, +ERL_NIF_TERM esock_recvfrom(ErlNifEnv* env, ESockDescriptor* descP, ERL_NIF_TERM sockRef, ERL_NIF_TERM recvRef, @@ -6982,7 +6998,7 @@ ERL_NIF_TERM nrecvfrom_erts(ErlNifEnv* env, ERL_NIF_TERM readerCheck; int bufSz = (len ? len : descP->rBufSz); - SSDBG( descP, ("SOCKET", "nrecvfrom_erts -> entry with" + SSDBG( descP, ("SOCKET", "esock_recvfrom -> entry with" "\r\n len: %d (%d)" "\r\n flags: %d" "\r\n", len, bufSz, flags) ); @@ -7080,10 +7096,10 @@ ERL_NIF_TERM nif_recvmsg(ErlNifEnv* env, !GET_UINT(env, argv[4], &eflags)) { return enif_make_badarg(env); } - sockRef = argv[0]; // We need this in case we send in case we send abort + sockRef = argv[0]; // We need this in case we send abort (to the caller) recvRef = argv[1]; - if (!enif_get_resource(env, sockRef, sockets, (void**) &descP)) { + if (!ESOCK_GET_RESOURCE(env, sockRef, (void**) &descP)) { return enif_make_badarg(env); } @@ -7121,7 +7137,7 @@ ERL_NIF_TERM nif_recvmsg(ErlNifEnv* env, * </KOLLA> */ - res = nrecvmsg_erts(env, descP, sockRef, recvRef, bufSz, ctrlSz, flags); + res = esock_recvmsg(env, descP, sockRef, recvRef, bufSz, ctrlSz, flags); MUNLOCK(descP->readMtx); @@ -7137,7 +7153,7 @@ ERL_NIF_TERM nif_recvmsg(ErlNifEnv* env, */ #if !defined(__WIN32__) static -ERL_NIF_TERM nrecvmsg_erts(ErlNifEnv* env, +ERL_NIF_TERM esock_recvmsg(ErlNifEnv* env, ESockDescriptor* descP, ERL_NIF_TERM sockRef, ERL_NIF_TERM recvRef, @@ -7157,7 +7173,7 @@ ERL_NIF_TERM nrecvmsg_erts(ErlNifEnv* env, ERL_NIF_TERM readerCheck; ESockAddress addr; - SSDBG( descP, ("SOCKET", "nrecvmsg_erts -> entry with" + SSDBG( descP, ("SOCKET", "esock_recvmsg -> entry with" "\r\n bufSz: %d (%d)" "\r\n ctrlSz: %d (%d)" "\r\n flags: %d" @@ -7246,28 +7262,28 @@ ERL_NIF_TERM nif_close(ErlNifEnv* env, ESockDescriptor* descP; if ((argc != 1) || - !enif_get_resource(env, argv[0], sockets, (void**) &descP)) { + !ESOCK_GET_RESOURCE(env, argv[0], (void**) &descP)) { return enif_make_badarg(env); } if (IS_CLOSED(descP) || IS_CLOSING(descP)) return esock_make_error(env, atom_closed); - return nclose(env, descP); + return esock_close(env, descP); #endif // if defined(__WIN32__) } #if !defined(__WIN32__) static -ERL_NIF_TERM nclose(ErlNifEnv* env, - ESockDescriptor* descP) +ERL_NIF_TERM esock_close(ErlNifEnv* env, + ESockDescriptor* descP) { ERL_NIF_TERM reply, reason; BOOLEAN_T doClose; SSDBG( descP, ("SOCKET", - "nclose -> [%d] entry (0x%lX, 0x%lX, 0x%lX, 0x%lX)\r\n", + "esock_close -> [%d] entry (0x%lX, 0x%lX, 0x%lX, 0x%lX)\r\n", descP->sock, descP->state, descP->currentWriterP, @@ -7276,10 +7292,10 @@ ERL_NIF_TERM nclose(ErlNifEnv* env, MLOCK(descP->closeMtx); - doClose = nclose_check(env, descP, &reason); + doClose = esock_close_check(env, descP, &reason); if (doClose) { - reply = nclose_do(env, descP); + reply = esock_close_do(env, descP); } else { reply = esock_make_error(env, reason); } @@ -7287,7 +7303,7 @@ ERL_NIF_TERM nclose(ErlNifEnv* env, MUNLOCK(descP->closeMtx); SSDBG( descP, - ("SOCKET", "nclose -> [%d] done when: " + ("SOCKET", "esock_close -> [%d] done when: " "\r\n state: 0x%lX" "\r\n reply: %T" "\r\n", descP->sock, descP->state, reply) ); @@ -7297,23 +7313,23 @@ ERL_NIF_TERM nclose(ErlNifEnv* env, -/* *** nclose_check *** +/* *** esock_close_check *** * * Check if we should try to perform the first stage close. */ static -BOOLEAN_T nclose_check(ErlNifEnv* env, - ESockDescriptor* descP, - ERL_NIF_TERM* reason) +BOOLEAN_T esock_close_check(ErlNifEnv* env, + ESockDescriptor* descP, + ERL_NIF_TERM* reason) { BOOLEAN_T doClose; - if (descP->state == SOCKET_STATE_CLOSED) { + if (descP->state == ESOCK_STATE_CLOSED) { doClose = FALSE; *reason = atom_closed; - } else if (descP->state == SOCKET_STATE_CLOSING) { + } else if (descP->state == ESOCK_STATE_CLOSING) { doClose = FALSE; *reason = atom_closing; @@ -7343,7 +7359,7 @@ BOOLEAN_T nclose_check(ErlNifEnv* env, * </KOLLA> */ - if (MONP("nclose_check -> closer", + if (MONP("esock_close_check -> closer", env, descP, &descP->closerPid, &descP->closerMon) != 0) { @@ -7354,7 +7370,7 @@ BOOLEAN_T nclose_check(ErlNifEnv* env, } else { descP->closeLocal = TRUE; - descP->state = SOCKET_STATE_CLOSING; + descP->state = ESOCK_STATE_CLOSING; descP->isReadable = FALSE; descP->isWritable = FALSE; doClose = TRUE; @@ -7370,13 +7386,13 @@ BOOLEAN_T nclose_check(ErlNifEnv* env, -/* *** nclose_do *** +/* *** esock_close_do *** * * Perform (do) the first stage close. */ static -ERL_NIF_TERM nclose_do(ErlNifEnv* env, - ESockDescriptor* descP) +ERL_NIF_TERM esock_close_do(ErlNifEnv* env, + ESockDescriptor* descP) { int domain = descP->domain; int type = descP->type; @@ -7384,7 +7400,7 @@ ERL_NIF_TERM nclose_do(ErlNifEnv* env, int sres; ERL_NIF_TERM reply, reason; - descP->closeEnv = esock_alloc_env("nclose-do - close-env"); + descP->closeEnv = esock_alloc_env("esock_close_do - close-env"); descP->closeRef = MKREF(descP->closeEnv); sres = esock_select_stop(env, descP->sock, descP); @@ -7393,7 +7409,8 @@ ERL_NIF_TERM nclose_do(ErlNifEnv* env, /* Prep done - inform the caller it can finalize (close) directly */ SSDBG( descP, - ("SOCKET", "nclose -> [%d] stop was called\r\n", descP->sock) ); + ("SOCKET", + "esock_close -> [%d] stop was called\r\n", descP->sock) ); dec_socket(domain, type, protocol); reply = esock_atom_ok; @@ -7403,7 +7420,7 @@ ERL_NIF_TERM nclose_do(ErlNifEnv* env, /* The stop callback function has been *scheduled* which means that we * have to wait for it to complete. */ SSDBG( descP, - ("SOCKET", "nclose -> [%d] stop was scheduled\r\n", + ("SOCKET", "esock_close -> [%d] stop was scheduled\r\n", descP->sock) ); dec_socket(domain, type, protocol); // SHALL WE DO THIS AT finalize? @@ -7412,7 +7429,7 @@ ERL_NIF_TERM nclose_do(ErlNifEnv* env, } else { SSDBG( descP, - ("SOCKET", "nclose -> [%d] stop failed: %d\r\n", + ("SOCKET", "esock_close -> [%d] stop failed: %d\r\n", descP->sock, sres) ); /* <KOLLA> @@ -7426,7 +7443,7 @@ ERL_NIF_TERM nclose_do(ErlNifEnv* env, */ // Do we need this? - DEMONP("nclose_do -> closer", env, descP, &descP->closerMon); + DEMONP("esock_close_do -> closer", env, descP, &descP->closerMon); reason = MKT2(env, esock_atom_select_failed, MKI(env, sres)); reply = esock_make_error(env, reason); @@ -7464,22 +7481,22 @@ ERL_NIF_TERM nif_finalize_close(ErlNifEnv* env, /* Extract arguments and perform preliminary validation */ if ((argc != 1) || - !enif_get_resource(env, argv[0], sockets, (void**) &descP)) { + !ESOCK_GET_RESOURCE(env, argv[0], (void**) &descP)) { return enif_make_badarg(env); } - return nfinalize_close(env, descP); + return esock_finalize_close(env, descP); #endif // if defined(__WIN32__) } -/* *** nfinalize_close *** +/* *** esock_finalize_close *** * Perform the final step in the socket close. */ #if !defined(__WIN32__) static -ERL_NIF_TERM nfinalize_close(ErlNifEnv* env, - ESockDescriptor* descP) +ERL_NIF_TERM esock_finalize_close(ErlNifEnv* env, + ESockDescriptor* descP) { ERL_NIF_TERM reply; @@ -7516,7 +7533,7 @@ ERL_NIF_TERM nfinalize_close(ErlNifEnv* env, descP->sock = INVALID_SOCKET; descP->event = INVALID_EVENT; - descP->state = SOCKET_STATE_CLOSED; + descP->state = ESOCK_STATE_CLOSED; return reply; } @@ -7548,7 +7565,7 @@ ERL_NIF_TERM nif_shutdown(ErlNifEnv* env, int how; if ((argc != 2) || - !enif_get_resource(env, argv[0], sockets, (void**) &descP) || + !ESOCK_GET_RESOURCE(env, argv[0], (void**) &descP) || !GET_UINT(env, argv[1], &ehow)) { return enif_make_badarg(env); } @@ -7559,7 +7576,7 @@ ERL_NIF_TERM nif_shutdown(ErlNifEnv* env, if (!ehow2how(ehow, &how)) return enif_make_badarg(env); - return nshutdown(env, descP, how); + return esock_shutdown(env, descP, how); #endif // if defined(__WIN32__) } @@ -7567,9 +7584,9 @@ ERL_NIF_TERM nif_shutdown(ErlNifEnv* env, #if !defined(__WIN32__) static -ERL_NIF_TERM nshutdown(ErlNifEnv* env, - ESockDescriptor* descP, - int how) +ERL_NIF_TERM esock_shutdown(ErlNifEnv* env, + ESockDescriptor* descP, + int how) { ERL_NIF_TERM reply; @@ -7637,7 +7654,7 @@ ERL_NIF_TERM nif_setopt(ErlNifEnv* env, /* Extract arguments and perform preliminary validation */ if ((argc != 5) || - !enif_get_resource(env, argv[0], sockets, (void**) &descP) || + !ESOCK_GET_RESOURCE(env, argv[0], (void**) &descP) || !GET_INT(env, argv[2], &eLevel) || !GET_INT(env, argv[3], &eOpt)) { SGDBG( ("SOCKET", "nif_setopt -> failed initial arg check\r\n") ); @@ -7674,7 +7691,7 @@ ERL_NIF_TERM nif_setopt(ErlNifEnv* env, MLOCK(descP->cfgMtx); - result = nsetopt(env, descP, isEncoded, isOTP, level, eOpt, eVal); + result = esock_setopt(env, descP, isEncoded, isOTP, level, eOpt, eVal); MUNLOCK(descP->cfgMtx); @@ -7691,13 +7708,13 @@ ERL_NIF_TERM nif_setopt(ErlNifEnv* env, #if !defined(__WIN32__) static -ERL_NIF_TERM nsetopt(ErlNifEnv* env, - ESockDescriptor* descP, - BOOLEAN_T isEncoded, - BOOLEAN_T isOTP, - int level, - int eOpt, - ERL_NIF_TERM eVal) +ERL_NIF_TERM esock_setopt(ErlNifEnv* env, + ESockDescriptor* descP, + BOOLEAN_T isEncoded, + BOOLEAN_T isOTP, + int level, + int eOpt, + ERL_NIF_TERM eVal) { ERL_NIF_TERM result; @@ -7705,11 +7722,11 @@ ERL_NIF_TERM nsetopt(ErlNifEnv* env, /* These are not actual socket options, * but options for our implementation. */ - result = nsetopt_otp(env, descP, eOpt, eVal); + result = esock_setopt_otp(env, descP, eOpt, eVal); } else if (!isEncoded) { - result = nsetopt_native(env, descP, level, eOpt, eVal); + result = esock_setopt_native(env, descP, level, eOpt, eVal); } else { - result = nsetopt_level(env, descP, level, eOpt, eVal); + result = esock_setopt_level(env, descP, level, eOpt, eVal); } return result; @@ -7717,45 +7734,45 @@ ERL_NIF_TERM nsetopt(ErlNifEnv* env, -/* nsetopt_otp - Handle OTP (level) options +/* esock_setopt_otp - Handle OTP (level) options */ static -ERL_NIF_TERM nsetopt_otp(ErlNifEnv* env, - ESockDescriptor* descP, - int eOpt, - ERL_NIF_TERM eVal) +ERL_NIF_TERM esock_setopt_otp(ErlNifEnv* env, + ESockDescriptor* descP, + int eOpt, + ERL_NIF_TERM eVal) { ERL_NIF_TERM result; SSDBG( descP, - ("SOCKET", "nsetopt_otp -> entry with" + ("SOCKET", "esock_setopt_otp -> entry with" "\r\n eOpt: %d" "\r\n eVal: %T" "\r\n", eOpt, eVal) ); switch (eOpt) { - case SOCKET_OPT_OTP_DEBUG: - result = nsetopt_otp_debug(env, descP, eVal); + case ESOCK_OPT_OTP_DEBUG: + result = esock_setopt_otp_debug(env, descP, eVal); break; - case SOCKET_OPT_OTP_IOW: - result = nsetopt_otp_iow(env, descP, eVal); + case ESOCK_OPT_OTP_IOW: + result = esock_setopt_otp_iow(env, descP, eVal); break; - case SOCKET_OPT_OTP_CTRL_PROC: - result = nsetopt_otp_ctrl_proc(env, descP, eVal); + case ESOCK_OPT_OTP_CTRL_PROC: + result = esock_setopt_otp_ctrl_proc(env, descP, eVal); break; - case SOCKET_OPT_OTP_RCVBUF: - result = nsetopt_otp_rcvbuf(env, descP, eVal); + case ESOCK_OPT_OTP_RCVBUF: + result = esock_setopt_otp_rcvbuf(env, descP, eVal); break; - case SOCKET_OPT_OTP_RCVCTRLBUF: - result = nsetopt_otp_rcvctrlbuf(env, descP, eVal); + case ESOCK_OPT_OTP_RCVCTRLBUF: + result = esock_setopt_otp_rcvctrlbuf(env, descP, eVal); break; - case SOCKET_OPT_OTP_SNDCTRLBUF: - result = nsetopt_otp_sndctrlbuf(env, descP, eVal); + case ESOCK_OPT_OTP_SNDCTRLBUF: + result = esock_setopt_otp_sndctrlbuf(env, descP, eVal); break; default: @@ -7767,12 +7784,12 @@ ERL_NIF_TERM nsetopt_otp(ErlNifEnv* env, } -/* nsetopt_otp_debug - Handle the OTP (level) debug options +/* esock_setopt_otp_debug - Handle the OTP (level) debug options */ static -ERL_NIF_TERM nsetopt_otp_debug(ErlNifEnv* env, - ESockDescriptor* descP, - ERL_NIF_TERM eVal) +ERL_NIF_TERM esock_setopt_otp_debug(ErlNifEnv* env, + ESockDescriptor* descP, + ERL_NIF_TERM eVal) { descP->dbg = esock_decode_bool(eVal); @@ -7780,12 +7797,12 @@ ERL_NIF_TERM nsetopt_otp_debug(ErlNifEnv* env, } -/* nsetopt_otp_iow - Handle the OTP (level) iow options +/* esock_setopt_otp_iow - Handle the OTP (level) iow options */ static -ERL_NIF_TERM nsetopt_otp_iow(ErlNifEnv* env, - ESockDescriptor* descP, - ERL_NIF_TERM eVal) +ERL_NIF_TERM esock_setopt_otp_iow(ErlNifEnv* env, + ESockDescriptor* descP, + ERL_NIF_TERM eVal) { descP->iow = esock_decode_bool(eVal); @@ -7794,19 +7811,20 @@ ERL_NIF_TERM nsetopt_otp_iow(ErlNifEnv* env, -/* nsetopt_otp_ctrl_proc - Handle the OTP (level) controlling_process options +/* esock_setopt_otp_ctrl_proc - Handle the OTP (level) + * controlling_process options */ static -ERL_NIF_TERM nsetopt_otp_ctrl_proc(ErlNifEnv* env, - ESockDescriptor* descP, - ERL_NIF_TERM eVal) +ERL_NIF_TERM esock_setopt_otp_ctrl_proc(ErlNifEnv* env, + ESockDescriptor* descP, + ERL_NIF_TERM eVal) { ErlNifPid caller, newCtrlPid; ESockMonitor newCtrlMon; int xres; SSDBG( descP, - ("SOCKET", "nsetopt_otp_ctrl_proc -> entry with" + ("SOCKET", "esock_setopt_otp_ctrl_proc -> entry with" "\r\n eVal: %T" "\r\n", eVal) ); @@ -7815,7 +7833,8 @@ ERL_NIF_TERM nsetopt_otp_ctrl_proc(ErlNifEnv* env, return esock_make_error(env, atom_exself); if (COMPARE_PIDS(&descP->ctrlPid, &caller) != 0) { - SSDBG( descP, ("SOCKET", "nsetopt_otp_ctrl_proc -> not owner (%T)\r\n", + SSDBG( descP, ("SOCKET", + "esock_setopt_otp_ctrl_proc -> not owner (%T)\r\n", descP->ctrlPid) ); return esock_make_error(env, esock_atom_not_owner); } @@ -7825,13 +7844,14 @@ ERL_NIF_TERM nsetopt_otp_ctrl_proc(ErlNifEnv* env, return esock_make_error(env, esock_atom_einval); } - if ((xres = MONP("nsetopt_otp_ctrl_proc -> (new) ctrl", + if ((xres = MONP("esock_setopt_otp_ctrl_proc -> (new) ctrl", env, descP, &newCtrlPid, &newCtrlMon)) != 0) { - esock_warning_msg("Failed monitor %d) (new) controlling process\r\n", xres); + esock_warning_msg("Failed monitor (%d) (new) controlling process\r\n", + xres); return esock_make_error(env, esock_atom_einval); } - if ((xres = DEMONP("nsetopt_otp_ctrl_proc -> (old) ctrl", + if ((xres = DEMONP("esock_setopt_otp_ctrl_proc -> (old) ctrl", env, descP, &descP->ctrlMon)) != 0) { esock_warning_msg("Failed demonitor (%d) " "old controlling process %T (%T)\r\n", @@ -7841,14 +7861,14 @@ ERL_NIF_TERM nsetopt_otp_ctrl_proc(ErlNifEnv* env, descP->ctrlPid = newCtrlPid; descP->ctrlMon = newCtrlMon; - SSDBG( descP, ("SOCKET", "nsetopt_otp_ctrl_proc -> done\r\n") ); + SSDBG( descP, ("SOCKET", "esock_setopt_otp_ctrl_proc -> done\r\n") ); return esock_atom_ok; } -/* nsetopt_otp_rcvbuf - Handle the OTP (level) rcvbuf option +/* esock_setopt_otp_rcvbuf - Handle the OTP (level) rcvbuf option * The (otp) rcvbuf option is provided as: * * BufSz :: integer() | {N :: pos_integer(), BufSz :: pod_integer()} @@ -7856,9 +7876,9 @@ ERL_NIF_TERM nsetopt_otp_ctrl_proc(ErlNifEnv* env, * Where N is the max number of reads. */ static -ERL_NIF_TERM nsetopt_otp_rcvbuf(ErlNifEnv* env, - ESockDescriptor* descP, - ERL_NIF_TERM eVal) +ERL_NIF_TERM esock_setopt_otp_rcvbuf(ErlNifEnv* env, + ESockDescriptor* descP, + ERL_NIF_TERM eVal) { const ERL_NIF_TERM* t; // The array of the elements of the tuple int tsz; // The size of the tuple - should be 2 @@ -7875,7 +7895,7 @@ ERL_NIF_TERM nsetopt_otp_rcvbuf(ErlNifEnv* env, if ((xres = esock_decode_bufsz(env, eVal, - SOCKET_RECV_BUFFER_SIZE_DEFAULT, + ESOCK_RECV_BUFFER_SIZE_DEFAULT, &bufSz)) != NULL) return esock_make_error_str(env, xres); @@ -7892,7 +7912,7 @@ ERL_NIF_TERM nsetopt_otp_rcvbuf(ErlNifEnv* env, if ((xres = esock_decode_bufsz(env, t[1], - SOCKET_RECV_BUFFER_SIZE_DEFAULT, + ESOCK_RECV_BUFFER_SIZE_DEFAULT, &bufSz)) != NULL) return esock_make_error_str(env, xres); @@ -7908,19 +7928,19 @@ ERL_NIF_TERM nsetopt_otp_rcvbuf(ErlNifEnv* env, -/* nsetopt_otp_rcvctrlbuf - Handle the OTP (level) rcvctrlbuf option +/* esock_setopt_otp_rcvctrlbuf - Handle the OTP (level) rcvctrlbuf option */ static -ERL_NIF_TERM nsetopt_otp_rcvctrlbuf(ErlNifEnv* env, - ESockDescriptor* descP, - ERL_NIF_TERM eVal) +ERL_NIF_TERM esock_setopt_otp_rcvctrlbuf(ErlNifEnv* env, + ESockDescriptor* descP, + ERL_NIF_TERM eVal) { size_t val; char* xres; if ((xres = esock_decode_bufsz(env, eVal, - SOCKET_RECV_CTRL_BUFFER_SIZE_DEFAULT, + ESOCK_RECV_CTRL_BUFFER_SIZE_DEFAULT, &val)) != NULL) return esock_make_error_str(env, xres); @@ -7931,19 +7951,19 @@ ERL_NIF_TERM nsetopt_otp_rcvctrlbuf(ErlNifEnv* env, -/* nsetopt_otp_sndctrlbuf - Handle the OTP (level) sndctrlbuf option +/* esock_setopt_otp_sndctrlbuf - Handle the OTP (level) sndctrlbuf option */ static -ERL_NIF_TERM nsetopt_otp_sndctrlbuf(ErlNifEnv* env, - ESockDescriptor* descP, - ERL_NIF_TERM eVal) +ERL_NIF_TERM esock_setopt_otp_sndctrlbuf(ErlNifEnv* env, + ESockDescriptor* descP, + ERL_NIF_TERM eVal) { size_t val; char* xres; if ((xres = esock_decode_bufsz(env, eVal, - SOCKET_SEND_CTRL_BUFFER_SIZE_DEFAULT, + ESOCK_SEND_CTRL_BUFFER_SIZE_DEFAULT, &val)) != NULL) return esock_make_error_str(env, xres); @@ -7958,17 +7978,17 @@ ERL_NIF_TERM nsetopt_otp_sndctrlbuf(ErlNifEnv* env, * in "native mode" (option is provided as is and value as a binary). */ static -ERL_NIF_TERM nsetopt_native(ErlNifEnv* env, - ESockDescriptor* descP, - int level, - int opt, - ERL_NIF_TERM eVal) +ERL_NIF_TERM esock_setopt_native(ErlNifEnv* env, + ESockDescriptor* descP, + int level, + int opt, + ERL_NIF_TERM eVal) { ErlNifBinary val; ERL_NIF_TERM result; SSDBG( descP, - ("SOCKET", "nsetopt_native -> entry with" + ("SOCKET", "esock_setopt_native -> entry with" "\r\n level: %d" "\r\n opt: %d" "\r\n eVal: %T" @@ -7986,7 +8006,7 @@ ERL_NIF_TERM nsetopt_native(ErlNifEnv* env, } SSDBG( descP, - ("SOCKET", "nsetopt_native -> done when" + ("SOCKET", "esock_setopt_native -> done when" "\r\n result: %T" "\r\n", result) ); @@ -7995,25 +8015,25 @@ ERL_NIF_TERM nsetopt_native(ErlNifEnv* env, -/* nsetopt_level - A "proper" level (option) has been specified +/* esock_setopt_level - A "proper" level (option) has been specified */ static -ERL_NIF_TERM nsetopt_level(ErlNifEnv* env, - ESockDescriptor* descP, - int level, - int eOpt, - ERL_NIF_TERM eVal) +ERL_NIF_TERM esock_setopt_level(ErlNifEnv* env, + ESockDescriptor* descP, + int level, + int eOpt, + ERL_NIF_TERM eVal) { ERL_NIF_TERM result; SSDBG( descP, - ("SOCKET", "nsetopt_level -> entry with" + ("SOCKET", "esock_setopt_level -> entry with" "\r\n level: %d" "\r\n", level) ); switch (level) { case SOL_SOCKET: - result = nsetopt_lvl_socket(env, descP, eOpt, eVal); + result = esock_setopt_lvl_socket(env, descP, eOpt, eVal); break; #if defined(SOL_IP) @@ -8021,7 +8041,7 @@ ERL_NIF_TERM nsetopt_level(ErlNifEnv* env, #else case IPPROTO_IP: #endif - result = nsetopt_lvl_ip(env, descP, eOpt, eVal); + result = esock_setopt_lvl_ip(env, descP, eOpt, eVal); break; #if defined(HAVE_IPV6) @@ -8030,33 +8050,34 @@ ERL_NIF_TERM nsetopt_level(ErlNifEnv* env, #else case IPPROTO_IPV6: #endif - result = nsetopt_lvl_ipv6(env, descP, eOpt, eVal); + result = esock_setopt_lvl_ipv6(env, descP, eOpt, eVal); break; #endif case IPPROTO_TCP: - result = nsetopt_lvl_tcp(env, descP, eOpt, eVal); + result = esock_setopt_lvl_tcp(env, descP, eOpt, eVal); break; case IPPROTO_UDP: - result = nsetopt_lvl_udp(env, descP, eOpt, eVal); + result = esock_setopt_lvl_udp(env, descP, eOpt, eVal); break; #if defined(HAVE_SCTP) case IPPROTO_SCTP: - result = nsetopt_lvl_sctp(env, descP, eOpt, eVal); + result = esock_setopt_lvl_sctp(env, descP, eOpt, eVal); break; #endif default: SSDBG( descP, - ("SOCKET", "nsetopt_level -> unknown level (%d)\r\n", level) ); + ("SOCKET", + "esock_setopt_level -> unknown level (%d)\r\n", level) ); result = esock_make_error(env, esock_atom_einval); break; } SSDBG( descP, - ("SOCKET", "nsetopt_level -> done when" + ("SOCKET", "esock_setopt_level -> done when" "\r\n result: %T" "\r\n", result) ); @@ -8065,139 +8086,140 @@ ERL_NIF_TERM nsetopt_level(ErlNifEnv* env, -/* nsetopt_lvl_socket - Level *SOCKET* option +/* esock_setopt_lvl_socket - Level *SOCKET* option */ static -ERL_NIF_TERM nsetopt_lvl_socket(ErlNifEnv* env, - ESockDescriptor* descP, - int eOpt, - ERL_NIF_TERM eVal) +ERL_NIF_TERM esock_setopt_lvl_socket(ErlNifEnv* env, + ESockDescriptor* descP, + int eOpt, + ERL_NIF_TERM eVal) { ERL_NIF_TERM result; SSDBG( descP, - ("SOCKET", "nsetopt_lvl_socket -> entry with" + ("SOCKET", "esock_setopt_lvl_socket -> entry with" "\r\n opt: %d" "\r\n", eOpt) ); switch (eOpt) { #if defined(SO_BINDTODEVICE) - case SOCKET_OPT_SOCK_BINDTODEVICE: - result = nsetopt_lvl_sock_bindtodevice(env, descP, eVal); + case ESOCK_OPT_SOCK_BINDTODEVICE: + result = esock_setopt_lvl_sock_bindtodevice(env, descP, eVal); break; #endif #if defined(SO_BROADCAST) - case SOCKET_OPT_SOCK_BROADCAST: - result = nsetopt_lvl_sock_broadcast(env, descP, eVal); + case ESOCK_OPT_SOCK_BROADCAST: + result = esock_setopt_lvl_sock_broadcast(env, descP, eVal); break; #endif #if defined(SO_DEBUG) - case SOCKET_OPT_SOCK_DEBUG: - result = nsetopt_lvl_sock_debug(env, descP, eVal); + case ESOCK_OPT_SOCK_DEBUG: + result = esock_setopt_lvl_sock_debug(env, descP, eVal); break; #endif #if defined(SO_DONTROUTE) - case SOCKET_OPT_SOCK_DONTROUTE: - result = nsetopt_lvl_sock_dontroute(env, descP, eVal); + case ESOCK_OPT_SOCK_DONTROUTE: + result = esock_setopt_lvl_sock_dontroute(env, descP, eVal); break; #endif #if defined(SO_KEEPALIVE) - case SOCKET_OPT_SOCK_KEEPALIVE: - result = nsetopt_lvl_sock_keepalive(env, descP, eVal); + case ESOCK_OPT_SOCK_KEEPALIVE: + result = esock_setopt_lvl_sock_keepalive(env, descP, eVal); break; #endif #if defined(SO_LINGER) - case SOCKET_OPT_SOCK_LINGER: - result = nsetopt_lvl_sock_linger(env, descP, eVal); + case ESOCK_OPT_SOCK_LINGER: + result = esock_setopt_lvl_sock_linger(env, descP, eVal); break; #endif #if defined(SO_PEEK_OFF) - case SOCKET_OPT_SOCK_PEEK_OFF: - result = nsetopt_lvl_sock_peek_off(env, descP, eVal); + case ESOCK_OPT_SOCK_PEEK_OFF: + result = esock_setopt_lvl_sock_peek_off(env, descP, eVal); break; #endif #if defined(SO_OOBINLINE) - case SOCKET_OPT_SOCK_OOBINLINE: - result = nsetopt_lvl_sock_oobinline(env, descP, eVal); + case ESOCK_OPT_SOCK_OOBINLINE: + result = esock_setopt_lvl_sock_oobinline(env, descP, eVal); break; #endif #if defined(SO_PRIORITY) - case SOCKET_OPT_SOCK_PRIORITY: - result = nsetopt_lvl_sock_priority(env, descP, eVal); + case ESOCK_OPT_SOCK_PRIORITY: + result = esock_setopt_lvl_sock_priority(env, descP, eVal); break; #endif #if defined(SO_RCVBUF) - case SOCKET_OPT_SOCK_RCVBUF: - result = nsetopt_lvl_sock_rcvbuf(env, descP, eVal); + case ESOCK_OPT_SOCK_RCVBUF: + result = esock_setopt_lvl_sock_rcvbuf(env, descP, eVal); break; #endif #if defined(SO_RCVLOWAT) - case SOCKET_OPT_SOCK_RCVLOWAT: - result = nsetopt_lvl_sock_rcvlowat(env, descP, eVal); + case ESOCK_OPT_SOCK_RCVLOWAT: + result = esock_setopt_lvl_sock_rcvlowat(env, descP, eVal); break; #endif #if defined(SO_RCVTIMEO) - case SOCKET_OPT_SOCK_RCVTIMEO: - result = nsetopt_lvl_sock_rcvtimeo(env, descP, eVal); + case ESOCK_OPT_SOCK_RCVTIMEO: + result = esock_setopt_lvl_sock_rcvtimeo(env, descP, eVal); break; #endif #if defined(SO_REUSEADDR) - case SOCKET_OPT_SOCK_REUSEADDR: - result = nsetopt_lvl_sock_reuseaddr(env, descP, eVal); + case ESOCK_OPT_SOCK_REUSEADDR: + result = esock_setopt_lvl_sock_reuseaddr(env, descP, eVal); break; #endif #if defined(SO_REUSEPORT) - case SOCKET_OPT_SOCK_REUSEPORT: - result = nsetopt_lvl_sock_reuseport(env, descP, eVal); + case ESOCK_OPT_SOCK_REUSEPORT: + result = esock_setopt_lvl_sock_reuseport(env, descP, eVal); break; #endif #if defined(SO_SNDBUF) - case SOCKET_OPT_SOCK_SNDBUF: - result = nsetopt_lvl_sock_sndbuf(env, descP, eVal); + case ESOCK_OPT_SOCK_SNDBUF: + result = esock_setopt_lvl_sock_sndbuf(env, descP, eVal); break; #endif #if defined(SO_SNDLOWAT) - case SOCKET_OPT_SOCK_SNDLOWAT: - result = nsetopt_lvl_sock_sndlowat(env, descP, eVal); + case ESOCK_OPT_SOCK_SNDLOWAT: + result = esock_setopt_lvl_sock_sndlowat(env, descP, eVal); break; #endif #if defined(SO_SNDTIMEO) - case SOCKET_OPT_SOCK_SNDTIMEO: - result = nsetopt_lvl_sock_sndtimeo(env, descP, eVal); + case ESOCK_OPT_SOCK_SNDTIMEO: + result = esock_setopt_lvl_sock_sndtimeo(env, descP, eVal); break; #endif #if defined(SO_TIMESTAMP) - case SOCKET_OPT_SOCK_TIMESTAMP: - result = nsetopt_lvl_sock_timestamp(env, descP, eVal); + case ESOCK_OPT_SOCK_TIMESTAMP: + result = esock_setopt_lvl_sock_timestamp(env, descP, eVal); break; #endif default: SSDBG( descP, - ("SOCKET", "nsetopt_lvl_socket -> unknown opt (%d)\r\n", eOpt) ); + ("SOCKET", + "esock_setopt_lvl_socket -> unknown opt (%d)\r\n", eOpt) ); result = esock_make_error(env, esock_atom_einval); break; } SSDBG( descP, - ("SOCKET", "nsetopt_lvl_socket -> done when" + ("SOCKET", "esock_setopt_lvl_socket -> done when" "\r\n result: %T" "\r\n", result) ); @@ -8207,66 +8229,66 @@ ERL_NIF_TERM nsetopt_lvl_socket(ErlNifEnv* env, #if defined(SO_BINDTODEVICE) static -ERL_NIF_TERM nsetopt_lvl_sock_bindtodevice(ErlNifEnv* env, - ESockDescriptor* descP, - ERL_NIF_TERM eVal) +ERL_NIF_TERM esock_setopt_lvl_sock_bindtodevice(ErlNifEnv* env, + ESockDescriptor* descP, + ERL_NIF_TERM eVal) { - return nsetopt_str_opt(env, descP, - SOL_SOCKET, SO_BROADCAST, - IFNAMSIZ, eVal); + return esock_setopt_str_opt(env, descP, + SOL_SOCKET, SO_BINDTODEVICE, + IFNAMSIZ, eVal); } #endif #if defined(SO_BROADCAST) static -ERL_NIF_TERM nsetopt_lvl_sock_broadcast(ErlNifEnv* env, - ESockDescriptor* descP, - ERL_NIF_TERM eVal) +ERL_NIF_TERM esock_setopt_lvl_sock_broadcast(ErlNifEnv* env, + ESockDescriptor* descP, + ERL_NIF_TERM eVal) { - return nsetopt_bool_opt(env, descP, SOL_SOCKET, SO_BROADCAST, eVal); + return esock_setopt_bool_opt(env, descP, SOL_SOCKET, SO_BROADCAST, eVal); } #endif #if defined(SO_DEBUG) static -ERL_NIF_TERM nsetopt_lvl_sock_debug(ErlNifEnv* env, - ESockDescriptor* descP, - ERL_NIF_TERM eVal) +ERL_NIF_TERM esock_setopt_lvl_sock_debug(ErlNifEnv* env, + ESockDescriptor* descP, + ERL_NIF_TERM eVal) { - return nsetopt_int_opt(env, descP, SOL_SOCKET, SO_DEBUG, eVal); + return esock_setopt_int_opt(env, descP, SOL_SOCKET, SO_DEBUG, eVal); } #endif #if defined(SO_DONTROUTE) static -ERL_NIF_TERM nsetopt_lvl_sock_dontroute(ErlNifEnv* env, - ESockDescriptor* descP, - ERL_NIF_TERM eVal) +ERL_NIF_TERM esock_setopt_lvl_sock_dontroute(ErlNifEnv* env, + ESockDescriptor* descP, + ERL_NIF_TERM eVal) { - return nsetopt_bool_opt(env, descP, SOL_SOCKET, SO_DONTROUTE, eVal); + return esock_setopt_bool_opt(env, descP, SOL_SOCKET, SO_DONTROUTE, eVal); } #endif #if defined(SO_KEEPALIVE) static -ERL_NIF_TERM nsetopt_lvl_sock_keepalive(ErlNifEnv* env, - ESockDescriptor* descP, - ERL_NIF_TERM eVal) +ERL_NIF_TERM esock_setopt_lvl_sock_keepalive(ErlNifEnv* env, + ESockDescriptor* descP, + ERL_NIF_TERM eVal) { - return nsetopt_bool_opt(env, descP, SOL_SOCKET, SO_KEEPALIVE, eVal); + return esock_setopt_bool_opt(env, descP, SOL_SOCKET, SO_KEEPALIVE, eVal); } #endif #if defined(SO_LINGER) static -ERL_NIF_TERM nsetopt_lvl_sock_linger(ErlNifEnv* env, - ESockDescriptor* descP, - ERL_NIF_TERM eVal) +ERL_NIF_TERM esock_setopt_lvl_sock_linger(ErlNifEnv* env, + ESockDescriptor* descP, + ERL_NIF_TERM eVal) { ERL_NIF_TERM result; struct linger val; @@ -8290,346 +8312,347 @@ ERL_NIF_TERM nsetopt_lvl_sock_linger(ErlNifEnv* env, #if defined(SO_OOBINLINE) static -ERL_NIF_TERM nsetopt_lvl_sock_oobinline(ErlNifEnv* env, - ESockDescriptor* descP, - ERL_NIF_TERM eVal) +ERL_NIF_TERM esock_setopt_lvl_sock_oobinline(ErlNifEnv* env, + ESockDescriptor* descP, + ERL_NIF_TERM eVal) { - return nsetopt_bool_opt(env, descP, SOL_SOCKET, SO_OOBINLINE, eVal); + return esock_setopt_bool_opt(env, descP, SOL_SOCKET, SO_OOBINLINE, eVal); } #endif #if defined(SO_PEEK_OFF) static -ERL_NIF_TERM nsetopt_lvl_sock_peek_off(ErlNifEnv* env, - ESockDescriptor* descP, - ERL_NIF_TERM eVal) +ERL_NIF_TERM esock_setopt_lvl_sock_peek_off(ErlNifEnv* env, + ESockDescriptor* descP, + ERL_NIF_TERM eVal) { - return nsetopt_int_opt(env, descP, SOL_SOCKET, SO_PEEK_OFF, eVal); + return esock_setopt_int_opt(env, descP, SOL_SOCKET, SO_PEEK_OFF, eVal); } #endif #if defined(SO_PRIORITY) static -ERL_NIF_TERM nsetopt_lvl_sock_priority(ErlNifEnv* env, - ESockDescriptor* descP, - ERL_NIF_TERM eVal) +ERL_NIF_TERM esock_setopt_lvl_sock_priority(ErlNifEnv* env, + ESockDescriptor* descP, + ERL_NIF_TERM eVal) { - return nsetopt_int_opt(env, descP, SOL_SOCKET, SO_PRIORITY, eVal); + return esock_setopt_int_opt(env, descP, SOL_SOCKET, SO_PRIORITY, eVal); } #endif #if defined(SO_RCVBUF) static -ERL_NIF_TERM nsetopt_lvl_sock_rcvbuf(ErlNifEnv* env, - ESockDescriptor* descP, - ERL_NIF_TERM eVal) +ERL_NIF_TERM esock_setopt_lvl_sock_rcvbuf(ErlNifEnv* env, + ESockDescriptor* descP, + ERL_NIF_TERM eVal) { - return nsetopt_int_opt(env, descP, SOL_SOCKET, SO_RCVBUF, eVal); + return esock_setopt_int_opt(env, descP, SOL_SOCKET, SO_RCVBUF, eVal); } #endif #if defined(SO_RCVLOWAT) static -ERL_NIF_TERM nsetopt_lvl_sock_rcvlowat(ErlNifEnv* env, - ESockDescriptor* descP, - ERL_NIF_TERM eVal) +ERL_NIF_TERM esock_setopt_lvl_sock_rcvlowat(ErlNifEnv* env, + ESockDescriptor* descP, + ERL_NIF_TERM eVal) { - return nsetopt_int_opt(env, descP, SOL_SOCKET, SO_RCVLOWAT, eVal); + return esock_setopt_int_opt(env, descP, SOL_SOCKET, SO_RCVLOWAT, eVal); } #endif #if defined(SO_RCVTIMEO) static -ERL_NIF_TERM nsetopt_lvl_sock_rcvtimeo(ErlNifEnv* env, - ESockDescriptor* descP, - ERL_NIF_TERM eVal) +ERL_NIF_TERM esock_setopt_lvl_sock_rcvtimeo(ErlNifEnv* env, + ESockDescriptor* descP, + ERL_NIF_TERM eVal) { - return nsetopt_timeval_opt(env, descP, SOL_SOCKET, SO_RCVTIMEO, eVal); + return esock_setopt_timeval_opt(env, descP, SOL_SOCKET, SO_RCVTIMEO, eVal); } #endif #if defined(SO_REUSEADDR) static -ERL_NIF_TERM nsetopt_lvl_sock_reuseaddr(ErlNifEnv* env, - ESockDescriptor* descP, - ERL_NIF_TERM eVal) +ERL_NIF_TERM esock_setopt_lvl_sock_reuseaddr(ErlNifEnv* env, + ESockDescriptor* descP, + ERL_NIF_TERM eVal) { - return nsetopt_bool_opt(env, descP, SOL_SOCKET, SO_REUSEADDR, eVal); + return esock_setopt_bool_opt(env, descP, SOL_SOCKET, SO_REUSEADDR, eVal); } #endif #if defined(SO_REUSEPORT) static -ERL_NIF_TERM nsetopt_lvl_sock_reuseport(ErlNifEnv* env, - ESockDescriptor* descP, - ERL_NIF_TERM eVal) +ERL_NIF_TERM esock_setopt_lvl_sock_reuseport(ErlNifEnv* env, + ESockDescriptor* descP, + ERL_NIF_TERM eVal) { - return nsetopt_bool_opt(env, descP, SOL_SOCKET, SO_REUSEPORT, eVal); + return esock_setopt_bool_opt(env, descP, SOL_SOCKET, SO_REUSEPORT, eVal); } #endif #if defined(SO_SNDBUF) static -ERL_NIF_TERM nsetopt_lvl_sock_sndbuf(ErlNifEnv* env, - ESockDescriptor* descP, - ERL_NIF_TERM eVal) +ERL_NIF_TERM esock_setopt_lvl_sock_sndbuf(ErlNifEnv* env, + ESockDescriptor* descP, + ERL_NIF_TERM eVal) { - return nsetopt_int_opt(env, descP, SOL_SOCKET, SO_SNDBUF, eVal); + return esock_setopt_int_opt(env, descP, SOL_SOCKET, SO_SNDBUF, eVal); } #endif #if defined(SO_SNDLOWAT) static -ERL_NIF_TERM nsetopt_lvl_sock_sndlowat(ErlNifEnv* env, - ESockDescriptor* descP, - ERL_NIF_TERM eVal) +ERL_NIF_TERM esock_setopt_lvl_sock_sndlowat(ErlNifEnv* env, + ESockDescriptor* descP, + ERL_NIF_TERM eVal) { - return nsetopt_int_opt(env, descP, SOL_SOCKET, SO_SNDLOWAT, eVal); + return esock_setopt_int_opt(env, descP, SOL_SOCKET, SO_SNDLOWAT, eVal); } #endif #if defined(SO_SNDTIMEO) static -ERL_NIF_TERM nsetopt_lvl_sock_sndtimeo(ErlNifEnv* env, - ESockDescriptor* descP, - ERL_NIF_TERM eVal) +ERL_NIF_TERM esock_setopt_lvl_sock_sndtimeo(ErlNifEnv* env, + ESockDescriptor* descP, + ERL_NIF_TERM eVal) { SSDBG( descP, - ("SOCKET", "nsetopt_lvl_sock_sndtimeo -> entry with" + ("SOCKET", "esock_setopt_lvl_sock_sndtimeo -> entry with" "\r\n eVal: %T" "\r\n", eVal) ); - return nsetopt_timeval_opt(env, descP, SOL_SOCKET, SO_SNDTIMEO, eVal); + return esock_setopt_timeval_opt(env, descP, SOL_SOCKET, SO_SNDTIMEO, eVal); } #endif #if defined(SO_TIMESTAMP) static -ERL_NIF_TERM nsetopt_lvl_sock_timestamp(ErlNifEnv* env, - ESockDescriptor* descP, - ERL_NIF_TERM eVal) +ERL_NIF_TERM esock_setopt_lvl_sock_timestamp(ErlNifEnv* env, + ESockDescriptor* descP, + ERL_NIF_TERM eVal) { - return nsetopt_bool_opt(env, descP, SOL_SOCKET, SO_TIMESTAMP, eVal); + return esock_setopt_bool_opt(env, descP, SOL_SOCKET, SO_TIMESTAMP, eVal); } #endif -/* nsetopt_lvl_ip - Level *IP* option(s) +/* esock_setopt_lvl_ip - Level *IP* option(s) */ static -ERL_NIF_TERM nsetopt_lvl_ip(ErlNifEnv* env, - ESockDescriptor* descP, - int eOpt, - ERL_NIF_TERM eVal) +ERL_NIF_TERM esock_setopt_lvl_ip(ErlNifEnv* env, + ESockDescriptor* descP, + int eOpt, + ERL_NIF_TERM eVal) { ERL_NIF_TERM result; SSDBG( descP, - ("SOCKET", "nsetopt_lvl_ip -> entry with" + ("SOCKET", "esock_setopt_lvl_ip -> entry with" "\r\n opt: %d" "\r\n", eOpt) ); switch (eOpt) { #if defined(IP_ADD_MEMBERSHIP) - case SOCKET_OPT_IP_ADD_MEMBERSHIP: - result = nsetopt_lvl_ip_add_membership(env, descP, eVal); + case ESOCK_OPT_IP_ADD_MEMBERSHIP: + result = esock_setopt_lvl_ip_add_membership(env, descP, eVal); break; #endif #if defined(IP_ADD_SOURCE_MEMBERSHIP) - case SOCKET_OPT_IP_ADD_SOURCE_MEMBERSHIP: - result = nsetopt_lvl_ip_add_source_membership(env, descP, eVal); + case ESOCK_OPT_IP_ADD_SOURCE_MEMBERSHIP: + result = esock_setopt_lvl_ip_add_source_membership(env, descP, eVal); break; #endif #if defined(IP_BLOCK_SOURCE) - case SOCKET_OPT_IP_BLOCK_SOURCE: - result = nsetopt_lvl_ip_block_source(env, descP, eVal); + case ESOCK_OPT_IP_BLOCK_SOURCE: + result = esock_setopt_lvl_ip_block_source(env, descP, eVal); break; #endif #if defined(IP_DROP_MEMBERSHIP) - case SOCKET_OPT_IP_DROP_MEMBERSHIP: - result = nsetopt_lvl_ip_drop_membership(env, descP, eVal); + case ESOCK_OPT_IP_DROP_MEMBERSHIP: + result = esock_setopt_lvl_ip_drop_membership(env, descP, eVal); break; #endif #if defined(IP_DROP_SOURCE_MEMBERSHIP) - case SOCKET_OPT_IP_DROP_SOURCE_MEMBERSHIP: - result = nsetopt_lvl_ip_drop_source_membership(env, descP, eVal); + case ESOCK_OPT_IP_DROP_SOURCE_MEMBERSHIP: + result = esock_setopt_lvl_ip_drop_source_membership(env, descP, eVal); break; #endif #if defined(IP_FREEBIND) - case SOCKET_OPT_IP_FREEBIND: - result = nsetopt_lvl_ip_freebind(env, descP, eVal); + case ESOCK_OPT_IP_FREEBIND: + result = esock_setopt_lvl_ip_freebind(env, descP, eVal); break; #endif #if defined(IP_HDRINCL) - case SOCKET_OPT_IP_HDRINCL: - result = nsetopt_lvl_ip_hdrincl(env, descP, eVal); + case ESOCK_OPT_IP_HDRINCL: + result = esock_setopt_lvl_ip_hdrincl(env, descP, eVal); break; #endif #if defined(IP_MINTTL) - case SOCKET_OPT_IP_MINTTL: - result = nsetopt_lvl_ip_minttl(env, descP, eVal); + case ESOCK_OPT_IP_MINTTL: + result = esock_setopt_lvl_ip_minttl(env, descP, eVal); break; #endif #if defined(IP_MSFILTER) && defined(IP_MSFILTER_SIZE) - case SOCKET_OPT_IP_MSFILTER: - result = nsetopt_lvl_ip_msfilter(env, descP, eVal); + case ESOCK_OPT_IP_MSFILTER: + result = esock_setopt_lvl_ip_msfilter(env, descP, eVal); break; #endif #if defined(IP_MTU_DISCOVER) - case SOCKET_OPT_IP_MTU_DISCOVER: - result = nsetopt_lvl_ip_mtu_discover(env, descP, eVal); + case ESOCK_OPT_IP_MTU_DISCOVER: + result = esock_setopt_lvl_ip_mtu_discover(env, descP, eVal); break; #endif #if defined(IP_MULTICAST_ALL) - case SOCKET_OPT_IP_MULTICAST_ALL: - result = nsetopt_lvl_ip_multicast_all(env, descP, eVal); + case ESOCK_OPT_IP_MULTICAST_ALL: + result = esock_setopt_lvl_ip_multicast_all(env, descP, eVal); break; #endif #if defined(IP_MULTICAST_IF) - case SOCKET_OPT_IP_MULTICAST_IF: - result = nsetopt_lvl_ip_multicast_if(env, descP, eVal); + case ESOCK_OPT_IP_MULTICAST_IF: + result = esock_setopt_lvl_ip_multicast_if(env, descP, eVal); break; #endif #if defined(IP_MULTICAST_LOOP) - case SOCKET_OPT_IP_MULTICAST_LOOP: - result = nsetopt_lvl_ip_multicast_loop(env, descP, eVal); + case ESOCK_OPT_IP_MULTICAST_LOOP: + result = esock_setopt_lvl_ip_multicast_loop(env, descP, eVal); break; #endif #if defined(IP_MULTICAST_TTL) - case SOCKET_OPT_IP_MULTICAST_TTL: - result = nsetopt_lvl_ip_multicast_ttl(env, descP, eVal); + case ESOCK_OPT_IP_MULTICAST_TTL: + result = esock_setopt_lvl_ip_multicast_ttl(env, descP, eVal); break; #endif #if defined(IP_NODEFRAG) - case SOCKET_OPT_IP_NODEFRAG: - result = nsetopt_lvl_ip_nodefrag(env, descP, eVal); + case ESOCK_OPT_IP_NODEFRAG: + result = esock_setopt_lvl_ip_nodefrag(env, descP, eVal); break; #endif #if defined(IP_PKTINFO) - case SOCKET_OPT_IP_PKTINFO: - result = nsetopt_lvl_ip_pktinfo(env, descP, eVal); + case ESOCK_OPT_IP_PKTINFO: + result = esock_setopt_lvl_ip_pktinfo(env, descP, eVal); break; #endif #if defined(IP_RECVDSTADDR) - case SOCKET_OPT_IP_RECVDSTADDR: - result = nsetopt_lvl_ip_recvdstaddr(env, descP, eVal); + case ESOCK_OPT_IP_RECVDSTADDR: + result = esock_setopt_lvl_ip_recvdstaddr(env, descP, eVal); break; #endif #if defined(IP_RECVERR) - case SOCKET_OPT_IP_RECVERR: - result = nsetopt_lvl_ip_recverr(env, descP, eVal); + case ESOCK_OPT_IP_RECVERR: + result = esock_setopt_lvl_ip_recverr(env, descP, eVal); break; #endif #if defined(IP_RECVIF) - case SOCKET_OPT_IP_RECVIF: - result = nsetopt_lvl_ip_recvif(env, descP, eVal); + case ESOCK_OPT_IP_RECVIF: + result = esock_setopt_lvl_ip_recvif(env, descP, eVal); break; #endif #if defined(IP_RECVOPTS) - case SOCKET_OPT_IP_RECVOPTS: - result = nsetopt_lvl_ip_recvopts(env, descP, eVal); + case ESOCK_OPT_IP_RECVOPTS: + result = esock_setopt_lvl_ip_recvopts(env, descP, eVal); break; #endif #if defined(IP_RECVORIGDSTADDR) - case SOCKET_OPT_IP_RECVORIGDSTADDR: - result = nsetopt_lvl_ip_recvorigdstaddr(env, descP, eVal); + case ESOCK_OPT_IP_RECVORIGDSTADDR: + result = esock_setopt_lvl_ip_recvorigdstaddr(env, descP, eVal); break; #endif #if defined(IP_RECVTOS) - case SOCKET_OPT_IP_RECVTOS: - result = nsetopt_lvl_ip_recvtos(env, descP, eVal); + case ESOCK_OPT_IP_RECVTOS: + result = esock_setopt_lvl_ip_recvtos(env, descP, eVal); break; #endif #if defined(IP_RECVTTL) - case SOCKET_OPT_IP_RECVTTL: - result = nsetopt_lvl_ip_recvttl(env, descP, eVal); + case ESOCK_OPT_IP_RECVTTL: + result = esock_setopt_lvl_ip_recvttl(env, descP, eVal); break; #endif #if defined(IP_RETOPTS) - case SOCKET_OPT_IP_RETOPTS: - result = nsetopt_lvl_ip_retopts(env, descP, eVal); + case ESOCK_OPT_IP_RETOPTS: + result = esock_setopt_lvl_ip_retopts(env, descP, eVal); break; #endif #if defined(IP_ROUTER_ALERT) - case SOCKET_OPT_IP_ROUTER_ALERT: - result = nsetopt_lvl_ip_router_alert(env, descP, eVal); + case ESOCK_OPT_IP_ROUTER_ALERT: + result = esock_setopt_lvl_ip_router_alert(env, descP, eVal); break; #endif #if defined(IP_SENDSRCADDR) - case SOCKET_OPT_IP_SENDSRCADDR: - result = nsetopt_lvl_ip_sendsrcaddr(env, descP, eVal); + case ESOCK_OPT_IP_SENDSRCADDR: + result = esock_setopt_lvl_ip_sendsrcaddr(env, descP, eVal); break; #endif #if defined(IP_TOS) - case SOCKET_OPT_IP_TOS: - result = nsetopt_lvl_ip_tos(env, descP, eVal); + case ESOCK_OPT_IP_TOS: + result = esock_setopt_lvl_ip_tos(env, descP, eVal); break; #endif #if defined(IP_TRANSPARENT) - case SOCKET_OPT_IP_TRANSPARENT: - result = nsetopt_lvl_ip_transparent(env, descP, eVal); + case ESOCK_OPT_IP_TRANSPARENT: + result = esock_setopt_lvl_ip_transparent(env, descP, eVal); break; #endif #if defined(IP_TTL) - case SOCKET_OPT_IP_TTL: - result = nsetopt_lvl_ip_ttl(env, descP, eVal); + case ESOCK_OPT_IP_TTL: + result = esock_setopt_lvl_ip_ttl(env, descP, eVal); break; #endif #if defined(IP_UNBLOCK_SOURCE) - case SOCKET_OPT_IP_UNBLOCK_SOURCE: - result = nsetopt_lvl_ip_unblock_source(env, descP, eVal); + case ESOCK_OPT_IP_UNBLOCK_SOURCE: + result = esock_setopt_lvl_ip_unblock_source(env, descP, eVal); break; #endif default: - SSDBG( descP, ("SOCKET", "nsetopt_lvl_ip -> unknown opt (%d)\r\n", eOpt) ); + SSDBG( descP, ("SOCKET", + "esock_setopt_lvl_ip -> unknown opt (%d)\r\n", eOpt) ); result = esock_make_error(env, esock_atom_einval); break; } SSDBG( descP, - ("SOCKET", "nsetopt_lvl_ip -> done when" + ("SOCKET", "esock_setopt_lvl_ip -> done when" "\r\n result: %T" "\r\n", result) ); @@ -8637,7 +8660,7 @@ ERL_NIF_TERM nsetopt_lvl_ip(ErlNifEnv* env, } -/* nsetopt_lvl_ip_add_membership - Level IP ADD_MEMBERSHIP option +/* esock_setopt_lvl_ip_add_membership - Level IP ADD_MEMBERSHIP option * * The value is a map with two attributes: multiaddr and interface. * The attribute 'multiaddr' is always a 4-tuple (IPv4 address). @@ -8646,16 +8669,18 @@ ERL_NIF_TERM nsetopt_lvl_ip(ErlNifEnv* env, */ #if defined(IP_ADD_MEMBERSHIP) static -ERL_NIF_TERM nsetopt_lvl_ip_add_membership(ErlNifEnv* env, - ESockDescriptor* descP, - ERL_NIF_TERM eVal) +ERL_NIF_TERM esock_setopt_lvl_ip_add_membership(ErlNifEnv* env, + ESockDescriptor* descP, + ERL_NIF_TERM eVal) { - return nsetopt_lvl_ip_update_membership(env, descP, eVal, IP_ADD_MEMBERSHIP); + return esock_setopt_lvl_ip_update_membership(env, descP, eVal, + IP_ADD_MEMBERSHIP); } #endif -/* nsetopt_lvl_ip_add_source_membership - Level IP ADD_SOURCE_MEMBERSHIP option +/* esock_setopt_lvl_ip_add_source_membership - + * Level IP ADD_SOURCE_MEMBERSHIP option * * The value is a map with three attributes: multiaddr, interface and * sourceaddr. @@ -8666,17 +8691,17 @@ ERL_NIF_TERM nsetopt_lvl_ip_add_membership(ErlNifEnv* env, */ #if defined(IP_ADD_SOURCE_MEMBERSHIP) static -ERL_NIF_TERM nsetopt_lvl_ip_add_source_membership(ErlNifEnv* env, - ESockDescriptor* descP, - ERL_NIF_TERM eVal) +ERL_NIF_TERM esock_setopt_lvl_ip_add_source_membership(ErlNifEnv* env, + ESockDescriptor* descP, + ERL_NIF_TERM eVal) { - return nsetopt_lvl_ip_update_source(env, descP, eVal, - IP_ADD_SOURCE_MEMBERSHIP); + return esock_setopt_lvl_ip_update_source(env, descP, eVal, + IP_ADD_SOURCE_MEMBERSHIP); } #endif -/* nsetopt_lvl_ip_block_source - Level IP BLOCK_SOURCE option +/* esock_setopt_lvl_ip_block_source - Level IP BLOCK_SOURCE option * * The value is a map with three attributes: multiaddr, interface and * sourceaddr. @@ -8687,16 +8712,16 @@ ERL_NIF_TERM nsetopt_lvl_ip_add_source_membership(ErlNifEnv* env, */ #if defined(IP_BLOCK_SOURCE) static -ERL_NIF_TERM nsetopt_lvl_ip_block_source(ErlNifEnv* env, - ESockDescriptor* descP, - ERL_NIF_TERM eVal) +ERL_NIF_TERM esock_setopt_lvl_ip_block_source(ErlNifEnv* env, + ESockDescriptor* descP, + ERL_NIF_TERM eVal) { - return nsetopt_lvl_ip_update_source(env, descP, eVal, IP_BLOCK_SOURCE); + return esock_setopt_lvl_ip_update_source(env, descP, eVal, IP_BLOCK_SOURCE); } #endif -/* nsetopt_lvl_ip_drop_membership - Level IP DROP_MEMBERSHIP option +/* esock_setopt_lvl_ip_drop_membership - Level IP DROP_MEMBERSHIP option * * The value is a map with two attributes: multiaddr and interface. * The attribute 'multiaddr' is always a 4-tuple (IPv4 address). @@ -8709,18 +8734,19 @@ ERL_NIF_TERM nsetopt_lvl_ip_block_source(ErlNifEnv* env, */ #if defined(IP_DROP_MEMBERSHIP) static -ERL_NIF_TERM nsetopt_lvl_ip_drop_membership(ErlNifEnv* env, - ESockDescriptor* descP, - ERL_NIF_TERM eVal) +ERL_NIF_TERM esock_setopt_lvl_ip_drop_membership(ErlNifEnv* env, + ESockDescriptor* descP, + ERL_NIF_TERM eVal) { - return nsetopt_lvl_ip_update_membership(env, descP, eVal, - IP_DROP_MEMBERSHIP); + return esock_setopt_lvl_ip_update_membership(env, descP, eVal, + IP_DROP_MEMBERSHIP); } #endif -/* nsetopt_lvl_ip_drop_source_membership - Level IP DROP_SOURCE_MEMBERSHIP option +/* esock_setopt_lvl_ip_drop_source_membership - + * Level IP DROP_SOURCE_MEMBERSHIP option * * The value is a map with three attributes: multiaddr, interface and * sourceaddr. @@ -8731,24 +8757,24 @@ ERL_NIF_TERM nsetopt_lvl_ip_drop_membership(ErlNifEnv* env, */ #if defined(IP_DROP_SOURCE_MEMBERSHIP) static -ERL_NIF_TERM nsetopt_lvl_ip_drop_source_membership(ErlNifEnv* env, - ESockDescriptor* descP, - ERL_NIF_TERM eVal) +ERL_NIF_TERM esock_setopt_lvl_ip_drop_source_membership(ErlNifEnv* env, + ESockDescriptor* descP, + ERL_NIF_TERM eVal) { - return nsetopt_lvl_ip_update_source(env, descP, eVal, - IP_DROP_SOURCE_MEMBERSHIP); + return esock_setopt_lvl_ip_update_source(env, descP, eVal, + IP_DROP_SOURCE_MEMBERSHIP); } #endif -/* nsetopt_lvl_ip_freebind - Level IP FREEBIND option +/* esock_setopt_lvl_ip_freebind - Level IP FREEBIND option */ #if defined(IP_FREEBIND) static -ERL_NIF_TERM nsetopt_lvl_ip_freebind(ErlNifEnv* env, - ESockDescriptor* descP, - ERL_NIF_TERM eVal) +ERL_NIF_TERM esock_setopt_lvl_ip_freebind(ErlNifEnv* env, + ESockDescriptor* descP, + ERL_NIF_TERM eVal) { #if defined(SOL_IP) int level = SOL_IP; @@ -8756,19 +8782,19 @@ ERL_NIF_TERM nsetopt_lvl_ip_freebind(ErlNifEnv* env, int level = IPPROTO_IP; #endif - return nsetopt_bool_opt(env, descP, level, IP_FREEBIND, eVal); + return esock_setopt_bool_opt(env, descP, level, IP_FREEBIND, eVal); } #endif -/* nsetopt_lvl_ip_hdrincl - Level IP HDRINCL option +/* esock_setopt_lvl_ip_hdrincl - Level IP HDRINCL option */ #if defined(IP_HDRINCL) static -ERL_NIF_TERM nsetopt_lvl_ip_hdrincl(ErlNifEnv* env, - ESockDescriptor* descP, - ERL_NIF_TERM eVal) +ERL_NIF_TERM esock_setopt_lvl_ip_hdrincl(ErlNifEnv* env, + ESockDescriptor* descP, + ERL_NIF_TERM eVal) { #if defined(SOL_IP) int level = SOL_IP; @@ -8776,19 +8802,19 @@ ERL_NIF_TERM nsetopt_lvl_ip_hdrincl(ErlNifEnv* env, int level = IPPROTO_IP; #endif - return nsetopt_bool_opt(env, descP, level, IP_HDRINCL, eVal); + return esock_setopt_bool_opt(env, descP, level, IP_HDRINCL, eVal); } #endif -/* nsetopt_lvl_ip_minttl - Level IP MINTTL option +/* esock_setopt_lvl_ip_minttl - Level IP MINTTL option */ #if defined(IP_MINTTL) static -ERL_NIF_TERM nsetopt_lvl_ip_minttl(ErlNifEnv* env, - ESockDescriptor* descP, - ERL_NIF_TERM eVal) +ERL_NIF_TERM esock_setopt_lvl_ip_minttl(ErlNifEnv* env, + ESockDescriptor* descP, + ERL_NIF_TERM eVal) { #if defined(SOL_IP) int level = SOL_IP; @@ -8796,26 +8822,26 @@ ERL_NIF_TERM nsetopt_lvl_ip_minttl(ErlNifEnv* env, int level = IPPROTO_IP; #endif - return nsetopt_int_opt(env, descP, level, IP_MINTTL, eVal); + return esock_setopt_int_opt(env, descP, level, IP_MINTTL, eVal); } #endif -/* nsetopt_lvl_ip_msfilter - Level IP MSFILTER option +/* esock_setopt_lvl_ip_msfilter - Level IP MSFILTER option * * The value can be *either* the atom 'null' or a map of type ip_msfilter(). */ #if defined(IP_MSFILTER) && defined(IP_MSFILTER_SIZE) static -ERL_NIF_TERM nsetopt_lvl_ip_msfilter(ErlNifEnv* env, - ESockDescriptor* descP, - ERL_NIF_TERM eVal) +ERL_NIF_TERM esock_setopt_lvl_ip_msfilter(ErlNifEnv* env, + ESockDescriptor* descP, + ERL_NIF_TERM eVal) { ERL_NIF_TERM result; if (COMPARE(eVal, atom_null) == 0) { - return nsetopt_lvl_ip_msfilter_set(env, descP->sock, NULL, 0); + return esock_setopt_lvl_ip_msfilter_set(env, descP->sock, NULL, 0); } else { struct ip_msfilter* msfP; Uint32 msfSz; @@ -8880,7 +8906,8 @@ ERL_NIF_TERM nsetopt_lvl_ip_msfilter(ErlNifEnv* env, } /* And now, finally, set the option */ - result = nsetopt_lvl_ip_msfilter_set(env, descP->sock, msfP, msfSz); + result = esock_setopt_lvl_ip_msfilter_set(env, descP->sock, + msfP, msfSz); FREE(msfP); return result; } @@ -8910,10 +8937,10 @@ BOOLEAN_T decode_ip_msfilter_mode(ErlNifEnv* env, static -ERL_NIF_TERM nsetopt_lvl_ip_msfilter_set(ErlNifEnv* env, - SOCKET sock, - struct ip_msfilter* msfP, - SOCKLEN_T optLen) +ERL_NIF_TERM esock_setopt_lvl_ip_msfilter_set(ErlNifEnv* env, + SOCKET sock, + struct ip_msfilter* msfP, + SOCKLEN_T optLen) { ERL_NIF_TERM result; int res; @@ -8935,15 +8962,15 @@ ERL_NIF_TERM nsetopt_lvl_ip_msfilter_set(ErlNifEnv* env, -/* nsetopt_lvl_ip_mtu_discover - Level IP MTU_DISCOVER option +/* esock_setopt_lvl_ip_mtu_discover - Level IP MTU_DISCOVER option * * The value is an atom of the type ip_pmtudisc(). */ #if defined(IP_MTU_DISCOVER) static -ERL_NIF_TERM nsetopt_lvl_ip_mtu_discover(ErlNifEnv* env, - ESockDescriptor* descP, - ERL_NIF_TERM eVal) +ERL_NIF_TERM esock_setopt_lvl_ip_mtu_discover(ErlNifEnv* env, + ESockDescriptor* descP, + ERL_NIF_TERM eVal) { ERL_NIF_TERM result; int val; @@ -8976,13 +9003,13 @@ ERL_NIF_TERM nsetopt_lvl_ip_mtu_discover(ErlNifEnv* env, #endif -/* nsetopt_lvl_ip_multicast_all - Level IP MULTICAST_ALL option +/* esock_setopt_lvl_ip_multicast_all - Level IP MULTICAST_ALL option */ #if defined(IP_MULTICAST_ALL) static -ERL_NIF_TERM nsetopt_lvl_ip_multicast_all(ErlNifEnv* env, - ESockDescriptor* descP, - ERL_NIF_TERM eVal) +ERL_NIF_TERM esock_setopt_lvl_ip_multicast_all(ErlNifEnv* env, + ESockDescriptor* descP, + ERL_NIF_TERM eVal) { #if defined(SOL_IP) int level = SOL_IP; @@ -8990,20 +9017,20 @@ ERL_NIF_TERM nsetopt_lvl_ip_multicast_all(ErlNifEnv* env, int level = IPPROTO_IP; #endif - return nsetopt_bool_opt(env, descP, level, IP_MULTICAST_ALL, eVal); + return esock_setopt_bool_opt(env, descP, level, IP_MULTICAST_ALL, eVal); } #endif -/* nsetopt_lvl_ip_multicast_if - Level IP MULTICAST_IF option +/* esock_setopt_lvl_ip_multicast_if - Level IP MULTICAST_IF option * * The value is either the atom 'any' or a 4-tuple. */ #if defined(IP_MULTICAST_IF) static -ERL_NIF_TERM nsetopt_lvl_ip_multicast_if(ErlNifEnv* env, - ESockDescriptor* descP, - ERL_NIF_TERM eVal) +ERL_NIF_TERM esock_setopt_lvl_ip_multicast_if(ErlNifEnv* env, + ESockDescriptor* descP, + ERL_NIF_TERM eVal) { ERL_NIF_TERM result; struct in_addr ifAddr; @@ -9034,13 +9061,13 @@ ERL_NIF_TERM nsetopt_lvl_ip_multicast_if(ErlNifEnv* env, #endif -/* nsetopt_lvl_ip_multicast_loop - Level IP MULTICAST_LOOP option +/* esock_setopt_lvl_ip_multicast_loop - Level IP MULTICAST_LOOP option */ #if defined(IP_MULTICAST_LOOP) static -ERL_NIF_TERM nsetopt_lvl_ip_multicast_loop(ErlNifEnv* env, - ESockDescriptor* descP, - ERL_NIF_TERM eVal) +ERL_NIF_TERM esock_setopt_lvl_ip_multicast_loop(ErlNifEnv* env, + ESockDescriptor* descP, + ERL_NIF_TERM eVal) { #if defined(SOL_IP) int level = SOL_IP; @@ -9048,18 +9075,18 @@ ERL_NIF_TERM nsetopt_lvl_ip_multicast_loop(ErlNifEnv* env, int level = IPPROTO_IP; #endif - return nsetopt_bool_opt(env, descP, level, IP_MULTICAST_LOOP, eVal); + return esock_setopt_bool_opt(env, descP, level, IP_MULTICAST_LOOP, eVal); } #endif -/* nsetopt_lvl_ip_multicast_ttl - Level IP MULTICAST_TTL option +/* esock_setopt_lvl_ip_multicast_ttl - Level IP MULTICAST_TTL option */ #if defined(IP_MULTICAST_TTL) static -ERL_NIF_TERM nsetopt_lvl_ip_multicast_ttl(ErlNifEnv* env, - ESockDescriptor* descP, - ERL_NIF_TERM eVal) +ERL_NIF_TERM esock_setopt_lvl_ip_multicast_ttl(ErlNifEnv* env, + ESockDescriptor* descP, + ERL_NIF_TERM eVal) { #if defined(SOL_IP) int level = SOL_IP; @@ -9067,18 +9094,18 @@ ERL_NIF_TERM nsetopt_lvl_ip_multicast_ttl(ErlNifEnv* env, int level = IPPROTO_IP; #endif - return nsetopt_int_opt(env, descP, level, IP_MULTICAST_TTL, eVal); + return esock_setopt_int_opt(env, descP, level, IP_MULTICAST_TTL, eVal); } #endif -/* nsetopt_lvl_ip_nodefrag - Level IP NODEFRAG option +/* esock_setopt_lvl_ip_nodefrag - Level IP NODEFRAG option */ #if defined(IP_NODEFRAG) static -ERL_NIF_TERM nsetopt_lvl_ip_nodefrag(ErlNifEnv* env, - ESockDescriptor* descP, - ERL_NIF_TERM eVal) +ERL_NIF_TERM esock_setopt_lvl_ip_nodefrag(ErlNifEnv* env, + ESockDescriptor* descP, + ERL_NIF_TERM eVal) { #if defined(SOL_IP) int level = SOL_IP; @@ -9086,18 +9113,18 @@ ERL_NIF_TERM nsetopt_lvl_ip_nodefrag(ErlNifEnv* env, int level = IPPROTO_IP; #endif - return nsetopt_bool_opt(env, descP, level, IP_NODEFRAG, eVal); + return esock_setopt_bool_opt(env, descP, level, IP_NODEFRAG, eVal); } #endif -/* nsetopt_lvl_ip_pktinfo - Level IP PKTINFO option +/* esock_setopt_lvl_ip_pktinfo - Level IP PKTINFO option */ #if defined(IP_PKTINFO) static -ERL_NIF_TERM nsetopt_lvl_ip_pktinfo(ErlNifEnv* env, - ESockDescriptor* descP, - ERL_NIF_TERM eVal) +ERL_NIF_TERM esock_setopt_lvl_ip_pktinfo(ErlNifEnv* env, + ESockDescriptor* descP, + ERL_NIF_TERM eVal) { #if defined(SOL_IP) int level = SOL_IP; @@ -9105,18 +9132,18 @@ ERL_NIF_TERM nsetopt_lvl_ip_pktinfo(ErlNifEnv* env, int level = IPPROTO_IP; #endif - return nsetopt_bool_opt(env, descP, level, IP_PKTINFO, eVal); + return esock_setopt_bool_opt(env, descP, level, IP_PKTINFO, eVal); } #endif -/* nsetopt_lvl_ip_recvdstaddr - Level IP RECVDSTADDR option +/* esock_setopt_lvl_ip_recvdstaddr - Level IP RECVDSTADDR option */ #if defined(IP_RECVDSTADDR) static -ERL_NIF_TERM nsetopt_lvl_ip_recvdstaddr(ErlNifEnv* env, - ESockDescriptor* descP, - ERL_NIF_TERM eVal) +ERL_NIF_TERM esock_setopt_lvl_ip_recvdstaddr(ErlNifEnv* env, + ESockDescriptor* descP, + ERL_NIF_TERM eVal) { #if defined(SOL_IP) int level = SOL_IP; @@ -9124,18 +9151,18 @@ ERL_NIF_TERM nsetopt_lvl_ip_recvdstaddr(ErlNifEnv* env, int level = IPPROTO_IP; #endif - return nsetopt_bool_opt(env, descP, level, IP_RECVDSTADDR, eVal); + return esock_setopt_bool_opt(env, descP, level, IP_RECVDSTADDR, eVal); } #endif -/* nsetopt_lvl_ip_recverr - Level IP RECVERR option +/* esock_setopt_lvl_ip_recverr - Level IP RECVERR option */ #if defined(IP_RECVERR) static -ERL_NIF_TERM nsetopt_lvl_ip_recverr(ErlNifEnv* env, - ESockDescriptor* descP, - ERL_NIF_TERM eVal) +ERL_NIF_TERM esock_setopt_lvl_ip_recverr(ErlNifEnv* env, + ESockDescriptor* descP, + ERL_NIF_TERM eVal) { #if defined(SOL_IP) int level = SOL_IP; @@ -9143,18 +9170,18 @@ ERL_NIF_TERM nsetopt_lvl_ip_recverr(ErlNifEnv* env, int level = IPPROTO_IP; #endif - return nsetopt_bool_opt(env, descP, level, IP_RECVERR, eVal); + return esock_setopt_bool_opt(env, descP, level, IP_RECVERR, eVal); } #endif -/* nsetopt_lvl_ip_recvif - Level IP RECVIF option +/* esock_setopt_lvl_ip_recvif - Level IP RECVIF option */ #if defined(IP_RECVIF) static -ERL_NIF_TERM nsetopt_lvl_ip_recvif(ErlNifEnv* env, - ESockDescriptor* descP, - ERL_NIF_TERM eVal) +ERL_NIF_TERM esock_setopt_lvl_ip_recvif(ErlNifEnv* env, + ESockDescriptor* descP, + ERL_NIF_TERM eVal) { #if defined(SOL_IP) int level = SOL_IP; @@ -9162,18 +9189,18 @@ ERL_NIF_TERM nsetopt_lvl_ip_recvif(ErlNifEnv* env, int level = IPPROTO_IP; #endif - return nsetopt_bool_opt(env, descP, level, IP_RECVIF, eVal); + return esock_setopt_bool_opt(env, descP, level, IP_RECVIF, eVal); } #endif -/* nsetopt_lvl_ip_recvopts - Level IP RECVOPTS option +/* esock_setopt_lvl_ip_recvopts - Level IP RECVOPTS option */ #if defined(IP_RECVOPTS) static -ERL_NIF_TERM nsetopt_lvl_ip_recvopts(ErlNifEnv* env, - ESockDescriptor* descP, - ERL_NIF_TERM eVal) +ERL_NIF_TERM esock_setopt_lvl_ip_recvopts(ErlNifEnv* env, + ESockDescriptor* descP, + ERL_NIF_TERM eVal) { #if defined(SOL_IP) int level = SOL_IP; @@ -9181,18 +9208,18 @@ ERL_NIF_TERM nsetopt_lvl_ip_recvopts(ErlNifEnv* env, int level = IPPROTO_IP; #endif - return nsetopt_bool_opt(env, descP, level, IP_RECVOPTS, eVal); + return esock_setopt_bool_opt(env, descP, level, IP_RECVOPTS, eVal); } #endif -/* nsetopt_lvl_ip_recvorigdstaddr - Level IP RECVORIGDSTADDR option +/* esock_setopt_lvl_ip_recvorigdstaddr - Level IP RECVORIGDSTADDR option */ #if defined(IP_RECVORIGDSTADDR) static -ERL_NIF_TERM nsetopt_lvl_ip_recvorigdstaddr(ErlNifEnv* env, - ESockDescriptor* descP, - ERL_NIF_TERM eVal) +ERL_NIF_TERM esock_setopt_lvl_ip_recvorigdstaddr(ErlNifEnv* env, + ESockDescriptor* descP, + ERL_NIF_TERM eVal) { #if defined(SOL_IP) int level = SOL_IP; @@ -9200,18 +9227,18 @@ ERL_NIF_TERM nsetopt_lvl_ip_recvorigdstaddr(ErlNifEnv* env, int level = IPPROTO_IP; #endif - return nsetopt_bool_opt(env, descP, level, IP_RECVORIGDSTADDR, eVal); + return esock_setopt_bool_opt(env, descP, level, IP_RECVORIGDSTADDR, eVal); } #endif -/* nsetopt_lvl_ip_recvtos - Level IP RECVTOS option +/* esock_setopt_lvl_ip_recvtos - Level IP RECVTOS option */ #if defined(IP_RECVTOS) static -ERL_NIF_TERM nsetopt_lvl_ip_recvtos(ErlNifEnv* env, - ESockDescriptor* descP, - ERL_NIF_TERM eVal) +ERL_NIF_TERM esock_setopt_lvl_ip_recvtos(ErlNifEnv* env, + ESockDescriptor* descP, + ERL_NIF_TERM eVal) { #if defined(SOL_IP) int level = SOL_IP; @@ -9219,18 +9246,18 @@ ERL_NIF_TERM nsetopt_lvl_ip_recvtos(ErlNifEnv* env, int level = IPPROTO_IP; #endif - return nsetopt_bool_opt(env, descP, level, IP_RECVTOS, eVal); + return esock_setopt_bool_opt(env, descP, level, IP_RECVTOS, eVal); } #endif -/* nsetopt_lvl_ip_recvttl - Level IP RECVTTL option +/* esock_setopt_lvl_ip_recvttl - Level IP RECVTTL option */ #if defined(IP_RECVTTL) static -ERL_NIF_TERM nsetopt_lvl_ip_recvttl(ErlNifEnv* env, - ESockDescriptor* descP, - ERL_NIF_TERM eVal) +ERL_NIF_TERM esock_setopt_lvl_ip_recvttl(ErlNifEnv* env, + ESockDescriptor* descP, + ERL_NIF_TERM eVal) { #if defined(SOL_IP) int level = SOL_IP; @@ -9238,18 +9265,18 @@ ERL_NIF_TERM nsetopt_lvl_ip_recvttl(ErlNifEnv* env, int level = IPPROTO_IP; #endif - return nsetopt_bool_opt(env, descP, level, IP_RECVTTL, eVal); + return esock_setopt_bool_opt(env, descP, level, IP_RECVTTL, eVal); } #endif -/* nsetopt_lvl_ip_retopts - Level IP RETOPTS option +/* esock_setopt_lvl_ip_retopts - Level IP RETOPTS option */ #if defined(IP_RETOPTS) static -ERL_NIF_TERM nsetopt_lvl_ip_retopts(ErlNifEnv* env, - ESockDescriptor* descP, - ERL_NIF_TERM eVal) +ERL_NIF_TERM esock_setopt_lvl_ip_retopts(ErlNifEnv* env, + ESockDescriptor* descP, + ERL_NIF_TERM eVal) { #if defined(SOL_IP) int level = SOL_IP; @@ -9257,18 +9284,18 @@ ERL_NIF_TERM nsetopt_lvl_ip_retopts(ErlNifEnv* env, int level = IPPROTO_IP; #endif - return nsetopt_bool_opt(env, descP, level, IP_RETOPTS, eVal); + return esock_setopt_bool_opt(env, descP, level, IP_RETOPTS, eVal); } #endif -/* nsetopt_lvl_ip_router_alert - Level IP ROUTER_ALERT option +/* esock_setopt_lvl_ip_router_alert - Level IP ROUTER_ALERT option */ #if defined(IP_ROUTER_ALERT) static -ERL_NIF_TERM nsetopt_lvl_ip_router_alert(ErlNifEnv* env, - ESockDescriptor* descP, - ERL_NIF_TERM eVal) +ERL_NIF_TERM esock_setopt_lvl_ip_router_alert(ErlNifEnv* env, + ESockDescriptor* descP, + ERL_NIF_TERM eVal) { #if defined(SOL_IP) int level = SOL_IP; @@ -9276,18 +9303,18 @@ ERL_NIF_TERM nsetopt_lvl_ip_router_alert(ErlNifEnv* env, int level = IPPROTO_IP; #endif - return nsetopt_int_opt(env, descP, level, IP_ROUTER_ALERT, eVal); + return esock_setopt_int_opt(env, descP, level, IP_ROUTER_ALERT, eVal); } #endif -/* nsetopt_lvl_ip_sendsrcaddr - Level IP SENDSRCADDR option +/* esock_setopt_lvl_ip_sendsrcaddr - Level IP SENDSRCADDR option */ #if defined(IP_SENDSRCADDR) static -ERL_NIF_TERM nsetopt_lvl_ip_sendsrcaddr(ErlNifEnv* env, - ESockDescriptor* descP, - ERL_NIF_TERM eVal) +ERL_NIF_TERM esock_setopt_lvl_ip_sendsrcaddr(ErlNifEnv* env, + ESockDescriptor* descP, + ERL_NIF_TERM eVal) { #if defined(SOL_IP) int level = SOL_IP; @@ -9295,18 +9322,18 @@ ERL_NIF_TERM nsetopt_lvl_ip_sendsrcaddr(ErlNifEnv* env, int level = IPPROTO_IP; #endif - return nsetopt_bool_opt(env, descP, level, IP_SENDSRCADDR, eVal); + return esock_setopt_bool_opt(env, descP, level, IP_SENDSRCADDR, eVal); } #endif -/* nsetopt_lvl_ip_tos - Level IP TOS option +/* esock_setopt_lvl_ip_tos - Level IP TOS option */ #if defined(IP_TOS) static -ERL_NIF_TERM nsetopt_lvl_ip_tos(ErlNifEnv* env, - ESockDescriptor* descP, - ERL_NIF_TERM eVal) +ERL_NIF_TERM esock_setopt_lvl_ip_tos(ErlNifEnv* env, + ESockDescriptor* descP, + ERL_NIF_TERM eVal) { #if defined(SOL_IP) int level = SOL_IP; @@ -9333,13 +9360,13 @@ ERL_NIF_TERM nsetopt_lvl_ip_tos(ErlNifEnv* env, #endif -/* nsetopt_lvl_ip_transparent - Level IP TRANSPARENT option +/* esock_setopt_lvl_ip_transparent - Level IP TRANSPARENT option */ #if defined(IP_TRANSPARENT) static -ERL_NIF_TERM nsetopt_lvl_ip_transparent(ErlNifEnv* env, - ESockDescriptor* descP, - ERL_NIF_TERM eVal) +ERL_NIF_TERM esock_setopt_lvl_ip_transparent(ErlNifEnv* env, + ESockDescriptor* descP, + ERL_NIF_TERM eVal) { #if defined(SOL_IP) int level = SOL_IP; @@ -9347,19 +9374,19 @@ ERL_NIF_TERM nsetopt_lvl_ip_transparent(ErlNifEnv* env, int level = IPPROTO_IP; #endif - return nsetopt_bool_opt(env, descP, level, IP_TRANSPARENT, eVal); + return esock_setopt_bool_opt(env, descP, level, IP_TRANSPARENT, eVal); } #endif -/* nsetopt_lvl_ip_ttl - Level IP TTL option +/* esock_setopt_lvl_ip_ttl - Level IP TTL option */ #if defined(IP_TTL) static -ERL_NIF_TERM nsetopt_lvl_ip_ttl(ErlNifEnv* env, - ESockDescriptor* descP, - ERL_NIF_TERM eVal) +ERL_NIF_TERM esock_setopt_lvl_ip_ttl(ErlNifEnv* env, + ESockDescriptor* descP, + ERL_NIF_TERM eVal) { #if defined(SOL_IP) int level = SOL_IP; @@ -9367,13 +9394,13 @@ ERL_NIF_TERM nsetopt_lvl_ip_ttl(ErlNifEnv* env, int level = IPPROTO_IP; #endif - return nsetopt_int_opt(env, descP, level, IP_TTL, eVal); + return esock_setopt_int_opt(env, descP, level, IP_TTL, eVal); } #endif -/* nsetopt_lvl_ip_unblock_source - Level IP UNBLOCK_SOURCE option +/* esock_setopt_lvl_ip_unblock_source - Level IP UNBLOCK_SOURCE option * * The value is a map with three attributes: multiaddr, interface and * sourceaddr. @@ -9384,11 +9411,12 @@ ERL_NIF_TERM nsetopt_lvl_ip_ttl(ErlNifEnv* env, */ #if defined(IP_UNBLOCK_SOURCE) static -ERL_NIF_TERM nsetopt_lvl_ip_unblock_source(ErlNifEnv* env, - ESockDescriptor* descP, - ERL_NIF_TERM eVal) +ERL_NIF_TERM esock_setopt_lvl_ip_unblock_source(ErlNifEnv* env, + ESockDescriptor* descP, + ERL_NIF_TERM eVal) { - return nsetopt_lvl_ip_update_source(env, descP, eVal, IP_UNBLOCK_SOURCE); + return esock_setopt_lvl_ip_update_source(env, descP, eVal, + IP_UNBLOCK_SOURCE); } #endif @@ -9396,10 +9424,10 @@ ERL_NIF_TERM nsetopt_lvl_ip_unblock_source(ErlNifEnv* env, #if defined(IP_ADD_MEMBERSHIP) || defined(IP_DROP_MEMBERSHIP) static -ERL_NIF_TERM nsetopt_lvl_ip_update_membership(ErlNifEnv* env, - ESockDescriptor* descP, - ERL_NIF_TERM eVal, - int opt) +ERL_NIF_TERM esock_setopt_lvl_ip_update_membership(ErlNifEnv* env, + ESockDescriptor* descP, + ERL_NIF_TERM eVal, + int opt) { ERL_NIF_TERM result, eMultiAddr, eInterface; struct ip_mreq mreq; @@ -9415,7 +9443,7 @@ ERL_NIF_TERM nsetopt_lvl_ip_update_membership(ErlNifEnv* env, // It must be a map if (!IS_MAP(env, eVal)) { SSDBG( descP, - ("SOCKET", "nsetopt_lvl_ip_update_membership -> " + ("SOCKET", "esock_setopt_lvl_ip_update_membership -> " "value *not* a map\r\n") ); return enif_make_badarg(env); } @@ -9423,21 +9451,21 @@ ERL_NIF_TERM nsetopt_lvl_ip_update_membership(ErlNifEnv* env, // It must have atleast two attributes if (!enif_get_map_size(env, eVal, &sz) || (sz < 2)) { SSDBG( descP, - ("SOCKET", "nsetopt_lvl_ip_update_membership -> " + ("SOCKET", "esock_setopt_lvl_ip_update_membership -> " "invalid map value: %T\r\n", eVal) ); return enif_make_badarg(env); } if (!GET_MAP_VAL(env, eVal, atom_multiaddr, &eMultiAddr)) { SSDBG( descP, - ("SOCKET", "nsetopt_lvl_ip_update_membership -> " + ("SOCKET", "esock_setopt_lvl_ip_update_membership -> " "failed get multiaddr (map) attribute\r\n") ); return enif_make_badarg(env); } if (!GET_MAP_VAL(env, eVal, atom_interface, &eInterface)) { SSDBG( descP, - ("SOCKET", "nsetopt_lvl_ip_update_membership -> " + ("SOCKET", "esock_setopt_lvl_ip_update_membership -> " "failed get interface (map) attribute\r\n") ); return enif_make_badarg(env); } @@ -9446,7 +9474,7 @@ ERL_NIF_TERM nsetopt_lvl_ip_update_membership(ErlNifEnv* env, eMultiAddr, &mreq.imr_multiaddr)) != NULL) { SSDBG( descP, - ("SOCKET", "nsetopt_lvl_ip_update_membership -> " + ("SOCKET", "esock_setopt_lvl_ip_update_membership -> " "failed decode multiaddr %T: %s\r\n", eMultiAddr, xres) ); return esock_make_error_str(env, xres); } @@ -9455,7 +9483,7 @@ ERL_NIF_TERM nsetopt_lvl_ip_update_membership(ErlNifEnv* env, eInterface, &mreq.imr_interface)) != NULL) { SSDBG( descP, - ("SOCKET", "nsetopt_lvl_ip_update_membership -> " + ("SOCKET", "esock_setopt_lvl_ip_update_membership -> " "failed decode interface %T: %s\r\n", eInterface, xres) ); return esock_make_error_str(env, xres); } @@ -9468,7 +9496,7 @@ ERL_NIF_TERM nsetopt_lvl_ip_update_membership(ErlNifEnv* env, result = esock_make_error_errno(env, save_errno); SSDBG( descP, - ("SOCKET", "nsetopt_lvl_ip_update_membership -> " + ("SOCKET", "esock_setopt_lvl_ip_update_membership -> " "failed setopt: %T (%d)\r\n", result, save_errno) ); } else { @@ -9482,10 +9510,10 @@ ERL_NIF_TERM nsetopt_lvl_ip_update_membership(ErlNifEnv* env, #if defined(IP_ADD_SOURCE_MEMBERSHIP) || defined(IP_DROP_SOURCE_MEMBERSHIP) || defined(IP_BLOCK_SOURCE) || defined(IP_UNBLOCK_SOURCE) static -ERL_NIF_TERM nsetopt_lvl_ip_update_source(ErlNifEnv* env, - ESockDescriptor* descP, - ERL_NIF_TERM eVal, - int opt) +ERL_NIF_TERM esock_setopt_lvl_ip_update_source(ErlNifEnv* env, + ESockDescriptor* descP, + ERL_NIF_TERM eVal, + int opt) { ERL_NIF_TERM result, eMultiAddr, eInterface, eSourceAddr; struct ip_mreq_source mreq; @@ -9545,146 +9573,147 @@ ERL_NIF_TERM nsetopt_lvl_ip_update_source(ErlNifEnv* env, /* *** Handling set of socket options for level = ipv6 *** */ -/* nsetopt_lvl_ipv6 - Level *IPv6* option(s) +/* esock_setopt_lvl_ipv6 - Level *IPv6* option(s) */ #if defined(HAVE_IPV6) static -ERL_NIF_TERM nsetopt_lvl_ipv6(ErlNifEnv* env, - ESockDescriptor* descP, - int eOpt, - ERL_NIF_TERM eVal) +ERL_NIF_TERM esock_setopt_lvl_ipv6(ErlNifEnv* env, + ESockDescriptor* descP, + int eOpt, + ERL_NIF_TERM eVal) { ERL_NIF_TERM result; SSDBG( descP, - ("SOCKET", "nsetopt_lvl_ipv6 -> entry with" + ("SOCKET", "esock_setopt_lvl_ipv6 -> entry with" "\r\n opt: %d" "\r\n", eOpt) ); switch (eOpt) { #if defined(IPV6_ADDRFORM) - case SOCKET_OPT_IPV6_ADDRFORM: - result = nsetopt_lvl_ipv6_addrform(env, descP, eVal); + case ESOCK_OPT_IPV6_ADDRFORM: + result = esock_setopt_lvl_ipv6_addrform(env, descP, eVal); break; #endif #if defined(IPV6_ADD_MEMBERSHIP) - case SOCKET_OPT_IPV6_ADD_MEMBERSHIP: - result = nsetopt_lvl_ipv6_add_membership(env, descP, eVal); + case ESOCK_OPT_IPV6_ADD_MEMBERSHIP: + result = esock_setopt_lvl_ipv6_add_membership(env, descP, eVal); break; #endif #if defined(IPV6_AUTHHDR) - case SOCKET_OPT_IPV6_AUTHHDR: - result = nsetopt_lvl_ipv6_authhdr(env, descP, eVal); + case ESOCK_OPT_IPV6_AUTHHDR: + result = esock_setopt_lvl_ipv6_authhdr(env, descP, eVal); break; #endif #if defined(IPV6_DROP_MEMBERSHIP) - case SOCKET_OPT_IPV6_DROP_MEMBERSHIP: - result = nsetopt_lvl_ipv6_drop_membership(env, descP, eVal); + case ESOCK_OPT_IPV6_DROP_MEMBERSHIP: + result = esock_setopt_lvl_ipv6_drop_membership(env, descP, eVal); break; #endif #if defined(IPV6_DSTOPTS) - case SOCKET_OPT_IPV6_DSTOPTS: - result = nsetopt_lvl_ipv6_dstopts(env, descP, eVal); + case ESOCK_OPT_IPV6_DSTOPTS: + result = esock_setopt_lvl_ipv6_dstopts(env, descP, eVal); break; #endif #if defined(IPV6_FLOWINFO) - case SOCKET_OPT_IPV6_FLOWINFO: - result = nsetopt_lvl_ipv6_flowinfo(env, descP, eVal); + case ESOCK_OPT_IPV6_FLOWINFO: + result = esock_setopt_lvl_ipv6_flowinfo(env, descP, eVal); break; #endif #if defined(IPV6_HOPLIMIT) - case SOCKET_OPT_IPV6_HOPLIMIT: - result = nsetopt_lvl_ipv6_hoplimit(env, descP, eVal); + case ESOCK_OPT_IPV6_HOPLIMIT: + result = esock_setopt_lvl_ipv6_hoplimit(env, descP, eVal); break; #endif #if defined(IPV6_HOPOPTS) - case SOCKET_OPT_IPV6_HOPOPTS: - result = nsetopt_lvl_ipv6_hopopts(env, descP, eVal); + case ESOCK_OPT_IPV6_HOPOPTS: + result = esock_setopt_lvl_ipv6_hopopts(env, descP, eVal); break; #endif #if defined(IPV6_MTU) - case SOCKET_OPT_IPV6_MTU: - result = nsetopt_lvl_ipv6_mtu(env, descP, eVal); + case ESOCK_OPT_IPV6_MTU: + result = esock_setopt_lvl_ipv6_mtu(env, descP, eVal); break; #endif #if defined(IPV6_MTU_DISCOVER) - case SOCKET_OPT_IPV6_MTU_DISCOVER: - result = nsetopt_lvl_ipv6_mtu_discover(env, descP, eVal); + case ESOCK_OPT_IPV6_MTU_DISCOVER: + result = esock_setopt_lvl_ipv6_mtu_discover(env, descP, eVal); break; #endif #if defined(IPV6_MULTICAST_HOPS) - case SOCKET_OPT_IPV6_MULTICAST_HOPS: - result = nsetopt_lvl_ipv6_multicast_hops(env, descP, eVal); + case ESOCK_OPT_IPV6_MULTICAST_HOPS: + result = esock_setopt_lvl_ipv6_multicast_hops(env, descP, eVal); break; #endif #if defined(IPV6_MULTICAST_IF) - case SOCKET_OPT_IPV6_MULTICAST_IF: - result = nsetopt_lvl_ipv6_multicast_if(env, descP, eVal); + case ESOCK_OPT_IPV6_MULTICAST_IF: + result = esock_setopt_lvl_ipv6_multicast_if(env, descP, eVal); break; #endif #if defined(IPV6_MULTICAST_LOOP) - case SOCKET_OPT_IPV6_MULTICAST_LOOP: - result = nsetopt_lvl_ipv6_multicast_loop(env, descP, eVal); + case ESOCK_OPT_IPV6_MULTICAST_LOOP: + result = esock_setopt_lvl_ipv6_multicast_loop(env, descP, eVal); break; #endif #if defined(IPV6_RECVERR) - case SOCKET_OPT_IPV6_RECVERR: - result = nsetopt_lvl_ipv6_recverr(env, descP, eVal); + case ESOCK_OPT_IPV6_RECVERR: + result = esock_setopt_lvl_ipv6_recverr(env, descP, eVal); break; #endif #if defined(IPV6_RECVPKTINFO) || defined(IPV6_PKTINFO) - case SOCKET_OPT_IPV6_RECVPKTINFO: - result = nsetopt_lvl_ipv6_recvpktinfo(env, descP, eVal); + case ESOCK_OPT_IPV6_RECVPKTINFO: + result = esock_setopt_lvl_ipv6_recvpktinfo(env, descP, eVal); break; #endif #if defined(IPV6_ROUTER_ALERT) - case SOCKET_OPT_IPV6_ROUTER_ALERT: - result = nsetopt_lvl_ipv6_router_alert(env, descP, eVal); + case ESOCK_OPT_IPV6_ROUTER_ALERT: + result = esock_setopt_lvl_ipv6_router_alert(env, descP, eVal); break; #endif #if defined(IPV6_RTHDR) - case SOCKET_OPT_IPV6_RTHDR: - result = nsetopt_lvl_ipv6_rthdr(env, descP, eVal); + case ESOCK_OPT_IPV6_RTHDR: + result = esock_setopt_lvl_ipv6_rthdr(env, descP, eVal); break; #endif #if defined(IPV6_UNICAST_HOPS) - case SOCKET_OPT_IPV6_UNICAST_HOPS: - result = nsetopt_lvl_ipv6_unicast_hops(env, descP, eVal); + case ESOCK_OPT_IPV6_UNICAST_HOPS: + result = esock_setopt_lvl_ipv6_unicast_hops(env, descP, eVal); break; #endif #if defined(IPV6_V6ONLY) - case SOCKET_OPT_IPV6_V6ONLY: - result = nsetopt_lvl_ipv6_v6only(env, descP, eVal); + case ESOCK_OPT_IPV6_V6ONLY: + result = esock_setopt_lvl_ipv6_v6only(env, descP, eVal); break; #endif default: SSDBG( descP, - ("SOCKET", "nsetopt_lvl_ipv6 -> unknown opt (%d)\r\n", eOpt) ); + ("SOCKET", + "esock_setopt_lvl_ipv6 -> unknown opt (%d)\r\n", eOpt) ); result = esock_make_error(env, esock_atom_einval); break; } SSDBG( descP, - ("SOCKET", "nsetopt_lvl_ipv6 -> done when" + ("SOCKET", "esock_setopt_lvl_ipv6 -> done when" "\r\n result: %T" "\r\n", result) ); @@ -9694,15 +9723,15 @@ ERL_NIF_TERM nsetopt_lvl_ipv6(ErlNifEnv* env, #if defined(IPV6_ADDRFORM) static -ERL_NIF_TERM nsetopt_lvl_ipv6_addrform(ErlNifEnv* env, - ESockDescriptor* descP, - ERL_NIF_TERM eVal) +ERL_NIF_TERM esock_setopt_lvl_ipv6_addrform(ErlNifEnv* env, + ESockDescriptor* descP, + ERL_NIF_TERM eVal) { ERL_NIF_TERM result; int res, edomain, domain; SSDBG( descP, - ("SOCKET", "nsetopt_lvl_ipv6_addrform -> entry with" + ("SOCKET", "esock_setopt_lvl_ipv6_addrform -> entry with" "\r\n eVal: %T" "\r\n", eVal) ); @@ -9710,14 +9739,15 @@ ERL_NIF_TERM nsetopt_lvl_ipv6_addrform(ErlNifEnv* env, return esock_make_error(env, esock_atom_einval); SSDBG( descP, - ("SOCKET", "nsetopt_lvl_ipv6_addrform -> decode" + ("SOCKET", "esock_setopt_lvl_ipv6_addrform -> decode" "\r\n edomain: %d" "\r\n", edomain) ); if (!edomain2domain(edomain, &domain)) return esock_make_error(env, esock_atom_einval); - SSDBG( descP, ("SOCKET", "nsetopt_lvl_ipv6_addrform -> try set opt to %d\r\n", + SSDBG( descP, ("SOCKET", + "esock_setopt_lvl_ipv6_addrform -> try set opt to %d\r\n", domain) ); res = socket_setopt(descP->sock, @@ -9740,11 +9770,11 @@ ERL_NIF_TERM nsetopt_lvl_ipv6_addrform(ErlNifEnv* env, #if defined(IPV6_ADD_MEMBERSHIP) static -ERL_NIF_TERM nsetopt_lvl_ipv6_add_membership(ErlNifEnv* env, - ESockDescriptor* descP, - ERL_NIF_TERM eVal) +ERL_NIF_TERM esock_setopt_lvl_ipv6_add_membership(ErlNifEnv* env, + ESockDescriptor* descP, + ERL_NIF_TERM eVal) { - return nsetopt_lvl_ipv6_update_membership(env, descP, eVal, + return esock_setopt_lvl_ipv6_update_membership(env, descP, eVal, IPV6_ADD_MEMBERSHIP); } #endif @@ -9752,28 +9782,29 @@ ERL_NIF_TERM nsetopt_lvl_ipv6_add_membership(ErlNifEnv* env, #if defined(IPV6_AUTHHDR) static -ERL_NIF_TERM nsetopt_lvl_ipv6_authhdr(ErlNifEnv* env, - ESockDescriptor* descP, - ERL_NIF_TERM eVal) +ERL_NIF_TERM esock_setopt_lvl_ipv6_authhdr(ErlNifEnv* env, + ESockDescriptor* descP, + ERL_NIF_TERM eVal) { - return nsetopt_bool_opt(env, descP, #if defined(SOL_IPV6) - SOL_IPV6, + int level = SOL_IPV6; #else - IPPROTO_IPV6, + int level = IPPROTO_IPV6; #endif - IPV6_AUTHHDR, eVal); + + + return esock_setopt_bool_opt(env, descP, level, IPV6_AUTHHDR, eVal); } #endif #if defined(IPV6_DROP_MEMBERSHIP) static -ERL_NIF_TERM nsetopt_lvl_ipv6_drop_membership(ErlNifEnv* env, - ESockDescriptor* descP, - ERL_NIF_TERM eVal) +ERL_NIF_TERM esock_setopt_lvl_ipv6_drop_membership(ErlNifEnv* env, + ESockDescriptor* descP, + ERL_NIF_TERM eVal) { - return nsetopt_lvl_ipv6_update_membership(env, descP, eVal, + return esock_setopt_lvl_ipv6_update_membership(env, descP, eVal, IPV6_DROP_MEMBERSHIP); } #endif @@ -9781,9 +9812,9 @@ ERL_NIF_TERM nsetopt_lvl_ipv6_drop_membership(ErlNifEnv* env, #if defined(IPV6_DSTOPTS) static -ERL_NIF_TERM nsetopt_lvl_ipv6_dstopts(ErlNifEnv* env, - ESockDescriptor* descP, - ERL_NIF_TERM eVal) +ERL_NIF_TERM esock_setopt_lvl_ipv6_dstopts(ErlNifEnv* env, + ESockDescriptor* descP, + ERL_NIF_TERM eVal) { #if defined(SOL_IPV6) int level = SOL_IPV6; @@ -9791,16 +9822,16 @@ ERL_NIF_TERM nsetopt_lvl_ipv6_dstopts(ErlNifEnv* env, int level = IPPROTO_IPV6; #endif - return nsetopt_bool_opt(env, descP, level, IPV6_DSTOPTS, eVal); + return esock_setopt_bool_opt(env, descP, level, IPV6_DSTOPTS, eVal); } #endif #if defined(IPV6_FLOWINFO) static -ERL_NIF_TERM nsetopt_lvl_ipv6_flowinfo(ErlNifEnv* env, - ESockDescriptor* descP, - ERL_NIF_TERM eVal) +ERL_NIF_TERM esock_setopt_lvl_ipv6_flowinfo(ErlNifEnv* env, + ESockDescriptor* descP, + ERL_NIF_TERM eVal) { #if defined(SOL_IPV6) int level = SOL_IPV6; @@ -9808,16 +9839,16 @@ ERL_NIF_TERM nsetopt_lvl_ipv6_flowinfo(ErlNifEnv* env, int level = IPPROTO_IPV6; #endif - return nsetopt_bool_opt(env, descP, level, IPV6_FLOWINFO, eVal); + return esock_setopt_bool_opt(env, descP, level, IPV6_FLOWINFO, eVal); } #endif #if defined(IPV6_HOPLIMIT) static -ERL_NIF_TERM nsetopt_lvl_ipv6_hoplimit(ErlNifEnv* env, - ESockDescriptor* descP, - ERL_NIF_TERM eVal) +ERL_NIF_TERM esock_setopt_lvl_ipv6_hoplimit(ErlNifEnv* env, + ESockDescriptor* descP, + ERL_NIF_TERM eVal) { #if defined(SOL_IPV6) int level = SOL_IPV6; @@ -9825,16 +9856,16 @@ ERL_NIF_TERM nsetopt_lvl_ipv6_hoplimit(ErlNifEnv* env, int level = IPPROTO_IPV6; #endif - return nsetopt_bool_opt(env, descP, level, IPV6_HOPLIMIT, eVal); + return esock_setopt_bool_opt(env, descP, level, IPV6_HOPLIMIT, eVal); } #endif #if defined(IPV6_HOPOPTS) static -ERL_NIF_TERM nsetopt_lvl_ipv6_hopopts(ErlNifEnv* env, - ESockDescriptor* descP, - ERL_NIF_TERM eVal) +ERL_NIF_TERM esock_setopt_lvl_ipv6_hopopts(ErlNifEnv* env, + ESockDescriptor* descP, + ERL_NIF_TERM eVal) { #if defined(SOL_IPV6) int level = SOL_IPV6; @@ -9842,14 +9873,14 @@ ERL_NIF_TERM nsetopt_lvl_ipv6_hopopts(ErlNifEnv* env, int level = IPPROTO_IPV6; #endif - return nsetopt_bool_opt(env, descP, level, IPV6_HOPOPTS, eVal); + return esock_setopt_bool_opt(env, descP, level, IPV6_HOPOPTS, eVal); } #endif #if defined(IPV6_MTU) static -ERL_NIF_TERM nsetopt_lvl_ipv6_mtu(ErlNifEnv* env, +ERL_NIF_TERM esock_setopt_lvl_ipv6_mtu(ErlNifEnv* env, ESockDescriptor* descP, ERL_NIF_TERM eVal) { @@ -9859,20 +9890,20 @@ ERL_NIF_TERM nsetopt_lvl_ipv6_mtu(ErlNifEnv* env, int level = IPPROTO_IPV6; #endif - return nsetopt_int_opt(env, descP, level, IPV6_MTU, eVal); + return esock_setopt_int_opt(env, descP, level, IPV6_MTU, eVal); } #endif -/* nsetopt_lvl_ipv6_mtu_discover - Level IPv6 MTU_DISCOVER option +/* esock_setopt_lvl_ipv6_mtu_discover - Level IPv6 MTU_DISCOVER option * * The value is an atom of the type ipv6_pmtudisc(). */ #if defined(IPV6_MTU_DISCOVER) static -ERL_NIF_TERM nsetopt_lvl_ipv6_mtu_discover(ErlNifEnv* env, - ESockDescriptor* descP, - ERL_NIF_TERM eVal) +ERL_NIF_TERM esock_setopt_lvl_ipv6_mtu_discover(ErlNifEnv* env, + ESockDescriptor* descP, + ERL_NIF_TERM eVal) { ERL_NIF_TERM result; int val; @@ -9908,9 +9939,9 @@ ERL_NIF_TERM nsetopt_lvl_ipv6_mtu_discover(ErlNifEnv* env, #if defined(IPV6_MULTICAST_HOPS) static -ERL_NIF_TERM nsetopt_lvl_ipv6_multicast_hops(ErlNifEnv* env, - ESockDescriptor* descP, - ERL_NIF_TERM eVal) +ERL_NIF_TERM esock_setopt_lvl_ipv6_multicast_hops(ErlNifEnv* env, + ESockDescriptor* descP, + ERL_NIF_TERM eVal) { #if defined(SOL_IPV6) int level = SOL_IPV6; @@ -9918,7 +9949,7 @@ ERL_NIF_TERM nsetopt_lvl_ipv6_multicast_hops(ErlNifEnv* env, int level = IPPROTO_IPV6; #endif - return nsetopt_int_opt(env, descP, level, IPV6_MULTICAST_HOPS, eVal); + return esock_setopt_int_opt(env, descP, level, IPV6_MULTICAST_HOPS, eVal); } #endif @@ -9926,9 +9957,9 @@ ERL_NIF_TERM nsetopt_lvl_ipv6_multicast_hops(ErlNifEnv* env, #if defined(IPV6_MULTICAST_IF) static -ERL_NIF_TERM nsetopt_lvl_ipv6_multicast_if(ErlNifEnv* env, - ESockDescriptor* descP, - ERL_NIF_TERM eVal) +ERL_NIF_TERM esock_setopt_lvl_ipv6_multicast_if(ErlNifEnv* env, + ESockDescriptor* descP, + ERL_NIF_TERM eVal) { #if defined(SOL_IPV6) int level = SOL_IPV6; @@ -9936,7 +9967,7 @@ ERL_NIF_TERM nsetopt_lvl_ipv6_multicast_if(ErlNifEnv* env, int level = IPPROTO_IPV6; #endif - return nsetopt_int_opt(env, descP, level, IPV6_MULTICAST_IF, eVal); + return esock_setopt_int_opt(env, descP, level, IPV6_MULTICAST_IF, eVal); } #endif @@ -9944,9 +9975,9 @@ ERL_NIF_TERM nsetopt_lvl_ipv6_multicast_if(ErlNifEnv* env, #if defined(IPV6_MULTICAST_LOOP) static -ERL_NIF_TERM nsetopt_lvl_ipv6_multicast_loop(ErlNifEnv* env, - ESockDescriptor* descP, - ERL_NIF_TERM eVal) +ERL_NIF_TERM esock_setopt_lvl_ipv6_multicast_loop(ErlNifEnv* env, + ESockDescriptor* descP, + ERL_NIF_TERM eVal) { #if defined(SOL_IPV6) int level = SOL_IPV6; @@ -9954,16 +9985,16 @@ ERL_NIF_TERM nsetopt_lvl_ipv6_multicast_loop(ErlNifEnv* env, int level = IPPROTO_IPV6; #endif - return nsetopt_bool_opt(env, descP, level, IPV6_MULTICAST_LOOP, eVal); + return esock_setopt_bool_opt(env, descP, level, IPV6_MULTICAST_LOOP, eVal); } #endif #if defined(IPV6_RECVERR) static -ERL_NIF_TERM nsetopt_lvl_ipv6_recverr(ErlNifEnv* env, - ESockDescriptor* descP, - ERL_NIF_TERM eVal) +ERL_NIF_TERM esock_setopt_lvl_ipv6_recverr(ErlNifEnv* env, + ESockDescriptor* descP, + ERL_NIF_TERM eVal) { #if defined(SOL_IPV6) int level = SOL_IPV6; @@ -9971,16 +10002,16 @@ ERL_NIF_TERM nsetopt_lvl_ipv6_recverr(ErlNifEnv* env, int level = IPPROTO_IPV6; #endif - return nsetopt_bool_opt(env, descP, level, IPV6_RECVERR, eVal); + return esock_setopt_bool_opt(env, descP, level, IPV6_RECVERR, eVal); } #endif #if defined(IPV6_RECVPKTINFO) || defined(IPV6_PKTINFO) static -ERL_NIF_TERM nsetopt_lvl_ipv6_recvpktinfo(ErlNifEnv* env, - ESockDescriptor* descP, - ERL_NIF_TERM eVal) +ERL_NIF_TERM esock_setopt_lvl_ipv6_recvpktinfo(ErlNifEnv* env, + ESockDescriptor* descP, + ERL_NIF_TERM eVal) { #if defined(SOL_IPV6) int level = SOL_IPV6; @@ -9993,16 +10024,16 @@ ERL_NIF_TERM nsetopt_lvl_ipv6_recvpktinfo(ErlNifEnv* env, int opt = IPV6_PKTINFO; #endif - return nsetopt_bool_opt(env, descP, level, opt, eVal); + return esock_setopt_bool_opt(env, descP, level, opt, eVal); } #endif #if defined(IPV6_ROUTER_ALERT) static -ERL_NIF_TERM nsetopt_lvl_ipv6_router_alert(ErlNifEnv* env, - ESockDescriptor* descP, - ERL_NIF_TERM eVal) +ERL_NIF_TERM esock_setopt_lvl_ipv6_router_alert(ErlNifEnv* env, + ESockDescriptor* descP, + ERL_NIF_TERM eVal) { #if defined(SOL_IPV6) int level = SOL_IPV6; @@ -10010,7 +10041,7 @@ ERL_NIF_TERM nsetopt_lvl_ipv6_router_alert(ErlNifEnv* env, int level = IPPROTO_IPV6; #endif - return nsetopt_int_opt(env, descP, level, IPV6_ROUTER_ALERT, eVal); + return esock_setopt_int_opt(env, descP, level, IPV6_ROUTER_ALERT, eVal); } #endif @@ -10018,9 +10049,9 @@ ERL_NIF_TERM nsetopt_lvl_ipv6_router_alert(ErlNifEnv* env, #if defined(IPV6_RTHDR) static -ERL_NIF_TERM nsetopt_lvl_ipv6_rthdr(ErlNifEnv* env, - ESockDescriptor* descP, - ERL_NIF_TERM eVal) +ERL_NIF_TERM esock_setopt_lvl_ipv6_rthdr(ErlNifEnv* env, + ESockDescriptor* descP, + ERL_NIF_TERM eVal) { #if defined(SOL_IPV6) int level = SOL_IPV6; @@ -10028,16 +10059,16 @@ ERL_NIF_TERM nsetopt_lvl_ipv6_rthdr(ErlNifEnv* env, int level = IPPROTO_IPV6; #endif - return nsetopt_bool_opt(env, descP, level, IPV6_RTHDR, eVal); + return esock_setopt_bool_opt(env, descP, level, IPV6_RTHDR, eVal); } #endif #if defined(IPV6_UNICAST_HOPS) static -ERL_NIF_TERM nsetopt_lvl_ipv6_unicast_hops(ErlNifEnv* env, - ESockDescriptor* descP, - ERL_NIF_TERM eVal) +ERL_NIF_TERM esock_setopt_lvl_ipv6_unicast_hops(ErlNifEnv* env, + ESockDescriptor* descP, + ERL_NIF_TERM eVal) { #if defined(SOL_IPV6) int level = SOL_IPV6; @@ -10045,7 +10076,7 @@ ERL_NIF_TERM nsetopt_lvl_ipv6_unicast_hops(ErlNifEnv* env, int level = IPPROTO_IPV6; #endif - return nsetopt_int_opt(env, descP, level, IPV6_UNICAST_HOPS, eVal); + return esock_setopt_int_opt(env, descP, level, IPV6_UNICAST_HOPS, eVal); } #endif @@ -10053,9 +10084,9 @@ ERL_NIF_TERM nsetopt_lvl_ipv6_unicast_hops(ErlNifEnv* env, #if defined(IPV6_V6ONLY) static -ERL_NIF_TERM nsetopt_lvl_ipv6_v6only(ErlNifEnv* env, - ESockDescriptor* descP, - ERL_NIF_TERM eVal) +ERL_NIF_TERM esock_setopt_lvl_ipv6_v6only(ErlNifEnv* env, + ESockDescriptor* descP, + ERL_NIF_TERM eVal) { #if defined(SOL_IPV6) int level = SOL_IPV6; @@ -10063,17 +10094,17 @@ ERL_NIF_TERM nsetopt_lvl_ipv6_v6only(ErlNifEnv* env, int level = IPPROTO_IPV6; #endif - return nsetopt_bool_opt(env, descP, level, IPV6_V6ONLY, eVal); + return esock_setopt_bool_opt(env, descP, level, IPV6_V6ONLY, eVal); } #endif #if defined(IPV6_ADD_MEMBERSHIP) || defined(IPV6_DROP_MEMBERSHIP) static -ERL_NIF_TERM nsetopt_lvl_ipv6_update_membership(ErlNifEnv* env, - ESockDescriptor* descP, - ERL_NIF_TERM eVal, - int opt) +ERL_NIF_TERM esock_setopt_lvl_ipv6_update_membership(ErlNifEnv* env, + ESockDescriptor* descP, + ERL_NIF_TERM eVal, + int opt) { ERL_NIF_TERM result, eMultiAddr, eInterface; struct ipv6_mreq mreq; @@ -10089,7 +10120,7 @@ ERL_NIF_TERM nsetopt_lvl_ipv6_update_membership(ErlNifEnv* env, // It must be a map if (!IS_MAP(env, eVal)) { SSDBG( descP, - ("SOCKET", "nsetopt_lvl_ipv6_update_membership -> " + ("SOCKET", "esock_setopt_lvl_ipv6_update_membership -> " "value *not* a map\r\n") ); return enif_make_badarg(env); } @@ -10097,21 +10128,21 @@ ERL_NIF_TERM nsetopt_lvl_ipv6_update_membership(ErlNifEnv* env, // It must have atleast two attributes if (!enif_get_map_size(env, eVal, &sz) || (sz < 2)) { SSDBG( descP, - ("SOCKET", "nsetopt_lvl_ipv6_update_membership -> " + ("SOCKET", "esock_setopt_lvl_ipv6_update_membership -> " "invalid map value: %T\r\n", eVal) ); return enif_make_badarg(env); } if (!GET_MAP_VAL(env, eVal, atom_multiaddr, &eMultiAddr)) { SSDBG( descP, - ("SOCKET", "nsetopt_lvl_ipv6_update_membership -> " + ("SOCKET", "esock_setopt_lvl_ipv6_update_membership -> " "failed get multiaddr (map) attribute\r\n") ); return enif_make_badarg(env); } if (!GET_MAP_VAL(env, eVal, atom_interface, &eInterface)) { SSDBG( descP, - ("SOCKET", "nsetopt_lvl_ipv6_update_membership -> " + ("SOCKET", "esock_setopt_lvl_ipv6_update_membership -> " "failed get interface (map) attribute\r\n") ); return enif_make_badarg(env); } @@ -10120,14 +10151,14 @@ ERL_NIF_TERM nsetopt_lvl_ipv6_update_membership(ErlNifEnv* env, eMultiAddr, &mreq.ipv6mr_multiaddr)) != NULL) { SSDBG( descP, - ("SOCKET", "nsetopt_lvl_ipv6_update_membership -> " + ("SOCKET", "esock_setopt_lvl_ipv6_update_membership -> " "failed decode multiaddr %T: %s\r\n", eMultiAddr, xres) ); return esock_make_error_str(env, xres); } if (!GET_UINT(env, eInterface, &mreq.ipv6mr_interface)) { SSDBG( descP, - ("SOCKET", "nsetopt_lvl_ip_update_membership -> " + ("SOCKET", "esock_setopt_lvl_ip_update_membership -> " "failed decode interface %T: %s\r\n", eInterface, xres) ); return esock_make_error(env, esock_atom_einval); } @@ -10140,7 +10171,7 @@ ERL_NIF_TERM nsetopt_lvl_ipv6_update_membership(ErlNifEnv* env, result = esock_make_error_errno(env, save_errno); SSDBG( descP, - ("SOCKET", "nsetopt_lvl_ipv6_update_membership -> " + ("SOCKET", "esock_setopt_lvl_ipv6_update_membership -> " "failed setopt: %T (%d)\r\n", result, save_errno) ); } else { @@ -10157,37 +10188,37 @@ ERL_NIF_TERM nsetopt_lvl_ipv6_update_membership(ErlNifEnv* env, -/* nsetopt_lvl_tcp - Level *TCP* option(s) +/* esock_setopt_lvl_tcp - Level *TCP* option(s) */ static -ERL_NIF_TERM nsetopt_lvl_tcp(ErlNifEnv* env, - ESockDescriptor* descP, - int eOpt, - ERL_NIF_TERM eVal) +ERL_NIF_TERM esock_setopt_lvl_tcp(ErlNifEnv* env, + ESockDescriptor* descP, + int eOpt, + ERL_NIF_TERM eVal) { ERL_NIF_TERM result; SSDBG( descP, - ("SOCKET", "nsetopt_lvl_tcp -> entry with" + ("SOCKET", "esock_setopt_lvl_tcp -> entry with" "\r\n opt: %d" "\r\n", eOpt) ); switch (eOpt) { #if defined(TCP_CONGESTION) - case SOCKET_OPT_TCP_CONGESTION: - result = nsetopt_lvl_tcp_congestion(env, descP, eVal); + case ESOCK_OPT_TCP_CONGESTION: + result = esock_setopt_lvl_tcp_congestion(env, descP, eVal); break; #endif #if defined(TCP_MAXSEG) - case SOCKET_OPT_TCP_MAXSEG: - result = nsetopt_lvl_tcp_maxseg(env, descP, eVal); + case ESOCK_OPT_TCP_MAXSEG: + result = esock_setopt_lvl_tcp_maxseg(env, descP, eVal); break; #endif #if defined(TCP_NODELAY) - case SOCKET_OPT_TCP_NODELAY: - result = nsetopt_lvl_tcp_nodelay(env, descP, eVal); + case ESOCK_OPT_TCP_NODELAY: + result = esock_setopt_lvl_tcp_nodelay(env, descP, eVal); break; #endif @@ -10200,67 +10231,68 @@ ERL_NIF_TERM nsetopt_lvl_tcp(ErlNifEnv* env, } -/* nsetopt_lvl_tcp_congestion - Level TCP CONGESTION option +/* esock_setopt_lvl_tcp_congestion - Level TCP CONGESTION option */ #if defined(TCP_CONGESTION) static -ERL_NIF_TERM nsetopt_lvl_tcp_congestion(ErlNifEnv* env, - ESockDescriptor* descP, - ERL_NIF_TERM eVal) +ERL_NIF_TERM esock_setopt_lvl_tcp_congestion(ErlNifEnv* env, + ESockDescriptor* descP, + ERL_NIF_TERM eVal) { - int max = SOCKET_OPT_TCP_CONGESTION_NAME_MAX+1; + int max = ESOCK_OPT_TCP_CONGESTION_NAME_MAX+1; - return nsetopt_str_opt(env, descP, IPPROTO_TCP, TCP_CONGESTION, max, eVal); + return esock_setopt_str_opt(env, descP, + IPPROTO_TCP, TCP_CONGESTION, max, eVal); } #endif -/* nsetopt_lvl_tcp_maxseg - Level TCP MAXSEG option +/* esock_setopt_lvl_tcp_maxseg - Level TCP MAXSEG option */ #if defined(TCP_MAXSEG) static -ERL_NIF_TERM nsetopt_lvl_tcp_maxseg(ErlNifEnv* env, - ESockDescriptor* descP, - ERL_NIF_TERM eVal) +ERL_NIF_TERM esock_setopt_lvl_tcp_maxseg(ErlNifEnv* env, + ESockDescriptor* descP, + ERL_NIF_TERM eVal) { - return nsetopt_int_opt(env, descP, IPPROTO_TCP, TCP_MAXSEG, eVal); + return esock_setopt_int_opt(env, descP, IPPROTO_TCP, TCP_MAXSEG, eVal); } #endif -/* nsetopt_lvl_tcp_nodelay - Level TCP NODELAY option +/* esock_setopt_lvl_tcp_nodelay - Level TCP NODELAY option */ #if defined(TCP_NODELAY) static -ERL_NIF_TERM nsetopt_lvl_tcp_nodelay(ErlNifEnv* env, - ESockDescriptor* descP, - ERL_NIF_TERM eVal) +ERL_NIF_TERM esock_setopt_lvl_tcp_nodelay(ErlNifEnv* env, + ESockDescriptor* descP, + ERL_NIF_TERM eVal) { - return nsetopt_bool_opt(env, descP, IPPROTO_TCP, TCP_NODELAY, eVal); + return esock_setopt_bool_opt(env, descP, IPPROTO_TCP, TCP_NODELAY, eVal); } #endif -/* nsetopt_lvl_udp - Level *UDP* option(s) +/* esock_setopt_lvl_udp - Level *UDP* option(s) */ static -ERL_NIF_TERM nsetopt_lvl_udp(ErlNifEnv* env, - ESockDescriptor* descP, - int eOpt, - ERL_NIF_TERM eVal) +ERL_NIF_TERM esock_setopt_lvl_udp(ErlNifEnv* env, + ESockDescriptor* descP, + int eOpt, + ERL_NIF_TERM eVal) { ERL_NIF_TERM result; SSDBG( descP, - ("SOCKET", "nsetopt_lvl_udp -> entry with" + ("SOCKET", "esock_setopt_lvl_udp -> entry with" "\r\n opt: %d" "\r\n", eOpt) ); switch (eOpt) { #if defined(UDP_CORK) - case SOCKET_OPT_UDP_CORK: - result = nsetopt_lvl_udp_cork(env, descP, eVal); + case ESOCK_OPT_UDP_CORK: + result = esock_setopt_lvl_udp_cork(env, descP, eVal); break; #endif @@ -10273,83 +10305,83 @@ ERL_NIF_TERM nsetopt_lvl_udp(ErlNifEnv* env, } -/* nsetopt_lvl_udp_cork - Level UDP CORK option +/* esock_setopt_lvl_udp_cork - Level UDP CORK option */ #if defined(UDP_CORK) static -ERL_NIF_TERM nsetopt_lvl_udp_cork(ErlNifEnv* env, - ESockDescriptor* descP, - ERL_NIF_TERM eVal) +ERL_NIF_TERM esock_setopt_lvl_udp_cork(ErlNifEnv* env, + ESockDescriptor* descP, + ERL_NIF_TERM eVal) { - return nsetopt_bool_opt(env, descP, IPPROTO_UDP, UDP_CORK, eVal); + return esock_setopt_bool_opt(env, descP, IPPROTO_UDP, UDP_CORK, eVal); } #endif -/* nsetopt_lvl_sctp - Level *SCTP* option(s) +/* esock_setopt_lvl_sctp - Level *SCTP* option(s) */ #if defined(HAVE_SCTP) static -ERL_NIF_TERM nsetopt_lvl_sctp(ErlNifEnv* env, - ESockDescriptor* descP, - int eOpt, - ERL_NIF_TERM eVal) +ERL_NIF_TERM esock_setopt_lvl_sctp(ErlNifEnv* env, + ESockDescriptor* descP, + int eOpt, + ERL_NIF_TERM eVal) { ERL_NIF_TERM result; SSDBG( descP, - ("SOCKET", "nsetopt_lvl_sctp -> entry with" + ("SOCKET", "esock_setopt_lvl_sctp -> entry with" "\r\n opt: %d" "\r\n", eOpt) ); switch (eOpt) { #if defined(SCTP_ASSOCINFO) - case SOCKET_OPT_SCTP_ASSOCINFO: - result = nsetopt_lvl_sctp_associnfo(env, descP, eVal); + case ESOCK_OPT_SCTP_ASSOCINFO: + result = esock_setopt_lvl_sctp_associnfo(env, descP, eVal); break; #endif #if defined(SCTP_AUTOCLOSE) - case SOCKET_OPT_SCTP_AUTOCLOSE: - result = nsetopt_lvl_sctp_autoclose(env, descP, eVal); + case ESOCK_OPT_SCTP_AUTOCLOSE: + result = esock_setopt_lvl_sctp_autoclose(env, descP, eVal); break; #endif #if defined(SCTP_DISABLE_FRAGMENTS) - case SOCKET_OPT_SCTP_DISABLE_FRAGMENTS: - result = nsetopt_lvl_sctp_disable_fragments(env, descP, eVal); + case ESOCK_OPT_SCTP_DISABLE_FRAGMENTS: + result = esock_setopt_lvl_sctp_disable_fragments(env, descP, eVal); break; #endif #if defined(SCTP_EVENTS) - case SOCKET_OPT_SCTP_EVENTS: - result = nsetopt_lvl_sctp_events(env, descP, eVal); + case ESOCK_OPT_SCTP_EVENTS: + result = esock_setopt_lvl_sctp_events(env, descP, eVal); break; #endif #if defined(SCTP_INITMSG) - case SOCKET_OPT_SCTP_INITMSG: - result = nsetopt_lvl_sctp_initmsg(env, descP, eVal); + case ESOCK_OPT_SCTP_INITMSG: + result = esock_setopt_lvl_sctp_initmsg(env, descP, eVal); break; #endif #if defined(SCTP_MAXSEG) - case SOCKET_OPT_SCTP_MAXSEG: - result = nsetopt_lvl_sctp_maxseg(env, descP, eVal); + case ESOCK_OPT_SCTP_MAXSEG: + result = esock_setopt_lvl_sctp_maxseg(env, descP, eVal); break; #endif #if defined(SCTP_NODELAY) - case SOCKET_OPT_SCTP_NODELAY: - result = nsetopt_lvl_sctp_nodelay(env, descP, eVal); + case ESOCK_OPT_SCTP_NODELAY: + result = esock_setopt_lvl_sctp_nodelay(env, descP, eVal); break; #endif #if defined(SCTP_RTOINFO) - case SOCKET_OPT_SCTP_RTOINFO: - result = nsetopt_lvl_sctp_rtoinfo(env, descP, eVal); + case ESOCK_OPT_SCTP_RTOINFO: + result = esock_setopt_lvl_sctp_rtoinfo(env, descP, eVal); break; #endif @@ -10362,13 +10394,13 @@ ERL_NIF_TERM nsetopt_lvl_sctp(ErlNifEnv* env, } -/* nsetopt_lvl_sctp_associnfo - Level SCTP ASSOCINFO option +/* esock_setopt_lvl_sctp_associnfo - Level SCTP ASSOCINFO option */ #if defined(SCTP_ASSOCINFO) static -ERL_NIF_TERM nsetopt_lvl_sctp_associnfo(ErlNifEnv* env, - ESockDescriptor* descP, - ERL_NIF_TERM eVal) +ERL_NIF_TERM esock_setopt_lvl_sctp_associnfo(ErlNifEnv* env, + ESockDescriptor* descP, + ERL_NIF_TERM eVal) { ERL_NIF_TERM result; ERL_NIF_TERM eAssocId, eMaxRxt, eNumPeerDests; @@ -10379,7 +10411,7 @@ ERL_NIF_TERM nsetopt_lvl_sctp_associnfo(ErlNifEnv* env, unsigned int tmp; SSDBG( descP, - ("SOCKET", "nsetopt_lvl_sctp_associnfo -> entry with" + ("SOCKET", "esock_setopt_lvl_sctp_associnfo -> entry with" "\r\n eVal: %T" "\r\n", eVal) ); @@ -10392,7 +10424,8 @@ ERL_NIF_TERM nsetopt_lvl_sctp_associnfo(ErlNifEnv* env, return esock_make_error(env, esock_atom_einval); SSDBG( descP, - ("SOCKET", "nsetopt_lvl_sctp_associnfo -> extract attributes\r\n") ); + ("SOCKET", + "esock_setopt_lvl_sctp_associnfo -> extract attributes\r\n") ); if (!GET_MAP_VAL(env, eVal, atom_assoc_id, &eAssocId)) return esock_make_error(env, esock_atom_einval); @@ -10413,7 +10446,8 @@ ERL_NIF_TERM nsetopt_lvl_sctp_associnfo(ErlNifEnv* env, return esock_make_error(env, esock_atom_einval); SSDBG( descP, - ("SOCKET", "nsetopt_lvl_sctp_associnfo -> decode attributes\r\n") ); + ("SOCKET", + "esock_setopt_lvl_sctp_associnfo -> decode attributes\r\n") ); /* On some platforms the assoc id is typed as an unsigned integer (uint32) * So, to avoid warnings there, we always make an explicit cast... @@ -10466,7 +10500,8 @@ ERL_NIF_TERM nsetopt_lvl_sctp_associnfo(ErlNifEnv* env, return esock_make_error(env, esock_atom_einval); SSDBG( descP, - ("SOCKET", "nsetopt_lvl_sctp_associnfo -> set associnfo option\r\n") ); + ("SOCKET", + "esock_setopt_lvl_sctp_associnfo -> set associnfo option\r\n") ); res = socket_setopt(descP->sock, IPPROTO_SCTP, SCTP_ASSOCINFO, &assocParams, sizeof(assocParams)); @@ -10477,7 +10512,7 @@ ERL_NIF_TERM nsetopt_lvl_sctp_associnfo(ErlNifEnv* env, result = esock_atom_ok; SSDBG( descP, - ("SOCKET", "nsetopt_lvl_sctp_associnfo -> done with" + ("SOCKET", "esock_setopt_lvl_sctp_associnfo -> done with" "\r\n result: %T" "\r\n", result) ); @@ -10487,39 +10522,42 @@ ERL_NIF_TERM nsetopt_lvl_sctp_associnfo(ErlNifEnv* env, #endif -/* nsetopt_lvl_sctp_autoclose - Level SCTP AUTOCLOSE option +/* esock_setopt_lvl_sctp_autoclose - Level SCTP AUTOCLOSE option */ #if defined(SCTP_AUTOCLOSE) static -ERL_NIF_TERM nsetopt_lvl_sctp_autoclose(ErlNifEnv* env, - ESockDescriptor* descP, - ERL_NIF_TERM eVal) +ERL_NIF_TERM esock_setopt_lvl_sctp_autoclose(ErlNifEnv* env, + ESockDescriptor* descP, + ERL_NIF_TERM eVal) { - return nsetopt_int_opt(env, descP, IPPROTO_SCTP, SCTP_AUTOCLOSE, eVal); + return esock_setopt_int_opt(env, descP, + IPPROTO_SCTP, SCTP_AUTOCLOSE, eVal); } #endif -/* nsetopt_lvl_sctp_disable_fragments - Level SCTP DISABLE_FRAGMENTS option +/* esock_setopt_lvl_sctp_disable_fragments - + * Level SCTP DISABLE_FRAGMENTS option */ #if defined(SCTP_DISABLE_FRAGMENTS) static -ERL_NIF_TERM nsetopt_lvl_sctp_disable_fragments(ErlNifEnv* env, - ESockDescriptor* descP, - ERL_NIF_TERM eVal) +ERL_NIF_TERM esock_setopt_lvl_sctp_disable_fragments(ErlNifEnv* env, + ESockDescriptor* descP, + ERL_NIF_TERM eVal) { - return nsetopt_bool_opt(env, descP, IPPROTO_SCTP, SCTP_DISABLE_FRAGMENTS, eVal); + return esock_setopt_bool_opt(env, descP, + IPPROTO_SCTP, SCTP_DISABLE_FRAGMENTS, eVal); } #endif -/* nsetopt_lvl_sctp_events - Level SCTP EVENTS option +/* esock_setopt_lvl_sctp_events - Level SCTP EVENTS option */ #if defined(SCTP_EVENTS) static -ERL_NIF_TERM nsetopt_lvl_sctp_events(ErlNifEnv* env, - ESockDescriptor* descP, - ERL_NIF_TERM eVal) +ERL_NIF_TERM esock_setopt_lvl_sctp_events(ErlNifEnv* env, + ESockDescriptor* descP, + ERL_NIF_TERM eVal) { ERL_NIF_TERM result; ERL_NIF_TERM eDataIn, eAssoc, eAddr, eSndFailure; @@ -10536,7 +10574,7 @@ ERL_NIF_TERM nsetopt_lvl_sctp_events(ErlNifEnv* env, size_t sz; SSDBG( descP, - ("SOCKET", "nsetopt_lvl_sctp_events -> entry with" + ("SOCKET", "esock_setopt_lvl_sctp_events -> entry with" "\r\n eVal: %T" "\r\n", eVal) ); @@ -10549,7 +10587,8 @@ ERL_NIF_TERM nsetopt_lvl_sctp_events(ErlNifEnv* env, return esock_make_error(env, esock_atom_einval); SSDBG( descP, - ("SOCKET", "nsetopt_lvl_sctp_events -> extract attributes\r\n") ); + ("SOCKET", + "esock_setopt_lvl_sctp_events -> extract attributes\r\n") ); if (!GET_MAP_VAL(env, eVal, atom_data_in, &eDataIn)) return esock_make_error(env, esock_atom_einval); @@ -10586,7 +10625,8 @@ ERL_NIF_TERM nsetopt_lvl_sctp_events(ErlNifEnv* env, #endif SSDBG( descP, - ("SOCKET", "nsetopt_lvl_sctp_events -> decode attributes\r\n") ); + ("SOCKET", + "esock_setopt_lvl_sctp_events -> decode attributes\r\n") ); events.sctp_data_io_event = esock_decode_bool(eDataIn); events.sctp_association_event = esock_decode_bool(eAssoc); @@ -10604,7 +10644,8 @@ ERL_NIF_TERM nsetopt_lvl_sctp_events(ErlNifEnv* env, #endif SSDBG( descP, - ("SOCKET", "nsetopt_lvl_sctp_events -> set events option\r\n") ); + ("SOCKET", + "esock_setopt_lvl_sctp_events -> set events option\r\n") ); res = socket_setopt(descP->sock, IPPROTO_SCTP, SCTP_EVENTS, &events, sizeof(events)); @@ -10615,7 +10656,7 @@ ERL_NIF_TERM nsetopt_lvl_sctp_events(ErlNifEnv* env, result = esock_atom_ok; SSDBG( descP, - ("SOCKET", "nsetopt_lvl_sctp_events -> done with" + ("SOCKET", "esock_setopt_lvl_sctp_events -> done with" "\r\n result: %T" "\r\n", result) ); @@ -10625,13 +10666,13 @@ ERL_NIF_TERM nsetopt_lvl_sctp_events(ErlNifEnv* env, #endif -/* nsetopt_lvl_sctp_initmsg - Level SCTP INITMSG option +/* esock_setopt_lvl_sctp_initmsg - Level SCTP INITMSG option */ #if defined(SCTP_INITMSG) static -ERL_NIF_TERM nsetopt_lvl_sctp_initmsg(ErlNifEnv* env, - ESockDescriptor* descP, - ERL_NIF_TERM eVal) +ERL_NIF_TERM esock_setopt_lvl_sctp_initmsg(ErlNifEnv* env, + ESockDescriptor* descP, + ERL_NIF_TERM eVal) { ERL_NIF_TERM result; ERL_NIF_TERM eNumOut, eMaxIn, eMaxAttempts, eMaxInitTO; @@ -10641,7 +10682,7 @@ ERL_NIF_TERM nsetopt_lvl_sctp_initmsg(ErlNifEnv* env, unsigned int tmp; SSDBG( descP, - ("SOCKET", "nsetopt_lvl_sctp_initmsg -> entry with" + ("SOCKET", "esock_setopt_lvl_sctp_initmsg -> entry with" "\r\n eVal: %T" "\r\n", eVal) ); @@ -10654,7 +10695,8 @@ ERL_NIF_TERM nsetopt_lvl_sctp_initmsg(ErlNifEnv* env, return esock_make_error(env, esock_atom_einval); SSDBG( descP, - ("SOCKET", "nsetopt_lvl_sctp_initmsg -> extract attributes\r\n") ); + ("SOCKET", + "esock_setopt_lvl_sctp_initmsg -> extract attributes\r\n") ); if (!GET_MAP_VAL(env, eVal, atom_num_outstreams, &eNumOut)) return esock_make_error(env, esock_atom_einval); @@ -10669,7 +10711,8 @@ ERL_NIF_TERM nsetopt_lvl_sctp_initmsg(ErlNifEnv* env, return esock_make_error(env, esock_atom_einval); SSDBG( descP, - ("SOCKET", "nsetopt_lvl_sctp_initmsg -> decode attributes\r\n") ); + ("SOCKET", + "esock_setopt_lvl_sctp_initmsg -> decode attributes\r\n") ); if (!GET_UINT(env, eNumOut, &tmp)) return esock_make_error(env, esock_atom_einval); @@ -10688,7 +10731,8 @@ ERL_NIF_TERM nsetopt_lvl_sctp_initmsg(ErlNifEnv* env, initMsg.sinit_max_init_timeo = (Uint16) tmp; SSDBG( descP, - ("SOCKET", "nsetopt_lvl_sctp_initmsg -> set initmsg option\r\n") ); + ("SOCKET", + "esock_setopt_lvl_sctp_initmsg -> set initmsg option\r\n") ); res = socket_setopt(descP->sock, IPPROTO_SCTP, SCTP_INITMSG, &initMsg, sizeof(initMsg)); @@ -10699,7 +10743,7 @@ ERL_NIF_TERM nsetopt_lvl_sctp_initmsg(ErlNifEnv* env, result = esock_atom_ok; SSDBG( descP, - ("SOCKET", "nsetopt_lvl_sctp_initmsg -> done with" + ("SOCKET", "esock_setopt_lvl_sctp_initmsg -> done with" "\r\n result: %T" "\r\n", result) ); @@ -10709,39 +10753,39 @@ ERL_NIF_TERM nsetopt_lvl_sctp_initmsg(ErlNifEnv* env, #endif -/* nsetopt_lvl_sctp_maxseg - Level SCTP MAXSEG option +/* esock_setopt_lvl_sctp_maxseg - Level SCTP MAXSEG option */ #if defined(SCTP_MAXSEG) static -ERL_NIF_TERM nsetopt_lvl_sctp_maxseg(ErlNifEnv* env, - ESockDescriptor* descP, - ERL_NIF_TERM eVal) +ERL_NIF_TERM esock_setopt_lvl_sctp_maxseg(ErlNifEnv* env, + ESockDescriptor* descP, + ERL_NIF_TERM eVal) { - return nsetopt_int_opt(env, descP, IPPROTO_SCTP, SCTP_MAXSEG, eVal); + return esock_setopt_int_opt(env, descP, IPPROTO_SCTP, SCTP_MAXSEG, eVal); } #endif -/* nsetopt_lvl_sctp_nodelay - Level SCTP NODELAY option +/* esock_setopt_lvl_sctp_nodelay - Level SCTP NODELAY option */ #if defined(SCTP_NODELAY) static -ERL_NIF_TERM nsetopt_lvl_sctp_nodelay(ErlNifEnv* env, - ESockDescriptor* descP, - ERL_NIF_TERM eVal) +ERL_NIF_TERM esock_setopt_lvl_sctp_nodelay(ErlNifEnv* env, + ESockDescriptor* descP, + ERL_NIF_TERM eVal) { - return nsetopt_bool_opt(env, descP, IPPROTO_SCTP, SCTP_NODELAY, eVal); + return esock_setopt_bool_opt(env, descP, IPPROTO_SCTP, SCTP_NODELAY, eVal); } #endif -/* nsetopt_lvl_sctp_rtoinfo - Level SCTP RTOINFO option +/* esock_setopt_lvl_sctp_rtoinfo - Level SCTP RTOINFO option */ #if defined(SCTP_RTOINFO) static -ERL_NIF_TERM nsetopt_lvl_sctp_rtoinfo(ErlNifEnv* env, - ESockDescriptor* descP, - ERL_NIF_TERM eVal) +ERL_NIF_TERM esock_setopt_lvl_sctp_rtoinfo(ErlNifEnv* env, + ESockDescriptor* descP, + ERL_NIF_TERM eVal) { ERL_NIF_TERM result; ERL_NIF_TERM eAssocId, eInitial, eMax, eMin; @@ -10750,7 +10794,7 @@ ERL_NIF_TERM nsetopt_lvl_sctp_rtoinfo(ErlNifEnv* env, size_t sz; SSDBG( descP, - ("SOCKET", "nsetopt_lvl_sctp_rtoinfo -> entry with" + ("SOCKET", "esock_setopt_lvl_sctp_rtoinfo -> entry with" "\r\n eVal: %T" "\r\n", eVal) ); @@ -10763,7 +10807,8 @@ ERL_NIF_TERM nsetopt_lvl_sctp_rtoinfo(ErlNifEnv* env, return esock_make_error(env, esock_atom_einval); SSDBG( descP, - ("SOCKET", "nsetopt_lvl_sctp_rtoinfo -> extract attributes\r\n") ); + ("SOCKET", + "esock_setopt_lvl_sctp_rtoinfo -> extract attributes\r\n") ); if (!GET_MAP_VAL(env, eVal, atom_assoc_id, &eAssocId)) return esock_make_error(env, esock_atom_einval); @@ -10778,7 +10823,8 @@ ERL_NIF_TERM nsetopt_lvl_sctp_rtoinfo(ErlNifEnv* env, return esock_make_error(env, esock_atom_einval); SSDBG( descP, - ("SOCKET", "nsetopt_lvl_sctp_rtoinfo -> decode attributes\r\n") ); + ("SOCKET", + "esock_setopt_lvl_sctp_rtoinfo -> decode attributes\r\n") ); /* On some platforms the assoc id is typed as an unsigned integer (uint32) * So, to avoid warnings there, we always make an explicit cast... @@ -10813,7 +10859,8 @@ ERL_NIF_TERM nsetopt_lvl_sctp_rtoinfo(ErlNifEnv* env, return esock_make_error(env, esock_atom_einval); SSDBG( descP, - ("SOCKET", "nsetopt_lvl_sctp_rtoinfo -> set associnfo option\r\n") ); + ("SOCKET", + "esock_setopt_lvl_sctp_rtoinfo -> set associnfo option\r\n") ); res = socket_setopt(descP->sock, IPPROTO_SCTP, SCTP_RTOINFO, &rtoInfo, sizeof(rtoInfo)); @@ -10824,7 +10871,7 @@ ERL_NIF_TERM nsetopt_lvl_sctp_rtoinfo(ErlNifEnv* env, result = esock_atom_ok; SSDBG( descP, - ("SOCKET", "nsetopt_lvl_sctp_rtoinfo -> done with" + ("SOCKET", "esock_setopt_lvl_sctp_rtoinfo -> done with" "\r\n result: %T" "\r\n", result) ); @@ -10840,14 +10887,14 @@ ERL_NIF_TERM nsetopt_lvl_sctp_rtoinfo(ErlNifEnv* env, -/* nsetopt_bool_opt - set an option that has an (integer) bool value +/* esock_setopt_bool_opt - set an option that has an (integer) bool value */ static -ERL_NIF_TERM nsetopt_bool_opt(ErlNifEnv* env, - ESockDescriptor* descP, - int level, - int opt, - ERL_NIF_TERM eVal) +ERL_NIF_TERM esock_setopt_bool_opt(ErlNifEnv* env, + ESockDescriptor* descP, + int level, + int opt, + ERL_NIF_TERM eVal) { ERL_NIF_TERM result; BOOLEAN_T val; @@ -10867,14 +10914,14 @@ ERL_NIF_TERM nsetopt_bool_opt(ErlNifEnv* env, } -/* nsetopt_int_opt - set an option that has an integer value +/* esock_setopt_int_opt - set an option that has an integer value */ static -ERL_NIF_TERM nsetopt_int_opt(ErlNifEnv* env, - ESockDescriptor* descP, - int level, - int opt, - ERL_NIF_TERM eVal) +ERL_NIF_TERM esock_setopt_int_opt(ErlNifEnv* env, + ESockDescriptor* descP, + int level, + int opt, + ERL_NIF_TERM eVal) { ERL_NIF_TERM result; int val; @@ -10884,7 +10931,7 @@ ERL_NIF_TERM nsetopt_int_opt(ErlNifEnv* env, /* SSDBG( descP, - ("SOCKET", "nsetopt_int_opt -> set option" + ("SOCKET", "esock_setopt_int_opt -> set option" "\r\n opt: %d" "\r\n val: %d" "\r\n", opt, val) ); @@ -10905,16 +10952,16 @@ ERL_NIF_TERM nsetopt_int_opt(ErlNifEnv* env, } -/* nsetopt_str_opt - set an option that has an string value +/* esock_setopt_str_opt - set an option that has an string value */ #if defined(USE_SETOPT_STR_OPT) static -ERL_NIF_TERM nsetopt_str_opt(ErlNifEnv* env, - ESockDescriptor* descP, - int level, - int opt, - int max, - ERL_NIF_TERM eVal) +ERL_NIF_TERM esock_setopt_str_opt(ErlNifEnv* env, + ESockDescriptor* descP, + int level, + int opt, + int max, + ERL_NIF_TERM eVal) { ERL_NIF_TERM result; char* val = MALLOC(max); @@ -10939,14 +10986,14 @@ ERL_NIF_TERM nsetopt_str_opt(ErlNifEnv* env, #endif -/* nsetopt_timeval_opt - set an option that has an (timeval) bool value +/* esock_setopt_timeval_opt - set an option that has an (timeval) bool value */ static -ERL_NIF_TERM nsetopt_timeval_opt(ErlNifEnv* env, - ESockDescriptor* descP, - int level, - int opt, - ERL_NIF_TERM eVal) +ERL_NIF_TERM esock_setopt_timeval_opt(ErlNifEnv* env, + ESockDescriptor* descP, + int level, + int opt, + ERL_NIF_TERM eVal) { ERL_NIF_TERM result; struct timeval timeVal; @@ -10954,7 +11001,7 @@ ERL_NIF_TERM nsetopt_timeval_opt(ErlNifEnv* env, char* xres; SSDBG( descP, - ("SOCKET", "nsetopt_timeval_opt -> entry with" + ("SOCKET", "esock_setopt_timeval_opt -> entry with" "\r\n eVal: %T" "\r\n", eVal) ); @@ -10962,7 +11009,7 @@ ERL_NIF_TERM nsetopt_timeval_opt(ErlNifEnv* env, return esock_make_error_str(env, xres); SSDBG( descP, - ("SOCKET", "nsetopt_timeval_opt -> set timeval option\r\n") ); + ("SOCKET", "esock_setopt_timeval_opt -> set timeval option\r\n") ); res = socket_setopt(descP->sock, level, opt, &timeVal, sizeof(timeVal)); @@ -10972,7 +11019,7 @@ ERL_NIF_TERM nsetopt_timeval_opt(ErlNifEnv* env, result = esock_atom_ok; SSDBG( descP, - ("SOCKET", "nsetopt_timeval_opt -> done with" + ("SOCKET", "esock_setopt_timeval_opt -> done with" "\r\n result: %T" "\r\n", result) ); @@ -10992,19 +11039,19 @@ BOOLEAN_T elevel2level(BOOLEAN_T isEncoded, if (isEncoded) { switch (eLevel) { - case SOCKET_OPT_LEVEL_OTP: + case ESOCK_OPT_LEVEL_OTP: *isOTP = TRUE; *level = -1; result = TRUE; break; - case SOCKET_OPT_LEVEL_SOCKET: + case ESOCK_OPT_LEVEL_SOCKET: *isOTP = FALSE; *level = SOL_SOCKET; result = TRUE; break; - case SOCKET_OPT_LEVEL_IP: + case ESOCK_OPT_LEVEL_IP: *isOTP = FALSE; #if defined(SOL_IP) *level = SOL_IP; @@ -11015,7 +11062,7 @@ BOOLEAN_T elevel2level(BOOLEAN_T isEncoded, break; #if defined(HAVE_IPV6) - case SOCKET_OPT_LEVEL_IPV6: + case ESOCK_OPT_LEVEL_IPV6: *isOTP = FALSE; #if defined(SOL_IPV6) *level = SOL_IPV6; @@ -11026,20 +11073,20 @@ BOOLEAN_T elevel2level(BOOLEAN_T isEncoded, break; #endif - case SOCKET_OPT_LEVEL_TCP: + case ESOCK_OPT_LEVEL_TCP: *isOTP = FALSE; *level = IPPROTO_TCP; result = TRUE; break; - case SOCKET_OPT_LEVEL_UDP: + case ESOCK_OPT_LEVEL_UDP: *isOTP = FALSE; *level = IPPROTO_UDP; result = TRUE; break; #ifdef HAVE_SCTP - case SOCKET_OPT_LEVEL_SCTP: + case ESOCK_OPT_LEVEL_SCTP: *isOTP = FALSE; *level = IPPROTO_SCTP; result = TRUE; @@ -11184,7 +11231,7 @@ ERL_NIF_TERM nif_getopt(ErlNifEnv* env, SGDBG( ("SOCKET", "nif_getopt -> entry with argc: %d\r\n", argc) ); if ((argc != 4) || - !enif_get_resource(env, argv[0], sockets, (void**) &descP) || + !ESOCK_GET_RESOURCE(env, argv[0], (void**) &descP) || !GET_INT(env, argv[2], &eLevel)) { SGDBG( ("SOCKET", "nif_getopt -> failed processing args\r\n") ); return enif_make_badarg(env); @@ -11210,7 +11257,7 @@ ERL_NIF_TERM nif_getopt(ErlNifEnv* env, MLOCK(descP->cfgMtx); - result = ngetopt(env, descP, isEncoded, isOTP, level, eOpt); + result = esock_getopt(env, descP, isEncoded, isOTP, level, eOpt); MUNLOCK(descP->cfgMtx); @@ -11223,18 +11270,18 @@ ERL_NIF_TERM nif_getopt(ErlNifEnv* env, #if !defined(__WIN32__) static -ERL_NIF_TERM ngetopt(ErlNifEnv* env, - ESockDescriptor* descP, - BOOLEAN_T isEncoded, - BOOLEAN_T isOTP, - int level, - ERL_NIF_TERM eOpt) +ERL_NIF_TERM esock_getopt(ErlNifEnv* env, + ESockDescriptor* descP, + BOOLEAN_T isEncoded, + BOOLEAN_T isOTP, + int level, + ERL_NIF_TERM eOpt) { ERL_NIF_TERM result; int opt; SSDBG( descP, - ("SOCKET", "ngetopt -> entry with" + ("SOCKET", "esock_getopt -> entry with" "\r\n isEncoded: %s" "\r\n isOTP: %s" "\r\n level: %d" @@ -11246,20 +11293,20 @@ ERL_NIF_TERM ngetopt(ErlNifEnv* env, * but options for our implementation. */ if (GET_INT(env, eOpt, &opt)) - result = ngetopt_otp(env, descP, opt); + result = esock_getopt_otp(env, descP, opt); else result = esock_make_error(env, esock_atom_einval); } else if (!isEncoded) { - result = ngetopt_native(env, descP, level, eOpt); + result = esock_getopt_native(env, descP, level, eOpt); } else { if (GET_INT(env, eOpt, &opt)) - result = ngetopt_level(env, descP, level, opt); + result = esock_getopt_level(env, descP, level, opt); else result = esock_make_error(env, esock_atom_einval); } SSDBG( descP, - ("SOCKET", "ngetopt -> done when" + ("SOCKET", "esock_getopt -> done when" "\r\n result: %T" "\r\n", result) ); @@ -11268,60 +11315,60 @@ ERL_NIF_TERM ngetopt(ErlNifEnv* env, -/* ngetopt_otp - Handle OTP (level) options +/* esock_getopt_otp - Handle OTP (level) options */ static -ERL_NIF_TERM ngetopt_otp(ErlNifEnv* env, - ESockDescriptor* descP, - int eOpt) +ERL_NIF_TERM esock_getopt_otp(ErlNifEnv* env, + ESockDescriptor* descP, + int eOpt) { ERL_NIF_TERM result; SSDBG( descP, - ("SOCKET", "ngetopt_otp -> entry with" + ("SOCKET", "esock_getopt_otp -> entry with" "\r\n eOpt: %d" "\r\n", eOpt) ); switch (eOpt) { - case SOCKET_OPT_OTP_DEBUG: - result = ngetopt_otp_debug(env, descP); + case ESOCK_OPT_OTP_DEBUG: + result = esock_getopt_otp_debug(env, descP); break; - case SOCKET_OPT_OTP_IOW: - result = ngetopt_otp_iow(env, descP); + case ESOCK_OPT_OTP_IOW: + result = esock_getopt_otp_iow(env, descP); break; - case SOCKET_OPT_OTP_CTRL_PROC: - result = ngetopt_otp_ctrl_proc(env, descP); + case ESOCK_OPT_OTP_CTRL_PROC: + result = esock_getopt_otp_ctrl_proc(env, descP); break; - case SOCKET_OPT_OTP_RCVBUF: - result = ngetopt_otp_rcvbuf(env, descP); + case ESOCK_OPT_OTP_RCVBUF: + result = esock_getopt_otp_rcvbuf(env, descP); break; - case SOCKET_OPT_OTP_RCVCTRLBUF: - result = ngetopt_otp_rcvctrlbuf(env, descP); + case ESOCK_OPT_OTP_RCVCTRLBUF: + result = esock_getopt_otp_rcvctrlbuf(env, descP); break; - case SOCKET_OPT_OTP_SNDCTRLBUF: - result = ngetopt_otp_sndctrlbuf(env, descP); + case ESOCK_OPT_OTP_SNDCTRLBUF: + result = esock_getopt_otp_sndctrlbuf(env, descP); break; - case SOCKET_OPT_OTP_FD: - result = ngetopt_otp_fd(env, descP); + case ESOCK_OPT_OTP_FD: + result = esock_getopt_otp_fd(env, descP); break; /* *** INTERNAL *** */ - case SOCKET_OPT_OTP_DOMAIN: - result = ngetopt_otp_domain(env, descP); + case ESOCK_OPT_OTP_DOMAIN: + result = esock_getopt_otp_domain(env, descP); break; - case SOCKET_OPT_OTP_TYPE: - result = ngetopt_otp_type(env, descP); + case ESOCK_OPT_OTP_TYPE: + result = esock_getopt_otp_type(env, descP); break; - case SOCKET_OPT_OTP_PROTOCOL: - result = ngetopt_otp_protocol(env, descP); + case ESOCK_OPT_OTP_PROTOCOL: + result = esock_getopt_otp_protocol(env, descP); break; default: @@ -11330,7 +11377,7 @@ ERL_NIF_TERM ngetopt_otp(ErlNifEnv* env, } SSDBG( descP, - ("SOCKET", "ngetopt_otp -> done when" + ("SOCKET", "esock_getopt_otp -> done when" "\r\n result: %T" "\r\n", result) ); @@ -11338,11 +11385,11 @@ ERL_NIF_TERM ngetopt_otp(ErlNifEnv* env, } -/* ngetopt_otp_debug - Handle the OTP (level) debug option +/* esock_getopt_otp_debug - Handle the OTP (level) debug option */ static -ERL_NIF_TERM ngetopt_otp_debug(ErlNifEnv* env, - ESockDescriptor* descP) +ERL_NIF_TERM esock_getopt_otp_debug(ErlNifEnv* env, + ESockDescriptor* descP) { ERL_NIF_TERM eVal = esock_encode_bool(descP->dbg); @@ -11350,11 +11397,11 @@ ERL_NIF_TERM ngetopt_otp_debug(ErlNifEnv* env, } -/* ngetopt_otp_iow - Handle the OTP (level) iow option +/* esock_getopt_otp_iow - Handle the OTP (level) iow option */ static -ERL_NIF_TERM ngetopt_otp_iow(ErlNifEnv* env, - ESockDescriptor* descP) +ERL_NIF_TERM esock_getopt_otp_iow(ErlNifEnv* env, + ESockDescriptor* descP) { ERL_NIF_TERM eVal = esock_encode_bool(descP->iow); @@ -11362,11 +11409,11 @@ ERL_NIF_TERM ngetopt_otp_iow(ErlNifEnv* env, } -/* ngetopt_otp_ctrl_proc - Handle the OTP (level) controlling_process option +/* esock_getopt_otp_ctrl_proc - Handle the OTP (level) controlling_process option */ static -ERL_NIF_TERM ngetopt_otp_ctrl_proc(ErlNifEnv* env, - ESockDescriptor* descP) +ERL_NIF_TERM esock_getopt_otp_ctrl_proc(ErlNifEnv* env, + ESockDescriptor* descP) { ERL_NIF_TERM eVal = MKPID(env, &descP->ctrlPid); @@ -11375,11 +11422,11 @@ ERL_NIF_TERM ngetopt_otp_ctrl_proc(ErlNifEnv* env, -/* ngetopt_otp_rcvbuf - Handle the OTP (level) rcvbuf option +/* esock_getopt_otp_rcvbuf - Handle the OTP (level) rcvbuf option */ static -ERL_NIF_TERM ngetopt_otp_rcvbuf(ErlNifEnv* env, - ESockDescriptor* descP) +ERL_NIF_TERM esock_getopt_otp_rcvbuf(ErlNifEnv* env, + ESockDescriptor* descP) { ERL_NIF_TERM eVal; @@ -11393,11 +11440,11 @@ ERL_NIF_TERM ngetopt_otp_rcvbuf(ErlNifEnv* env, } -/* ngetopt_otp_rcvctrlbuf - Handle the OTP (level) rcvctrlbuf option +/* esock_getopt_otp_rcvctrlbuf - Handle the OTP (level) rcvctrlbuf option */ static -ERL_NIF_TERM ngetopt_otp_rcvctrlbuf(ErlNifEnv* env, - ESockDescriptor* descP) +ERL_NIF_TERM esock_getopt_otp_rcvctrlbuf(ErlNifEnv* env, + ESockDescriptor* descP) { ERL_NIF_TERM eVal = MKI(env, descP->rCtrlSz); @@ -11405,11 +11452,11 @@ ERL_NIF_TERM ngetopt_otp_rcvctrlbuf(ErlNifEnv* env, } -/* ngetopt_otp_sndctrlbuf - Handle the OTP (level) sndctrlbuf option +/* esock_getopt_otp_sndctrlbuf - Handle the OTP (level) sndctrlbuf option */ static -ERL_NIF_TERM ngetopt_otp_sndctrlbuf(ErlNifEnv* env, - ESockDescriptor* descP) +ERL_NIF_TERM esock_getopt_otp_sndctrlbuf(ErlNifEnv* env, + ESockDescriptor* descP) { ERL_NIF_TERM eVal = MKI(env, descP->wCtrlSz); @@ -11417,11 +11464,11 @@ ERL_NIF_TERM ngetopt_otp_sndctrlbuf(ErlNifEnv* env, } -/* ngetopt_otp_fd - Handle the OTP (level) fd option +/* esock_getopt_otp_fd - Handle the OTP (level) fd option */ static -ERL_NIF_TERM ngetopt_otp_fd(ErlNifEnv* env, - ESockDescriptor* descP) +ERL_NIF_TERM esock_getopt_otp_fd(ErlNifEnv* env, + ESockDescriptor* descP) { ERL_NIF_TERM eVal = MKI(env, descP->sock); @@ -11429,11 +11476,11 @@ ERL_NIF_TERM ngetopt_otp_fd(ErlNifEnv* env, } -/* ngetopt_otp_domain - Handle the OTP (level) domain option +/* esock_getopt_otp_domain - Handle the OTP (level) domain option */ static -ERL_NIF_TERM ngetopt_otp_domain(ErlNifEnv* env, - ESockDescriptor* descP) +ERL_NIF_TERM esock_getopt_otp_domain(ErlNifEnv* env, + ESockDescriptor* descP) { ERL_NIF_TERM result, reason; int val = descP->domain; @@ -11465,11 +11512,11 @@ ERL_NIF_TERM ngetopt_otp_domain(ErlNifEnv* env, } -/* ngetopt_otp_type - Handle the OTP (level) type options. +/* esock_getopt_otp_type - Handle the OTP (level) type options. */ static -ERL_NIF_TERM ngetopt_otp_type(ErlNifEnv* env, - ESockDescriptor* descP) +ERL_NIF_TERM esock_getopt_otp_type(ErlNifEnv* env, + ESockDescriptor* descP) { ERL_NIF_TERM result, reason; int val = descP->type; @@ -11506,11 +11553,11 @@ ERL_NIF_TERM ngetopt_otp_type(ErlNifEnv* env, } -/* ngetopt_otp_protocol - Handle the OTP (level) protocol options. +/* esock_getopt_otp_protocol - Handle the OTP (level) protocol options. */ static -ERL_NIF_TERM ngetopt_otp_protocol(ErlNifEnv* env, - ESockDescriptor* descP) +ERL_NIF_TERM esock_getopt_otp_protocol(ErlNifEnv* env, + ESockDescriptor* descP) { ERL_NIF_TERM result, reason; int val = descP->protocol; @@ -11558,10 +11605,10 @@ ERL_NIF_TERM ngetopt_otp_protocol(ErlNifEnv* env, * format: {NativeOpt :: integer(), ValueSize :: non_neg_integer()} */ static -ERL_NIF_TERM ngetopt_native(ErlNifEnv* env, - ESockDescriptor* descP, - int level, - ERL_NIF_TERM eOpt) +ERL_NIF_TERM esock_getopt_native(ErlNifEnv* env, + ESockDescriptor* descP, + int level, + ERL_NIF_TERM eOpt) { ERL_NIF_TERM result = enif_make_badarg(env); int opt; @@ -11569,7 +11616,7 @@ ERL_NIF_TERM ngetopt_native(ErlNifEnv* env, SOCKOPTLEN_T valueSz; SSDBG( descP, - ("SOCKET", "ngetopt_native -> entry with" + ("SOCKET", "esock_getopt_native -> entry with" "\r\n level: %d" "\r\n eOpt: %T" "\r\n", level, eOpt) ); @@ -11583,20 +11630,21 @@ ERL_NIF_TERM ngetopt_native(ErlNifEnv* env, if (decode_native_get_opt(env, eOpt, &opt, &valueType, (int*) &valueSz)) { SSDBG( descP, - ("SOCKET", "ngetopt_native -> decoded opt" + ("SOCKET", "esock_getopt_native -> decoded opt" "\r\n valueType: %d (%s)" "\r\n ValueSize: %d" "\r\n", valueType, VT2S(valueType), valueSz) ); switch (valueType) { - case SOCKET_OPT_VALUE_TYPE_UNSPEC: - result = ngetopt_native_unspec(env, descP, level, opt, valueSz); + case ESOCK_OPT_VALUE_TYPE_UNSPEC: + result = esock_getopt_native_unspec(env, descP, + level, opt, valueSz); break; - case SOCKET_OPT_VALUE_TYPE_INT: - result = ngetopt_int_opt(env, descP, level, opt); + case ESOCK_OPT_VALUE_TYPE_INT: + result = esock_getopt_int_opt(env, descP, level, opt); break; - case SOCKET_OPT_VALUE_TYPE_BOOL: - result = ngetopt_bool_opt(env, descP, level, opt); + case ESOCK_OPT_VALUE_TYPE_BOOL: + result = esock_getopt_bool_opt(env, descP, level, opt); break; default: result = esock_make_error(env, esock_atom_einval); @@ -11607,7 +11655,7 @@ ERL_NIF_TERM ngetopt_native(ErlNifEnv* env, } SSDBG( descP, - ("SOCKET", "ngetopt_native -> done when" + ("SOCKET", "esock_getopt_native -> done when" "\r\n result: %T" "\r\n", result) ); @@ -11616,17 +11664,17 @@ ERL_NIF_TERM ngetopt_native(ErlNifEnv* env, static -ERL_NIF_TERM ngetopt_native_unspec(ErlNifEnv* env, - ESockDescriptor* descP, - int level, - int opt, - SOCKOPTLEN_T valueSz) +ERL_NIF_TERM esock_getopt_native_unspec(ErlNifEnv* env, + ESockDescriptor* descP, + int level, + int opt, + SOCKOPTLEN_T valueSz) { ERL_NIF_TERM result = esock_make_error(env, esock_atom_einval); int res; SSDBG( descP, - ("SOCKET", "ngetopt_native_unspec -> entry with" + ("SOCKET", "esock_getopt_native_unspec -> entry with" "\r\n level: %d" "\r\n opt: %d" "\r\n valueSz: %d" @@ -11642,7 +11690,8 @@ ERL_NIF_TERM ngetopt_native_unspec(ErlNifEnv* env, SOCKOPTLEN_T vsz = valueSz; ErlNifBinary val; - SSDBG( descP, ("SOCKET", "ngetopt_native_unspec -> try alloc buffer\r\n") ); + SSDBG( descP, ("SOCKET", + "esock_getopt_native_unspec -> try alloc buffer\r\n") ); if (ALLOC_BIN(vsz, &val)) { int saveErrno; @@ -11674,7 +11723,7 @@ ERL_NIF_TERM ngetopt_native_unspec(ErlNifEnv* env, } SSDBG( descP, - ("SOCKET", "ngetopt_native_unspec -> done when" + ("SOCKET", "esock_getopt_native_unspec -> done when" "\r\n result: %T" "\r\n", result) ); @@ -11683,25 +11732,25 @@ ERL_NIF_TERM ngetopt_native_unspec(ErlNifEnv* env, -/* ngetopt_level - A "proper" level (option) has been specified +/* esock_getopt_level - A "proper" level (option) has been specified */ static -ERL_NIF_TERM ngetopt_level(ErlNifEnv* env, - ESockDescriptor* descP, - int level, - int eOpt) +ERL_NIF_TERM esock_getopt_level(ErlNifEnv* env, + ESockDescriptor* descP, + int level, + int eOpt) { ERL_NIF_TERM result; SSDBG( descP, - ("SOCKET", "ngetopt_level -> entry with" + ("SOCKET", "esock_getopt_level -> entry with" "\r\n level: %d" "\r\n eOpt: %d" "\r\n", level, eOpt) ); switch (level) { case SOL_SOCKET: - result = ngetopt_lvl_socket(env, descP, eOpt); + result = esock_getopt_lvl_socket(env, descP, eOpt); break; #if defined(SOL_IP) @@ -11709,7 +11758,7 @@ ERL_NIF_TERM ngetopt_level(ErlNifEnv* env, #else case IPPROTO_IP: #endif - result = ngetopt_lvl_ip(env, descP, eOpt); + result = esock_getopt_lvl_ip(env, descP, eOpt); break; #if defined(HAVE_IPV6) @@ -11718,21 +11767,21 @@ ERL_NIF_TERM ngetopt_level(ErlNifEnv* env, #else case IPPROTO_IPV6: #endif - result = ngetopt_lvl_ipv6(env, descP, eOpt); + result = esock_getopt_lvl_ipv6(env, descP, eOpt); break; #endif case IPPROTO_TCP: - result = ngetopt_lvl_tcp(env, descP, eOpt); + result = esock_getopt_lvl_tcp(env, descP, eOpt); break; case IPPROTO_UDP: - result = ngetopt_lvl_udp(env, descP, eOpt); + result = esock_getopt_lvl_udp(env, descP, eOpt); break; #if defined(HAVE_SCTP) case IPPROTO_SCTP: - result = ngetopt_lvl_sctp(env, descP, eOpt); + result = esock_getopt_lvl_sctp(env, descP, eOpt); break; #endif @@ -11742,7 +11791,7 @@ ERL_NIF_TERM ngetopt_level(ErlNifEnv* env, } SSDBG( descP, - ("SOCKET", "ngetopt_level -> done when" + ("SOCKET", "esock_getopt_level -> done when" "\r\n result: %T" "\r\n", result) ); @@ -11750,150 +11799,150 @@ ERL_NIF_TERM ngetopt_level(ErlNifEnv* env, } -/* ngetopt_lvl_socket - Level *SOCKET* option +/* esock_getopt_lvl_socket - Level *SOCKET* option */ static -ERL_NIF_TERM ngetopt_lvl_socket(ErlNifEnv* env, - ESockDescriptor* descP, - int eOpt) +ERL_NIF_TERM esock_getopt_lvl_socket(ErlNifEnv* env, + ESockDescriptor* descP, + int eOpt) { ERL_NIF_TERM result; SSDBG( descP, - ("SOCKET", "ngetopt_lvl_socket -> entry with" + ("SOCKET", "esock_getopt_lvl_socket -> entry with" "\r\n eOpt: %d" "\r\n", eOpt) ); switch (eOpt) { #if defined(SO_ACCEPTCONN) - case SOCKET_OPT_SOCK_ACCEPTCONN: - result = ngetopt_lvl_sock_acceptconn(env, descP); + case ESOCK_OPT_SOCK_ACCEPTCONN: + result = esock_getopt_lvl_sock_acceptconn(env, descP); break; #endif #if defined(SO_BINDTODEVICE) - case SOCKET_OPT_SOCK_BINDTODEVICE: - result = ngetopt_lvl_sock_bindtodevice(env, descP); + case ESOCK_OPT_SOCK_BINDTODEVICE: + result = esock_getopt_lvl_sock_bindtodevice(env, descP); break; #endif #if defined(SO_BROADCAST) - case SOCKET_OPT_SOCK_BROADCAST: - result = ngetopt_lvl_sock_broadcast(env, descP); + case ESOCK_OPT_SOCK_BROADCAST: + result = esock_getopt_lvl_sock_broadcast(env, descP); break; #endif #if defined(SO_DEBUG) - case SOCKET_OPT_SOCK_DEBUG: - result = ngetopt_lvl_sock_debug(env, descP); + case ESOCK_OPT_SOCK_DEBUG: + result = esock_getopt_lvl_sock_debug(env, descP); break; #endif #if defined(SO_DOMAIN) - case SOCKET_OPT_SOCK_DOMAIN: - result = ngetopt_lvl_sock_domain(env, descP); + case ESOCK_OPT_SOCK_DOMAIN: + result = esock_getopt_lvl_sock_domain(env, descP); break; #endif #if defined(SO_DONTROUTE) - case SOCKET_OPT_SOCK_DONTROUTE: - result = ngetopt_lvl_sock_dontroute(env, descP); + case ESOCK_OPT_SOCK_DONTROUTE: + result = esock_getopt_lvl_sock_dontroute(env, descP); break; #endif #if defined(SO_KEEPALIVE) - case SOCKET_OPT_SOCK_KEEPALIVE: - result = ngetopt_lvl_sock_keepalive(env, descP); + case ESOCK_OPT_SOCK_KEEPALIVE: + result = esock_getopt_lvl_sock_keepalive(env, descP); break; #endif #if defined(SO_LINGER) - case SOCKET_OPT_SOCK_LINGER: - result = ngetopt_lvl_sock_linger(env, descP); + case ESOCK_OPT_SOCK_LINGER: + result = esock_getopt_lvl_sock_linger(env, descP); break; #endif #if defined(SO_OOBINLINE) - case SOCKET_OPT_SOCK_OOBINLINE: - result = ngetopt_lvl_sock_oobinline(env, descP); + case ESOCK_OPT_SOCK_OOBINLINE: + result = esock_getopt_lvl_sock_oobinline(env, descP); break; #endif #if defined(SO_PEEK_OFF) - case SOCKET_OPT_SOCK_PEEK_OFF: - result = ngetopt_lvl_sock_peek_off(env, descP); + case ESOCK_OPT_SOCK_PEEK_OFF: + result = esock_getopt_lvl_sock_peek_off(env, descP); break; #endif #if defined(SO_PRIORITY) - case SOCKET_OPT_SOCK_PRIORITY: - result = ngetopt_lvl_sock_priority(env, descP); + case ESOCK_OPT_SOCK_PRIORITY: + result = esock_getopt_lvl_sock_priority(env, descP); break; #endif #if defined(SO_PROTOCOL) - case SOCKET_OPT_SOCK_PROTOCOL: - result = ngetopt_lvl_sock_protocol(env, descP); + case ESOCK_OPT_SOCK_PROTOCOL: + result = esock_getopt_lvl_sock_protocol(env, descP); break; #endif #if defined(SO_RCVBUF) - case SOCKET_OPT_SOCK_RCVBUF: - result = ngetopt_lvl_sock_rcvbuf(env, descP); + case ESOCK_OPT_SOCK_RCVBUF: + result = esock_getopt_lvl_sock_rcvbuf(env, descP); break; #endif #if defined(SO_RCVLOWAT) - case SOCKET_OPT_SOCK_RCVLOWAT: - result = ngetopt_lvl_sock_rcvlowat(env, descP); + case ESOCK_OPT_SOCK_RCVLOWAT: + result = esock_getopt_lvl_sock_rcvlowat(env, descP); break; #endif #if defined(SO_RCVTIMEO) - case SOCKET_OPT_SOCK_RCVTIMEO: - result = ngetopt_lvl_sock_rcvtimeo(env, descP); + case ESOCK_OPT_SOCK_RCVTIMEO: + result = esock_getopt_lvl_sock_rcvtimeo(env, descP); break; #endif #if defined(SO_REUSEADDR) - case SOCKET_OPT_SOCK_REUSEADDR: - result = ngetopt_lvl_sock_reuseaddr(env, descP); + case ESOCK_OPT_SOCK_REUSEADDR: + result = esock_getopt_lvl_sock_reuseaddr(env, descP); break; #endif #if defined(SO_REUSEPORT) - case SOCKET_OPT_SOCK_REUSEPORT: - result = ngetopt_lvl_sock_reuseport(env, descP); + case ESOCK_OPT_SOCK_REUSEPORT: + result = esock_getopt_lvl_sock_reuseport(env, descP); break; #endif #if defined(SO_SNDBUF) - case SOCKET_OPT_SOCK_SNDBUF: - result = ngetopt_lvl_sock_sndbuf(env, descP); + case ESOCK_OPT_SOCK_SNDBUF: + result = esock_getopt_lvl_sock_sndbuf(env, descP); break; #endif #if defined(SO_SNDLOWAT) - case SOCKET_OPT_SOCK_SNDLOWAT: - result = ngetopt_lvl_sock_sndlowat(env, descP); + case ESOCK_OPT_SOCK_SNDLOWAT: + result = esock_getopt_lvl_sock_sndlowat(env, descP); break; #endif #if defined(SO_SNDTIMEO) - case SOCKET_OPT_SOCK_SNDTIMEO: - result = ngetopt_lvl_sock_sndtimeo(env, descP); + case ESOCK_OPT_SOCK_SNDTIMEO: + result = esock_getopt_lvl_sock_sndtimeo(env, descP); break; #endif #if defined(SO_TIMESTAMP) - case SOCKET_OPT_SOCK_TIMESTAMP: - result = ngetopt_lvl_sock_timestamp(env, descP); + case ESOCK_OPT_SOCK_TIMESTAMP: + result = esock_getopt_lvl_sock_timestamp(env, descP); break; #endif #if defined(SO_TYPE) - case SOCKET_OPT_SOCK_TYPE: - result = ngetopt_lvl_sock_type(env, descP); + case ESOCK_OPT_SOCK_TYPE: + result = esock_getopt_lvl_sock_type(env, descP); break; #endif @@ -11903,7 +11952,7 @@ ERL_NIF_TERM ngetopt_lvl_socket(ErlNifEnv* env, } SSDBG( descP, - ("SOCKET", "ngetopt_lvl_socket -> done when" + ("SOCKET", "esock_getopt_lvl_socket -> done when" "\r\n result: %T" "\r\n", result) ); @@ -11913,51 +11962,52 @@ ERL_NIF_TERM ngetopt_lvl_socket(ErlNifEnv* env, #if defined(SO_ACCEPTCONN) static -ERL_NIF_TERM ngetopt_lvl_sock_acceptconn(ErlNifEnv* env, - ESockDescriptor* descP) +ERL_NIF_TERM esock_getopt_lvl_sock_acceptconn(ErlNifEnv* env, + ESockDescriptor* descP) { - return ngetopt_bool_opt(env, descP, SOL_SOCKET, SO_ACCEPTCONN); + return esock_getopt_bool_opt(env, descP, SOL_SOCKET, SO_ACCEPTCONN); } #endif #if defined(SO_BINDTODEVICE) static -ERL_NIF_TERM ngetopt_lvl_sock_bindtodevice(ErlNifEnv* env, - ESockDescriptor* descP) +ERL_NIF_TERM esock_getopt_lvl_sock_bindtodevice(ErlNifEnv* env, + ESockDescriptor* descP) { SSDBG( descP, - ("SOCKET", "ngetopt_lvl_sock_bindtodevice -> entry with\r\n") ); + ("SOCKET", "esock_getopt_lvl_sock_bindtodevice -> entry with\r\n") ); - return ngetopt_str_opt(env, descP, SOL_SOCKET, SO_BROADCAST, IFNAMSIZ+1); + return esock_getopt_str_opt(env, descP, + SOL_SOCKET, SO_BINDTODEVICE, IFNAMSIZ+1); } #endif #if defined(SO_BROADCAST) static -ERL_NIF_TERM ngetopt_lvl_sock_broadcast(ErlNifEnv* env, - ESockDescriptor* descP) +ERL_NIF_TERM esock_getopt_lvl_sock_broadcast(ErlNifEnv* env, + ESockDescriptor* descP) { - return ngetopt_bool_opt(env, descP, SOL_SOCKET, SO_BROADCAST); + return esock_getopt_bool_opt(env, descP, SOL_SOCKET, SO_BROADCAST); } #endif #if defined(SO_DEBUG) static -ERL_NIF_TERM ngetopt_lvl_sock_debug(ErlNifEnv* env, - ESockDescriptor* descP) +ERL_NIF_TERM esock_getopt_lvl_sock_debug(ErlNifEnv* env, + ESockDescriptor* descP) { - return ngetopt_int_opt(env, descP, SOL_SOCKET, SO_DEBUG); + return esock_getopt_int_opt(env, descP, SOL_SOCKET, SO_DEBUG); } #endif #if defined(SO_DOMAIN) static -ERL_NIF_TERM ngetopt_lvl_sock_domain(ErlNifEnv* env, - ESockDescriptor* descP) +ERL_NIF_TERM esock_getopt_lvl_sock_domain(ErlNifEnv* env, + ESockDescriptor* descP) { ERL_NIF_TERM result, reason; int val; @@ -12001,28 +12051,28 @@ ERL_NIF_TERM ngetopt_lvl_sock_domain(ErlNifEnv* env, #if defined(SO_DONTROUTE) static -ERL_NIF_TERM ngetopt_lvl_sock_dontroute(ErlNifEnv* env, - ESockDescriptor* descP) +ERL_NIF_TERM esock_getopt_lvl_sock_dontroute(ErlNifEnv* env, + ESockDescriptor* descP) { - return ngetopt_bool_opt(env, descP, SOL_SOCKET, SO_DONTROUTE); + return esock_getopt_bool_opt(env, descP, SOL_SOCKET, SO_DONTROUTE); } #endif #if defined(SO_KEEPALIVE) static -ERL_NIF_TERM ngetopt_lvl_sock_keepalive(ErlNifEnv* env, - ESockDescriptor* descP) +ERL_NIF_TERM esock_getopt_lvl_sock_keepalive(ErlNifEnv* env, + ESockDescriptor* descP) { - return ngetopt_bool_opt(env, descP, SOL_SOCKET, SO_KEEPALIVE); + return esock_getopt_bool_opt(env, descP, SOL_SOCKET, SO_KEEPALIVE); } #endif #if defined(SO_LINGER) static -ERL_NIF_TERM ngetopt_lvl_sock_linger(ErlNifEnv* env, - ESockDescriptor* descP) +ERL_NIF_TERM esock_getopt_lvl_sock_linger(ErlNifEnv* env, + ESockDescriptor* descP) { ERL_NIF_TERM result; struct linger val; @@ -12051,38 +12101,38 @@ ERL_NIF_TERM ngetopt_lvl_sock_linger(ErlNifEnv* env, #if defined(SO_OOBINLINE) static -ERL_NIF_TERM ngetopt_lvl_sock_oobinline(ErlNifEnv* env, - ESockDescriptor* descP) +ERL_NIF_TERM esock_getopt_lvl_sock_oobinline(ErlNifEnv* env, + ESockDescriptor* descP) { - return ngetopt_bool_opt(env, descP, SOL_SOCKET, SO_OOBINLINE); + return esock_getopt_bool_opt(env, descP, SOL_SOCKET, SO_OOBINLINE); } #endif #if defined(SO_PEEK_OFF) static -ERL_NIF_TERM ngetopt_lvl_sock_peek_off(ErlNifEnv* env, - ESockDescriptor* descP) +ERL_NIF_TERM esock_getopt_lvl_sock_peek_off(ErlNifEnv* env, + ESockDescriptor* descP) { - return ngetopt_int_opt(env, descP, SOL_SOCKET, SO_PEEK_OFF); + return esock_getopt_int_opt(env, descP, SOL_SOCKET, SO_PEEK_OFF); } #endif #if defined(SO_PRIORITY) static -ERL_NIF_TERM ngetopt_lvl_sock_priority(ErlNifEnv* env, - ESockDescriptor* descP) +ERL_NIF_TERM esock_getopt_lvl_sock_priority(ErlNifEnv* env, + ESockDescriptor* descP) { - return ngetopt_int_opt(env, descP, SOL_SOCKET, SO_PRIORITY); + return esock_getopt_int_opt(env, descP, SOL_SOCKET, SO_PRIORITY); } #endif #if defined(SO_PROTOCOL) static -ERL_NIF_TERM ngetopt_lvl_sock_protocol(ErlNifEnv* env, - ESockDescriptor* descP) +ERL_NIF_TERM esock_getopt_lvl_sock_protocol(ErlNifEnv* env, + ESockDescriptor* descP) { ERL_NIF_TERM result, reason; int val; @@ -12135,98 +12185,98 @@ ERL_NIF_TERM ngetopt_lvl_sock_protocol(ErlNifEnv* env, #if defined(SO_RCVBUF) static -ERL_NIF_TERM ngetopt_lvl_sock_rcvbuf(ErlNifEnv* env, - ESockDescriptor* descP) +ERL_NIF_TERM esock_getopt_lvl_sock_rcvbuf(ErlNifEnv* env, + ESockDescriptor* descP) { - return ngetopt_int_opt(env, descP, SOL_SOCKET, SO_RCVBUF); + return esock_getopt_int_opt(env, descP, SOL_SOCKET, SO_RCVBUF); } #endif #if defined(SO_RCVLOWAT) static -ERL_NIF_TERM ngetopt_lvl_sock_rcvlowat(ErlNifEnv* env, - ESockDescriptor* descP) +ERL_NIF_TERM esock_getopt_lvl_sock_rcvlowat(ErlNifEnv* env, + ESockDescriptor* descP) { - return ngetopt_int_opt(env, descP, SOL_SOCKET, SO_RCVLOWAT); + return esock_getopt_int_opt(env, descP, SOL_SOCKET, SO_RCVLOWAT); } #endif #if defined(SO_RCVTIMEO) static -ERL_NIF_TERM ngetopt_lvl_sock_rcvtimeo(ErlNifEnv* env, - ESockDescriptor* descP) +ERL_NIF_TERM esock_getopt_lvl_sock_rcvtimeo(ErlNifEnv* env, + ESockDescriptor* descP) { - return ngetopt_timeval_opt(env, descP, SOL_SOCKET, SO_RCVTIMEO); + return esock_getopt_timeval_opt(env, descP, SOL_SOCKET, SO_RCVTIMEO); } #endif #if defined(SO_REUSEADDR) static -ERL_NIF_TERM ngetopt_lvl_sock_reuseaddr(ErlNifEnv* env, - ESockDescriptor* descP) +ERL_NIF_TERM esock_getopt_lvl_sock_reuseaddr(ErlNifEnv* env, + ESockDescriptor* descP) { - return ngetopt_bool_opt(env, descP, SOL_SOCKET, SO_REUSEADDR); + return esock_getopt_bool_opt(env, descP, SOL_SOCKET, SO_REUSEADDR); } #endif #if defined(SO_REUSEPORT) static -ERL_NIF_TERM ngetopt_lvl_sock_reuseport(ErlNifEnv* env, - ESockDescriptor* descP) +ERL_NIF_TERM esock_getopt_lvl_sock_reuseport(ErlNifEnv* env, + ESockDescriptor* descP) { - return ngetopt_bool_opt(env, descP, SOL_SOCKET, SO_REUSEPORT); + return esock_getopt_bool_opt(env, descP, SOL_SOCKET, SO_REUSEPORT); } #endif #if defined(SO_SNDBUF) static -ERL_NIF_TERM ngetopt_lvl_sock_sndbuf(ErlNifEnv* env, - ESockDescriptor* descP) +ERL_NIF_TERM esock_getopt_lvl_sock_sndbuf(ErlNifEnv* env, + ESockDescriptor* descP) { - return ngetopt_int_opt(env, descP, SOL_SOCKET, SO_SNDBUF); + return esock_getopt_int_opt(env, descP, SOL_SOCKET, SO_SNDBUF); } #endif #if defined(SO_SNDLOWAT) static -ERL_NIF_TERM ngetopt_lvl_sock_sndlowat(ErlNifEnv* env, - ESockDescriptor* descP) +ERL_NIF_TERM esock_getopt_lvl_sock_sndlowat(ErlNifEnv* env, + ESockDescriptor* descP) { - return ngetopt_int_opt(env, descP, SOL_SOCKET, SO_SNDLOWAT); + return esock_getopt_int_opt(env, descP, SOL_SOCKET, SO_SNDLOWAT); } #endif #if defined(SO_SNDTIMEO) static -ERL_NIF_TERM ngetopt_lvl_sock_sndtimeo(ErlNifEnv* env, - ESockDescriptor* descP) +ERL_NIF_TERM esock_getopt_lvl_sock_sndtimeo(ErlNifEnv* env, + ESockDescriptor* descP) { - return ngetopt_timeval_opt(env, descP, SOL_SOCKET, SO_SNDTIMEO); + return esock_getopt_timeval_opt(env, descP, SOL_SOCKET, SO_SNDTIMEO); } #endif #if defined(SO_TIMESTAMP) static -ERL_NIF_TERM ngetopt_lvl_sock_timestamp(ErlNifEnv* env, - ESockDescriptor* descP) +ERL_NIF_TERM esock_getopt_lvl_sock_timestamp(ErlNifEnv* env, + ESockDescriptor* descP) { - return ngetopt_bool_opt(env, descP, SOL_SOCKET, SO_TIMESTAMP); + return esock_getopt_bool_opt(env, descP, SOL_SOCKET, SO_TIMESTAMP); } #endif #if defined(SO_TYPE) static -ERL_NIF_TERM ngetopt_lvl_sock_type(ErlNifEnv* env, - ESockDescriptor* descP) +ERL_NIF_TERM esock_getopt_lvl_sock_type(ErlNifEnv* env, + ESockDescriptor* descP) { ERL_NIF_TERM result, reason; int val; @@ -12268,174 +12318,174 @@ ERL_NIF_TERM ngetopt_lvl_sock_type(ErlNifEnv* env, #endif -/* ngetopt_lvl_ip - Level *IP* option(s) +/* esock_getopt_lvl_ip - Level *IP* option(s) */ static -ERL_NIF_TERM ngetopt_lvl_ip(ErlNifEnv* env, - ESockDescriptor* descP, - int eOpt) +ERL_NIF_TERM esock_getopt_lvl_ip(ErlNifEnv* env, + ESockDescriptor* descP, + int eOpt) { ERL_NIF_TERM result; SSDBG( descP, - ("SOCKET", "ngetopt_lvl_ip -> entry with" + ("SOCKET", "esock_getopt_lvl_ip -> entry with" "\r\n eOpt: %d" "\r\n", eOpt) ); switch (eOpt) { #if defined(IP_FREEBIND) - case SOCKET_OPT_IP_FREEBIND: - result = ngetopt_lvl_ip_freebind(env, descP); + case ESOCK_OPT_IP_FREEBIND: + result = esock_getopt_lvl_ip_freebind(env, descP); break; #endif #if defined(IP_HDRINCL) - case SOCKET_OPT_IP_HDRINCL: - result = ngetopt_lvl_ip_hdrincl(env, descP); + case ESOCK_OPT_IP_HDRINCL: + result = esock_getopt_lvl_ip_hdrincl(env, descP); break; #endif #if defined(IP_MINTTL) - case SOCKET_OPT_IP_MINTTL: - result = ngetopt_lvl_ip_minttl(env, descP); + case ESOCK_OPT_IP_MINTTL: + result = esock_getopt_lvl_ip_minttl(env, descP); break; #endif #if defined(IP_MTU) - case SOCKET_OPT_IP_MTU: - result = ngetopt_lvl_ip_mtu(env, descP); + case ESOCK_OPT_IP_MTU: + result = esock_getopt_lvl_ip_mtu(env, descP); break; #endif #if defined(IP_MTU_DISCOVER) - case SOCKET_OPT_IP_MTU_DISCOVER: - result = ngetopt_lvl_ip_mtu_discover(env, descP); + case ESOCK_OPT_IP_MTU_DISCOVER: + result = esock_getopt_lvl_ip_mtu_discover(env, descP); break; #endif #if defined(IP_MULTICAST_ALL) - case SOCKET_OPT_IP_MULTICAST_ALL: - result = ngetopt_lvl_ip_multicast_all(env, descP); + case ESOCK_OPT_IP_MULTICAST_ALL: + result = esock_getopt_lvl_ip_multicast_all(env, descP); break; #endif #if defined(IP_MULTICAST_IF) - case SOCKET_OPT_IP_MULTICAST_IF: - result = ngetopt_lvl_ip_multicast_if(env, descP); + case ESOCK_OPT_IP_MULTICAST_IF: + result = esock_getopt_lvl_ip_multicast_if(env, descP); break; #endif #if defined(IP_MULTICAST_LOOP) - case SOCKET_OPT_IP_MULTICAST_LOOP: - result = ngetopt_lvl_ip_multicast_loop(env, descP); + case ESOCK_OPT_IP_MULTICAST_LOOP: + result = esock_getopt_lvl_ip_multicast_loop(env, descP); break; #endif #if defined(IP_MULTICAST_TTL) - case SOCKET_OPT_IP_MULTICAST_TTL: - result = ngetopt_lvl_ip_multicast_ttl(env, descP); + case ESOCK_OPT_IP_MULTICAST_TTL: + result = esock_getopt_lvl_ip_multicast_ttl(env, descP); break; #endif #if defined(IP_NODEFRAG) - case SOCKET_OPT_IP_NODEFRAG: - result = ngetopt_lvl_ip_nodefrag(env, descP); + case ESOCK_OPT_IP_NODEFRAG: + result = esock_getopt_lvl_ip_nodefrag(env, descP); break; #endif #if defined(IP_PKTINFO) - case SOCKET_OPT_IP_PKTINFO: - result = ngetopt_lvl_ip_pktinfo(env, descP); + case ESOCK_OPT_IP_PKTINFO: + result = esock_getopt_lvl_ip_pktinfo(env, descP); break; #endif #if defined(IP_RECVDSTADDR) - case SOCKET_OPT_IP_RECVDSTADDR: - result = ngetopt_lvl_ip_recvdstaddr(env, descP); + case ESOCK_OPT_IP_RECVDSTADDR: + result = esock_getopt_lvl_ip_recvdstaddr(env, descP); break; #endif #if defined(IP_RECVERR) - case SOCKET_OPT_IP_RECVERR: - result = ngetopt_lvl_ip_recverr(env, descP); + case ESOCK_OPT_IP_RECVERR: + result = esock_getopt_lvl_ip_recverr(env, descP); break; #endif #if defined(IP_RECVIF) - case SOCKET_OPT_IP_RECVIF: - result = ngetopt_lvl_ip_recvif(env, descP); + case ESOCK_OPT_IP_RECVIF: + result = esock_getopt_lvl_ip_recvif(env, descP); break; #endif #if defined(IP_RECVOPTS) - case SOCKET_OPT_IP_RECVOPTS: - result = ngetopt_lvl_ip_recvopts(env, descP); + case ESOCK_OPT_IP_RECVOPTS: + result = esock_getopt_lvl_ip_recvopts(env, descP); break; #endif #if defined(IP_RECVORIGDSTADDR) - case SOCKET_OPT_IP_RECVORIGDSTADDR: - result = ngetopt_lvl_ip_recvorigdstaddr(env, descP); + case ESOCK_OPT_IP_RECVORIGDSTADDR: + result = esock_getopt_lvl_ip_recvorigdstaddr(env, descP); break; #endif #if defined(IP_RECVTOS) - case SOCKET_OPT_IP_RECVTOS: - result = ngetopt_lvl_ip_recvtos(env, descP); + case ESOCK_OPT_IP_RECVTOS: + result = esock_getopt_lvl_ip_recvtos(env, descP); break; #endif #if defined(IP_RECVTTL) - case SOCKET_OPT_IP_RECVTTL: - result = ngetopt_lvl_ip_recvttl(env, descP); + case ESOCK_OPT_IP_RECVTTL: + result = esock_getopt_lvl_ip_recvttl(env, descP); break; #endif #if defined(IP_RETOPTS) - case SOCKET_OPT_IP_RETOPTS: - result = ngetopt_lvl_ip_retopts(env, descP); + case ESOCK_OPT_IP_RETOPTS: + result = esock_getopt_lvl_ip_retopts(env, descP); break; #endif #if defined(IP_ROUTER_ALERT) - case SOCKET_OPT_IP_ROUTER_ALERT: - result = ngetopt_lvl_ip_router_alert(env, descP); + case ESOCK_OPT_IP_ROUTER_ALERT: + result = esock_getopt_lvl_ip_router_alert(env, descP); break; #endif #if defined(IP_SENDSRCADDR) - case SOCKET_OPT_IP_SENDSRCADDR: - result = ngetopt_lvl_ip_sendsrcaddr(env, descP); + case ESOCK_OPT_IP_SENDSRCADDR: + result = esock_getopt_lvl_ip_sendsrcaddr(env, descP); break; #endif #if defined(IP_TOS) - case SOCKET_OPT_IP_TOS: - result = ngetopt_lvl_ip_tos(env, descP); + case ESOCK_OPT_IP_TOS: + result = esock_getopt_lvl_ip_tos(env, descP); break; #endif #if defined(IP_TRANSPARENT) - case SOCKET_OPT_IP_TRANSPARENT: - result = ngetopt_lvl_ip_transparent(env, descP); + case ESOCK_OPT_IP_TRANSPARENT: + result = esock_getopt_lvl_ip_transparent(env, descP); break; #endif #if defined(IP_TTL) - case SOCKET_OPT_IP_TTL: - result = ngetopt_lvl_ip_ttl(env, descP); + case ESOCK_OPT_IP_TTL: + result = esock_getopt_lvl_ip_ttl(env, descP); break; #endif default: SSDBG( descP, - ("SOCKET", "ngetopt_lvl_ip -> unknown opt %d\r\n", eOpt) ); + ("SOCKET", "esock_getopt_lvl_ip -> unknown opt %d\r\n", eOpt) ); result = esock_make_error(env, esock_atom_einval); break; } SSDBG( descP, - ("SOCKET", "ngetopt_lvl_ip -> done when" + ("SOCKET", "esock_getopt_lvl_ip -> done when" "\r\n result: %T" "\r\n", result) ); @@ -12443,12 +12493,12 @@ ERL_NIF_TERM ngetopt_lvl_ip(ErlNifEnv* env, } -/* ngetopt_lvl_ip_minttl - Level IP MINTTL option +/* esock_getopt_lvl_ip_minttl - Level IP MINTTL option */ #if defined(IP_MINTTL) static -ERL_NIF_TERM ngetopt_lvl_ip_minttl(ErlNifEnv* env, - ESockDescriptor* descP) +ERL_NIF_TERM esock_getopt_lvl_ip_minttl(ErlNifEnv* env, + ESockDescriptor* descP) { #if defined(SOL_IP) int level = SOL_IP; @@ -12456,17 +12506,17 @@ ERL_NIF_TERM ngetopt_lvl_ip_minttl(ErlNifEnv* env, int level = IPPROTO_IP; #endif - return ngetopt_int_opt(env, descP, level, IP_MINTTL); + return esock_getopt_int_opt(env, descP, level, IP_MINTTL); } #endif -/* ngetopt_lvl_ip_freebind - Level IP FREEBIND option +/* esock_getopt_lvl_ip_freebind - Level IP FREEBIND option */ #if defined(IP_FREEBIND) static -ERL_NIF_TERM ngetopt_lvl_ip_freebind(ErlNifEnv* env, - ESockDescriptor* descP) +ERL_NIF_TERM esock_getopt_lvl_ip_freebind(ErlNifEnv* env, + ESockDescriptor* descP) { #if defined(SOL_IP) int level = SOL_IP; @@ -12474,17 +12524,17 @@ ERL_NIF_TERM ngetopt_lvl_ip_freebind(ErlNifEnv* env, int level = IPPROTO_IP; #endif - return ngetopt_bool_opt(env, descP, level, IP_FREEBIND); + return esock_getopt_bool_opt(env, descP, level, IP_FREEBIND); } #endif -/* ngetopt_lvl_ip_hdrincl - Level IP HDRINCL option +/* esock_getopt_lvl_ip_hdrincl - Level IP HDRINCL option */ #if defined(IP_HDRINCL) static -ERL_NIF_TERM ngetopt_lvl_ip_hdrincl(ErlNifEnv* env, - ESockDescriptor* descP) +ERL_NIF_TERM esock_getopt_lvl_ip_hdrincl(ErlNifEnv* env, + ESockDescriptor* descP) { #if defined(SOL_IP) int level = SOL_IP; @@ -12492,17 +12542,17 @@ ERL_NIF_TERM ngetopt_lvl_ip_hdrincl(ErlNifEnv* env, int level = IPPROTO_IP; #endif - return ngetopt_bool_opt(env, descP, level, IP_HDRINCL); + return esock_getopt_bool_opt(env, descP, level, IP_HDRINCL); } #endif -/* ngetopt_lvl_ip_mtu - Level IP MTU option +/* esock_getopt_lvl_ip_mtu - Level IP MTU option */ #if defined(IP_MTU) static -ERL_NIF_TERM ngetopt_lvl_ip_mtu(ErlNifEnv* env, - ESockDescriptor* descP) +ERL_NIF_TERM esock_getopt_lvl_ip_mtu(ErlNifEnv* env, + ESockDescriptor* descP) { #if defined(SOL_IP) int level = SOL_IP; @@ -12510,17 +12560,17 @@ ERL_NIF_TERM ngetopt_lvl_ip_mtu(ErlNifEnv* env, int level = IPPROTO_IP; #endif - return ngetopt_int_opt(env, descP, level, IP_MTU); + return esock_getopt_int_opt(env, descP, level, IP_MTU); } #endif -/* ngetopt_lvl_ip_mtu_discover - Level IP MTU_DISCOVER option +/* esock_getopt_lvl_ip_mtu_discover - Level IP MTU_DISCOVER option */ #if defined(IP_MTU_DISCOVER) static -ERL_NIF_TERM ngetopt_lvl_ip_mtu_discover(ErlNifEnv* env, - ESockDescriptor* descP) +ERL_NIF_TERM esock_getopt_lvl_ip_mtu_discover(ErlNifEnv* env, + ESockDescriptor* descP) { ERL_NIF_TERM result; ERL_NIF_TERM eMtuDisc; @@ -12549,12 +12599,12 @@ ERL_NIF_TERM ngetopt_lvl_ip_mtu_discover(ErlNifEnv* env, #endif -/* ngetopt_lvl_ip_multicast_all - Level IP MULTICAST_ALL option +/* esock_getopt_lvl_ip_multicast_all - Level IP MULTICAST_ALL option */ #if defined(IP_MULTICAST_ALL) static -ERL_NIF_TERM ngetopt_lvl_ip_multicast_all(ErlNifEnv* env, - ESockDescriptor* descP) +ERL_NIF_TERM esock_getopt_lvl_ip_multicast_all(ErlNifEnv* env, + ESockDescriptor* descP) { #if defined(SOL_IP) int level = SOL_IP; @@ -12562,17 +12612,17 @@ ERL_NIF_TERM ngetopt_lvl_ip_multicast_all(ErlNifEnv* env, int level = IPPROTO_IP; #endif - return ngetopt_bool_opt(env, descP, level, IP_MULTICAST_ALL); + return esock_getopt_bool_opt(env, descP, level, IP_MULTICAST_ALL); } #endif -/* ngetopt_lvl_ip_multicast_if - Level IP MULTICAST_IF option +/* esock_getopt_lvl_ip_multicast_if - Level IP MULTICAST_IF option */ #if defined(IP_MULTICAST_IF) static -ERL_NIF_TERM ngetopt_lvl_ip_multicast_if(ErlNifEnv* env, - ESockDescriptor* descP) +ERL_NIF_TERM esock_getopt_lvl_ip_multicast_if(ErlNifEnv* env, + ESockDescriptor* descP) { ERL_NIF_TERM result; ERL_NIF_TERM eAddr; @@ -12604,12 +12654,12 @@ ERL_NIF_TERM ngetopt_lvl_ip_multicast_if(ErlNifEnv* env, #endif -/* ngetopt_lvl_ip_multicast_loop - Level IP MULTICAST_LOOP option +/* esock_getopt_lvl_ip_multicast_loop - Level IP MULTICAST_LOOP option */ #if defined(IP_MULTICAST_LOOP) static -ERL_NIF_TERM ngetopt_lvl_ip_multicast_loop(ErlNifEnv* env, - ESockDescriptor* descP) +ERL_NIF_TERM esock_getopt_lvl_ip_multicast_loop(ErlNifEnv* env, + ESockDescriptor* descP) { #if defined(SOL_IP) int level = SOL_IP; @@ -12617,17 +12667,17 @@ ERL_NIF_TERM ngetopt_lvl_ip_multicast_loop(ErlNifEnv* env, int level = IPPROTO_IP; #endif - return ngetopt_bool_opt(env, descP, level, IP_MULTICAST_LOOP); + return esock_getopt_bool_opt(env, descP, level, IP_MULTICAST_LOOP); } #endif -/* ngetopt_lvl_ip_multicast_ttl - Level IP MULTICAST_TTL option +/* esock_getopt_lvl_ip_multicast_ttl - Level IP MULTICAST_TTL option */ #if defined(IP_MULTICAST_TTL) static -ERL_NIF_TERM ngetopt_lvl_ip_multicast_ttl(ErlNifEnv* env, - ESockDescriptor* descP) +ERL_NIF_TERM esock_getopt_lvl_ip_multicast_ttl(ErlNifEnv* env, + ESockDescriptor* descP) { #if defined(SOL_IP) int level = SOL_IP; @@ -12635,17 +12685,17 @@ ERL_NIF_TERM ngetopt_lvl_ip_multicast_ttl(ErlNifEnv* env, int level = IPPROTO_IP; #endif - return ngetopt_int_opt(env, descP, level, IP_MULTICAST_TTL); + return esock_getopt_int_opt(env, descP, level, IP_MULTICAST_TTL); } #endif -/* ngetopt_lvl_ip_nodefrag - Level IP NODEFRAG option +/* esock_getopt_lvl_ip_nodefrag - Level IP NODEFRAG option */ #if defined(IP_NODEFRAG) static -ERL_NIF_TERM ngetopt_lvl_ip_nodefrag(ErlNifEnv* env, - ESockDescriptor* descP) +ERL_NIF_TERM esock_getopt_lvl_ip_nodefrag(ErlNifEnv* env, + ESockDescriptor* descP) { #if defined(SOL_IP) int level = SOL_IP; @@ -12653,17 +12703,17 @@ ERL_NIF_TERM ngetopt_lvl_ip_nodefrag(ErlNifEnv* env, int level = IPPROTO_IP; #endif - return ngetopt_bool_opt(env, descP, level, IP_NODEFRAG); + return esock_getopt_bool_opt(env, descP, level, IP_NODEFRAG); } #endif -/* ngetopt_lvl_ip_pktinfo - Level IP PKTINFO option +/* esock_getopt_lvl_ip_pktinfo - Level IP PKTINFO option */ #if defined(IP_PKTINFO) static -ERL_NIF_TERM ngetopt_lvl_ip_pktinfo(ErlNifEnv* env, - ESockDescriptor* descP) +ERL_NIF_TERM esock_getopt_lvl_ip_pktinfo(ErlNifEnv* env, + ESockDescriptor* descP) { #if defined(SOL_IP) int level = SOL_IP; @@ -12671,17 +12721,17 @@ ERL_NIF_TERM ngetopt_lvl_ip_pktinfo(ErlNifEnv* env, int level = IPPROTO_IP; #endif - return ngetopt_bool_opt(env, descP, level, IP_PKTINFO); + return esock_getopt_bool_opt(env, descP, level, IP_PKTINFO); } #endif -/* ngetopt_lvl_ip_recvtos - Level IP RECVTOS option +/* esock_getopt_lvl_ip_recvtos - Level IP RECVTOS option */ #if defined(IP_RECVTOS) static -ERL_NIF_TERM ngetopt_lvl_ip_recvtos(ErlNifEnv* env, - ESockDescriptor* descP) +ERL_NIF_TERM esock_getopt_lvl_ip_recvtos(ErlNifEnv* env, + ESockDescriptor* descP) { #if defined(SOL_IP) int level = SOL_IP; @@ -12689,17 +12739,17 @@ ERL_NIF_TERM ngetopt_lvl_ip_recvtos(ErlNifEnv* env, int level = IPPROTO_IP; #endif - return ngetopt_bool_opt(env, descP, level, IP_RECVTOS); + return esock_getopt_bool_opt(env, descP, level, IP_RECVTOS); } #endif -/* ngetopt_lvl_ip_recvdstaddr - Level IP RECVDSTADDR option +/* esock_getopt_lvl_ip_recvdstaddr - Level IP RECVDSTADDR option */ #if defined(IP_RECVDSTADDR) static -ERL_NIF_TERM ngetopt_lvl_ip_recvdstaddr(ErlNifEnv* env, - ESockDescriptor* descP) +ERL_NIF_TERM esock_getopt_lvl_ip_recvdstaddr(ErlNifEnv* env, + ESockDescriptor* descP) { #if defined(SOL_IP) int level = SOL_IP; @@ -12707,17 +12757,17 @@ ERL_NIF_TERM ngetopt_lvl_ip_recvdstaddr(ErlNifEnv* env, int level = IPPROTO_IP; #endif - return ngetopt_bool_opt(env, descP, level, IP_RECVDSTADDR); + return esock_getopt_bool_opt(env, descP, level, IP_RECVDSTADDR); } #endif -/* ngetopt_lvl_ip_recverr - Level IP RECVERR option +/* esock_getopt_lvl_ip_recverr - Level IP RECVERR option */ #if defined(IP_RECVERR) static -ERL_NIF_TERM ngetopt_lvl_ip_recverr(ErlNifEnv* env, - ESockDescriptor* descP) +ERL_NIF_TERM esock_getopt_lvl_ip_recverr(ErlNifEnv* env, + ESockDescriptor* descP) { #if defined(SOL_IP) int level = SOL_IP; @@ -12725,17 +12775,17 @@ ERL_NIF_TERM ngetopt_lvl_ip_recverr(ErlNifEnv* env, int level = IPPROTO_IP; #endif - return ngetopt_bool_opt(env, descP, level, IP_RECVERR); + return esock_getopt_bool_opt(env, descP, level, IP_RECVERR); } #endif -/* ngetopt_lvl_ip_recvif - Level IP RECVIF option +/* esock_getopt_lvl_ip_recvif - Level IP RECVIF option */ #if defined(IP_RECVIF) static -ERL_NIF_TERM ngetopt_lvl_ip_recvif(ErlNifEnv* env, - ESockDescriptor* descP) +ERL_NIF_TERM esock_getopt_lvl_ip_recvif(ErlNifEnv* env, + ESockDescriptor* descP) { #if defined(SOL_IP) int level = SOL_IP; @@ -12743,17 +12793,17 @@ ERL_NIF_TERM ngetopt_lvl_ip_recvif(ErlNifEnv* env, int level = IPPROTO_IP; #endif - return ngetopt_bool_opt(env, descP, level, IP_RECVIF); + return esock_getopt_bool_opt(env, descP, level, IP_RECVIF); } #endif -/* ngetopt_lvl_ip_recvopt - Level IP RECVOPTS option +/* esock_getopt_lvl_ip_recvopt - Level IP RECVOPTS option */ #if defined(IP_RECVOPTS) static -ERL_NIF_TERM ngetopt_lvl_ip_recvopts(ErlNifEnv* env, - ESockDescriptor* descP) +ERL_NIF_TERM esock_getopt_lvl_ip_recvopts(ErlNifEnv* env, + ESockDescriptor* descP) { #if defined(SOL_IP) int level = SOL_IP; @@ -12761,17 +12811,17 @@ ERL_NIF_TERM ngetopt_lvl_ip_recvopts(ErlNifEnv* env, int level = IPPROTO_IP; #endif - return ngetopt_bool_opt(env, descP, level, IP_RECVOPTS); + return esock_getopt_bool_opt(env, descP, level, IP_RECVOPTS); } #endif -/* ngetopt_lvl_ip_recvorigdstaddr - Level IP RECVORIGDSTADDR option +/* esock_getopt_lvl_ip_recvorigdstaddr - Level IP RECVORIGDSTADDR option */ #if defined(IP_RECVORIGDSTADDR) static -ERL_NIF_TERM ngetopt_lvl_ip_recvorigdstaddr(ErlNifEnv* env, - ESockDescriptor* descP) +ERL_NIF_TERM esock_getopt_lvl_ip_recvorigdstaddr(ErlNifEnv* env, + ESockDescriptor* descP) { #if defined(SOL_IP) int level = SOL_IP; @@ -12779,17 +12829,17 @@ ERL_NIF_TERM ngetopt_lvl_ip_recvorigdstaddr(ErlNifEnv* env, int level = IPPROTO_IP; #endif - return ngetopt_bool_opt(env, descP, level, IP_RECVORIGDSTADDR); + return esock_getopt_bool_opt(env, descP, level, IP_RECVORIGDSTADDR); } #endif -/* ngetopt_lvl_ip_recvttl - Level IP RECVTTL option +/* esock_getopt_lvl_ip_recvttl - Level IP RECVTTL option */ #if defined(IP_RECVTTL) static -ERL_NIF_TERM ngetopt_lvl_ip_recvttl(ErlNifEnv* env, - ESockDescriptor* descP) +ERL_NIF_TERM esock_getopt_lvl_ip_recvttl(ErlNifEnv* env, + ESockDescriptor* descP) { #if defined(SOL_IP) int level = SOL_IP; @@ -12797,17 +12847,17 @@ ERL_NIF_TERM ngetopt_lvl_ip_recvttl(ErlNifEnv* env, int level = IPPROTO_IP; #endif - return ngetopt_bool_opt(env, descP, level, IP_RECVTTL); + return esock_getopt_bool_opt(env, descP, level, IP_RECVTTL); } #endif -/* ngetopt_lvl_ip_retopts - Level IP RETOPTS option +/* esock_getopt_lvl_ip_retopts - Level IP RETOPTS option */ #if defined(IP_RETOPTS) static -ERL_NIF_TERM ngetopt_lvl_ip_retopts(ErlNifEnv* env, - ESockDescriptor* descP) +ERL_NIF_TERM esock_getopt_lvl_ip_retopts(ErlNifEnv* env, + ESockDescriptor* descP) { #if defined(SOL_IP) int level = SOL_IP; @@ -12815,17 +12865,17 @@ ERL_NIF_TERM ngetopt_lvl_ip_retopts(ErlNifEnv* env, int level = IPPROTO_IP; #endif - return ngetopt_bool_opt(env, descP, level, IP_RETOPTS); + return esock_getopt_bool_opt(env, descP, level, IP_RETOPTS); } #endif -/* ngetopt_lvl_ip_router_alert - Level IP ROUTER_ALERT option +/* esock_getopt_lvl_ip_router_alert - Level IP ROUTER_ALERT option */ #if defined(IP_ROUTER_ALERT) static -ERL_NIF_TERM ngetopt_lvl_ip_router_alert(ErlNifEnv* env, - ESockDescriptor* descP) +ERL_NIF_TERM esock_getopt_lvl_ip_router_alert(ErlNifEnv* env, + ESockDescriptor* descP) { #if defined(SOL_IP) int level = SOL_IP; @@ -12833,17 +12883,17 @@ ERL_NIF_TERM ngetopt_lvl_ip_router_alert(ErlNifEnv* env, int level = IPPROTO_IP; #endif - return ngetopt_int_opt(env, descP, level, IP_ROUTER_ALERT); + return esock_getopt_int_opt(env, descP, level, IP_ROUTER_ALERT); } #endif -/* ngetopt_lvl_ip_sendsrcaddr - Level IP SENDSRCADDR option +/* esock_getopt_lvl_ip_sendsrcaddr - Level IP SENDSRCADDR option */ #if defined(IP_SENDSRCADDR) static -ERL_NIF_TERM ngetopt_lvl_ip_sendsrcaddr(ErlNifEnv* env, - ESockDescriptor* descP) +ERL_NIF_TERM esock_getopt_lvl_ip_sendsrcaddr(ErlNifEnv* env, + ESockDescriptor* descP) { #if defined(SOL_IP) int level = SOL_IP; @@ -12851,17 +12901,17 @@ ERL_NIF_TERM ngetopt_lvl_ip_sendsrcaddr(ErlNifEnv* env, int level = IPPROTO_IP; #endif - return ngetopt_bool_opt(env, descP, level, IP_SENDSRCADDR); + return esock_getopt_bool_opt(env, descP, level, IP_SENDSRCADDR); } #endif -/* ngetopt_lvl_ip_tos - Level IP TOS option +/* esock_getopt_lvl_ip_tos - Level IP TOS option */ #if defined(IP_TOS) static -ERL_NIF_TERM ngetopt_lvl_ip_tos(ErlNifEnv* env, - ESockDescriptor* descP) +ERL_NIF_TERM esock_getopt_lvl_ip_tos(ErlNifEnv* env, + ESockDescriptor* descP) { #if defined(SOL_IP) int level = SOL_IP; @@ -12886,12 +12936,12 @@ ERL_NIF_TERM ngetopt_lvl_ip_tos(ErlNifEnv* env, #endif -/* ngetopt_lvl_ip_transparent - Level IP TRANSPARENT option +/* esock_getopt_lvl_ip_transparent - Level IP TRANSPARENT option */ #if defined(IP_TRANSPARENT) static -ERL_NIF_TERM ngetopt_lvl_ip_transparent(ErlNifEnv* env, - ESockDescriptor* descP) +ERL_NIF_TERM esock_getopt_lvl_ip_transparent(ErlNifEnv* env, + ESockDescriptor* descP) { #if defined(SOL_IP) int level = SOL_IP; @@ -12899,18 +12949,18 @@ ERL_NIF_TERM ngetopt_lvl_ip_transparent(ErlNifEnv* env, int level = IPPROTO_IP; #endif - return ngetopt_bool_opt(env, descP, level, IP_TRANSPARENT); + return esock_getopt_bool_opt(env, descP, level, IP_TRANSPARENT); } #endif -/* ngetopt_lvl_ip_ttl - Level IP TTL option +/* esock_getopt_lvl_ip_ttl - Level IP TTL option */ #if defined(IP_TTL) static -ERL_NIF_TERM ngetopt_lvl_ip_ttl(ErlNifEnv* env, - ESockDescriptor* descP) +ERL_NIF_TERM esock_getopt_lvl_ip_ttl(ErlNifEnv* env, + ESockDescriptor* descP) { #if defined(SOL_IP) int level = SOL_IP; @@ -12918,121 +12968,121 @@ ERL_NIF_TERM ngetopt_lvl_ip_ttl(ErlNifEnv* env, int level = IPPROTO_IP; #endif - return ngetopt_int_opt(env, descP, level, IP_TTL); + return esock_getopt_int_opt(env, descP, level, IP_TTL); } #endif -/* ngetopt_lvl_ipv6 - Level *IPv6* option(s) +/* esock_getopt_lvl_ipv6 - Level *IPv6* option(s) */ #if defined(HAVE_IPV6) static -ERL_NIF_TERM ngetopt_lvl_ipv6(ErlNifEnv* env, - ESockDescriptor* descP, - int eOpt) +ERL_NIF_TERM esock_getopt_lvl_ipv6(ErlNifEnv* env, + ESockDescriptor* descP, + int eOpt) { ERL_NIF_TERM result; SSDBG( descP, - ("SOCKET", "ngetopt_lvl_ipv6 -> entry with" + ("SOCKET", "esock_getopt_lvl_ipv6 -> entry with" "\r\n eOpt: %d" "\r\n", eOpt) ); switch (eOpt) { #if defined(IPV6_AUTHHDR) - case SOCKET_OPT_IPV6_AUTHHDR: - result = ngetopt_lvl_ipv6_authhdr(env, descP); + case ESOCK_OPT_IPV6_AUTHHDR: + result = esock_getopt_lvl_ipv6_authhdr(env, descP); break; #endif #if defined(IPV6_DSTOPTS) - case SOCKET_OPT_IPV6_DSTOPTS: - result = ngetopt_lvl_ipv6_dstopts(env, descP); + case ESOCK_OPT_IPV6_DSTOPTS: + result = esock_getopt_lvl_ipv6_dstopts(env, descP); break; #endif #if defined(IPV6_FLOWINFO) - case SOCKET_OPT_IPV6_FLOWINFO: - result = ngetopt_lvl_ipv6_flowinfo(env, descP); + case ESOCK_OPT_IPV6_FLOWINFO: + result = esock_getopt_lvl_ipv6_flowinfo(env, descP); break; #endif #if defined(IPV6_HOPLIMIT) - case SOCKET_OPT_IPV6_HOPLIMIT: - result = ngetopt_lvl_ipv6_hoplimit(env, descP); + case ESOCK_OPT_IPV6_HOPLIMIT: + result = esock_getopt_lvl_ipv6_hoplimit(env, descP); break; #endif #if defined(IPV6_HOPOPTS) - case SOCKET_OPT_IPV6_HOPOPTS: - result = ngetopt_lvl_ipv6_hopopts(env, descP); + case ESOCK_OPT_IPV6_HOPOPTS: + result = esock_getopt_lvl_ipv6_hopopts(env, descP); break; #endif #if defined(IPV6_MTU) - case SOCKET_OPT_IPV6_MTU: - result = ngetopt_lvl_ipv6_mtu(env, descP); + case ESOCK_OPT_IPV6_MTU: + result = esock_getopt_lvl_ipv6_mtu(env, descP); break; #endif #if defined(IPV6_MTU_DISCOVER) - case SOCKET_OPT_IPV6_MTU_DISCOVER: - result = ngetopt_lvl_ipv6_mtu_discover(env, descP); + case ESOCK_OPT_IPV6_MTU_DISCOVER: + result = esock_getopt_lvl_ipv6_mtu_discover(env, descP); break; #endif #if defined(IPV6_MULTICAST_HOPS) - case SOCKET_OPT_IPV6_MULTICAST_HOPS: - result = ngetopt_lvl_ipv6_multicast_hops(env, descP); + case ESOCK_OPT_IPV6_MULTICAST_HOPS: + result = esock_getopt_lvl_ipv6_multicast_hops(env, descP); break; #endif #if defined(IPV6_MULTICAST_IF) - case SOCKET_OPT_IPV6_MULTICAST_IF: - result = ngetopt_lvl_ipv6_multicast_if(env, descP); + case ESOCK_OPT_IPV6_MULTICAST_IF: + result = esock_getopt_lvl_ipv6_multicast_if(env, descP); break; #endif #if defined(IPV6_MULTICAST_LOOP) - case SOCKET_OPT_IPV6_MULTICAST_LOOP: - result = ngetopt_lvl_ipv6_multicast_loop(env, descP); + case ESOCK_OPT_IPV6_MULTICAST_LOOP: + result = esock_getopt_lvl_ipv6_multicast_loop(env, descP); break; #endif #if defined(IPV6_RECVERR) - case SOCKET_OPT_IPV6_RECVERR: - result = ngetopt_lvl_ipv6_recverr(env, descP); + case ESOCK_OPT_IPV6_RECVERR: + result = esock_getopt_lvl_ipv6_recverr(env, descP); break; #endif #if defined(IPV6_RECVPKTINFO) || defined(IPV6_PKTINFO) - case SOCKET_OPT_IPV6_RECVPKTINFO: - result = ngetopt_lvl_ipv6_recvpktinfo(env, descP); + case ESOCK_OPT_IPV6_RECVPKTINFO: + result = esock_getopt_lvl_ipv6_recvpktinfo(env, descP); break; #endif #if defined(IPV6_ROUTER_ALERT) - case SOCKET_OPT_IPV6_ROUTER_ALERT: - result = ngetopt_lvl_ipv6_router_alert(env, descP); + case ESOCK_OPT_IPV6_ROUTER_ALERT: + result = esock_getopt_lvl_ipv6_router_alert(env, descP); break; #endif #if defined(IPV6_RTHDR) - case SOCKET_OPT_IPV6_RTHDR: - result = ngetopt_lvl_ipv6_rthdr(env, descP); + case ESOCK_OPT_IPV6_RTHDR: + result = esock_getopt_lvl_ipv6_rthdr(env, descP); break; #endif #if defined(IPV6_UNICAST_HOPS) - case SOCKET_OPT_IPV6_UNICAST_HOPS: - result = ngetopt_lvl_ipv6_unicast_hops(env, descP); + case ESOCK_OPT_IPV6_UNICAST_HOPS: + result = esock_getopt_lvl_ipv6_unicast_hops(env, descP); break; #endif #if defined(IPV6_V6ONLY) - case SOCKET_OPT_IPV6_V6ONLY: - result = ngetopt_lvl_ipv6_v6only(env, descP); + case ESOCK_OPT_IPV6_V6ONLY: + result = esock_getopt_lvl_ipv6_v6only(env, descP); break; #endif @@ -13042,7 +13092,7 @@ ERL_NIF_TERM ngetopt_lvl_ipv6(ErlNifEnv* env, } SSDBG( descP, - ("SOCKET", "ngetopt_lvl_ipv6 -> done when" + ("SOCKET", "esock_getopt_lvl_ipv6 -> done when" "\r\n result: %T" "\r\n", result) ); @@ -13052,33 +13102,33 @@ ERL_NIF_TERM ngetopt_lvl_ipv6(ErlNifEnv* env, #if defined(IPV6_AUTHHDR) static -ERL_NIF_TERM ngetopt_lvl_ipv6_authhdr(ErlNifEnv* env, - ESockDescriptor* descP) +ERL_NIF_TERM esock_getopt_lvl_ipv6_authhdr(ErlNifEnv* env, + ESockDescriptor* descP) { - return ngetopt_bool_opt(env, descP, SOL_IPV6, IPV6_AUTHHDR); + return esock_getopt_bool_opt(env, descP, SOL_IPV6, IPV6_AUTHHDR); } #endif #if defined(IPV6_DSTOPTS) static -ERL_NIF_TERM ngetopt_lvl_ipv6_dstopts(ErlNifEnv* env, - ESockDescriptor* descP) +ERL_NIF_TERM esock_getopt_lvl_ipv6_dstopts(ErlNifEnv* env, + ESockDescriptor* descP) { #if defined(SOL_IPV6) int level = SOL_IPV6; #else int level = IPPROTO_IPV6; #endif - return ngetopt_bool_opt(env, descP, level, IPV6_DSTOPTS); + return esock_getopt_bool_opt(env, descP, level, IPV6_DSTOPTS); } #endif #if defined(IPV6_FLOWINFO) static -ERL_NIF_TERM ngetopt_lvl_ipv6_flowinfo(ErlNifEnv* env, - ESockDescriptor* descP) +ERL_NIF_TERM esock_getopt_lvl_ipv6_flowinfo(ErlNifEnv* env, + ESockDescriptor* descP) { #if defined(SOL_IPV6) int level = SOL_IPV6; @@ -13086,15 +13136,15 @@ ERL_NIF_TERM ngetopt_lvl_ipv6_flowinfo(ErlNifEnv* env, int level = IPPROTO_IPV6; #endif - return ngetopt_bool_opt(env, descP, level, IPV6_FLOWINFO); + return esock_getopt_bool_opt(env, descP, level, IPV6_FLOWINFO); } #endif #if defined(IPV6_HOPLIMIT) static -ERL_NIF_TERM ngetopt_lvl_ipv6_hoplimit(ErlNifEnv* env, - ESockDescriptor* descP) +ERL_NIF_TERM esock_getopt_lvl_ipv6_hoplimit(ErlNifEnv* env, + ESockDescriptor* descP) { #if defined(SOL_IPV6) int level = SOL_IPV6; @@ -13102,15 +13152,15 @@ ERL_NIF_TERM ngetopt_lvl_ipv6_hoplimit(ErlNifEnv* env, int level = IPPROTO_IPV6; #endif - return ngetopt_bool_opt(env, descP, level, IPV6_HOPLIMIT); + return esock_getopt_bool_opt(env, descP, level, IPV6_HOPLIMIT); } #endif #if defined(IPV6_HOPOPTS) static -ERL_NIF_TERM ngetopt_lvl_ipv6_hopopts(ErlNifEnv* env, - ESockDescriptor* descP) +ERL_NIF_TERM esock_getopt_lvl_ipv6_hopopts(ErlNifEnv* env, + ESockDescriptor* descP) { #if defined(SOL_IPV6) int level = SOL_IPV6; @@ -13118,15 +13168,15 @@ ERL_NIF_TERM ngetopt_lvl_ipv6_hopopts(ErlNifEnv* env, int level = IPPROTO_IPV6; #endif - return ngetopt_bool_opt(env, descP, level, IPV6_HOPOPTS); + return esock_getopt_bool_opt(env, descP, level, IPV6_HOPOPTS); } #endif #if defined(IPV6_MTU) static -ERL_NIF_TERM ngetopt_lvl_ipv6_mtu(ErlNifEnv* env, - ESockDescriptor* descP) +ERL_NIF_TERM esock_getopt_lvl_ipv6_mtu(ErlNifEnv* env, + ESockDescriptor* descP) { #if defined(SOL_IPV6) int level = SOL_IPV6; @@ -13134,17 +13184,17 @@ ERL_NIF_TERM ngetopt_lvl_ipv6_mtu(ErlNifEnv* env, int level = IPPROTO_IPV6; #endif - return ngetopt_int_opt(env, descP, level, IPV6_MTU); + return esock_getopt_int_opt(env, descP, level, IPV6_MTU); } #endif -/* ngetopt_lvl_ipv6_mtu_discover - Level IPv6 MTU_DISCOVER option +/* esock_getopt_lvl_ipv6_mtu_discover - Level IPv6 MTU_DISCOVER option */ #if defined(IPV6_MTU_DISCOVER) static -ERL_NIF_TERM ngetopt_lvl_ipv6_mtu_discover(ErlNifEnv* env, - ESockDescriptor* descP) +ERL_NIF_TERM esock_getopt_lvl_ipv6_mtu_discover(ErlNifEnv* env, + ESockDescriptor* descP) { ERL_NIF_TERM result; ERL_NIF_TERM eMtuDisc; @@ -13175,8 +13225,8 @@ ERL_NIF_TERM ngetopt_lvl_ipv6_mtu_discover(ErlNifEnv* env, #if defined(IPV6_MULTICAST_HOPS) static -ERL_NIF_TERM ngetopt_lvl_ipv6_multicast_hops(ErlNifEnv* env, - ESockDescriptor* descP) +ERL_NIF_TERM esock_getopt_lvl_ipv6_multicast_hops(ErlNifEnv* env, + ESockDescriptor* descP) { #if defined(SOL_IPV6) int level = SOL_IPV6; @@ -13184,15 +13234,15 @@ ERL_NIF_TERM ngetopt_lvl_ipv6_multicast_hops(ErlNifEnv* env, int level = IPPROTO_IPV6; #endif - return ngetopt_int_opt(env, descP, level, IPV6_MULTICAST_HOPS); + return esock_getopt_int_opt(env, descP, level, IPV6_MULTICAST_HOPS); } #endif #if defined(IPV6_MULTICAST_IF) static -ERL_NIF_TERM ngetopt_lvl_ipv6_multicast_if(ErlNifEnv* env, - ESockDescriptor* descP) +ERL_NIF_TERM esock_getopt_lvl_ipv6_multicast_if(ErlNifEnv* env, + ESockDescriptor* descP) { #if defined(SOL_IPV6) int level = SOL_IPV6; @@ -13200,15 +13250,15 @@ ERL_NIF_TERM ngetopt_lvl_ipv6_multicast_if(ErlNifEnv* env, int level = IPPROTO_IPV6; #endif - return ngetopt_int_opt(env, descP, level, IPV6_MULTICAST_IF); + return esock_getopt_int_opt(env, descP, level, IPV6_MULTICAST_IF); } #endif #if defined(IPV6_MULTICAST_LOOP) static -ERL_NIF_TERM ngetopt_lvl_ipv6_multicast_loop(ErlNifEnv* env, - ESockDescriptor* descP) +ERL_NIF_TERM esock_getopt_lvl_ipv6_multicast_loop(ErlNifEnv* env, + ESockDescriptor* descP) { #if defined(SOL_IPV6) int level = SOL_IPV6; @@ -13216,15 +13266,15 @@ ERL_NIF_TERM ngetopt_lvl_ipv6_multicast_loop(ErlNifEnv* env, int level = IPPROTO_IPV6; #endif - return ngetopt_bool_opt(env, descP, level, IPV6_MULTICAST_LOOP); + return esock_getopt_bool_opt(env, descP, level, IPV6_MULTICAST_LOOP); } #endif #if defined(IPV6_RECVERR) static -ERL_NIF_TERM ngetopt_lvl_ipv6_recverr(ErlNifEnv* env, - ESockDescriptor* descP) +ERL_NIF_TERM esock_getopt_lvl_ipv6_recverr(ErlNifEnv* env, + ESockDescriptor* descP) { #if defined(SOL_IPV6) int level = SOL_IPV6; @@ -13232,15 +13282,15 @@ ERL_NIF_TERM ngetopt_lvl_ipv6_recverr(ErlNifEnv* env, int level = IPPROTO_IPV6; #endif - return ngetopt_bool_opt(env, descP, level, IPV6_RECVERR); + return esock_getopt_bool_opt(env, descP, level, IPV6_RECVERR); } #endif #if defined(IPV6_RECVPKTINFO) || defined(IPV6_PKTINFO) static -ERL_NIF_TERM ngetopt_lvl_ipv6_recvpktinfo(ErlNifEnv* env, - ESockDescriptor* descP) +ERL_NIF_TERM esock_getopt_lvl_ipv6_recvpktinfo(ErlNifEnv* env, + ESockDescriptor* descP) { #if defined(SOL_IPV6) int level = SOL_IPV6; @@ -13253,15 +13303,15 @@ ERL_NIF_TERM ngetopt_lvl_ipv6_recvpktinfo(ErlNifEnv* env, int opt = IPV6_PKTINFO; #endif - return ngetopt_bool_opt(env, descP, level, opt); + return esock_getopt_bool_opt(env, descP, level, opt); } #endif #if defined(IPV6_ROUTER_ALERT) static -ERL_NIF_TERM ngetopt_lvl_ipv6_router_alert(ErlNifEnv* env, - ESockDescriptor* descP) +ERL_NIF_TERM esock_getopt_lvl_ipv6_router_alert(ErlNifEnv* env, + ESockDescriptor* descP) { #if defined(SOL_IPV6) int level = SOL_IPV6; @@ -13269,15 +13319,15 @@ ERL_NIF_TERM ngetopt_lvl_ipv6_router_alert(ErlNifEnv* env, int level = IPPROTO_IPV6; #endif - return ngetopt_int_opt(env, descP, level, IPV6_ROUTER_ALERT); + return esock_getopt_int_opt(env, descP, level, IPV6_ROUTER_ALERT); } #endif #if defined(IPV6_RTHDR) static -ERL_NIF_TERM ngetopt_lvl_ipv6_rthdr(ErlNifEnv* env, - ESockDescriptor* descP) +ERL_NIF_TERM esock_getopt_lvl_ipv6_rthdr(ErlNifEnv* env, + ESockDescriptor* descP) { #if defined(SOL_IPV6) int level = SOL_IPV6; @@ -13285,15 +13335,15 @@ ERL_NIF_TERM ngetopt_lvl_ipv6_rthdr(ErlNifEnv* env, int level = IPPROTO_IPV6; #endif - return ngetopt_bool_opt(env, descP, level, IPV6_RTHDR); + return esock_getopt_bool_opt(env, descP, level, IPV6_RTHDR); } #endif #if defined(IPV6_UNICAST_HOPS) static -ERL_NIF_TERM ngetopt_lvl_ipv6_unicast_hops(ErlNifEnv* env, - ESockDescriptor* descP) +ERL_NIF_TERM esock_getopt_lvl_ipv6_unicast_hops(ErlNifEnv* env, + ESockDescriptor* descP) { #if defined(SOL_IPV6) int level = SOL_IPV6; @@ -13301,15 +13351,15 @@ ERL_NIF_TERM ngetopt_lvl_ipv6_unicast_hops(ErlNifEnv* env, int level = IPPROTO_IPV6; #endif - return ngetopt_int_opt(env, descP, level, IPV6_UNICAST_HOPS); + return esock_getopt_int_opt(env, descP, level, IPV6_UNICAST_HOPS); } #endif #if defined(IPV6_V6ONLY) static -ERL_NIF_TERM ngetopt_lvl_ipv6_v6only(ErlNifEnv* env, - ESockDescriptor* descP) +ERL_NIF_TERM esock_getopt_lvl_ipv6_v6only(ErlNifEnv* env, + ESockDescriptor* descP) { #if defined(SOL_IPV6) int level = SOL_IPV6; @@ -13317,7 +13367,7 @@ ERL_NIF_TERM ngetopt_lvl_ipv6_v6only(ErlNifEnv* env, int level = IPPROTO_IPV6; #endif - return ngetopt_bool_opt(env, descP, level, IPV6_V6ONLY); + return esock_getopt_bool_opt(env, descP, level, IPV6_V6ONLY); } #endif @@ -13326,31 +13376,31 @@ ERL_NIF_TERM ngetopt_lvl_ipv6_v6only(ErlNifEnv* env, -/* ngetopt_lvl_tcp - Level *TCP* option(s) +/* esock_getopt_lvl_tcp - Level *TCP* option(s) */ static -ERL_NIF_TERM ngetopt_lvl_tcp(ErlNifEnv* env, - ESockDescriptor* descP, - int eOpt) +ERL_NIF_TERM esock_getopt_lvl_tcp(ErlNifEnv* env, + ESockDescriptor* descP, + int eOpt) { ERL_NIF_TERM result; switch (eOpt) { #if defined(TCP_CONGESTION) - case SOCKET_OPT_TCP_CONGESTION: - result = ngetopt_lvl_tcp_congestion(env, descP); + case ESOCK_OPT_TCP_CONGESTION: + result = esock_getopt_lvl_tcp_congestion(env, descP); break; #endif #if defined(TCP_MAXSEG) - case SOCKET_OPT_TCP_MAXSEG: - result = ngetopt_lvl_tcp_maxseg(env, descP); + case ESOCK_OPT_TCP_MAXSEG: + result = esock_getopt_lvl_tcp_maxseg(env, descP); break; #endif #if defined(TCP_NODELAY) - case SOCKET_OPT_TCP_NODELAY: - result = ngetopt_lvl_tcp_nodelay(env, descP); + case ESOCK_OPT_TCP_NODELAY: + result = esock_getopt_lvl_tcp_nodelay(env, descP); break; #endif @@ -13363,58 +13413,58 @@ ERL_NIF_TERM ngetopt_lvl_tcp(ErlNifEnv* env, } -/* ngetopt_lvl_tcp_congestion - Level TCP CONGESTION option +/* esock_getopt_lvl_tcp_congestion - Level TCP CONGESTION option */ #if defined(TCP_CONGESTION) static -ERL_NIF_TERM ngetopt_lvl_tcp_congestion(ErlNifEnv* env, - ESockDescriptor* descP) +ERL_NIF_TERM esock_getopt_lvl_tcp_congestion(ErlNifEnv* env, + ESockDescriptor* descP) { - int max = SOCKET_OPT_TCP_CONGESTION_NAME_MAX+1; + int max = ESOCK_OPT_TCP_CONGESTION_NAME_MAX+1; - return ngetopt_str_opt(env, descP, IPPROTO_TCP, TCP_CONGESTION, max); + return esock_getopt_str_opt(env, descP, IPPROTO_TCP, TCP_CONGESTION, max); } #endif -/* ngetopt_lvl_tcp_maxseg - Level TCP MAXSEG option +/* esock_getopt_lvl_tcp_maxseg - Level TCP MAXSEG option */ #if defined(TCP_MAXSEG) static -ERL_NIF_TERM ngetopt_lvl_tcp_maxseg(ErlNifEnv* env, - ESockDescriptor* descP) +ERL_NIF_TERM esock_getopt_lvl_tcp_maxseg(ErlNifEnv* env, + ESockDescriptor* descP) { - return ngetopt_int_opt(env, descP, IPPROTO_TCP, TCP_MAXSEG); + return esock_getopt_int_opt(env, descP, IPPROTO_TCP, TCP_MAXSEG); } #endif -/* ngetopt_lvl_tcp_nodelay - Level TCP NODELAY option +/* esock_getopt_lvl_tcp_nodelay - Level TCP NODELAY option */ #if defined(TCP_NODELAY) static -ERL_NIF_TERM ngetopt_lvl_tcp_nodelay(ErlNifEnv* env, - ESockDescriptor* descP) +ERL_NIF_TERM esock_getopt_lvl_tcp_nodelay(ErlNifEnv* env, + ESockDescriptor* descP) { - return ngetopt_bool_opt(env, descP, IPPROTO_TCP, TCP_NODELAY); + return esock_getopt_bool_opt(env, descP, IPPROTO_TCP, TCP_NODELAY); } #endif -/* ngetopt_lvl_udp - Level *UDP* option(s) +/* esock_getopt_lvl_udp - Level *UDP* option(s) */ static -ERL_NIF_TERM ngetopt_lvl_udp(ErlNifEnv* env, - ESockDescriptor* descP, - int eOpt) +ERL_NIF_TERM esock_getopt_lvl_udp(ErlNifEnv* env, + ESockDescriptor* descP, + int eOpt) { ERL_NIF_TERM result; switch (eOpt) { #if defined(UDP_CORK) - case SOCKET_OPT_UDP_CORK: - result = ngetopt_lvl_udp_cork(env, descP); + case ESOCK_OPT_UDP_CORK: + result = esock_getopt_lvl_udp_cork(env, descP); break; #endif @@ -13427,74 +13477,74 @@ ERL_NIF_TERM ngetopt_lvl_udp(ErlNifEnv* env, } -/* ngetopt_lvl_udp_cork - Level UDP CORK option +/* esock_getopt_lvl_udp_cork - Level UDP CORK option */ #if defined(UDP_CORK) static -ERL_NIF_TERM ngetopt_lvl_udp_cork(ErlNifEnv* env, - ESockDescriptor* descP) +ERL_NIF_TERM esock_getopt_lvl_udp_cork(ErlNifEnv* env, + ESockDescriptor* descP) { - return ngetopt_bool_opt(env, descP, IPPROTO_UDP, UDP_CORK); + return esock_getopt_bool_opt(env, descP, IPPROTO_UDP, UDP_CORK); } #endif -/* ngetopt_lvl_sctp - Level *SCTP* option(s) +/* esock_getopt_lvl_sctp - Level *SCTP* option(s) */ #if defined(HAVE_SCTP) static -ERL_NIF_TERM ngetopt_lvl_sctp(ErlNifEnv* env, - ESockDescriptor* descP, - int eOpt) +ERL_NIF_TERM esock_getopt_lvl_sctp(ErlNifEnv* env, + ESockDescriptor* descP, + int eOpt) { ERL_NIF_TERM result; SSDBG( descP, - ("SOCKET", "ngetopt_lvl_sctp -> entry with" + ("SOCKET", "esock_getopt_lvl_sctp -> entry with" "\r\n opt: %d" "\r\n", eOpt) ); switch (eOpt) { #if defined(SCTP_ASSOCINFO) - case SOCKET_OPT_SCTP_ASSOCINFO: - result = ngetopt_lvl_sctp_associnfo(env, descP); + case ESOCK_OPT_SCTP_ASSOCINFO: + result = esock_getopt_lvl_sctp_associnfo(env, descP); break; #endif #if defined(SCTP_AUTOCLOSE) - case SOCKET_OPT_SCTP_AUTOCLOSE: - result = ngetopt_lvl_sctp_autoclose(env, descP); + case ESOCK_OPT_SCTP_AUTOCLOSE: + result = esock_getopt_lvl_sctp_autoclose(env, descP); break; #endif #if defined(SCTP_DISABLE_FRAGMENTS) - case SOCKET_OPT_SCTP_DISABLE_FRAGMENTS: - result = ngetopt_lvl_sctp_disable_fragments(env, descP); + case ESOCK_OPT_SCTP_DISABLE_FRAGMENTS: + result = esock_getopt_lvl_sctp_disable_fragments(env, descP); break; #endif #if defined(SCTP_INITMSG) - case SOCKET_OPT_SCTP_INITMSG: - result = ngetopt_lvl_sctp_initmsg(env, descP); + case ESOCK_OPT_SCTP_INITMSG: + result = esock_getopt_lvl_sctp_initmsg(env, descP); break; #endif #if defined(SCTP_MAXSEG) - case SOCKET_OPT_SCTP_MAXSEG: - result = ngetopt_lvl_sctp_maxseg(env, descP); + case ESOCK_OPT_SCTP_MAXSEG: + result = esock_getopt_lvl_sctp_maxseg(env, descP); break; #endif #if defined(SCTP_NODELAY) - case SOCKET_OPT_SCTP_NODELAY: - result = ngetopt_lvl_sctp_nodelay(env, descP); + case ESOCK_OPT_SCTP_NODELAY: + result = esock_getopt_lvl_sctp_nodelay(env, descP); break; #endif #if defined(SCTP_RTOINFO) - case SOCKET_OPT_SCTP_RTOINFO: - result = ngetopt_lvl_sctp_rtoinfo(env, descP); + case ESOCK_OPT_SCTP_RTOINFO: + result = esock_getopt_lvl_sctp_rtoinfo(env, descP); break; #endif @@ -13504,7 +13554,7 @@ ERL_NIF_TERM ngetopt_lvl_sctp(ErlNifEnv* env, } SSDBG( descP, - ("SOCKET", "ngetopt_lvl_sctp -> done when" + ("SOCKET", "esock_getopt_lvl_sctp -> done when" "\r\n result: %T" "\r\n", result) ); @@ -13512,7 +13562,7 @@ ERL_NIF_TERM ngetopt_lvl_sctp(ErlNifEnv* env, } -/* ngetopt_lvl_sctp_associnfo - Level SCTP ASSOCINFO option +/* esock_getopt_lvl_sctp_associnfo - Level SCTP ASSOCINFO option * * <KOLLA> * @@ -13527,15 +13577,15 @@ ERL_NIF_TERM ngetopt_lvl_sctp(ErlNifEnv* env, */ #if defined(SCTP_ASSOCINFO) static -ERL_NIF_TERM ngetopt_lvl_sctp_associnfo(ErlNifEnv* env, - ESockDescriptor* descP) +ERL_NIF_TERM esock_getopt_lvl_sctp_associnfo(ErlNifEnv* env, + ESockDescriptor* descP) { ERL_NIF_TERM result; struct sctp_assocparams val; SOCKOPTLEN_T valSz = sizeof(val); int res; - SSDBG( descP, ("SOCKET", "ngetopt_lvl_sctp_associnfo -> entry\r\n") ); + SSDBG( descP, ("SOCKET", "esock_getopt_lvl_sctp_associnfo -> entry\r\n") ); sys_memzero((char*) &val, valSz); res = sock_getopt(descP->sock, IPPROTO_SCTP, SCTP_ASSOCINFO, &val, &valSz); @@ -13564,7 +13614,7 @@ ERL_NIF_TERM ngetopt_lvl_sctp_associnfo(ErlNifEnv* env, } SSDBG( descP, - ("SOCKET", "ngetopt_lvl_sctp_associnfo -> done with" + ("SOCKET", "esock_getopt_lvl_sctp_associnfo -> done with" "\r\n res: %d" "\r\n result: %T" "\r\n", res, result) ); @@ -13574,44 +13624,45 @@ ERL_NIF_TERM ngetopt_lvl_sctp_associnfo(ErlNifEnv* env, #endif -/* ngetopt_lvl_sctp_autoclose - Level SCTP AUTOCLOSE option +/* esock_getopt_lvl_sctp_autoclose - Level SCTP AUTOCLOSE option */ #if defined(SCTP_AUTOCLOSE) static -ERL_NIF_TERM ngetopt_lvl_sctp_autoclose(ErlNifEnv* env, - ESockDescriptor* descP) +ERL_NIF_TERM esock_getopt_lvl_sctp_autoclose(ErlNifEnv* env, + ESockDescriptor* descP) { - return ngetopt_int_opt(env, descP, IPPROTO_SCTP, SCTP_AUTOCLOSE); + return esock_getopt_int_opt(env, descP, IPPROTO_SCTP, SCTP_AUTOCLOSE); } #endif -/* ngetopt_lvl_sctp_disable_fragments - Level SCTP DISABLE:FRAGMENTS option +/* esock_getopt_lvl_sctp_disable_fragments - Level SCTP DISABLE:FRAGMENTS option */ #if defined(SCTP_DISABLE_FRAGMENTS) static -ERL_NIF_TERM ngetopt_lvl_sctp_disable_fragments(ErlNifEnv* env, - ESockDescriptor* descP) +ERL_NIF_TERM esock_getopt_lvl_sctp_disable_fragments(ErlNifEnv* env, + ESockDescriptor* descP) { - return ngetopt_bool_opt(env, descP, IPPROTO_SCTP, SCTP_DISABLE_FRAGMENTS); + return esock_getopt_bool_opt(env, descP, + IPPROTO_SCTP, SCTP_DISABLE_FRAGMENTS); } #endif -/* ngetopt_lvl_sctp_initmsg - Level SCTP INITMSG option +/* esock_getopt_lvl_sctp_initmsg - Level SCTP INITMSG option * */ #if defined(SCTP_INITMSG) static -ERL_NIF_TERM ngetopt_lvl_sctp_initmsg(ErlNifEnv* env, - ESockDescriptor* descP) +ERL_NIF_TERM esock_getopt_lvl_sctp_initmsg(ErlNifEnv* env, + ESockDescriptor* descP) { ERL_NIF_TERM result; struct sctp_initmsg val; SOCKOPTLEN_T valSz = sizeof(val); int res; - SSDBG( descP, ("SOCKET", "ngetopt_lvl_sctp_initmsg -> entry\r\n") ); + SSDBG( descP, ("SOCKET", "esock_getopt_lvl_sctp_initmsg -> entry\r\n") ); sys_memzero((char*) &val, valSz); res = sock_getopt(descP->sock, IPPROTO_SCTP, SCTP_INITMSG, &val, &valSz); @@ -13638,7 +13689,7 @@ ERL_NIF_TERM ngetopt_lvl_sctp_initmsg(ErlNifEnv* env, } SSDBG( descP, - ("SOCKET", "ngetopt_lvl_sctp_initmsg -> done with" + ("SOCKET", "esock_getopt_lvl_sctp_initmsg -> done with" "\r\n res: %d" "\r\n result: %T" "\r\n", res, result) ); @@ -13648,31 +13699,31 @@ ERL_NIF_TERM ngetopt_lvl_sctp_initmsg(ErlNifEnv* env, #endif -/* ngetopt_lvl_sctp_maxseg - Level SCTP MAXSEG option +/* esock_getopt_lvl_sctp_maxseg - Level SCTP MAXSEG option */ #if defined(SCTP_MAXSEG) static -ERL_NIF_TERM ngetopt_lvl_sctp_maxseg(ErlNifEnv* env, - ESockDescriptor* descP) +ERL_NIF_TERM esock_getopt_lvl_sctp_maxseg(ErlNifEnv* env, + ESockDescriptor* descP) { - return ngetopt_int_opt(env, descP, IPPROTO_SCTP, SCTP_MAXSEG); + return esock_getopt_int_opt(env, descP, IPPROTO_SCTP, SCTP_MAXSEG); } #endif -/* ngetopt_lvl_sctp_nodelay - Level SCTP NODELAY option +/* esock_getopt_lvl_sctp_nodelay - Level SCTP NODELAY option */ #if defined(SCTP_NODELAY) static -ERL_NIF_TERM ngetopt_lvl_sctp_nodelay(ErlNifEnv* env, - ESockDescriptor* descP) +ERL_NIF_TERM esock_getopt_lvl_sctp_nodelay(ErlNifEnv* env, + ESockDescriptor* descP) { - return ngetopt_bool_opt(env, descP, IPPROTO_SCTP, SCTP_NODELAY); + return esock_getopt_bool_opt(env, descP, IPPROTO_SCTP, SCTP_NODELAY); } #endif -/* ngetopt_lvl_sctp_associnfo - Level SCTP ASSOCINFO option +/* esock_getopt_lvl_sctp_associnfo - Level SCTP ASSOCINFO option * * <KOLLA> * @@ -13687,15 +13738,15 @@ ERL_NIF_TERM ngetopt_lvl_sctp_nodelay(ErlNifEnv* env, */ #if defined(SCTP_RTOINFO) static -ERL_NIF_TERM ngetopt_lvl_sctp_rtoinfo(ErlNifEnv* env, - ESockDescriptor* descP) +ERL_NIF_TERM esock_getopt_lvl_sctp_rtoinfo(ErlNifEnv* env, + ESockDescriptor* descP) { ERL_NIF_TERM result; struct sctp_rtoinfo val; SOCKOPTLEN_T valSz = sizeof(val); int res; - SSDBG( descP, ("SOCKET", "ngetopt_lvl_sctp_rtoinfo -> entry\r\n") ); + SSDBG( descP, ("SOCKET", "esock_getopt_lvl_sctp_rtoinfo -> entry\r\n") ); sys_memzero((char*) &val, valSz); res = sock_getopt(descP->sock, IPPROTO_SCTP, SCTP_RTOINFO, &val, &valSz); @@ -13721,7 +13772,7 @@ ERL_NIF_TERM ngetopt_lvl_sctp_rtoinfo(ErlNifEnv* env, } SSDBG( descP, - ("SOCKET", "ngetopt_lvl_sctp_rtoinfo -> done with" + ("SOCKET", "esock_getopt_lvl_sctp_rtoinfo -> done with" "\r\n res: %d" "\r\n result: %T" "\r\n", res, result) ); @@ -13736,13 +13787,13 @@ ERL_NIF_TERM ngetopt_lvl_sctp_rtoinfo(ErlNifEnv* env, -/* ngetopt_bool_opt - get an (integer) bool option +/* esock_getopt_bool_opt - get an (integer) bool option */ static -ERL_NIF_TERM ngetopt_bool_opt(ErlNifEnv* env, - ESockDescriptor* descP, - int level, - int opt) +ERL_NIF_TERM esock_getopt_bool_opt(ErlNifEnv* env, + ESockDescriptor* descP, + int level, + int opt) { ERL_NIF_TERM result; int val; @@ -13750,7 +13801,7 @@ ERL_NIF_TERM ngetopt_bool_opt(ErlNifEnv* env, int res; /* - SSDBG( descP, ("SOCKET", "ngetopt_bool_opt -> entry with" + SSDBG( descP, ("SOCKET", "esock_getopt_bool_opt -> entry with" "\r\n: level: %d" "\r\n: opt: %d" "\r\n", level, opt) ); @@ -13767,7 +13818,7 @@ ERL_NIF_TERM ngetopt_bool_opt(ErlNifEnv* env, } /* - SSDBG( descP, ("SOCKET", "ngetopt_bool_opt -> done when" + SSDBG( descP, ("SOCKET", "esock_getopt_bool_opt -> done when" "\r\n: res: %d" "\r\n: result: %T" "\r\n", res, result) ); @@ -13777,13 +13828,13 @@ ERL_NIF_TERM ngetopt_bool_opt(ErlNifEnv* env, } -/* ngetopt_int_opt - get an integer option +/* esock_getopt_int_opt - get an integer option */ static -ERL_NIF_TERM ngetopt_int_opt(ErlNifEnv* env, - ESockDescriptor* descP, - int level, - int opt) +ERL_NIF_TERM esock_getopt_int_opt(ErlNifEnv* env, + ESockDescriptor* descP, + int level, + int opt) { ERL_NIF_TERM result; int val; @@ -13803,13 +13854,13 @@ ERL_NIF_TERM ngetopt_int_opt(ErlNifEnv* env, -/* ngetopt_timeval_opt - get an timeval option +/* esock_getopt_timeval_opt - get an timeval option */ static -ERL_NIF_TERM ngetopt_timeval_opt(ErlNifEnv* env, - ESockDescriptor* descP, - int level, - int opt) +ERL_NIF_TERM esock_getopt_timeval_opt(ErlNifEnv* env, + ESockDescriptor* descP, + int level, + int opt) { ERL_NIF_TERM result; struct timeval val; @@ -13817,7 +13868,7 @@ ERL_NIF_TERM ngetopt_timeval_opt(ErlNifEnv* env, int res; SSDBG( descP, - ("SOCKET", "ngetopt_timeval_opt -> entry with" + ("SOCKET", "esock_getopt_timeval_opt -> entry with" "\r\n level: %d" "\r\n opt: %d" "\r\n", level, opt) ); @@ -13838,7 +13889,7 @@ ERL_NIF_TERM ngetopt_timeval_opt(ErlNifEnv* env, } SSDBG( descP, - ("SOCKET", "ngetopt_timeval_opt -> done when" + ("SOCKET", "esock_getopt_timeval_opt -> done when" "\r\n result: %T" "\r\n", result) ); @@ -13847,7 +13898,7 @@ ERL_NIF_TERM ngetopt_timeval_opt(ErlNifEnv* env, -/* ngetopt_str_opt - get an string option +/* esock_getopt_str_opt - get an string option * * We provide the max size of the string. This is the * size of the buffer we allocate for the value. @@ -13856,11 +13907,11 @@ ERL_NIF_TERM ngetopt_timeval_opt(ErlNifEnv* env, */ #if defined(USE_GETOPT_STR_OPT) static -ERL_NIF_TERM ngetopt_str_opt(ErlNifEnv* env, - ESockDescriptor* descP, - int level, - int opt, - int max) +ERL_NIF_TERM esock_getopt_str_opt(ErlNifEnv* env, + ESockDescriptor* descP, + int level, + int opt, + int max) { ERL_NIF_TERM result; char* val = MALLOC(max); @@ -13868,7 +13919,7 @@ ERL_NIF_TERM ngetopt_str_opt(ErlNifEnv* env, int res; SSDBG( descP, - ("SOCKET", "ngetopt_str_opt -> entry with" + ("SOCKET", "esock_getopt_str_opt -> entry with" "\r\n level: %d" "\r\n opt: %d" "\r\n max: %d" @@ -13885,7 +13936,7 @@ ERL_NIF_TERM ngetopt_str_opt(ErlNifEnv* env, } SSDBG( descP, - ("SOCKET", "ngetopt_str_opt -> done when" + ("SOCKET", "esock_getopt_str_opt -> done when" "\r\n result: %T" "\r\n", result) ); @@ -13924,7 +13975,7 @@ ERL_NIF_TERM nif_sockname(ErlNifEnv* env, /* Extract arguments and perform preliminary validation */ if ((argc != 1) || - !enif_get_resource(env, argv[0], sockets, (void**) &descP)) { + !ESOCK_GET_RESOURCE(env, argv[0], (void**) &descP)) { return enif_make_badarg(env); } @@ -13936,7 +13987,7 @@ ERL_NIF_TERM nif_sockname(ErlNifEnv* env, "\r\n Socket: %T" "\r\n", descP->sock, argv[0]) ); - res = nsockname(env, descP); + res = esock_sockname(env, descP); SSDBG( descP, ("SOCKET", "nif_sockname -> done with res = %T\r\n", res) ); @@ -13948,8 +13999,8 @@ ERL_NIF_TERM nif_sockname(ErlNifEnv* env, #if !defined(__WIN32__) static -ERL_NIF_TERM nsockname(ErlNifEnv* env, - ESockDescriptor* descP) +ERL_NIF_TERM esock_sockname(ErlNifEnv* env, + ESockDescriptor* descP) { ESockAddress sa; ESockAddress* saP = &sa; @@ -13998,7 +14049,7 @@ ERL_NIF_TERM nif_peername(ErlNifEnv* env, /* Extract arguments and perform preliminary validation */ if ((argc != 1) || - !enif_get_resource(env, argv[0], sockets, (void**) &descP)) { + !ESOCK_GET_RESOURCE(env, argv[0], (void**) &descP)) { return enif_make_badarg(env); } @@ -14010,7 +14061,7 @@ ERL_NIF_TERM nif_peername(ErlNifEnv* env, "\r\n Socket: %T" "\r\n", descP->sock, argv[0]) ); - res = npeername(env, descP); + res = esock_peername(env, descP); SSDBG( descP, ("SOCKET", "nif_peername -> done with res = %T\r\n", res) ); @@ -14022,8 +14073,8 @@ ERL_NIF_TERM nif_peername(ErlNifEnv* env, #if !defined(__WIN32__) static -ERL_NIF_TERM npeername(ErlNifEnv* env, - ESockDescriptor* descP) +ERL_NIF_TERM esock_peername(ErlNifEnv* env, + ESockDescriptor* descP) { ESockAddress sa; ESockAddress* saP = &sa; @@ -14074,7 +14125,7 @@ ERL_NIF_TERM nif_cancel(ErlNifEnv* env, sockRef = argv[0]; if ((argc != 3) || - !enif_get_resource(env, sockRef, sockets, (void**) &descP)) { + !ESOCK_GET_RESOURCE(env, sockRef, (void**) &descP)) { return enif_make_badarg(env); } op = argv[1]; @@ -14089,7 +14140,7 @@ ERL_NIF_TERM nif_cancel(ErlNifEnv* env, "\r\n opRef: %T" "\r\n", descP->sock, op, opRef) ); - result = ncancel(env, descP, op, sockRef, opRef); + result = esock_cancel(env, descP, op, sockRef, opRef); SSDBG( descP, ("SOCKET", "nif_cancel -> done with result: " @@ -14103,11 +14154,11 @@ ERL_NIF_TERM nif_cancel(ErlNifEnv* env, #if !defined(__WIN32__) static -ERL_NIF_TERM ncancel(ErlNifEnv* env, - ESockDescriptor* descP, - ERL_NIF_TERM op, - ERL_NIF_TERM sockRef, - ERL_NIF_TERM opRef) +ERL_NIF_TERM esock_cancel(ErlNifEnv* env, + ESockDescriptor* descP, + ERL_NIF_TERM op, + ERL_NIF_TERM sockRef, + ERL_NIF_TERM opRef) { /* <KOLLA> * @@ -14118,21 +14169,21 @@ ERL_NIF_TERM ncancel(ErlNifEnv* env, * </KOLLA> */ if (COMPARE(op, esock_atom_connect) == 0) { - return ncancel_connect(env, descP, opRef); + return esock_cancel_connect(env, descP, opRef); } else if (COMPARE(op, esock_atom_accept) == 0) { - return ncancel_accept(env, descP, sockRef, opRef); + return esock_cancel_accept(env, descP, sockRef, opRef); } else if (COMPARE(op, esock_atom_send) == 0) { - return ncancel_send(env, descP, sockRef, opRef); + return esock_cancel_send(env, descP, sockRef, opRef); } else if (COMPARE(op, esock_atom_sendto) == 0) { - return ncancel_send(env, descP, sockRef, opRef); + return esock_cancel_send(env, descP, sockRef, opRef); } else if (COMPARE(op, esock_atom_sendmsg) == 0) { - return ncancel_send(env, descP, sockRef, opRef); + return esock_cancel_send(env, descP, sockRef, opRef); } else if (COMPARE(op, esock_atom_recv) == 0) { - return ncancel_recv(env, descP, sockRef, opRef); + return esock_cancel_recv(env, descP, sockRef, opRef); } else if (COMPARE(op, esock_atom_recvfrom) == 0) { - return ncancel_recv(env, descP, sockRef, opRef); + return esock_cancel_recv(env, descP, sockRef, opRef); } else if (COMPARE(op, esock_atom_recvmsg) == 0) { - return ncancel_recv(env, descP, sockRef, opRef); + return esock_cancel_recv(env, descP, sockRef, opRef); } else { return esock_make_error(env, esock_atom_einval); } @@ -14140,20 +14191,20 @@ ERL_NIF_TERM ncancel(ErlNifEnv* env, -/* *** ncancel_connect *** +/* *** esock_cancel_connect *** * * */ static -ERL_NIF_TERM ncancel_connect(ErlNifEnv* env, - ESockDescriptor* descP, - ERL_NIF_TERM opRef) +ERL_NIF_TERM esock_cancel_connect(ErlNifEnv* env, + ESockDescriptor* descP, + ERL_NIF_TERM opRef) { - return ncancel_write_select(env, descP, opRef); + return esock_cancel_write_select(env, descP, opRef); } -/* *** ncancel_accept *** +/* *** esock_cancel_accept *** * * We have two different cases: * *) Its the current acceptor @@ -14164,15 +14215,15 @@ ERL_NIF_TERM ncancel_connect(ErlNifEnv* env, * */ static -ERL_NIF_TERM ncancel_accept(ErlNifEnv* env, - ESockDescriptor* descP, - ERL_NIF_TERM sockRef, - ERL_NIF_TERM opRef) +ERL_NIF_TERM esock_cancel_accept(ErlNifEnv* env, + ESockDescriptor* descP, + ERL_NIF_TERM sockRef, + ERL_NIF_TERM opRef) { ERL_NIF_TERM res; SSDBG( descP, - ("SOCKET", "ncancel_accept -> entry with" + ("SOCKET", "esock_cancel_accept -> entry with" "\r\n opRef: %T" "\r\n %s" "\r\n", opRef, @@ -14182,9 +14233,9 @@ ERL_NIF_TERM ncancel_accept(ErlNifEnv* env, if (descP->currentAcceptorP != NULL) { if (COMPARE(opRef, descP->currentAcceptor.ref) == 0) { - res = ncancel_accept_current(env, descP, sockRef); + res = esock_cancel_accept_current(env, descP, sockRef); } else { - res = ncancel_accept_waiting(env, descP, opRef); + res = esock_cancel_accept_waiting(env, descP, opRef); } } else { /* Or badarg? */ @@ -14194,7 +14245,7 @@ ERL_NIF_TERM ncancel_accept(ErlNifEnv* env, MUNLOCK(descP->accMtx); SSDBG( descP, - ("SOCKET", "ncancel_accept -> done with result:" + ("SOCKET", "esock_cancel_accept -> done with result:" "\r\n %T" "\r\n", res) ); @@ -14207,27 +14258,27 @@ ERL_NIF_TERM ncancel_accept(ErlNifEnv* env, * in the acceptor queue). */ static -ERL_NIF_TERM ncancel_accept_current(ErlNifEnv* env, - ESockDescriptor* descP, - ERL_NIF_TERM sockRef) +ERL_NIF_TERM esock_cancel_accept_current(ErlNifEnv* env, + ESockDescriptor* descP, + ERL_NIF_TERM sockRef) { ERL_NIF_TERM res; - SSDBG( descP, ("SOCKET", "ncancel_accept_current -> entry\r\n") ); + SSDBG( descP, ("SOCKET", "esock_cancel_accept_current -> entry\r\n") ); - DEMONP("ncancel_accept_current -> current acceptor", + DEMONP("esock_cancel_accept_current -> current acceptor", env, descP, &descP->currentAcceptor.mon); - res = ncancel_read_select(env, descP, descP->currentAcceptor.ref); + res = esock_cancel_read_select(env, descP, descP->currentAcceptor.ref); SSDBG( descP, ("SOCKET", - "ncancel_accept_current -> cancel res: %T\r\n", res) ); + "esock_cancel_accept_current -> cancel res: %T\r\n", res) ); if (!activate_next_acceptor(env, descP, sockRef)) { SSDBG( descP, - ("SOCKET", "ncancel_accept_current -> no more writers\r\n") ); + ("SOCKET", "esock_cancel_accept_current -> no more writers\r\n") ); - descP->state = SOCKET_STATE_LISTENING; + descP->state = ESOCK_STATE_LISTENING; descP->currentAcceptorP = NULL; descP->currentAcceptor.ref = esock_atom_undefined; @@ -14235,7 +14286,7 @@ ERL_NIF_TERM ncancel_accept_current(ErlNifEnv* env, esock_monitor_init(&descP->currentAcceptor.mon); } - SSDBG( descP, ("SOCKET", "ncancel_accept_current -> done with result:" + SSDBG( descP, ("SOCKET", "esock_cancel_accept_current -> done with result:" "\r\n %T" "\r\n", res) ); @@ -14247,9 +14298,9 @@ ERL_NIF_TERM ncancel_accept_current(ErlNifEnv* env, * remove them from the acceptor queue. */ static -ERL_NIF_TERM ncancel_accept_waiting(ErlNifEnv* env, - ESockDescriptor* descP, - ERL_NIF_TERM opRef) +ERL_NIF_TERM esock_cancel_accept_waiting(ErlNifEnv* env, + ESockDescriptor* descP, + ERL_NIF_TERM opRef) { ErlNifPid caller; @@ -14268,23 +14319,23 @@ ERL_NIF_TERM ncancel_accept_waiting(ErlNifEnv* env, -/* *** ncancel_send *** +/* *** esock_cancel_send *** * * Cancel a send operation. * Its either the current writer or one of the waiting writers. */ static -ERL_NIF_TERM ncancel_send(ErlNifEnv* env, - ESockDescriptor* descP, - ERL_NIF_TERM sockRef, - ERL_NIF_TERM opRef) +ERL_NIF_TERM esock_cancel_send(ErlNifEnv* env, + ESockDescriptor* descP, + ERL_NIF_TERM sockRef, + ERL_NIF_TERM opRef) { ERL_NIF_TERM res; MLOCK(descP->writeMtx); SSDBG( descP, - ("SOCKET", "ncancel_send -> entry with" + ("SOCKET", "esock_cancel_send -> entry with" "\r\n opRef: %T" "\r\n %s" "\r\n", opRef, @@ -14292,9 +14343,9 @@ ERL_NIF_TERM ncancel_send(ErlNifEnv* env, if (descP->currentWriterP != NULL) { if (COMPARE(opRef, descP->currentWriter.ref) == 0) { - res = ncancel_send_current(env, descP, sockRef); + res = esock_cancel_send_current(env, descP, sockRef); } else { - res = ncancel_send_waiting(env, descP, opRef); + res = esock_cancel_send_waiting(env, descP, opRef); } } else { /* Or badarg? */ @@ -14304,7 +14355,7 @@ ERL_NIF_TERM ncancel_send(ErlNifEnv* env, MUNLOCK(descP->writeMtx); SSDBG( descP, - ("SOCKET", "ncancel_send -> done with result:" + ("SOCKET", "esock_cancel_send -> done with result:" "\r\n %T" "\r\n", res) ); @@ -14318,31 +14369,31 @@ ERL_NIF_TERM ncancel_send(ErlNifEnv* env, * in the writer queue). */ static -ERL_NIF_TERM ncancel_send_current(ErlNifEnv* env, - ESockDescriptor* descP, - ERL_NIF_TERM sockRef) +ERL_NIF_TERM esock_cancel_send_current(ErlNifEnv* env, + ESockDescriptor* descP, + ERL_NIF_TERM sockRef) { ERL_NIF_TERM res; - SSDBG( descP, ("SOCKET", "ncancel_send_current -> entry\r\n") ); + SSDBG( descP, ("SOCKET", "esock_cancel_send_current -> entry\r\n") ); - DEMONP("ncancel_send_current -> current writer", + DEMONP("esock_cancel_send_current -> current writer", env, descP, &descP->currentWriter.mon); - res = ncancel_write_select(env, descP, descP->currentWriter.ref); + res = esock_cancel_write_select(env, descP, descP->currentWriter.ref); SSDBG( descP, - ("SOCKET", "ncancel_send_current -> cancel res: %T\r\n", res) ); + ("SOCKET", "esock_cancel_send_current -> cancel res: %T\r\n", res) ); if (!activate_next_writer(env, descP, sockRef)) { SSDBG( descP, - ("SOCKET", "ncancel_send_current -> no more writers\r\n") ); + ("SOCKET", "esock_cancel_send_current -> no more writers\r\n") ); descP->currentWriterP = NULL; descP->currentWriter.ref = esock_atom_undefined; enif_set_pid_undefined(&descP->currentWriter.pid); esock_monitor_init(&descP->currentWriter.mon); } - SSDBG( descP, ("SOCKET", "ncancel_send_current -> done with result:" + SSDBG( descP, ("SOCKET", "esock_cancel_send_current -> done with result:" "\r\n %T" "\r\n", res) ); @@ -14354,9 +14405,9 @@ ERL_NIF_TERM ncancel_send_current(ErlNifEnv* env, * remove them from the writer queue. */ static -ERL_NIF_TERM ncancel_send_waiting(ErlNifEnv* env, - ESockDescriptor* descP, - ERL_NIF_TERM opRef) +ERL_NIF_TERM esock_cancel_send_waiting(ErlNifEnv* env, + ESockDescriptor* descP, + ERL_NIF_TERM opRef) { ErlNifPid caller; @@ -14375,23 +14426,23 @@ ERL_NIF_TERM ncancel_send_waiting(ErlNifEnv* env, -/* *** ncancel_recv *** +/* *** esock_cancel_recv *** * * Cancel a read operation. * Its either the current reader or one of the waiting readers. */ static -ERL_NIF_TERM ncancel_recv(ErlNifEnv* env, - ESockDescriptor* descP, - ERL_NIF_TERM sockRef, - ERL_NIF_TERM opRef) +ERL_NIF_TERM esock_cancel_recv(ErlNifEnv* env, + ESockDescriptor* descP, + ERL_NIF_TERM sockRef, + ERL_NIF_TERM opRef) { ERL_NIF_TERM res; MLOCK(descP->readMtx); SSDBG( descP, - ("SOCKET", "ncancel_recv -> entry with" + ("SOCKET", "esock_cancel_recv -> entry with" "\r\n opRef: %T" "\r\n %s" "\r\n", opRef, @@ -14399,9 +14450,9 @@ ERL_NIF_TERM ncancel_recv(ErlNifEnv* env, if (descP->currentReaderP != NULL) { if (COMPARE(opRef, descP->currentReader.ref) == 0) { - res = ncancel_recv_current(env, descP, sockRef); + res = esock_cancel_recv_current(env, descP, sockRef); } else { - res = ncancel_recv_waiting(env, descP, opRef); + res = esock_cancel_recv_waiting(env, descP, opRef); } } else { /* Or badarg? */ @@ -14411,7 +14462,7 @@ ERL_NIF_TERM ncancel_recv(ErlNifEnv* env, MUNLOCK(descP->readMtx); SSDBG( descP, - ("SOCKET", "ncancel_recv -> done with result:" + ("SOCKET", "esock_cancel_recv -> done with result:" "\r\n %T" "\r\n", res) ); @@ -14424,31 +14475,31 @@ ERL_NIF_TERM ncancel_recv(ErlNifEnv* env, * in the reader queue). */ static -ERL_NIF_TERM ncancel_recv_current(ErlNifEnv* env, - ESockDescriptor* descP, - ERL_NIF_TERM sockRef) +ERL_NIF_TERM esock_cancel_recv_current(ErlNifEnv* env, + ESockDescriptor* descP, + ERL_NIF_TERM sockRef) { ERL_NIF_TERM res; - SSDBG( descP, ("SOCKET", "ncancel_recv_current -> entry\r\n") ); + SSDBG( descP, ("SOCKET", "esock_cancel_recv_current -> entry\r\n") ); - DEMONP("ncancel_recv_current -> current reader", + DEMONP("esock_cancel_recv_current -> current reader", env, descP, &descP->currentReader.mon); - res = ncancel_read_select(env, descP, descP->currentReader.ref); + res = esock_cancel_read_select(env, descP, descP->currentReader.ref); SSDBG( descP, - ("SOCKET", "ncancel_recv_current -> cancel res: %T\r\n", res) ); + ("SOCKET", "esock_cancel_recv_current -> cancel res: %T\r\n", res) ); if (!activate_next_reader(env, descP, sockRef)) { SSDBG( descP, - ("SOCKET", "ncancel_recv_current -> no more readers\r\n") ); + ("SOCKET", "esock_cancel_recv_current -> no more readers\r\n") ); descP->currentReaderP = NULL; descP->currentReader.ref = esock_atom_undefined; enif_set_pid_undefined(&descP->currentReader.pid); esock_monitor_init(&descP->currentReader.mon); } - SSDBG( descP, ("SOCKET", "ncancel_recv_current -> done with result:" + SSDBG( descP, ("SOCKET", "esock_cancel_recv_current -> done with result:" "\r\n %T" "\r\n", res) ); @@ -14460,9 +14511,9 @@ ERL_NIF_TERM ncancel_recv_current(ErlNifEnv* env, * remove them from the reader queue. */ static -ERL_NIF_TERM ncancel_recv_waiting(ErlNifEnv* env, - ESockDescriptor* descP, - ERL_NIF_TERM opRef) +ERL_NIF_TERM esock_cancel_recv_waiting(ErlNifEnv* env, + ESockDescriptor* descP, + ERL_NIF_TERM opRef) { ErlNifPid caller; @@ -14482,33 +14533,33 @@ ERL_NIF_TERM ncancel_recv_waiting(ErlNifEnv* env, static -ERL_NIF_TERM ncancel_read_select(ErlNifEnv* env, - ESockDescriptor* descP, - ERL_NIF_TERM opRef) +ERL_NIF_TERM esock_cancel_read_select(ErlNifEnv* env, + ESockDescriptor* descP, + ERL_NIF_TERM opRef) { - return ncancel_mode_select(env, descP, opRef, - ERL_NIF_SELECT_READ, - ERL_NIF_SELECT_READ_CANCELLED); + return esock_cancel_mode_select(env, descP, opRef, + ERL_NIF_SELECT_READ, + ERL_NIF_SELECT_READ_CANCELLED); } static -ERL_NIF_TERM ncancel_write_select(ErlNifEnv* env, +ERL_NIF_TERM esock_cancel_write_select(ErlNifEnv* env, ESockDescriptor* descP, ERL_NIF_TERM opRef) { - return ncancel_mode_select(env, descP, opRef, - ERL_NIF_SELECT_WRITE, - ERL_NIF_SELECT_WRITE_CANCELLED); + return esock_cancel_mode_select(env, descP, opRef, + ERL_NIF_SELECT_WRITE, + ERL_NIF_SELECT_WRITE_CANCELLED); } static -ERL_NIF_TERM ncancel_mode_select(ErlNifEnv* env, - ESockDescriptor* descP, - ERL_NIF_TERM opRef, - int smode, - int rmode) +ERL_NIF_TERM esock_cancel_mode_select(ErlNifEnv* env, + ESockDescriptor* descP, + ERL_NIF_TERM opRef, + int smode, + int rmode) { int selectRes = esock_select_cancel(env, descP->sock, smode, descP); @@ -14520,7 +14571,8 @@ ERL_NIF_TERM ncancel_mode_select(ErlNifEnv* env, return esock_make_error(env, esock_atom_select_sent); } else { /* Stopped? */ - SSDBG( descP, ("SOCKET", "ncancel_mode_select -> failed: %d (0x%lX)" + SSDBG( descP, ("SOCKET", + "esock_cancel_mode_select -> failed: %d (0x%lX)" "\r\n", selectRes, selectRes) ); return esock_make_error(env, esock_atom_einval); } @@ -15358,7 +15410,7 @@ ERL_NIF_TERM recv_check_fail_closed(ErlNifEnv* env, */ descP->closeLocal = FALSE; - descP->state = SOCKET_STATE_CLOSING; + descP->state = ESOCK_STATE_CLOSING; recv_error_current_reader(env, descP, sockRef, res); @@ -17378,11 +17430,11 @@ BOOLEAN_T decode_native_get_opt(ErlNifEnv* env, ERL_NIF_TERM eVal, if (COMPARE(nativeOptT[1], atom_int) == 0) { SGDBG( ("SOCKET", "decode_native_get_opt -> int\r\n") ); - *valueType = SOCKET_OPT_VALUE_TYPE_INT; + *valueType = ESOCK_OPT_VALUE_TYPE_INT; *valueSz = sizeof(int); // Just to be sure } else if (COMPARE(nativeOptT[1], atom_bool) == 0) { SGDBG( ("SOCKET", "decode_native_get_opt -> bool\r\n") ); - *valueType = SOCKET_OPT_VALUE_TYPE_BOOL; + *valueType = ESOCK_OPT_VALUE_TYPE_BOOL; *valueSz = sizeof(int); // Just to be sure } else { return FALSE; @@ -17390,7 +17442,7 @@ BOOLEAN_T decode_native_get_opt(ErlNifEnv* env, ERL_NIF_TERM eVal, } else if (IS_NUM(env, nativeOptT[1])) { if (GET_INT(env, nativeOptT[1], valueSz)) { SGDBG( ("SOCKET", "decode_native_get_opt -> unspec\r\n") ); - *valueType = SOCKET_OPT_VALUE_TYPE_UNSPEC; + *valueType = ESOCK_OPT_VALUE_TYPE_UNSPEC; } else { return FALSE; } @@ -17457,7 +17509,7 @@ ESockDescriptor* alloc_descriptor(SOCKET sock, HANDLE event) { ESockDescriptor* descP; - if ((descP = enif_alloc_resource(sockets, sizeof(ESockDescriptor))) != NULL) { + if ((descP = enif_alloc_resource(esocks, sizeof(ESockDescriptor))) != NULL) { char buf[64]; /* Buffer used for building the mutex name */ descP->pattern = ESOCK_DESC_PATTERN_CREATED; @@ -17516,13 +17568,13 @@ ESockDescriptor* alloc_descriptor(SOCKET sock, HANDLE event) sprintf(buf, "esock[cfg,%d]", sock); descP->cfgMtx = MCREATE(buf); - descP->rBufSz = SOCKET_RECV_BUFFER_SIZE_DEFAULT; + descP->rBufSz = ESOCK_RECV_BUFFER_SIZE_DEFAULT; descP->rNum = 0; descP->rNumCnt = 0; - descP->rCtrlSz = SOCKET_RECV_CTRL_BUFFER_SIZE_DEFAULT; - descP->wCtrlSz = SOCKET_SEND_CTRL_BUFFER_SIZE_DEFAULT; + descP->rCtrlSz = ESOCK_RECV_CTRL_BUFFER_SIZE_DEFAULT; + descP->wCtrlSz = ESOCK_SEND_CTRL_BUFFER_SIZE_DEFAULT; descP->iow = FALSE; - descP->dbg = SOCKET_DEBUG_DEFAULT; + descP->dbg = ESOCK_DEBUG_DEFAULT; descP->sock = sock; descP->event = event; @@ -17649,17 +17701,17 @@ static BOOLEAN_T edomain2domain(int edomain, int* domain) { switch (edomain) { - case SOCKET_DOMAIN_INET: + case ESOCK_DOMAIN_INET: *domain = AF_INET; break; #if defined(HAVE_IN6) && defined(AF_INET6) - case SOCKET_DOMAIN_INET6: + case ESOCK_DOMAIN_INET6: *domain = AF_INET6; break; #endif #ifdef HAVE_SYS_UN_H - case SOCKET_DOMAIN_LOCAL: + case ESOCK_DOMAIN_LOCAL: *domain = AF_UNIX; break; #endif @@ -17681,20 +17733,20 @@ static BOOLEAN_T etype2type(int etype, int* type) { switch (etype) { - case SOCKET_TYPE_STREAM: + case ESOCK_TYPE_STREAM: *type = SOCK_STREAM; break; - case SOCKET_TYPE_DGRAM: + case ESOCK_TYPE_DGRAM: *type = SOCK_DGRAM; break; - case SOCKET_TYPE_RAW: + case ESOCK_TYPE_RAW: *type = SOCK_RAW; break; #ifdef HAVE_SCTP - case SOCKET_TYPE_SEQPACKET: + case ESOCK_TYPE_SEQPACKET: *type = SOCK_SEQPACKET; break; #endif @@ -17726,33 +17778,33 @@ BOOLEAN_T eproto2proto(ErlNifEnv* env, } switch (ep) { - case SOCKET_PROTOCOL_DEFAULT: + case ESOCK_PROTOCOL_DEFAULT: *proto = 0; // default - note that _IP also has the value 0... break; - case SOCKET_PROTOCOL_IP: + case ESOCK_PROTOCOL_IP: *proto = IPPROTO_IP; break; - case SOCKET_PROTOCOL_TCP: + case ESOCK_PROTOCOL_TCP: *proto = IPPROTO_TCP; break; - case SOCKET_PROTOCOL_UDP: + case ESOCK_PROTOCOL_UDP: *proto = IPPROTO_UDP; break; #if defined(HAVE_SCTP) - case SOCKET_PROTOCOL_SCTP: + case ESOCK_PROTOCOL_SCTP: *proto = IPPROTO_SCTP; break; #endif - case SOCKET_PROTOCOL_ICMP: + case ESOCK_PROTOCOL_ICMP: *proto = IPPROTO_ICMP; break; - case SOCKET_PROTOCOL_IGMP: + case ESOCK_PROTOCOL_IGMP: *proto = IPPROTO_IGMP; break; @@ -17861,47 +17913,47 @@ BOOLEAN_T esendflags2sendflags(unsigned int eflags, int* flags) return TRUE; } - for (ef = SOCKET_SEND_FLAG_LOW; ef <= SOCKET_SEND_FLAG_HIGH; ef++) { + for (ef = ESOCK_SEND_FLAG_LOW; ef <= ESOCK_SEND_FLAG_HIGH; ef++) { switch (ef) { #if defined(MSG_CONFIRM) - case SOCKET_SEND_FLAG_CONFIRM: - if ((1 << SOCKET_SEND_FLAG_CONFIRM) & eflags) + case ESOCK_SEND_FLAG_CONFIRM: + if ((1 << ESOCK_SEND_FLAG_CONFIRM) & eflags) tmp |= MSG_CONFIRM; break; #endif #if defined(MSG_DONTROUTE) - case SOCKET_SEND_FLAG_DONTROUTE: - if ((1 << SOCKET_SEND_FLAG_DONTROUTE) & eflags) + case ESOCK_SEND_FLAG_DONTROUTE: + if ((1 << ESOCK_SEND_FLAG_DONTROUTE) & eflags) tmp |= MSG_DONTROUTE; break; #endif #if defined(MSG_EOR) - case SOCKET_SEND_FLAG_EOR: - if ((1 << SOCKET_SEND_FLAG_EOR) & eflags) + case ESOCK_SEND_FLAG_EOR: + if ((1 << ESOCK_SEND_FLAG_EOR) & eflags) tmp |= MSG_EOR; break; #endif #if defined(MSG_MORE) - case SOCKET_SEND_FLAG_MORE: - if ((1 << SOCKET_SEND_FLAG_MORE) & eflags) + case ESOCK_SEND_FLAG_MORE: + if ((1 << ESOCK_SEND_FLAG_MORE) & eflags) tmp |= MSG_MORE; break; #endif #if defined(MSG_NOSIGNAL) - case SOCKET_SEND_FLAG_NOSIGNAL: - if ((1 << SOCKET_SEND_FLAG_NOSIGNAL) & eflags) + case ESOCK_SEND_FLAG_NOSIGNAL: + if ((1 << ESOCK_SEND_FLAG_NOSIGNAL) & eflags) tmp |= MSG_NOSIGNAL; break; #endif #if defined(MSG_OOB) - case SOCKET_SEND_FLAG_OOB: - if ((1 << SOCKET_SEND_FLAG_OOB) & eflags) + case ESOCK_SEND_FLAG_OOB: + if ((1 << ESOCK_SEND_FLAG_OOB) & eflags) tmp |= MSG_OOB; break; #endif @@ -17937,7 +17989,7 @@ BOOLEAN_T erecvflags2recvflags(unsigned int eflags, int* flags) return TRUE; } - for (ef = SOCKET_RECV_FLAG_LOW; ef <= SOCKET_RECV_FLAG_HIGH; ef++) { + for (ef = ESOCK_RECV_FLAG_LOW; ef <= ESOCK_RECV_FLAG_HIGH; ef++) { SGDBG( ("SOCKET", "erecvflags2recvflags -> iteration" "\r\n ef: %d" @@ -17946,22 +17998,22 @@ BOOLEAN_T erecvflags2recvflags(unsigned int eflags, int* flags) switch (ef) { #if defined(MSG_CMSG_CLOEXEC) - case SOCKET_RECV_FLAG_CMSG_CLOEXEC: - if ((1 << SOCKET_RECV_FLAG_CMSG_CLOEXEC) & eflags) + case ESOCK_RECV_FLAG_CMSG_CLOEXEC: + if ((1 << ESOCK_RECV_FLAG_CMSG_CLOEXEC) & eflags) tmp |= MSG_CMSG_CLOEXEC; break; #endif #if defined(MSG_ERRQUEUE) - case SOCKET_RECV_FLAG_ERRQUEUE: - if ((1 << SOCKET_RECV_FLAG_ERRQUEUE) & eflags) + case ESOCK_RECV_FLAG_ERRQUEUE: + if ((1 << ESOCK_RECV_FLAG_ERRQUEUE) & eflags) tmp |= MSG_ERRQUEUE; break; #endif #if defined(MSG_OOB) - case SOCKET_RECV_FLAG_OOB: - if ((1 << SOCKET_RECV_FLAG_OOB) & eflags) + case ESOCK_RECV_FLAG_OOB: + if ((1 << ESOCK_RECV_FLAG_OOB) & eflags) tmp |= MSG_OOB; break; #endif @@ -17974,15 +18026,15 @@ BOOLEAN_T erecvflags2recvflags(unsigned int eflags, int* flags) * </KOLLA> */ #if defined(MSG_PEEK) - case SOCKET_RECV_FLAG_PEEK: - if ((1 << SOCKET_RECV_FLAG_PEEK) & eflags) + case ESOCK_RECV_FLAG_PEEK: + if ((1 << ESOCK_RECV_FLAG_PEEK) & eflags) tmp |= MSG_PEEK; break; #endif #if defined(MSG_TRUNC) - case SOCKET_RECV_FLAG_TRUNC: - if ((1 << SOCKET_RECV_FLAG_TRUNC) & eflags) + case ESOCK_RECV_FLAG_TRUNC: + if ((1 << ESOCK_RECV_FLAG_TRUNC) & eflags) tmp |= MSG_TRUNC; break; #endif @@ -18008,15 +18060,15 @@ static BOOLEAN_T ehow2how(unsigned int ehow, int* how) { switch (ehow) { - case SOCKET_SHUTDOWN_HOW_RD: + case ESOCK_SHUTDOWN_HOW_RD: *how = SHUT_RD; break; - case SOCKET_SHUTDOWN_HOW_WR: + case ESOCK_SHUTDOWN_HOW_WR: *how = SHUT_WR; break; - case SOCKET_SHUTDOWN_HOW_RDWR: + case ESOCK_SHUTDOWN_HOW_RDWR: *how = SHUT_RDWR; break; @@ -18062,7 +18114,7 @@ BOOLEAN_T ecommand2command(ErlNifEnv* env, return FALSE; } if (COMPARE(ecmd, esock_atom_debug) == 0) { - *command = SOCKET_CMD_DEBUG; + *command = ESOCK_CMD_DEBUG; } else { SGDBG( ("SOCKET", "ecommand2command -> unknown command %T\r\n", ecmd) ); return FALSE; @@ -18884,11 +18936,11 @@ static void free_request_queue(ESockRequestQueue* q) } /* ========================================================================= - * socket_dtor - Callback function for resource destructor + * esock_dtor - Callback function for resource destructor * */ static -void socket_dtor(ErlNifEnv* env, void* obj) +void esock_dtor(ErlNifEnv* env, void* obj) { #if !defined(__WIN32__) ESockDescriptor* descP = (ESockDescriptor*) obj; @@ -18915,14 +18967,14 @@ void socket_dtor(ErlNifEnv* env, void* obj) free_request_queue(&descP->writersQ); free_request_queue(&descP->acceptorsQ); - descP->state = SOCKET_STATE_DTOR; + descP->state = ESOCK_STATE_DTOR; descP->pattern = ESOCK_DESC_PATTERN_DTOR; #endif } /* ========================================================================= - * socket_stop - Callback function for resource stop + * esock_stop - Callback function for resource stop * * When the socket is stopped, we need to inform: * @@ -18937,14 +18989,14 @@ void socket_dtor(ErlNifEnv* env, void* obj) * */ static -void socket_stop(ErlNifEnv* env, void* obj, int fd, int is_direct_call) +void esock_stop(ErlNifEnv* env, void* obj, int fd, int is_direct_call) { #if !defined(__WIN32__) ESockDescriptor* descP = (ESockDescriptor*) obj; ERL_NIF_TERM sockRef; SSDBG( descP, - ("SOCKET", "socket_stop -> entry when %s" + ("SOCKET", "esock_stop -> entry when %s" "\r\n sock: %d (%d)" "\r\n", ((is_direct_call) ? "called" : "scheduled"), descP->sock, fd) ); @@ -18957,7 +19009,7 @@ void socket_stop(ErlNifEnv* env, void* obj, int fd, int is_direct_call) MLOCK(descP->cfgMtx); if (!is_direct_call) MLOCK(descP->closeMtx); - SSDBG( descP, ("SOCKET", "socket_stop -> " + SSDBG( descP, ("SOCKET", "esock_stop -> " "[%d, %T] all mutex(s) locked when counters:" "\r\n writePkgCnt: %u" "\r\n writeByteCnt: %u" @@ -18981,7 +19033,7 @@ void socket_stop(ErlNifEnv* env, void* obj, int fd, int is_direct_call) descP->readWaits) ); sockRef = enif_make_resource(env, descP); - descP->state = SOCKET_STATE_CLOSING; // Just in case...??? + descP->state = ESOCK_STATE_CLOSING; // Just in case...??? descP->isReadable = FALSE; descP->isWritable = FALSE; @@ -18992,7 +19044,7 @@ void socket_stop(ErlNifEnv* env, void* obj, int fd, int is_direct_call) * there is no point to demonitor. Also, we do not actually * have a monitor in that case... */ - DEMONP("socket_stop -> ctrl", env, descP, &descP->ctrlMon); + DEMONP("esock_stop -> ctrl", env, descP, &descP->ctrlMon); @@ -19009,12 +19061,12 @@ void socket_stop(ErlNifEnv* env, void* obj, int fd, int is_direct_call) * writers waiting. */ - socket_stop_handle_current(env, - "writer", - descP, sockRef, &descP->currentWriter); + esock_stop_handle_current(env, + "writer", + descP, sockRef, &descP->currentWriter); /* And also deal with the waiting writers (in the same way) */ - SSDBG( descP, ("SOCKET", "socket_stop -> handle waiting writer(s)\r\n") ); + SSDBG( descP, ("SOCKET", "esock_stop -> handle waiting writer(s)\r\n") ); inform_waiting_procs(env, "writer", descP, sockRef, &descP->writersQ, TRUE, atom_closed); } @@ -19033,12 +19085,12 @@ void socket_stop(ErlNifEnv* env, void* obj, int fd, int is_direct_call) * readers waiting. */ - socket_stop_handle_current(env, - "reader", - descP, sockRef, &descP->currentReader); + esock_stop_handle_current(env, + "reader", + descP, sockRef, &descP->currentReader); /* And also deal with the waiting readers (in the same way) */ - SSDBG( descP, ("SOCKET", "socket_stop -> handle waiting reader(s)\r\n") ); + SSDBG( descP, ("SOCKET", "esock_stop -> handle waiting reader(s)\r\n") ); inform_waiting_procs(env, "reader", descP, sockRef, &descP->readersQ, TRUE, atom_closed); } @@ -19058,12 +19110,12 @@ void socket_stop(ErlNifEnv* env, void* obj, int fd, int is_direct_call) * acceptors waiting. */ - socket_stop_handle_current(env, - "acceptor", - descP, sockRef, &descP->currentAcceptor); - + esock_stop_handle_current(env, + "acceptor", + descP, sockRef, &descP->currentAcceptor); + /* And also deal with the waiting acceptors (in the same way) */ - SSDBG( descP, ("SOCKET", "socket_stop -> handle waiting acceptor(s)\r\n") ); + SSDBG( descP, ("SOCKET", "esock_stop -> handle waiting acceptor(s)\r\n") ); inform_waiting_procs(env, "acceptor", descP, sockRef, &descP->acceptorsQ, TRUE, atom_closed); } @@ -19087,7 +19139,7 @@ void socket_stop(ErlNifEnv* env, void* obj, int fd, int is_direct_call) esock_send_close_msg(env, descP, &descP->closerPid); - DEMONP("socket_stop -> closer", env, descP, &descP->closerMon); + DEMONP("esock_stop -> closer", env, descP, &descP->closerMon); } else { @@ -19096,14 +19148,14 @@ void socket_stop(ErlNifEnv* env, void* obj, int fd, int is_direct_call) */ if (descP->closeEnv != NULL) - esock_free_env("socket_stop - close-env", descP->closeEnv); + esock_free_env("esock_stop - close-env", descP->closeEnv); } } } - SSDBG( descP, ("SOCKET", "socket_stop -> unlock all mutex(s)\r\n") ); + SSDBG( descP, ("SOCKET", "esock_stop -> unlock all mutex(s)\r\n") ); if (!is_direct_call) MUNLOCK(descP->closeMtx); MUNLOCK(descP->cfgMtx); @@ -19112,33 +19164,33 @@ void socket_stop(ErlNifEnv* env, void* obj, int fd, int is_direct_call) MUNLOCK(descP->writeMtx); SSDBG( descP, - ("SOCKET", "socket_stop -> done (%d, %d)\r\n", descP->sock, fd) ); + ("SOCKET", "esock_stop -> done (%d, %d)\r\n", descP->sock, fd) ); #endif // if !defined(__WIN32__) } -/* *** socket_stop_handle_current *** +/* *** esock_stop_handle_current *** * * Handle current requestor (reader, writer or acceptor) during * socket stop. */ #if !defined(__WIN32__) static -void socket_stop_handle_current(ErlNifEnv* env, - const char* role, - ESockDescriptor* descP, - ERL_NIF_TERM sockRef, - ESockRequestor* reqP) +void esock_stop_handle_current(ErlNifEnv* env, + const char* role, + ESockDescriptor* descP, + ERL_NIF_TERM sockRef, + ESockRequestor* reqP) { - SSDBG( descP, ("SOCKET", "socket_stop -> handle current %s\r\n", role) ); + SSDBG( descP, ("SOCKET", "esock_stop -> handle current %s\r\n", role) ); - DEMONP("socket_stop_handle_current", env, descP, &reqP->mon); + DEMONP("esock_stop_handle_current", env, descP, &reqP->mon); if (COMPARE_PIDS(&descP->closerPid, &reqP->pid) != 0) { - SSDBG( descP, ("SOCKET", "socket_stop_handle_current -> " + SSDBG( descP, ("SOCKET", "esock_stop_handle_current -> " "send abort message to current %s %T\r\n", role, reqP->pid) ); @@ -19223,21 +19275,21 @@ void inform_waiting_procs(ErlNifEnv* env, /* ========================================================================= - * socket_down - Callback function for resource down (monitored processes) + * esock_down - Callback function for resource down (monitored processes) * */ static -void socket_down(ErlNifEnv* env, - void* obj, - const ErlNifPid* pid, - const ErlNifMonitor* mon) +void esock_down(ErlNifEnv* env, + void* obj, + const ErlNifPid* pid, + const ErlNifMonitor* mon) { #if !defined(__WIN32__) ESockDescriptor* descP = (ESockDescriptor*) obj; int sres; ERL_NIF_TERM sockRef; - SSDBG( descP, ("SOCKET", "socket_down -> entry with" + SSDBG( descP, ("SOCKET", "esock_down -> entry with" "\r\n sock: %d" "\r\n pid: %T" "\r\n Close: %s (%s)" @@ -19255,9 +19307,9 @@ void socket_down(ErlNifEnv* env, */ SSDBG( descP, - ("SOCKET", "socket_down -> controlling process exit\r\n") ); + ("SOCKET", "esock_down -> controlling process exit\r\n") ); - descP->state = SOCKET_STATE_CLOSING; + descP->state = ESOCK_STATE_CLOSING; descP->closeLocal = TRUE; descP->closerPid = *pid; MON_INIT(&descP->closerMon); @@ -19269,10 +19321,10 @@ void socket_down(ErlNifEnv* env, /* We are done - we can finalize (socket close) directly */ SSDBG( descP, ("SOCKET", - "socket_down -> [%d] stop called\r\n", descP->sock) ); + "esock_down -> [%d] stop called\r\n", descP->sock) ); dec_socket(descP->domain, descP->type, descP->protocol); - descP->state = SOCKET_STATE_CLOSED; + descP->state = ESOCK_STATE_CLOSED; /* And finally close the socket. * Since we close the socket because of an exiting owner, @@ -19295,7 +19347,7 @@ void socket_down(ErlNifEnv* env, descP->sock = INVALID_SOCKET; descP->event = INVALID_EVENT; - descP->state = SOCKET_STATE_CLOSED; + descP->state = ESOCK_STATE_CLOSED; } else if (sres & ERL_NIF_SELECT_STOP_SCHEDULED) { @@ -19306,7 +19358,7 @@ void socket_down(ErlNifEnv* env, */ SSDBG( descP, ("SOCKET", - "socket_down -> [%d] stop scheduled\r\n", + "esock_down -> [%d] stop scheduled\r\n", descP->sock) ); dec_socket(descP->domain, descP->type, descP->protocol); @@ -19346,9 +19398,9 @@ void socket_down(ErlNifEnv* env, * The same goes for the monitor (connMon). */ - descP->state = SOCKET_STATE_OPEN; /* restore state */ + descP->state = ESOCK_STATE_OPEN; /* restore state */ enif_set_pid_undefined(&descP->connPid); - DEMONP("socket_down -> connector", + DEMONP("esock_down -> connector", env, descP, &descP->connMon); } else { @@ -19359,43 +19411,43 @@ void socket_down(ErlNifEnv* env, * */ - SSDBG( descP, ("SOCKET", "socket_down -> other process term\r\n") ); + SSDBG( descP, ("SOCKET", "esock_down -> other process term\r\n") ); sockRef = enif_make_resource(env, descP); MLOCK(descP->accMtx); if (descP->currentAcceptorP != NULL) - socket_down_acceptor(env, descP, sockRef, pid); + esock_down_acceptor(env, descP, sockRef, pid); MUNLOCK(descP->accMtx); MLOCK(descP->writeMtx); if (descP->currentWriterP != NULL) - socket_down_writer(env, descP, sockRef, pid); + esock_down_writer(env, descP, sockRef, pid); MUNLOCK(descP->writeMtx); MLOCK(descP->readMtx); if (descP->currentReaderP != NULL) - socket_down_reader(env, descP, sockRef, pid); + esock_down_reader(env, descP, sockRef, pid); MUNLOCK(descP->readMtx); } } - SSDBG( descP, ("SOCKET", "socket_down -> done\r\n") ); + SSDBG( descP, ("SOCKET", "esock_down -> done\r\n") ); #endif // if !defined(__WIN32__) } -/* *** socket_down_acceptor *** +/* *** esock_down_acceptor *** * * Check and then handle a downed acceptor process. * */ #if !defined(__WIN32__) static -void socket_down_acceptor(ErlNifEnv* env, +void esock_down_acceptor(ErlNifEnv* env, ESockDescriptor* descP, ERL_NIF_TERM sockRef, const ErlNifPid* pid) @@ -19403,15 +19455,15 @@ void socket_down_acceptor(ErlNifEnv* env, if (COMPARE_PIDS(&descP->currentAcceptor.pid, pid) == 0) { SSDBG( descP, ("SOCKET", - "socket_down_acceptor -> " + "esock_down_acceptor -> " "current acceptor - try activate next\r\n") ); if (!activate_next_acceptor(env, descP, sockRef)) { SSDBG( descP, - ("SOCKET", "socket_down_acceptor -> no more writers\r\n") ); + ("SOCKET", "esock_down_acceptor -> no more writers\r\n") ); - descP->state = SOCKET_STATE_LISTENING; + descP->state = ESOCK_STATE_LISTENING; descP->currentAcceptorP = NULL; descP->currentAcceptor.ref = esock_atom_undefined; @@ -19424,7 +19476,7 @@ void socket_down_acceptor(ErlNifEnv* env, /* Maybe unqueue one of the waiting acceptors */ SSDBG( descP, ("SOCKET", - "socket_down_acceptor -> " + "esock_down_acceptor -> " "not current acceptor - maybe a waiting acceptor\r\n") ); acceptor_unqueue(env, descP, pid); @@ -19434,13 +19486,13 @@ void socket_down_acceptor(ErlNifEnv* env, -/* *** socket_down_writer *** +/* *** esock_down_writer *** * * Check and then handle a downed writer process. * */ static -void socket_down_writer(ErlNifEnv* env, +void esock_down_writer(ErlNifEnv* env, ESockDescriptor* descP, ERL_NIF_TERM sockRef, const ErlNifPid* pid) @@ -19448,12 +19500,12 @@ void socket_down_writer(ErlNifEnv* env, if (COMPARE_PIDS(&descP->currentWriter.pid, pid) == 0) { SSDBG( descP, ("SOCKET", - "socket_down_writer -> " + "esock_down_writer -> " "current writer - try activate next\r\n") ); if (!activate_next_writer(env, descP, sockRef)) { SSDBG( descP, ("SOCKET", - "socket_down_writer -> no active writer\r\n") ); + "esock_down_writer -> no active writer\r\n") ); descP->currentWriterP = NULL; descP->currentWriter.ref = esock_atom_undefined; enif_set_pid_undefined(&descP->currentWriter.pid); @@ -19465,7 +19517,7 @@ void socket_down_writer(ErlNifEnv* env, /* Maybe unqueue one of the waiting writer(s) */ SSDBG( descP, ("SOCKET", - "socket_down_writer -> " + "esock_down_writer -> " "not current writer - maybe a waiting writer\r\n") ); writer_unqueue(env, descP, pid); @@ -19475,13 +19527,13 @@ void socket_down_writer(ErlNifEnv* env, -/* *** socket_down_reader *** +/* *** esock_down_reader *** * * Check and then handle a downed reader process. * */ static -void socket_down_reader(ErlNifEnv* env, +void esock_down_reader(ErlNifEnv* env, ESockDescriptor* descP, ERL_NIF_TERM sockRef, const ErlNifPid* pid) @@ -19489,12 +19541,13 @@ void socket_down_reader(ErlNifEnv* env, if (COMPARE_PIDS(&descP->currentReader.pid, pid) == 0) { SSDBG( descP, ("SOCKET", - "socket_down_reader -> " + "esock_down_reader -> " "current reader - try activate next\r\n") ); if (!activate_next_reader(env, descP, sockRef)) { SSDBG( descP, - ("SOCKET", "ncancel_recv_current -> no more readers\r\n") ); + ("SOCKET", + "esock_down_reader -> no more readers\r\n") ); descP->currentReaderP = NULL; descP->currentReader.ref = esock_atom_undefined; enif_set_pid_undefined(&descP->currentReader.pid); @@ -19506,7 +19559,7 @@ void socket_down_reader(ErlNifEnv* env, /* Maybe unqueue one of the waiting reader(s) */ SSDBG( descP, ("SOCKET", - "socket_down_reader -> " + "esock_down_reader -> " "not current reader - maybe a waiting reader\r\n") ); reader_unqueue(env, descP, pid); @@ -19522,7 +19575,7 @@ void socket_down_reader(ErlNifEnv* env, */ static -ErlNifFunc socket_funcs[] = +ErlNifFunc esock_funcs[] = { // Some utility and support functions {"nif_info", 0, nif_info, 0}, @@ -19574,7 +19627,7 @@ BOOLEAN_T extract_debug(ErlNifEnv* env, */ ERL_NIF_TERM debug = MKA(env, "debug"); - return esock_extract_bool_from_map(env, map, debug, SOCKET_GLOBAL_DEBUG_DEFAULT); + return esock_extract_bool_from_map(env, map, debug, ESOCK_GLOBAL_DEBUG_DEFAULT); } static @@ -19587,7 +19640,7 @@ BOOLEAN_T extract_iow(ErlNifEnv* env, */ ERL_NIF_TERM iow = MKA(env, "iow"); - return esock_extract_bool_from_map(env, map, iow, SOCKET_NIF_IOW_DEFAULT); + return esock_extract_bool_from_map(env, map, iow, ESOCK_NIF_IOW_DEFAULT); } #endif // if !defined(__WIN32__) @@ -19608,7 +19661,7 @@ int on_load(ErlNifEnv* env, void** priv_data, ERL_NIF_TERM load_info) data.iow = extract_iow(env, load_info); /* +++ Global Counters +++ */ - data.cntMtx = MCREATE("socket[gcnt]"); + data.cntMtx = MCREATE("esock[gcnt]"); data.numSockets = 0; data.numTypeDGrams = 0; data.numTypeStreams = 0; @@ -19635,13 +19688,21 @@ GLOBAL_ERROR_REASON_ATOMS #undef GLOBAL_ATOM_DECL esock_atom_socket_tag = MKA(env, "$socket"); - sockets = enif_open_resource_type_x(env, - "sockets", - &socketInit, - ERL_NIF_RT_CREATE, - NULL); + esocks = enif_open_resource_type_x(env, + "sockets", + &esockInit, + ERL_NIF_RT_CREATE, + NULL); - return !sockets; + return !esocks; } -ERL_NIF_INIT(socket, socket_funcs, on_load, NULL, NULL, NULL) +/* + * MODULE: socket (the erlang API/interface module) + * funcs: esock_funcs (defines the API of this nif) + * load: on_load (load this nif) + * upgrade: NULL (not used) + * NULL: THIS IS NOT USED + * unload: NULL (not used) + */ +ERL_NIF_INIT(socket, esock_funcs, on_load, NULL, NULL, NULL) diff --git a/erts/emulator/nifs/common/socket_util.c b/erts/emulator/nifs/common/socket_util.c index 2740cb51ef..54c310ecc7 100644 --- a/erts/emulator/nifs/common/socket_util.c +++ b/erts/emulator/nifs/common/socket_util.c @@ -741,16 +741,24 @@ char* esock_decode_ip4_address(ErlNifEnv* env, "\r\n", eAddr) ); if (IS_ATOM(env, eAddr)) { - /* This is either 'any' or 'loopback' */ + + /* This is either 'any' | 'broadcast' | 'loopback' */ if (COMPARE(esock_atom_loopback, eAddr) == 0) { - UDBG( ("SUTIL", "esock_decode_ip4_address -> address: lookback\r\n") ); + UDBG( ("SUTIL", + "esock_decode_ip4_address -> address: lookback\r\n") ); addr.s_addr = htonl(INADDR_LOOPBACK); } else if (COMPARE(esock_atom_any, eAddr) == 0) { - UDBG( ("SUTIL", "esock_decode_ip4_address -> address: any\r\n") ); - addr.s_addr = htonl(INADDR_ANY); + UDBG( ("SUTIL", + "esock_decode_ip4_address -> address: any\r\n") ); + addr.s_addr = htonl(INADDR_ANY); + } else if (COMPARE(esock_atom_broadcast, eAddr) == 0) { + UDBG( ("SUTIL", + "esock_decode_ip4_address -> address: broadcast\r\n") ); + addr.s_addr = htonl(INADDR_BROADCAST); } else { - UDBG( ("SUTIL", "esock_decode_ip4_address -> address: unknown\r\n") ); + UDBG( ("SUTIL", + "esock_decode_ip4_address -> address: unknown\r\n") ); return ESOCK_STR_EINVAL; } diff --git a/erts/emulator/nifs/unix/unix_prim_file.c b/erts/emulator/nifs/unix/unix_prim_file.c index 20021b9358..176a9318b2 100644 --- a/erts/emulator/nifs/unix/unix_prim_file.c +++ b/erts/emulator/nifs/unix/unix_prim_file.c @@ -627,6 +627,33 @@ int efile_truncate(efile_data_t *d) { return 1; } +static void build_file_info(struct stat *data, efile_fileinfo_t *result) { + if(S_ISCHR(data->st_mode) || S_ISBLK(data->st_mode)) { + result->type = EFILE_FILETYPE_DEVICE; + } else if(S_ISDIR(data->st_mode)) { + result->type = EFILE_FILETYPE_DIRECTORY; + } else if(S_ISREG(data->st_mode)) { + result->type = EFILE_FILETYPE_REGULAR; + } else if(S_ISLNK(data->st_mode)) { + result->type = EFILE_FILETYPE_SYMLINK; + } else { + result->type = EFILE_FILETYPE_OTHER; + } + + result->a_time = (Sint64)data->st_atime; + result->m_time = (Sint64)data->st_mtime; + result->c_time = (Sint64)data->st_ctime; + result->size = data->st_size; + + result->major_device = data->st_dev; + result->minor_device = data->st_rdev; + result->links = data->st_nlink; + result->inode = data->st_ino; + result->mode = data->st_mode; + result->uid = data->st_uid; + result->gid = data->st_gid; +} + posix_errno_t efile_read_info(const efile_path_t *path, int follow_links, efile_fileinfo_t *result) { struct stat data; @@ -640,30 +667,7 @@ posix_errno_t efile_read_info(const efile_path_t *path, int follow_links, efile_ } } - if(S_ISCHR(data.st_mode) || S_ISBLK(data.st_mode)) { - result->type = EFILE_FILETYPE_DEVICE; - } else if(S_ISDIR(data.st_mode)) { - result->type = EFILE_FILETYPE_DIRECTORY; - } else if(S_ISREG(data.st_mode)) { - result->type = EFILE_FILETYPE_REGULAR; - } else if(S_ISLNK(data.st_mode)) { - result->type = EFILE_FILETYPE_SYMLINK; - } else { - result->type = EFILE_FILETYPE_OTHER; - } - - result->a_time = (Sint64)data.st_atime; - result->m_time = (Sint64)data.st_mtime; - result->c_time = (Sint64)data.st_ctime; - result->size = data.st_size; - - result->major_device = data.st_dev; - result->minor_device = data.st_rdev; - result->links = data.st_nlink; - result->inode = data.st_ino; - result->mode = data.st_mode; - result->uid = data.st_uid; - result->gid = data.st_gid; + build_file_info(&data, result); #ifndef NO_ACCESS result->access = EFILE_ACCESS_NONE; @@ -682,6 +686,56 @@ posix_errno_t efile_read_info(const efile_path_t *path, int follow_links, efile_ return 0; } +static int check_access(struct stat *st) { + int ret = EFILE_ACCESS_NONE; + + if(st->st_uid == getuid()) { + if(st->st_mode & S_IRUSR) { + ret |= EFILE_ACCESS_READ; + } + if(st->st_mode & S_IWUSR) { + ret |= EFILE_ACCESS_WRITE; + } + return ret; + } + + if(st->st_gid == getgid()) { + if(st->st_mode & S_IRGRP) { + ret |= EFILE_ACCESS_READ; + } + if(st->st_mode & S_IWGRP) { + ret |= EFILE_ACCESS_WRITE; + } + return ret; + } + + if(st->st_mode & S_IROTH) { + ret |= EFILE_ACCESS_READ; + } + if(st->st_mode & S_IWOTH) { + ret |= EFILE_ACCESS_WRITE; + } + return ret; +} + +posix_errno_t efile_read_handle_info(efile_data_t *d, efile_fileinfo_t *result) { + struct stat data; + efile_unix_t *u = (efile_unix_t*)d; + +#ifdef HAVE_FSTAT + if(fstat(u->fd, &data) < 0) { + return errno; + } + + build_file_info(&data, result); + result->access = check_access(&data); + + return 0; +#else + return ENOTSUP; +#endif +} + posix_errno_t efile_set_permissions(const efile_path_t *path, Uint32 permissions) { const mode_t MUTABLE_MODES = (S_ISUID | S_ISGID | S_IRWXU | S_IRWXG | S_IRWXO); mode_t new_modes = permissions & MUTABLE_MODES; diff --git a/erts/emulator/nifs/win32/win_prim_file.c b/erts/emulator/nifs/win32/win_prim_file.c index 13306104c0..839ac3ea6e 100644 --- a/erts/emulator/nifs/win32/win_prim_file.c +++ b/erts/emulator/nifs/win32/win_prim_file.c @@ -773,6 +773,71 @@ static int is_name_surrogate(const efile_path_t *path) { return result; } +static void build_file_info(BY_HANDLE_FILE_INFORMATION *native_file_info, const efile_path_t *path, int is_link, efile_fileinfo_t *result) { + DWORD attributes; + + attributes = native_file_info->dwFileAttributes; + + if(is_link) { + result->type = EFILE_FILETYPE_SYMLINK; + /* This should be _S_IFLNK, but the old driver always set + * non-directories to _S_IFREG. */ + result->mode |= _S_IFREG; + } else if(attributes & FILE_ATTRIBUTE_DIRECTORY) { + result->type = EFILE_FILETYPE_DIRECTORY; + result->mode |= _S_IFDIR | _S_IEXEC; + } else { + if(is_executable_file(path)) { + result->mode |= _S_IEXEC; + } + + result->type = EFILE_FILETYPE_REGULAR; + result->mode |= _S_IFREG; + } + + if(!(attributes & FILE_ATTRIBUTE_READONLY)) { + result->access = EFILE_ACCESS_READ | EFILE_ACCESS_WRITE; + result->mode |= _S_IREAD | _S_IWRITE; + } else { + result->access = EFILE_ACCESS_READ; + result->mode |= _S_IREAD; + } + + /* Propagate user mode-bits to group/other fields */ + result->mode |= (result->mode & 0700) >> 3; + result->mode |= (result->mode & 0700) >> 6; + + result->size = + ((Uint64)native_file_info->nFileSizeHigh << 32ull) | + (Uint64)native_file_info->nFileSizeLow; + result->links = MAX(1, native_file_info->nNumberOfLinks); + + result->major_device = get_drive_number(path); + result->minor_device = 0; + result->inode = 0; + result->uid = 0; + result->gid = 0; +} + +static void build_file_info_times(BY_HANDLE_FILE_INFORMATION *native_file_info, efile_fileinfo_t *result) { + FILETIME_TO_EPOCH(result->m_time, native_file_info->ftLastWriteTime); + FILETIME_TO_EPOCH(result->a_time, native_file_info->ftLastAccessTime); + FILETIME_TO_EPOCH(result->c_time, native_file_info->ftCreationTime); + + if(result->m_time == -EPOCH_DIFFERENCE) { + /* Default to 1970 just like the old driver. */ + result->m_time = 0; + } + + if(result->a_time == -EPOCH_DIFFERENCE) { + result->a_time = result->m_time; + } + + if(result->c_time == -EPOCH_DIFFERENCE) { + result->c_time = result->m_time; + } +} + posix_errno_t efile_read_info(const efile_path_t *path, int follow_links, efile_fileinfo_t *result) { BY_HANDLE_FILE_INFORMATION native_file_info; DWORD attributes; @@ -792,23 +857,41 @@ posix_errno_t efile_read_info(const efile_path_t *path, int follow_links, efile_ return windows_to_posix_errno(last_error); } - attributes = FILE_ATTRIBUTE_DIRECTORY; + native_file_info.dwFileAttributes = FILE_ATTRIBUTE_DIRECTORY; } else if(is_path_root(path)) { /* Local (or mounted) roots can be queried with GetFileAttributesW but * lack support for GetFileInformationByHandle, so we'll skip that * part. */ + native_file_info.dwFileAttributes = attributes; } else { HANDLE handle; + DWORD last_error; + DWORD flags; if(attributes & FILE_ATTRIBUTE_REPARSE_POINT) { is_link = is_name_surrogate(path); } + flags = FILE_FLAG_BACKUP_SEMANTICS; + if(!follow_links && is_link) { + flags |= FILE_FLAG_OPEN_REPARSE_POINT; + } + + handle = CreateFileW((const WCHAR*)path->data, GENERIC_READ, + FILE_SHARE_FLAGS, NULL, OPEN_EXISTING, flags, NULL); + last_error = GetLastError(); + + if(handle == INVALID_HANDLE_VALUE) { + return windows_to_posix_errno(last_error); + } + if(follow_links && is_link) { posix_errno_t posix_errno; efile_path_t resolved_path; - posix_errno = internal_read_link(path, &resolved_path); + posix_errno = internal_read_link(handle, &resolved_path); + + CloseHandle(handle); if(posix_errno != 0) { return posix_errno; @@ -817,74 +900,43 @@ posix_errno_t efile_read_info(const efile_path_t *path, int follow_links, efile_ return efile_read_info(&resolved_path, 0, result); } - handle = CreateFileW((const WCHAR*)path->data, GENERIC_READ, - FILE_SHARE_FLAGS, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, - NULL); - - /* The old driver never cared whether this succeeded. */ - if(handle != INVALID_HANDLE_VALUE) { - GetFileInformationByHandle(handle, &native_file_info); - CloseHandle(handle); - } + GetFileInformationByHandle(handle, &native_file_info); + CloseHandle(handle); - FILETIME_TO_EPOCH(result->m_time, native_file_info.ftLastWriteTime); - FILETIME_TO_EPOCH(result->a_time, native_file_info.ftLastAccessTime); - FILETIME_TO_EPOCH(result->c_time, native_file_info.ftCreationTime); + build_file_info_times(&native_file_info, result); + } - if(result->m_time == -EPOCH_DIFFERENCE) { - /* Default to 1970 just like the old driver. */ - result->m_time = 0; - } + build_file_info(&native_file_info, path, is_link, result); - if(result->a_time == -EPOCH_DIFFERENCE) { - result->a_time = result->m_time; - } + return 0; +} - if(result->c_time == -EPOCH_DIFFERENCE) { - result->c_time = result->m_time; - } - } +posix_errno_t efile_read_handle_info(efile_data_t *d, efile_fileinfo_t *result) { + efile_win_t *w = (efile_win_t*)d; + HANDLE handle; + BY_HANDLE_FILE_INFORMATION native_file_info; + posix_errno_t posix_errno; + efile_path_t path; + int length; - if(is_link) { - result->type = EFILE_FILETYPE_SYMLINK; - /* This should be _S_IFLNK, but the old driver always set - * non-directories to _S_IFREG. */ - result->mode |= _S_IFREG; - } else if(attributes & FILE_ATTRIBUTE_DIRECTORY) { - result->type = EFILE_FILETYPE_DIRECTORY; - result->mode |= _S_IFDIR | _S_IEXEC; - } else { - if(is_executable_file(path)) { - result->mode |= _S_IEXEC; - } + sys_memset(&native_file_info, 0, sizeof(native_file_info)); - result->type = EFILE_FILETYPE_REGULAR; - result->mode |= _S_IFREG; + posix_errno = internal_read_link(w->handle, &path); + if(posix_errno != 0) { + return posix_errno; } - if(!(attributes & FILE_ATTRIBUTE_READONLY)) { - result->access = EFILE_ACCESS_READ | EFILE_ACCESS_WRITE; - result->mode |= _S_IREAD | _S_IWRITE; + if(GetFileInformationByHandle(w->handle, &native_file_info)) { + build_file_info_times(&native_file_info, result); + } else if(is_path_root(&path)) { + /* GetFileInformationByHandle is not supported on path roots, so + * fall back to efile_read_info. */ + return efile_read_info(&path, 0, result); } else { - result->access = EFILE_ACCESS_READ; - result->mode |= _S_IREAD; + return windows_to_posix_errno(GetLastError()); } - /* Propagate user mode-bits to group/other fields */ - result->mode |= (result->mode & 0700) >> 3; - result->mode |= (result->mode & 0700) >> 6; - - result->size = - ((Uint64)native_file_info.nFileSizeHigh << 32ull) | - (Uint64)native_file_info.nFileSizeLow; - - result->links = MAX(1, native_file_info.nNumberOfLinks); - - result->major_device = get_drive_number(path); - result->minor_device = 0; - result->inode = 0; - result->uid = 0; - result->gid = 0; + build_file_info(&native_file_info, &path, 0, result); return 0; } @@ -963,31 +1015,20 @@ posix_errno_t efile_set_time(const efile_path_t *path, Sint64 a_time, Sint64 m_t return windows_to_posix_errno(last_error); } -static posix_errno_t internal_read_link(const efile_path_t *path, efile_path_t *result) { +static posix_errno_t internal_read_link(HANDLE link_handle, efile_path_t *result) { DWORD required_length, actual_length; - HANDLE link_handle; DWORD last_error; - link_handle = CreateFileW((WCHAR*)path->data, GENERIC_READ, - FILE_SHARE_FLAGS, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL); - last_error = GetLastError(); - - if(link_handle == INVALID_HANDLE_VALUE) { - return windows_to_posix_errno(last_error); - } - required_length = GetFinalPathNameByHandleW(link_handle, NULL, 0, 0); last_error = GetLastError(); if(required_length <= 0) { - CloseHandle(link_handle); return windows_to_posix_errno(last_error); } /* Unlike many other path functions (eg. GetFullPathNameW), this one * includes the NUL terminator in its required length. */ if(!enif_alloc_binary(required_length * sizeof(WCHAR), result)) { - CloseHandle(link_handle); return ENOMEM; } @@ -995,8 +1036,6 @@ static posix_errno_t internal_read_link(const efile_path_t *path, efile_path_t * (WCHAR*)result->data, required_length, 0); last_error = GetLastError(); - CloseHandle(link_handle); - if(actual_length == 0 || actual_length >= required_length) { enif_release_binary(result); return windows_to_posix_errno(last_error); @@ -1014,6 +1053,8 @@ posix_errno_t efile_read_link(ErlNifEnv *env, const efile_path_t *path, ERL_NIF_ posix_errno_t posix_errno; ErlNifBinary result_bin; DWORD attributes; + HANDLE handle; + DWORD last_error; ASSERT_PATH_FORMAT(path); @@ -1029,7 +1070,17 @@ posix_errno_t efile_read_link(ErlNifEnv *env, const efile_path_t *path, ERL_NIF_ return EINVAL; } - posix_errno = internal_read_link(path, &result_bin); + handle = CreateFileW((WCHAR*)path->data, GENERIC_READ, + FILE_SHARE_FLAGS, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, + NULL); + last_error = GetLastError(); + + if(handle == INVALID_HANDLE_VALUE) { + return windows_to_posix_errno(last_error); + } + posix_errno = internal_read_link(handle, &result_bin); + + CloseHandle(handle); if(posix_errno == 0) { if(!normalize_path_result(&result_bin)) { diff --git a/erts/emulator/sys/common/erl_osenv.h b/erts/emulator/sys/common/erl_osenv.h index 4777f2148a..f2e96a6af7 100644 --- a/erts/emulator/sys/common/erl_osenv.h +++ b/erts/emulator/sys/common/erl_osenv.h @@ -35,16 +35,10 @@ # include "config.h" #endif -typedef struct __erts_osenv_data_t erts_osenv_data_t; - -typedef struct __erts_osenv_t { - struct __env_rbtnode_t *tree; - int variable_count; - int content_size; -} erts_osenv_t; - #include "sys.h" +typedef struct __erts_osenv_data_t erts_osenv_data_t; + struct __erts_osenv_data_t { Sint length; void *data; diff --git a/erts/emulator/sys/unix/erl_child_setup.c b/erts/emulator/sys/unix/erl_child_setup.c index 9241660069..8f261761db 100644 --- a/erts/emulator/sys/unix/erl_child_setup.c +++ b/erts/emulator/sys/unix/erl_child_setup.c @@ -63,10 +63,13 @@ #include "erl_driver.h" #include "sys_uds.h" -#include "hash.h" #include "erl_term.h" #include "erl_child_setup.h" +#undef ERTS_GLB_INLINE_INCL_FUNC_DEF +#define ERTS_GLB_INLINE_INCL_FUNC_DEF 1 +#include "hash.h" + #define SET_CLOEXEC(fd) fcntl(fd, F_SETFD, fcntl(fd, F_GETFD) | FD_CLOEXEC) #if defined(__ANDROID__) diff --git a/erts/emulator/sys/unix/sys_drivers.c b/erts/emulator/sys/unix/sys_drivers.c index 664d677ebd..870d0bd28a 100644 --- a/erts/emulator/sys/unix/sys_drivers.c +++ b/erts/emulator/sys/unix/sys_drivers.c @@ -55,6 +55,7 @@ #define WANT_NONBLOCKING /* must define this to pull in defs from sys.h */ #include "sys.h" +#include "erl_osenv.h" #include "erl_threads.h" @@ -785,15 +786,15 @@ static ErlDrvSSizeT spawn_control(ErlDrvData e, unsigned int cmd, char *buf, static int fd_get_window_size(int fd, Uint32 *width, Uint32 *height) { -#ifdef TIOCGWINSZ +#ifdef TIOCGWINSZ struct winsize ws; if (ioctl(fd,TIOCGWINSZ,&ws) == 0) { *width = (Uint32) ws.ws_col; *height = (Uint32) ws.ws_row; - return 0; + return 1; } #endif - return -1; + return 0; } static ErlDrvSSizeT fd_control(ErlDrvData drv_data, @@ -801,16 +802,28 @@ static ErlDrvSSizeT fd_control(ErlDrvData drv_data, char *buf, ErlDrvSizeT len, char **rbuf, ErlDrvSizeT rlen) { - int fd = (int)(long)drv_data; char resbuff[2*sizeof(Uint32)]; - + ErtsSysDriverData* dd = (ErtsSysDriverData*)drv_data; command -= ERTS_TTYSL_DRV_CONTROL_MAGIC_NUMBER; switch (command) { case FD_CTRL_OP_GET_WINSIZE: { Uint32 w,h; - if (fd_get_window_size(fd,&w,&h)) - return 0; + int success = 0; + if (dd->ofd != NULL) { + /* Try with output file descriptor */ + int out_fd = dd->ofd->fd; + success = fd_get_window_size(out_fd,&w,&h); + } + if (!success && dd->ifd != NULL) { + /* Try with input file descriptor */ + int in_fd = dd->ifd->fd; + success = fd_get_window_size(in_fd,&w,&h); + } + if (!success) { + return -1; + } + /* Succeeded */ memcpy(resbuff,&w,sizeof(Uint32)); memcpy(resbuff+sizeof(Uint32),&h,sizeof(Uint32)); } diff --git a/erts/emulator/sys/win32/sys.c b/erts/emulator/sys/win32/sys.c index b95aadc9b2..bc3de42be7 100644 --- a/erts/emulator/sys/win32/sys.c +++ b/erts/emulator/sys/win32/sys.c @@ -27,6 +27,7 @@ #endif #include "sys.h" +#include "erl_osenv.h" #include "erl_alloc.h" #include "erl_sys_driver.h" #include "global.h" diff --git a/erts/emulator/sys/win32/sys_env.c b/erts/emulator/sys/win32/sys_env.c index c78161b344..36223c2c14 100644 --- a/erts/emulator/sys/win32/sys_env.c +++ b/erts/emulator/sys/win32/sys_env.c @@ -23,6 +23,7 @@ #endif #include "sys.h" +#include "erl_osenv.h" #include "erl_sys_driver.h" #include "erl_alloc.h" diff --git a/erts/emulator/test/bif_SUITE.erl b/erts/emulator/test/bif_SUITE.erl index c5abd04e07..cde2bbfa7c 100644 --- a/erts/emulator/test/bif_SUITE.erl +++ b/erts/emulator/test/bif_SUITE.erl @@ -29,8 +29,8 @@ shadow_comments/1,list_to_utf8_atom/1, specs/1,improper_bif_stubs/1,auto_imports/1, t_list_to_existing_atom/1,os_env/1,otp_7526/1, - binary_to_atom/1,binary_to_existing_atom/1, - atom_to_binary/1,min_max/1, erlang_halt/1, + t_binary_to_atom/1,t_binary_to_existing_atom/1, + t_atom_to_binary/1,min_max/1, erlang_halt/1, erl_crash_dump_bytes/1, is_builtin/1, error_stacktrace/1, error_stacktrace_during_call_trace/1, @@ -50,7 +50,7 @@ all() -> specs, improper_bif_stubs, auto_imports, t_list_to_existing_atom, os_env, otp_7526, display, display_string, list_to_utf8_atom, - atom_to_binary, binary_to_atom, binary_to_existing_atom, + t_atom_to_binary, t_binary_to_atom, t_binary_to_existing_atom, erl_crash_dump_bytes, min_max, erlang_halt, is_builtin, error_stacktrace, error_stacktrace_during_call_trace, group_leader_prio, group_leader_prio_dirty, @@ -496,7 +496,7 @@ test_7526(N) -> -define(BADARG(E), {'EXIT',{badarg,_}} = (catch E)). -define(SYS_LIMIT(E), {'EXIT',{system_limit,_}} = (catch E)). -binary_to_atom(Config) when is_list(Config) -> +t_binary_to_atom(Config) when is_list(Config) -> HalfLong = lists:seq(0, 127), HalfLongAtom = list_to_atom(HalfLong), HalfLongBin = list_to_binary(HalfLong), @@ -524,8 +524,10 @@ binary_to_atom(Config) when is_list(Config) -> test_binary_to_atom(<<C/utf8>>, utf8) end], - <<"こんにちは"/utf8>> = - atom_to_binary(test_binary_to_atom(<<"こんにちは"/utf8>>, utf8), utf8), + ExoticBin = <<"こんにちは"/utf8>>, + ExoticAtom = test_binary_to_atom(ExoticBin, utf8), + ExoticBin = atom_to_binary(ExoticAtom, utf8), + ExoticBin = atom_to_binary(ExoticAtom), %% badarg failures. fail_binary_to_atom(atom), @@ -543,6 +545,7 @@ binary_to_atom(Config) when is_list(Config) -> %% Bad UTF8 sequences. ?BADARG(binary_to_atom(id(<<255>>), utf8)), + ?BADARG(binary_to_atom(id(<<255>>))), ?BADARG(binary_to_atom(id(<<255,0>>), utf8)), ?BADARG(binary_to_atom(id(<<16#C0,16#80>>), utf8)), %Overlong 0. <<B:1/binary, _/binary>> = id(<<194, 163>>), %Truncated character ERL-474 @@ -550,6 +553,7 @@ binary_to_atom(Config) when is_list(Config) -> %% system_limit failures. ?SYS_LIMIT(binary_to_atom(id(<<0:512/unit:8,255>>), utf8)), + ?SYS_LIMIT(binary_to_atom(id(<<0:512/unit:8,255>>))), ?SYS_LIMIT(binary_to_atom(id(<<0:512/unit:8,255,0>>), utf8)), ?SYS_LIMIT(binary_to_atom(<<0:256/unit:8>>, latin1)), ?SYS_LIMIT(binary_to_atom(<<0:257/unit:8>>, latin1)), @@ -562,6 +566,14 @@ binary_to_atom(Config) when is_list(Config) -> test_binary_to_atom(Bin0, Encoding) -> Res = binary_to_atom(Bin0, Encoding), Res = binary_to_existing_atom(Bin0, Encoding), + if + Encoding =:= utf8; + Encoding =:= unicode -> + Res = binary_to_atom(Bin0), + Res = binary_to_existing_atom(Bin0); + true -> + ok + end, Bin1 = id(<<7:3,Bin0/binary,32:5>>), Sz = byte_size(Bin0), <<_:3,UnalignedBin:Sz/binary,_:5>> = Bin1, @@ -581,6 +593,12 @@ fail_binary_to_atom(Bin) -> ok end, try + binary_to_atom(Bin) + catch + error:badarg -> + ok + end, + try binary_to_existing_atom(Bin, latin1) catch error:badarg -> @@ -591,10 +609,16 @@ fail_binary_to_atom(Bin) -> catch error:badarg -> ok + end, + try + binary_to_existing_atom(Bin) + catch + error:badarg -> + ok end. -binary_to_existing_atom(Config) when is_list(Config) -> +t_binary_to_existing_atom(Config) when is_list(Config) -> UnlikelyBin = <<"ou0897979655678dsfj923874390867er869fds973qerueoru">>, try binary_to_existing_atom(UnlikelyBin, latin1), @@ -609,6 +633,12 @@ binary_to_existing_atom(Config) when is_list(Config) -> catch error:badarg -> ok end, + try + binary_to_existing_atom(UnlikelyBin), + ct:fail(atom_exists) + catch + error:badarg -> ok + end, UnlikelyAtom = binary_to_atom(id(UnlikelyBin), latin1), UnlikelyAtom = binary_to_existing_atom(UnlikelyBin, latin1), @@ -625,7 +655,7 @@ binary_to_existing_atom(Config) when is_list(Config) -> ok. -atom_to_binary(Config) when is_list(Config) -> +t_atom_to_binary(Config) when is_list(Config) -> HalfLong = lists:seq(0, 127), HalfLongAtom = list_to_atom(HalfLong), HalfLongBin = list_to_binary(HalfLong), @@ -641,12 +671,15 @@ atom_to_binary(Config) when is_list(Config) -> LongBin = atom_to_binary(LongAtom, latin1), %% utf8. + <<>> = atom_to_binary(''), <<>> = atom_to_binary('', utf8), <<>> = atom_to_binary('', unicode), <<127>> = atom_to_binary('\177', utf8), <<"abcdef">> = atom_to_binary(abcdef, utf8), HalfLongBin = atom_to_binary(HalfLongAtom, utf8), + HalfLongBin = atom_to_binary(HalfLongAtom), LongAtomBin = atom_to_binary(LongAtom, utf8), + LongAtomBin = atom_to_binary(LongAtom), verify_long_atom_bin(LongAtomBin, 0), %% Failing cases. @@ -678,8 +711,15 @@ fail_atom_to_binary(Term) -> catch error:badarg -> ok + end, + try + atom_to_binary(Term) + catch + error:badarg -> + ok end. + min_max(Config) when is_list(Config) -> a = erlang:min(id(a), a), a = erlang:min(id(a), b), @@ -860,6 +900,7 @@ error_stacktrace_test() -> Types = [apply_const_last, apply_const, apply_last, apply, double_apply_const_last, double_apply_const, double_apply_last, double_apply, multi_apply_const_last, + apply_const_only, apply_only, multi_apply_const, multi_apply_last, multi_apply, call_const_last, call_last, call_const, call], lists:foreach(fun (Type) -> @@ -897,6 +938,8 @@ error_stacktrace_test() -> ok. stk([], Type, Func) -> + put(erlang, erlang), + put(tail, []), tail(Type, Func, jump), ok; stk([_|L], Type, Func) -> @@ -910,6 +953,12 @@ tail(Type, error_1, do) -> tail(Type, error_2, do) -> do_error_2(Type). +do_error_2(apply_const_only) -> + apply(erlang, error, [oops, [apply_const_only]]); +do_error_2(apply_only) -> + Erlang = get(erlang), + Tail = get(tail), + apply(Erlang, error, [oops, [apply_only|Tail]]); do_error_2(apply_const_last) -> erlang:apply(erlang, error, [oops, [apply_const_last]]); do_error_2(apply_const) -> @@ -951,6 +1000,12 @@ do_error_2(call) -> erlang:error(id(oops), id([call])). +do_error_1(apply_const_only) -> + apply(erlang, error, [oops]); +do_error_1(apply_only) -> + Erlang = get(erlang), + Tail = get(tail), + apply(Erlang, error, [oops|Tail]); do_error_1(apply_const_last) -> erlang:apply(erlang, error, [oops]); do_error_1(apply_const) -> diff --git a/erts/emulator/test/binary_SUITE.erl b/erts/emulator/test/binary_SUITE.erl index 4fb339926e..fbd1325c3a 100644 --- a/erts/emulator/test/binary_SUITE.erl +++ b/erts/emulator/test/binary_SUITE.erl @@ -1438,7 +1438,8 @@ sleeper() -> gc_test(Config) when is_list(Config) -> %% Note: This test is only relevant for REFC binaries. %% Therefore, we take care that all binaries are REFC binaries. - B = list_to_binary(lists:seq(0, ?heap_binary_size)), + true = 192 > ?heap_binary_size, + B = list_to_binary(lists:seq(1, 192)), Self = self(), F1 = fun() -> gc(), @@ -1447,22 +1448,22 @@ gc_test(Config) when is_list(Config) -> end, F = fun() -> receive go -> ok end, - {binary,[{_,65,1}]} = process_info(self(), binary), + {binary,[{_,192,1}]} = process_info(self(), binary), gc(), - {B1,B2} = my_split_binary(B, 4), + {B1,B2} = my_split_binary(B, 68), gc(), gc(), {binary,L1} = process_info(self(), binary), [Binfo1,Binfo2,Binfo3] = L1, - {_,65,3} = Binfo1 = Binfo2 = Binfo3, - 65 = size(B), - 4 = size(B1), - 61 = size(B2), + {_,192,3} = Binfo1 = Binfo2 = Binfo3, + 192 = size(B), + 68 = size(B1), + 124 = size(B2), F1() end, gc(), gc(), - 65 = size(B), + 192 = size(B), gc_test1(spawn_opt(erlang, apply, [F,[]], [link,{fullsweep_after,0}])). gc_test1(Pid) -> diff --git a/erts/emulator/test/call_trace_SUITE.erl b/erts/emulator/test/call_trace_SUITE.erl index 742592f88e..477b0f5bb3 100644 --- a/erts/emulator/test/call_trace_SUITE.erl +++ b/erts/emulator/test/call_trace_SUITE.erl @@ -832,21 +832,27 @@ deep_exception() -> R1 -> ct:fail({returned,abbr(R1)}) catch error:badarg -> ok end, - expect(fun ({trace,S,call,{lists,reverse,[L1,L2]}}) + expect(fun ({trace,S,call,{lists,reverse,[L1,L2]}}, Traps) when is_list(L1), is_list(L2), S == Self -> - next; + %% Each trapping call to reverse/2 must have a corresponding + %% exception_from + {next, Traps + 1}; ({trace,S,exception_from, - {lists,reverse,2},{error,badarg}}) + {lists,reverse,2},{error,badarg}}, Traps) + when S == Self, Traps > 1 -> + {next, Traps - 1}; + ({trace,S,exception_from, + {lists,reverse,2},{error,badarg}}, 1) when S == Self -> expected; - ('_') -> + ('_', _Traps) -> {trace,Self,exception_from, {lists,reverse,2},{error,badarg}}; - (_) -> + (_, _Traps) -> {unexpected, {trace,Self,exception_from, {lists,reverse,2},{error,badarg}}} - end), + end, 0), deep_exception(?LINE, deep_5, [1,2], 7, [{trace,Self,call,{erlang,error,[undef]}}, {trace,Self,exception_from,{erlang,error,1}, @@ -896,21 +902,27 @@ deep_exception() -> R2 -> ct:fail({returned,abbr(R2)}) catch error:badarg -> ok end, - expect(fun ({trace,S,call,{lists,reverse,[L1,L2]}}) + expect(fun ({trace,S,call,{lists,reverse,[L1,L2]}}, Traps) when is_list(L1), is_list(L2), S == Self -> - next; + %% Each trapping call to reverse/2 must have a corresponding + %% exception_from + {next, Traps + 1}; + ({trace,S,exception_from, + {lists,reverse,2},{error,badarg}}, Traps) + when S == Self, Traps > 1 -> + {next, Traps - 1}; ({trace,S,exception_from, - {lists,reverse,2},{error,badarg}}) + {lists,reverse,2},{error,badarg}}, 1) when S == Self -> expected; - ('_') -> + ('_', _Traps) -> {trace,Self,exception_from, {lists,reverse,2},{error,badarg}}; - (_) -> + (_, _Traps) -> {unexpected, {trace,Self,exception_from, {lists,reverse,2},{error,badarg}}} - end), + end, 0), deep_exception(?LINE, apply, [?MODULE,deep_5,[1,2]], 7, [{trace,Self,call,{erlang,error,[undef]}}, {trace,Self,exception_from,{erlang,error,1}, @@ -975,21 +987,27 @@ deep_exception() -> R3 -> ct:fail({returned,abbr(R3)}) catch error:badarg -> ok end, - expect(fun ({trace,S,call,{lists,reverse,[L1,L2]}}) + expect(fun ({trace,S,call,{lists,reverse,[L1,L2]}}, Traps) when is_list(L1), is_list(L2), S == Self -> - next; + %% Each trapping call to reverse/2 must have a corresponding + %% exception_from + {next, Traps + 1}; + ({trace,S,exception_from, + {lists,reverse,2},{error,badarg}}, Traps) + when S == Self, Traps > 1 -> + {next, Traps - 1}; ({trace,S,exception_from, - {lists,reverse,2},{error,badarg}}) + {lists,reverse,2},{error,badarg}}, 1) when S == Self -> expected; - ('_') -> + ('_', _Traps) -> {trace,Self,exception_from, {lists,reverse,2},{error,badarg}}; - (_) -> + (_, _Traps) -> {unexpected, {trace,Self,exception_from, {lists,reverse,2},{error,badarg}}} - end), + end, 0), deep_exception(?LINE, apply, [fun () -> ?MODULE:deep_5(1,2) end, []], 7, [{trace,Self,call,{erlang,error,[undef]}}, @@ -1249,6 +1267,24 @@ expect(Message) -> ct:fail(no_trace_message) end. +expect(Validator, State0) when is_function(Validator) -> + receive + M -> + case Validator(M, State0) of + expected -> + ok = io:format("Expected and got ~p", [abbr(M)]); + {next, State} -> + ok = io:format("Expected and got ~p", [abbr(M)]), + expect(Validator, State); + {unexpected,Message} -> + io:format("Expected ~p; got ~p", [abbr(Message),abbr(M)]), + ct:fail({unexpected,abbr([M|flush()])}) + end + after 5000 -> + io:format("Expected ~p; got nothing", [abbr(Validator('_'))]), + ct:fail(no_trace_message) + end. + trace_info(What, Key) -> get(tracer) ! {apply,self(),{erlang,trace_info,[What,Key]}}, Res = receive diff --git a/erts/emulator/test/dirty_bif_SUITE.erl b/erts/emulator/test/dirty_bif_SUITE.erl index 4f5ad0295a..2ded862b8a 100644 --- a/erts/emulator/test/dirty_bif_SUITE.erl +++ b/erts/emulator/test/dirty_bif_SUITE.erl @@ -397,7 +397,9 @@ dirty_process_trace(Config) when is_list(Config) -> access_dirty_process( Config, fun() -> - erlang:trace_pattern({erts_debug,dirty_io,2}, + %% BIFs can only be traced when their modules are loaded. + code:ensure_loaded(erts_debug), + 1 = erlang:trace_pattern({erts_debug,dirty_io,2}, [{'_',[],[{return_trace}]}], [local,meta]), ok diff --git a/erts/emulator/test/esock_ttest/esock-ttest b/erts/emulator/test/esock_ttest/esock-ttest index 9adc51fc8b..2ded557484 100755 --- a/erts/emulator/test/esock_ttest/esock-ttest +++ b/erts/emulator/test/esock_ttest/esock-ttest @@ -203,7 +203,7 @@ process_client_args(["--max-outstanding", Max|Args], State) -> end; process_client_args(["--scon", Server|Args], State) -> - case string:tokens(Server, [$:]) of + case string:split(Server, ":", trailing) of [AddrStr,PortStr] -> Addr = case inet:parse_address(AddrStr) of {ok, A} -> @@ -343,9 +343,9 @@ exec(#{role := client, runtime := RunTime}) -> case socket_test_ttest_tcp_client_socket:start(true, Async, + Active, Method, ServerInfo, - Active, MsgID, MaxOutstanding, RunTime) of {ok, Pid} -> diff --git a/erts/emulator/test/esock_ttest/esock-ttest-client b/erts/emulator/test/esock_ttest/esock-ttest-client index 7c90ae6391..5ae05d03b8 100755 --- a/erts/emulator/test/esock_ttest/esock-ttest-client +++ b/erts/emulator/test/esock_ttest/esock-ttest-client @@ -20,23 +20,30 @@ # %CopyrightEnd% # +# +# This is just a simple convenience wrapper to the esock-ttest. +# That means that there are some options not available here. +# + EMU=$ERL_TOP/erts/emulator EMU_TEST=$EMU/test ESOCK_TTEST=$EMU_TEST/esock_ttest RUNTIME=30 +# RUNTIME=60 +# RUNTIME=600 if [ $# = 3 ]; then MSGID=$1 SERVER_INFO=$2:$3 ITERATIONS="\ - gen false $MSGID - gen true $MSGID - gen once $MSGID - sock false $MSGID - sock true $MSGID - sock once $MSGID" + gen false $MSGID + gen true $MSGID + gen once $MSGID + sock false $MSGID --async + sock true $MSGID --async + sock once $MSGID --async" else if [ $# = 2 ]; then @@ -44,9 +51,9 @@ else SERVER_INFO=$2 ITERATIONS="\ - sock false $MSGID - sock true $MSGID - sock once $MSGID" + sock false $MSGID --async + sock true $MSGID --async + sock once $MSGID --async" else echo "Invalid number of args" @@ -70,14 +77,14 @@ fi # --------------------------------------------------------------------------- echo "$ITERATIONS" | - while read TRANSPORT ACTIVE MSG_ID; do + while read TRANSPORT ACTIVE MSG_ID ASYNC; do echo "" echo "=========== transport = $TRANSPORT, active = $ACTIVE, msg-id = $MSG_ID ===========" # The /dev/null at the end is necessary because erlang "does things" with stdin # and this case would cause the 'while read' to "fail" so that we only would # loop one time - $ESOCK_TTEST/esock-ttest --client --transport $TRANSPORT --active $ACTIVE --msg-id $MSG_ID --scon $SERVER_INFO --runtime $RUNTIME </dev/null + $ESOCK_TTEST/esock-ttest --client --transport $TRANSPORT $ASYNC --active $ACTIVE --msg-id $MSG_ID --scon $SERVER_INFO --runtime $RUNTIME </dev/null echo "" done diff --git a/erts/emulator/test/esock_ttest/esock-ttest-server-sock b/erts/emulator/test/esock_ttest/esock-ttest-server-sock index fc87499f09..c443d42e64 100755 --- a/erts/emulator/test/esock_ttest/esock-ttest-server-sock +++ b/erts/emulator/test/esock_ttest/esock-ttest-server-sock @@ -24,9 +24,10 @@ EMU=$ERL_TOP/erts/emulator EMU_TEST=$EMU/test ESOCK_TTEST=$EMU_TEST/esock_ttest -# $1 - async - boolean() -# $2 - active - once | boolean() -if [ $# = 2 ]; then +# $1 - async - boolean() +# $2 - active - once | boolean() +# [$3 - domain - inet (default) | inet6 | local] +if [ $# -ge 2 ]; then async=$1 active=$2 @@ -39,6 +40,11 @@ if [ $# = 2 ]; then ACTIVE="--active $active" + if [ $# = 3 ]; then + DOMAIN="--domain $3" + fi + + else echo "<ERROR> Missing args: async and active" echo "" @@ -46,5 +52,5 @@ else fi -$ESOCK_TTEST/esock-ttest --server $ASYNC --transport sock $ACTIVE +$ESOCK_TTEST/esock-ttest --server $DOMAIN $ASYNC --transport sock $ACTIVE diff --git a/erts/emulator/test/fun_SUITE.erl b/erts/emulator/test/fun_SUITE.erl index 2cbde621ce..ad8ef0feff 100644 --- a/erts/emulator/test/fun_SUITE.erl +++ b/erts/emulator/test/fun_SUITE.erl @@ -27,7 +27,7 @@ fun_to_port/1,t_phash/1,t_phash2/1,md5/1, refc/1,refc_ets/1,refc_dist/1, const_propagation/1,t_arity/1,t_is_function2/1, - t_fun_info/1,t_fun_info_mfa/1]). + t_fun_info/1,t_fun_info_mfa/1,t_fun_to_list/1]). -export([nothing/0]). @@ -44,7 +44,7 @@ all() -> equality, ordering, fun_to_port, t_phash, t_phash2, md5, refc, refc_ets, refc_dist, const_propagation, t_arity, t_is_function2, t_fun_info, - t_fun_info_mfa]. + t_fun_info_mfa,t_fun_to_list]. %% Test that the correct EXIT code is returned for all types of bad funs. bad_apply(Config) when is_list(Config) -> @@ -802,6 +802,12 @@ t_fun_info_mfa(Config) when is_list(Config) -> {'EXIT',_} = (catch erlang:fun_info_mfa(id(d))), ok. +t_fun_to_list(Config) when is_list(Config) -> + "fun a:b/1" = erlang:fun_to_list(fun a:b/1), + "fun 'a-esc':'b-esc'/1" = erlang:fun_to_list(fun 'a-esc':'b-esc'/1), + "fun 'a-esc':b/1" = erlang:fun_to_list(fun 'a-esc':b/1), + "fun a:'b-esc'/1" = erlang:fun_to_list(fun a:'b-esc'/1), + ok. bad_info(Term) -> try erlang:fun_info(Term, module) of diff --git a/erts/emulator/test/hibernate_SUITE.erl b/erts/emulator/test/hibernate_SUITE.erl index a20f306e04..d65d0ff2fd 100644 --- a/erts/emulator/test/hibernate_SUITE.erl +++ b/erts/emulator/test/hibernate_SUITE.erl @@ -46,12 +46,17 @@ all() -> basic(Config) when is_list(Config) -> Ref = make_ref(), Info = {self(),Ref}, - ExpectedHeapSz = erts_debug:size([Info]), + ExpectedHeapSz = expected_heap_size([Info]), Child = spawn_link(fun() -> basic_hibernator(Info) end), hibernate_wake_up(100, ExpectedHeapSz, Child), Child ! please_quit_now, ok. +expected_heap_size(Term) -> + %% When hibernating, an extra word will be allocated on the stack + %% for a continuation pointer. + erts_debug:size(Term) + 1. + hibernate_wake_up(0, _, _) -> ok; hibernate_wake_up(N, ExpectedHeapSz, Child) -> {heap_size,Before} = process_info(Child, heap_size), @@ -142,7 +147,7 @@ whats_up_calc(A1, A2, A3, A4, A5, A6, A7, A8, A9, Acc) -> dynamic_call(Config) when is_list(Config) -> Ref = make_ref(), Info = {self(),Ref}, - ExpectedHeapSz = erts_debug:size([Info]), + ExpectedHeapSz = expected_heap_size([Info]), Child = spawn_link(fun() -> ?MODULE:dynamic_call_hibernator(Info, hibernate) end), hibernate_wake_up(100, ExpectedHeapSz, Child), Child ! please_quit_now, diff --git a/erts/emulator/test/lttng_SUITE.erl b/erts/emulator/test/lttng_SUITE.erl index 19c3844c40..f19047ba71 100644 --- a/erts/emulator/test/lttng_SUITE.erl +++ b/erts/emulator/test/lttng_SUITE.erl @@ -27,8 +27,7 @@ -export([t_lttng_list/1, t_carrier_pool/1, t_memory_carrier/1, - t_async_io_pool/1, - t_driver_control_ready_async/1, + t_driver_control/1, t_driver_start_stop/1, t_driver_ready_input_output/1, t_driver_timeout/1, @@ -36,6 +35,8 @@ t_driver_flush/1, t_scheduler_poll/1]). +-export([ets_load/0]). + -include_lib("common_test/include/ct.hrl"). suite() -> @@ -46,10 +47,9 @@ all() -> [t_lttng_list, t_memory_carrier, t_carrier_pool, - t_async_io_pool, t_driver_start_stop, t_driver_ready_input_output, - t_driver_control_ready_async, + t_driver_control, t_driver_timeout, t_driver_caller, t_driver_flush, @@ -124,7 +124,7 @@ t_carrier_pool(Config) -> true -> ok = lttng_start_event("org_erlang_otp:carrier_pool*", Config), - ok = ets_load(), + ok = ets_load(Config), Res = lttng_stop_and_view(Config), ok = check_tracepoint("org_erlang_otp:carrier_pool_get", Res), @@ -141,7 +141,7 @@ t_memory_carrier(Config) -> true -> ok = lttng_start_event("org_erlang_otp:carrier_*", Config), - ok = ets_load(), + ok = ets_load(Config), Res = lttng_stop_and_view(Config), ok = check_tracepoint("org_erlang_otp:carrier_destroy", Res), @@ -149,70 +149,49 @@ t_memory_carrier(Config) -> ok end. -%% org_erlang_otp:aio_pool_put -%% org_erlang_otp:aio_pool_get -t_async_io_pool(Config) -> - case have_async_threads() of - false -> - {skip, "No Async Threads configured on system."}; - true -> - ok = lttng_start_event("org_erlang_otp:aio_pool_*", Config), - - Path1 = proplists:get_value(priv_dir, Config), - {ok, [[Path2]]} = init:get_argument(home), - {ok, _} = file:list_dir(Path1), - {ok, _} = file:list_dir(Path2), - {ok, _} = file:list_dir(Path1), - {ok, _} = file:list_dir(Path2), - - Res = lttng_stop_and_view(Config), - ok = check_tracepoint("org_erlang_otp:aio_pool_put", Res), - ok = check_tracepoint("org_erlang_otp:aio_pool_get", Res), - ok - end. - - %% org_erlang_otp:driver_start %% org_erlang_otp:driver_stop t_driver_start_stop(Config) -> ok = lttng_start_event("org_erlang_otp:driver_*", Config), timer:sleep(500), - Path = proplists:get_value(priv_dir, Config), - Name = filename:join(Path, "sometext.txt"), - Bin = txt(), - ok = file:write_file(Name, Bin), - {ok, Bin} = file:read_file(Name), + os:cmd("echo hello"), timer:sleep(500), Res = lttng_stop_and_view(Config), ok = check_tracepoint("org_erlang_otp:driver_start", Res), ok = check_tracepoint("org_erlang_otp:driver_stop", Res), - ok = check_tracepoint("org_erlang_otp:driver_control", Res), - ok = check_tracepoint("org_erlang_otp:driver_outputv", Res), - ok = check_tracepoint("org_erlang_otp:driver_ready_async", Res), + ok = check_tracepoint("org_erlang_otp:driver_output", Res), ok. %% org_erlang_otp:driver_control %% org_erlang_otp:driver_outputv -%% org_erlang_otp:driver_ready_async -t_driver_control_ready_async(Config) -> +t_driver_control(Config) -> ok = lttng_start_event("org_erlang_otp:driver_control", Config), ok = lttng_start_event("org_erlang_otp:driver_outputv", Config), - ok = lttng_start_event("org_erlang_otp:driver_ready_async", Config), - Path = proplists:get_value(priv_dir, Config), - Name = filename:join(Path, "sometext.txt"), - Bin = txt(), - ok = file:write_file(Name, Bin), - {ok, Bin} = file:read_file(Name), + + timer:sleep(500), + Me = self(), + Pid = spawn_link(fun() -> tcp_server(Me, active) end), + receive {Pid, accept} -> ok end, + Bin = txt(), + Sz = byte_size(Bin), + + {ok, Sock} = gen_tcp:connect("localhost", 5679, [binary, {packet, 2}]), + ok = gen_tcp:send(Sock, <<Sz:16, Bin/binary>>), + ok = gen_tcp:send(Sock, <<Sz:16, Bin/binary>>), + ok = gen_tcp:close(Sock), + receive {Pid, done} -> ok end, + + timer:sleep(500), Res = lttng_stop_and_view(Config), ok = check_tracepoint("org_erlang_otp:driver_control", Res), ok = check_tracepoint("org_erlang_otp:driver_outputv", Res), - ok = check_tracepoint("org_erlang_otp:driver_ready_async", Res), ok. %% org_erlang_otp:driver_ready_input %% org_erlang_otp:driver_ready_output t_driver_ready_input_output(Config) -> ok = lttng_start_event("org_erlang_otp:driver_ready_*", Config), + timer:sleep(500), Me = self(), Pid = spawn_link(fun() -> tcp_server(Me, active) end), @@ -290,8 +269,27 @@ t_driver_caller(Config) -> t_scheduler_poll(Config) -> ok = lttng_start_event("org_erlang_otp:scheduler_poll", Config), + N = 100, + + Me = self(), + Pid = spawn_link(fun() -> tcp_server(Me, {active, N*2}) end), + receive {Pid, accept} -> ok end, + + %% We want to create a scenario where the fd is moved into a scheduler + %% pollset, this means we have to send many small packages to the + %% same socket, but not fast enough for them to all arrive at the + %% same time. + {ok, Sock} = gen_tcp:connect("localhost", 5679, [binary, {packet, 2}]), + [begin gen_tcp:send(Sock,txt()), receive ok -> ok end end || _ <- lists:seq(1,N)], + ok = memory_load(), + [begin gen_tcp:send(Sock,txt()), receive ok -> ok end end || _ <- lists:seq(1,N)], + + ok = gen_tcp:close(Sock), + Pid ! die, + receive {Pid, done} -> ok end, + Res = lttng_stop_and_view(Config), ok = check_tracepoint("org_erlang_otp:scheduler_poll", Res), ok. @@ -335,8 +333,37 @@ chk_caller(Port, Callback, ExpectedCaller) -> ExpectedCaller = Caller end. +memory_load() -> + Me = self(), + Pids0 = [spawn_link(fun() -> memory_loop(Me, 20, <<42>>) end) || _ <- lists:seq(1,30)], + timer:sleep(50), + Pids1 = [spawn_link(fun() -> memory_loop(Me, 20, <<42>>) end) || _ <- lists:seq(1,30)], + [receive {Pid, done} -> ok end || Pid <- Pids0 ++ Pids1], + timer:sleep(500), + ok. + +memory_loop(Parent, N, Bin) -> + memory_loop(Parent, N, Bin, []). + +memory_loop(Parent, 0, _Bin, _) -> + Parent ! {self(), done}; +memory_loop(Parent, N, Bin0, Ls) -> + Bin = binary:copy(<<Bin0/binary, Bin0/binary>>), + memory_loop(Parent, N - 1, Bin, [a,b,c|Ls]). + +ets_load(Config) -> + + %% Have to do on a fresh node to guarantee that carriers are created + {ok,Node} = start_node(Config), + + Res = rpc:call(Node, ?MODULE, ets_load, []), + + stop_node(Node), + + Res. ets_load() -> + Tid = ets:new(ets_load, [public,set]), N = erlang:system_info(schedulers_online), Pids = [spawn_link(fun() -> ets_shuffle(Tid) end) || _ <- lists:seq(1,N)], @@ -368,27 +395,6 @@ ets_shuffle(Tid, I, N, Data, Data0) -> ets_shuffle(Tid, I - 1, N, Data1, Data0) end. - - - -memory_load() -> - Me = self(), - Pids0 = [spawn_link(fun() -> memory_loop(Me, 20, <<42>>) end) || _ <- lists:seq(1,30)], - timer:sleep(50), - Pids1 = [spawn_link(fun() -> memory_loop(Me, 20, <<42>>) end) || _ <- lists:seq(1,30)], - [receive {Pid, done} -> ok end || Pid <- Pids0 ++ Pids1], - timer:sleep(500), - ok. - -memory_loop(Parent, N, Bin) -> - memory_loop(Parent, N, Bin, []). - -memory_loop(Parent, 0, _Bin, _) -> - Parent ! {self(), done}; -memory_loop(Parent, N, Bin0, Ls) -> - Bin = binary:copy(<<Bin0/binary, Bin0/binary>>), - memory_loop(Parent, N - 1, Bin, [a,b,c|Ls]). - tcp_server(Pid, Type) -> {ok, LSock} = gen_tcp:listen(5679, [binary, {reuseaddr, true}, @@ -399,14 +405,19 @@ tcp_server(Pid, Type) -> passive_no_read -> receive die -> ok end; active -> - inet:setopts(Sock, [{active, once}, {packet,2}]), + inet:setopts(Sock, [{active, 2}, {packet,2}]), receive Msg1 -> io:format("msg1: ~p~n", [Msg1]) end, - inet:setopts(Sock, [{active, once}, {packet,2}]), receive Msg2 -> io:format("msg2: ~p~n", [Msg2]) end, ok = gen_tcp:close(Sock); timeout -> Res = gen_tcp:recv(Sock, 2000, 1000), - io:format("res ~p~n", [Res]) + io:format("res ~p~n", [Res]); + {active, Number} when is_number(Number) -> + inet:setopts(Sock, [{active, Number}, {packet,2}]), + [begin + receive _Msg1 -> Pid ! ok, io:format("msg ~p~n", [I]) end + end || I <- lists:seq(1,Number)], + ok = gen_tcp:close(Sock) end, Pid ! {self(), done}, ok. @@ -497,3 +508,20 @@ cmd(Cmd) -> Res = os:cmd(Cmd), io:format(">> ~ts~n", [Res]), {ok,Res}. + +start_node(Config) -> + start_node(Config, ""). + +start_node(Config, Args) when is_list(Config) -> + Pa = filename:dirname(code:which(?MODULE)), + Name = list_to_atom(atom_to_list(?MODULE) + ++ "-" + ++ atom_to_list(proplists:get_value(testcase, Config)) + ++ "-" + ++ integer_to_list(erlang:system_time(second)) + ++ "-" + ++ integer_to_list(erlang:unique_integer([positive]))), + test_server:start_node(Name, slave, [{args, "-pa "++Pa++" "++Args}]). + +stop_node(Node) -> + test_server:stop_node(Node). diff --git a/erts/emulator/test/match_spec_SUITE.erl b/erts/emulator/test/match_spec_SUITE.erl index 21de6b1002..686b431876 100644 --- a/erts/emulator/test/match_spec_SUITE.erl +++ b/erts/emulator/test/match_spec_SUITE.erl @@ -198,7 +198,8 @@ caller_and_return_to(Config) -> {trace,Tracee,call,{?MODULE,do_the_put,[test]},{?MODULE,do_put,1}}, {trace,Tracee,call,{erlang,integer_to_list,[1]},{?MODULE,do_the_put,1}}, {trace,Tracee,return_to,{?MODULE,do_the_put,1}}, - {trace,Tracee,call,{erlang,put,[test,"1"]},{?MODULE,do_put,1}}, + {trace,Tracee,call,{erlang,put,[test,"1"]},{?MODULE,do_the_put,1}}, + {trace,Tracee,return_to,{?MODULE,do_the_put,1}}, {trace,Tracee,return_to,{?MODULE,do_put,1}}, %% These last trace messages are a bit strange... diff --git a/erts/emulator/test/node_container_SUITE.erl b/erts/emulator/test/node_container_SUITE.erl index 7d2db5257c..c44693f8d9 100644 --- a/erts/emulator/test/node_container_SUITE.erl +++ b/erts/emulator/test/node_container_SUITE.erl @@ -51,7 +51,8 @@ unique_pid/1, iter_max_procs/1, magic_ref/1, - dist_entry_gc/1]). + dist_entry_gc/1, + persistent_term/1]). suite() -> [{ct_hooks,[ts_install_cth]}, @@ -63,7 +64,8 @@ all() -> node_table_gc, dist_link_refc, dist_monitor_refc, node_controller_refc, ets_refc, match_spec_refc, timer_refc, pid_wrap, port_wrap, bad_nc, - unique_pid, iter_max_procs, magic_ref]. + unique_pid, iter_max_procs, + magic_ref, persistent_term]. init_per_suite(Config) -> Config. @@ -906,6 +908,44 @@ magic_ref(Config) when is_list(Config) -> true = erts_debug:get_internal_state({magic_ref,MRef2}), ok. +persistent_term(Config) when is_list(Config) -> + {ok, Node} = start_node(get_nodefirstname()), + Self = self(), + NcData = make_ref(), + RPid = spawn_link(Node, + fun () -> + Self ! {NcData, self(), hd(erlang:ports()), erlang:make_ref()} + end), + Data = receive + {NcData, RPid, RPort, RRef} -> + {RPid, RPort, RRef} + end, + unlink(RPid), + stop_node(Node), + Stuff = lists:foldl(fun (N, Acc) -> + persistent_term:put({?MODULE, N}, Data), + persistent_term:erase({?MODULE, N-1}), + node_container_refc_check(node()), + Data = persistent_term:get({?MODULE, N}), + try + persistent_term:get({?MODULE, N-1}) + catch + error:badarg -> + ok + end, + case N rem 4 of + 0 -> [persistent_term:get({?MODULE, N})|Acc]; + _ -> Acc + end + end, + [], + lists:seq(1, 100)), + persistent_term:erase({?MODULE, 100}), + receive after 2000 -> ok end, %% give literal gc some time to run... + node_container_refc_check(node()), + id(Stuff), + ok. + lost_pending_connection(Node) -> _ = (catch erts_internal:new_connection(Node)), diff --git a/erts/emulator/test/nofrag_SUITE.erl b/erts/emulator/test/nofrag_SUITE.erl index 8b1519ae36..d4c74579e2 100644 --- a/erts/emulator/test/nofrag_SUITE.erl +++ b/erts/emulator/test/nofrag_SUITE.erl @@ -22,6 +22,11 @@ -include_lib("common_test/include/ct.hrl"). +%% This suite alters the return values of functions which breaks certain +%% assumptions made by the compiler, so we have to turn off module-level type +%% optimization to be safe. +-compile(no_module_opt). + -export([all/0, suite/0, error_handler/1,error_handler_apply/1, error_handler_fixed_apply/1,error_handler_fun/1, diff --git a/erts/emulator/test/socket_SUITE.erl b/erts/emulator/test/socket_SUITE.erl index b80cc794e7..124ae09951 100644 --- a/erts/emulator/test/socket_SUITE.erl +++ b/erts/emulator/test/socket_SUITE.erl @@ -58,6 +58,7 @@ -include_lib("common_test/include/ct.hrl"). -include_lib("common_test/include/ct_event.hrl"). +-include("socket_test_evaluator.hrl"). %% Suite exports -export([suite/0, all/0, groups/0]). @@ -86,26 +87,52 @@ %% *** API async *** api_a_connect_tcp4/1, + api_a_connect_tcp6/1, api_a_sendto_and_recvfrom_udp4/1, + api_a_sendto_and_recvfrom_udp6/1, api_a_sendmsg_and_recvmsg_udp4/1, + api_a_sendmsg_and_recvmsg_udp6/1, api_a_send_and_recv_tcp4/1, + api_a_send_and_recv_tcp6/1, api_a_sendmsg_and_recvmsg_tcp4/1, + api_a_sendmsg_and_recvmsg_tcp6/1, api_a_recvfrom_cancel_udp4/1, + api_a_recvfrom_cancel_udp6/1, api_a_recvmsg_cancel_udp4/1, + api_a_recvmsg_cancel_udp6/1, api_a_accept_cancel_tcp4/1, + api_a_accept_cancel_tcp6/1, api_a_recv_cancel_tcp4/1, + api_a_recv_cancel_tcp6/1, api_a_recvmsg_cancel_tcp4/1, + api_a_recvmsg_cancel_tcp6/1, api_a_mrecvfrom_cancel_udp4/1, + api_a_mrecvfrom_cancel_udp6/1, api_a_mrecvmsg_cancel_udp4/1, + api_a_mrecvmsg_cancel_udp6/1, api_a_maccept_cancel_tcp4/1, + api_a_maccept_cancel_tcp6/1, api_a_mrecv_cancel_tcp4/1, + api_a_mrecv_cancel_tcp6/1, api_a_mrecvmsg_cancel_tcp4/1, + api_a_mrecvmsg_cancel_tcp6/1, %% *** API Options *** api_opt_simple_otp_options/1, api_opt_simple_otp_rcvbuf_option/1, api_opt_simple_otp_controlling_process/1, + api_opt_sock_acceptconn_udp/1, + api_opt_sock_acceptconn_tcp/1, + api_opt_sock_acceptfilter/1, + api_opt_sock_bindtodevice/1, + api_opt_sock_broadcast/1, + api_opt_sock_debug/1, + api_opt_sock_domain/1, + api_opt_sock_dontroute/1, + api_opt_sock_error/1, + api_opt_sock_keepalive/1, + api_opt_sock_linger/1, api_opt_ip_add_drop_membership/1, %% *** API Operation Timeout *** @@ -172,12 +199,16 @@ %% *** Traffic *** traffic_send_and_recv_counters_tcp4/1, + traffic_send_and_recv_counters_tcp6/1, traffic_send_and_recv_counters_tcpL/1, traffic_sendmsg_and_recvmsg_counters_tcp4/1, + traffic_sendmsg_and_recvmsg_counters_tcp6/1, traffic_sendmsg_and_recvmsg_counters_tcpL/1, traffic_sendto_and_recvfrom_counters_udp4/1, + traffic_sendto_and_recvfrom_counters_udp6/1, traffic_sendto_and_recvfrom_counters_udpL/1, traffic_sendmsg_and_recvmsg_counters_udp4/1, + traffic_sendmsg_and_recvmsg_counters_udp6/1, traffic_sendmsg_and_recvmsg_counters_udpL/1, traffic_send_and_recv_chunks_tcp4/1, @@ -526,30 +557,31 @@ ]). --include("socket_test_evaluator.hrl"). - %% Internal exports %% -export([]). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% --define(BASIC_REQ, <<"hejsan">>). --define(BASIC_REP, <<"hoppsan">>). +-define(LIB, socket_test_lib). +-define(TTEST_LIB, socket_test_ttest_lib). +-define(LOGGER, socket_test_logger). --define(DATA, <<"HOPPSAN">>). % Temporary --define(FAIL(R), exit(R)). +-define(BASIC_REQ, <<"hejsan">>). +-define(BASIC_REP, <<"hoppsan">>). --define(SLEEP(T), receive after T -> ok end). +-define(DATA, <<"HOPPSAN">>). % Temporary +-define(FAIL(R), exit(R)). --define(MINS(M), timer:minutes(M)). --define(SECS(S), timer:seconds(S)). +-define(SLEEP(T), receive after T -> ok end). --define(TT(T), ct:timetrap(T)). +-define(MINS(M), timer:minutes(M)). +-define(SECS(S), timer:seconds(S)). + +-define(TT(T), ct:timetrap(T)). + +-define(F(F, A), ?LIB:f(F, A)). --define(LIB, socket_test_lib). --define(TTEST_LIB, socket_test_ttest_lib). --define(LOGGER, socket_test_logger). -define(TPP_SMALL, lists:seq(1, 8)). -define(TPP_MEDIUM, lists:flatten(lists:duplicate(1024, ?TPP_SMALL))). @@ -594,80 +626,86 @@ use_group(Group, Env, Default) -> groups() -> - [{api, [], api_cases()}, - {api_misc, [], api_misc_cases()}, - {api_basic, [], api_basic_cases()}, - {api_async, [], api_async_cases()}, - {api_options, [], api_options_cases()}, - {api_options_otp, [], api_options_otp_cases()}, - {api_options_ip, [], api_options_ip_cases()}, - {api_op_with_timeout, [], api_op_with_timeout_cases()}, - {socket_close, [], socket_close_cases()}, - {sc_ctrl_proc_exit, [], sc_cp_exit_cases()}, - {sc_local_close, [], sc_lc_cases()}, - {sc_remote_close, [], sc_rc_cases()}, - {sc_remote_shutdown, [], sc_rs_cases()}, - {traffic, [], traffic_cases()}, - {traffic_counters, [], traffic_counters_cases()}, - {traffic_chunks, [], traffic_chunks_cases()}, - {traffic_pp_send_recv, [], traffic_pp_send_recv_cases()}, - {traffic_pp_sendto_recvfrom, [], traffic_pp_sendto_recvfrom_cases()}, - {traffic_pp_sendmsg_recvmsg, [], traffic_pp_sendmsg_recvmsg_cases()}, - {ttest, [], ttest_cases()}, - {ttest_sgenf, [], ttest_sgenf_cases()}, - {ttest_sgenf_cgen, [], ttest_sgenf_cgen_cases()}, - {ttest_sgenf_cgenf, [], ttest_sgenf_cgenf_cases()}, - {ttest_sgenf_cgeno, [], ttest_sgenf_cgeno_cases()}, - {ttest_sgenf_cgent, [], ttest_sgenf_cgent_cases()}, - {ttest_sgenf_csock, [], ttest_sgenf_csock_cases()}, - {ttest_sgenf_csockf, [], ttest_sgenf_csockf_cases()}, - {ttest_sgenf_csocko, [], ttest_sgenf_csocko_cases()}, - {ttest_sgenf_csockt, [], ttest_sgenf_csockt_cases()}, - {ttest_sgeno, [], ttest_sgeno_cases()}, - {ttest_sgeno_cgen, [], ttest_sgeno_cgen_cases()}, - {ttest_sgeno_cgenf, [], ttest_sgeno_cgenf_cases()}, - {ttest_sgeno_cgeno, [], ttest_sgeno_cgeno_cases()}, - {ttest_sgeno_cgent, [], ttest_sgeno_cgent_cases()}, - {ttest_sgeno_csock, [], ttest_sgeno_csock_cases()}, - {ttest_sgeno_csockf, [], ttest_sgeno_csockf_cases()}, - {ttest_sgeno_csocko, [], ttest_sgeno_csocko_cases()}, - {ttest_sgeno_csockt, [], ttest_sgeno_csockt_cases()}, - {ttest_sgent, [], ttest_sgent_cases()}, - {ttest_sgent_cgen, [], ttest_sgent_cgen_cases()}, - {ttest_sgent_cgenf, [], ttest_sgent_cgenf_cases()}, - {ttest_sgent_cgeno, [], ttest_sgent_cgeno_cases()}, - {ttest_sgent_cgent, [], ttest_sgent_cgent_cases()}, - {ttest_sgent_csock, [], ttest_sgent_csock_cases()}, - {ttest_sgent_csockf, [], ttest_sgent_csockf_cases()}, - {ttest_sgent_csocko, [], ttest_sgent_csocko_cases()}, - {ttest_sgent_csockt, [], ttest_sgent_csockt_cases()}, - {ttest_ssockf, [], ttest_ssockf_cases()}, - {ttest_ssockf_cgen, [], ttest_ssockf_cgen_cases()}, - {ttest_ssockf_cgenf, [], ttest_ssockf_cgenf_cases()}, - {ttest_ssockf_cgeno, [], ttest_ssockf_cgeno_cases()}, - {ttest_ssockf_cgent, [], ttest_ssockf_cgent_cases()}, - {ttest_ssockf_csock, [], ttest_ssockf_csock_cases()}, - {ttest_ssockf_csockf, [], ttest_ssockf_csockf_cases()}, - {ttest_ssockf_csocko, [], ttest_ssockf_csocko_cases()}, - {ttest_ssockf_csockt, [], ttest_ssockf_csockt_cases()}, - {ttest_ssocko, [], ttest_ssocko_cases()}, - {ttest_ssocko_cgen, [], ttest_ssocko_cgen_cases()}, - {ttest_ssocko_cgenf, [], ttest_ssocko_cgenf_cases()}, - {ttest_ssocko_cgeno, [], ttest_ssocko_cgeno_cases()}, - {ttest_ssocko_cgent, [], ttest_ssocko_cgent_cases()}, - {ttest_ssocko_csock, [], ttest_ssocko_csock_cases()}, - {ttest_ssocko_csockf, [], ttest_ssocko_csockf_cases()}, - {ttest_ssocko_csocko, [], ttest_ssocko_csocko_cases()}, - {ttest_ssocko_csockt, [], ttest_ssocko_csockt_cases()}, - {ttest_ssockt, [], ttest_ssockt_cases()}, - {ttest_ssockt_cgen, [], ttest_ssockt_cgen_cases()}, - {ttest_ssockt_cgenf, [], ttest_ssockt_cgenf_cases()}, - {ttest_ssockt_cgeno, [], ttest_ssockt_cgeno_cases()}, - {ttest_ssockt_cgent, [], ttest_ssockt_cgent_cases()}, - {ttest_ssockt_csock, [], ttest_ssockt_csock_cases()}, - {ttest_ssockt_csockf, [], ttest_ssockt_csockf_cases()}, - {ttest_ssockt_csocko, [], ttest_ssockt_csocko_cases()}, - {ttest_ssockt_csockt, [], ttest_ssockt_csockt_cases()} + [{api, [], api_cases()}, + {api_misc, [], api_misc_cases()}, + {api_basic, [], api_basic_cases()}, + {api_async, [], api_async_cases()}, + {api_options, [], api_options_cases()}, + {api_options_otp, [], api_options_otp_cases()}, + {api_options_socket, [], api_options_socket_cases()}, + {api_option_sock_acceptconn, [], api_option_sock_acceptconn_cases()}, + {api_options_ip, [], api_options_ip_cases()}, + %% {api_options_ipv6, [], api_options_ipv6_cases()}, + %% {api_options_tcp, [], api_options_tcp_cases()}, + %% {api_options_udp, [], api_options_udp_cases()}, + %% {api_options_sctp, [], api_options_sctp_cases()}, + {api_op_with_timeout, [], api_op_with_timeout_cases()}, + {socket_close, [], socket_close_cases()}, + {sc_ctrl_proc_exit, [], sc_cp_exit_cases()}, + {sc_local_close, [], sc_lc_cases()}, + {sc_remote_close, [], sc_rc_cases()}, + {sc_remote_shutdown, [], sc_rs_cases()}, + {traffic, [], traffic_cases()}, + {traffic_counters, [], traffic_counters_cases()}, + {traffic_chunks, [], traffic_chunks_cases()}, + {traffic_pp_send_recv, [], traffic_pp_send_recv_cases()}, + {traffic_pp_sendto_recvfrom, [], traffic_pp_sendto_recvfrom_cases()}, + {traffic_pp_sendmsg_recvmsg, [], traffic_pp_sendmsg_recvmsg_cases()}, + {ttest, [], ttest_cases()}, + {ttest_sgenf, [], ttest_sgenf_cases()}, + {ttest_sgenf_cgen, [], ttest_sgenf_cgen_cases()}, + {ttest_sgenf_cgenf, [], ttest_sgenf_cgenf_cases()}, + {ttest_sgenf_cgeno, [], ttest_sgenf_cgeno_cases()}, + {ttest_sgenf_cgent, [], ttest_sgenf_cgent_cases()}, + {ttest_sgenf_csock, [], ttest_sgenf_csock_cases()}, + {ttest_sgenf_csockf, [], ttest_sgenf_csockf_cases()}, + {ttest_sgenf_csocko, [], ttest_sgenf_csocko_cases()}, + {ttest_sgenf_csockt, [], ttest_sgenf_csockt_cases()}, + {ttest_sgeno, [], ttest_sgeno_cases()}, + {ttest_sgeno_cgen, [], ttest_sgeno_cgen_cases()}, + {ttest_sgeno_cgenf, [], ttest_sgeno_cgenf_cases()}, + {ttest_sgeno_cgeno, [], ttest_sgeno_cgeno_cases()}, + {ttest_sgeno_cgent, [], ttest_sgeno_cgent_cases()}, + {ttest_sgeno_csock, [], ttest_sgeno_csock_cases()}, + {ttest_sgeno_csockf, [], ttest_sgeno_csockf_cases()}, + {ttest_sgeno_csocko, [], ttest_sgeno_csocko_cases()}, + {ttest_sgeno_csockt, [], ttest_sgeno_csockt_cases()}, + {ttest_sgent, [], ttest_sgent_cases()}, + {ttest_sgent_cgen, [], ttest_sgent_cgen_cases()}, + {ttest_sgent_cgenf, [], ttest_sgent_cgenf_cases()}, + {ttest_sgent_cgeno, [], ttest_sgent_cgeno_cases()}, + {ttest_sgent_cgent, [], ttest_sgent_cgent_cases()}, + {ttest_sgent_csock, [], ttest_sgent_csock_cases()}, + {ttest_sgent_csockf, [], ttest_sgent_csockf_cases()}, + {ttest_sgent_csocko, [], ttest_sgent_csocko_cases()}, + {ttest_sgent_csockt, [], ttest_sgent_csockt_cases()}, + {ttest_ssockf, [], ttest_ssockf_cases()}, + {ttest_ssockf_cgen, [], ttest_ssockf_cgen_cases()}, + {ttest_ssockf_cgenf, [], ttest_ssockf_cgenf_cases()}, + {ttest_ssockf_cgeno, [], ttest_ssockf_cgeno_cases()}, + {ttest_ssockf_cgent, [], ttest_ssockf_cgent_cases()}, + {ttest_ssockf_csock, [], ttest_ssockf_csock_cases()}, + {ttest_ssockf_csockf, [], ttest_ssockf_csockf_cases()}, + {ttest_ssockf_csocko, [], ttest_ssockf_csocko_cases()}, + {ttest_ssockf_csockt, [], ttest_ssockf_csockt_cases()}, + {ttest_ssocko, [], ttest_ssocko_cases()}, + {ttest_ssocko_cgen, [], ttest_ssocko_cgen_cases()}, + {ttest_ssocko_cgenf, [], ttest_ssocko_cgenf_cases()}, + {ttest_ssocko_cgeno, [], ttest_ssocko_cgeno_cases()}, + {ttest_ssocko_cgent, [], ttest_ssocko_cgent_cases()}, + {ttest_ssocko_csock, [], ttest_ssocko_csock_cases()}, + {ttest_ssocko_csockf, [], ttest_ssocko_csockf_cases()}, + {ttest_ssocko_csocko, [], ttest_ssocko_csocko_cases()}, + {ttest_ssocko_csockt, [], ttest_ssocko_csockt_cases()}, + {ttest_ssockt, [], ttest_ssockt_cases()}, + {ttest_ssockt_cgen, [], ttest_ssockt_cgen_cases()}, + {ttest_ssockt_cgenf, [], ttest_ssockt_cgenf_cases()}, + {ttest_ssockt_cgeno, [], ttest_ssockt_cgeno_cases()}, + {ttest_ssockt_cgent, [], ttest_ssockt_cgent_cases()}, + {ttest_ssockt_csock, [], ttest_ssockt_csock_cases()}, + {ttest_ssockt_csockf, [], ttest_ssockt_csockf_cases()}, + {ttest_ssockt_csocko, [], ttest_ssockt_csocko_cases()}, + {ttest_ssockt_csockt, [], ttest_ssockt_csockt_cases()} %% {tickets, [], ticket_cases()} ]. @@ -705,26 +743,46 @@ api_basic_cases() -> api_async_cases() -> [ api_a_connect_tcp4, + api_a_connect_tcp6, api_a_sendto_and_recvfrom_udp4, + api_a_sendto_and_recvfrom_udp6, api_a_sendmsg_and_recvmsg_udp4, + api_a_sendmsg_and_recvmsg_udp6, api_a_send_and_recv_tcp4, + api_a_send_and_recv_tcp6, api_a_sendmsg_and_recvmsg_tcp4, + api_a_sendmsg_and_recvmsg_tcp6, api_a_recvfrom_cancel_udp4, + api_a_recvfrom_cancel_udp6, api_a_recvmsg_cancel_udp4, + api_a_recvmsg_cancel_udp6, api_a_accept_cancel_tcp4, + api_a_accept_cancel_tcp6, api_a_recv_cancel_tcp4, + api_a_recv_cancel_tcp6, api_a_recvmsg_cancel_tcp4, + api_a_recvmsg_cancel_tcp6, api_a_mrecvfrom_cancel_udp4, + api_a_mrecvfrom_cancel_udp6, api_a_mrecvmsg_cancel_udp4, + api_a_mrecvmsg_cancel_udp6, api_a_maccept_cancel_tcp4, + api_a_maccept_cancel_tcp6, api_a_mrecv_cancel_tcp4, - api_a_mrecvmsg_cancel_tcp4 + api_a_mrecv_cancel_tcp6, + api_a_mrecvmsg_cancel_tcp4, + api_a_mrecvmsg_cancel_tcp6 ]. api_options_cases() -> [ {group, api_options_otp}, - {group, api_options_ip} + {group, api_options_socket}, + {group, api_options_ip}% , + %% {group, api_options_ipv6}, + %% {group, api_options_tcp}, + %% {group, api_options_udp}, + %% {group, api_options_sctp} ]. api_options_otp_cases() -> @@ -734,11 +792,35 @@ api_options_otp_cases() -> api_opt_simple_otp_controlling_process ]. +api_options_socket_cases() -> + [ + {group, api_option_sock_acceptconn}, + api_opt_sock_acceptfilter, + api_opt_sock_bindtodevice, + api_opt_sock_broadcast, + api_opt_sock_debug, + api_opt_sock_domain, + api_opt_sock_dontroute, + api_opt_sock_error, + api_opt_sock_keepalive, + api_opt_sock_linger + ]. + +api_option_sock_acceptconn_cases() -> + [ + api_opt_sock_acceptconn_udp, + api_opt_sock_acceptconn_tcp + ]. + api_options_ip_cases() -> [ api_opt_ip_add_drop_membership ]. +%% api_options_ipv6_cases() -> +%% [ +%% ]. + api_op_with_timeout_cases() -> [ api_to_connect_tcp4, @@ -848,12 +930,16 @@ traffic_cases() -> traffic_counters_cases() -> [ traffic_send_and_recv_counters_tcp4, + traffic_send_and_recv_counters_tcp6, traffic_send_and_recv_counters_tcpL, traffic_sendmsg_and_recvmsg_counters_tcp4, + traffic_sendmsg_and_recvmsg_counters_tcp6, traffic_sendmsg_and_recvmsg_counters_tcpL, traffic_sendto_and_recvfrom_counters_udp4, + traffic_sendto_and_recvfrom_counters_udp6, traffic_sendto_and_recvfrom_counters_udpL, traffic_sendmsg_and_recvmsg_counters_udp4, + traffic_sendmsg_and_recvmsg_counters_udp6, traffic_sendmsg_and_recvmsg_counters_udpL ]. @@ -1690,7 +1776,7 @@ quiet_mode(Config) -> %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%% A simple test case that tests that the global debug can be channged. +%% A simple test case that tests that the global debug can be changed. %% At the same time, it will test the info function (since it uses it %% for verification). @@ -1708,19 +1794,22 @@ api_m_debug(_Config) when is_list(_Config) -> %% For some reason this test case triggers a gcc bug, which causes %% a segfault, on an ancient Fedora 16 VM. So, check the version of gcc... -%% Not pretty, but the simplest way to skip (without actually testing for the host). +%% Not pretty, but the simplest way to skip (without actually testing +%% for the host). has_bugfree_gcc() -> has_bugfree_gcc(os:type()). %% Make sure we are on linux has_bugfree_gcc({unix, linux}) -> - has_bugfree_gcc2(os:cmd("cat /etc/issue")); + has_bugfree_gcc2(string:trim(os:cmd("cat /etc/issue"))); has_bugfree_gcc(_) -> ok. %% Make sure we are on Fedora 16 has_bugfree_gcc2("Fedora release 16 " ++ _) -> has_bugfree_gcc3(os:cmd("gcc --version")); +has_bugfree_gcc2("Welcome to SUSE Linux " ++ _) -> + has_bugfree_gcc4(os:cmd("gcc --version")); has_bugfree_gcc2(_) -> ok. @@ -1729,6 +1818,11 @@ has_bugfree_gcc3("gcc (GCC) 4.6.3 20120306 (Red Hat 4.6.3-2" ++ _) -> has_bugfree_gcc3(_) -> ok. +has_bugfree_gcc4("gcc (SUSE Linux) 4.3.2" ++ _) -> + skip("Buggy GCC"); +has_bugfree_gcc4(_) -> + ok. + api_m_debug() -> i("get initial info"), #{debug := D0} = socket:info(), @@ -1746,6 +1840,7 @@ api_m_debug() -> ok. + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% %% @@ -2768,7 +2863,7 @@ api_b_send_and_recv_tcp(InitState) -> %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%% Basically establish a TCP connection via an async connect. +%% Basically establish a TCP connection via an async connect. IPv4. api_a_connect_tcp4(suite) -> []; @@ -2778,25 +2873,48 @@ api_a_connect_tcp4(_Config) when is_list(_Config) -> ?TT(?SECS(10)), tc_try(api_a_connect_tcp4, fun() -> - Connect = fun(Sock, SockAddr) -> - socket:connect(Sock, SockAddr, nowait) - end, - Send = fun(Sock, Data) -> - socket:send(Sock, Data) - end, - Recv = fun(Sock) -> - socket:recv(Sock) - end, - InitState = #{domain => inet, - connect => Connect, - send => Send, - recv => Recv}, - ok = api_a_connect_tcp(InitState) + ok = api_a_connect_tcpD(inet) + end). + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +%% Basically establish a TCP connection via an async connect. IPv6. + +api_a_connect_tcp6(suite) -> + []; +api_a_connect_tcp6(doc) -> + []; +api_a_connect_tcp6(_Config) when is_list(_Config) -> + ?TT(?SECS(10)), + tc_try(api_a_connect_tcp6, + fun() -> has_support_ipv6() end, + fun() -> + ok = api_a_connect_tcpD(inet6) end). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +api_a_connect_tcpD(Domain) -> + Connect = fun(Sock, SockAddr) -> + socket:connect(Sock, SockAddr, nowait) + end, + Send = fun(Sock, Data) -> + socket:send(Sock, Data) + end, + Recv = fun(Sock) -> + socket:recv(Sock) + end, + InitState = #{domain => Domain, + connect => Connect, + send => Send, + recv => Recv}, + api_a_connect_tcp(InitState). + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + api_a_connect_tcp(InitState) -> process_flag(trap_exit, true), ServerSeq = @@ -3296,6 +3414,37 @@ api_a_sendto_and_recvfrom_udp4(_Config) when is_list(_Config) -> %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% Basically send and receive on an IPv6 UDP (dgram) socket using +%% sendto and recvfrom. But we try to be async. That is, we use +%% the 'nowait' value for the Timeout argument (and await the eventual +%% select message). Note that we only do this for the recvfrom, +%% since its much more difficult to "arrange" for sendto. +%% +api_a_sendto_and_recvfrom_udp6(suite) -> + []; +api_a_sendto_and_recvfrom_udp6(doc) -> + []; +api_a_sendto_and_recvfrom_udp6(_Config) when is_list(_Config) -> + ?TT(?SECS(5)), + tc_try(api_a_sendto_and_recvfrom_udp6, + fun() -> has_support_ipv6() end, + fun() -> + Send = fun(Sock, Data, Dest) -> + socket:sendto(Sock, Data, Dest) + end, + Recv = fun(Sock) -> + socket:recvfrom(Sock, 0, nowait) + end, + InitState = #{domain => inet6, + send => Send, + recv => Recv}, + ok = api_a_send_and_recv_udp(InitState) + end). + + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + %% Basically send and receive on an IPv4 UDP (dgram) socket using %% sendto and recvfrom. But we try to be async. That is, we use %% the 'nowait' value for the Timeout argument (and await the eventual @@ -3339,6 +3488,50 @@ api_a_sendmsg_and_recvmsg_udp4(_Config) when is_list(_Config) -> %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% Basically send and receive on an IPv6 UDP (dgram) socket using +%% sendto and recvfrom. But we try to be async. That is, we use +%% the 'nowait' value for the Timeout argument (and await the eventual +%% select message). Note that we only do this for the recvmsg, +%% since its much more difficult to "arrange" for sendmsg. +%% +api_a_sendmsg_and_recvmsg_udp6(suite) -> + []; +api_a_sendmsg_and_recvmsg_udp6(doc) -> + []; +api_a_sendmsg_and_recvmsg_udp6(_Config) when is_list(_Config) -> + ?TT(?SECS(5)), + tc_try(api_a_sendmsg_and_recvmsg_udp6, + fun() -> has_support_ipv6() end, + fun() -> + Send = fun(Sock, Data, Dest) -> + MsgHdr = #{addr => Dest, + %% ctrl => CMsgHdrs, + iov => [Data]}, + socket:sendmsg(Sock, MsgHdr) + end, + Recv = fun(Sock) -> + case socket:recvmsg(Sock, nowait) of + {ok, #{addr := Source, + iov := [Data]}} -> + {ok, {Source, Data}}; + {ok, _} = OK -> + OK; + {select, _} = SELECT -> + SELECT; + {error, _} = ERROR -> + ERROR + end + end, + InitState = #{domain => inet6, + send => Send, + recv => Recv}, + ok = api_a_send_and_recv_udp(InitState) + end). + + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + api_a_send_and_recv_udp(InitState) -> ServerSeq = [ @@ -3788,6 +3981,37 @@ api_a_send_and_recv_tcp4(_Config) when is_list(_Config) -> %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% Basically send and receive using the "common" functions (send and recv) +%% on an IPv6 TCP (stream) socket. But we try to be async. That is, we use +%% the 'nowait' value for the Timeout argument (and await the eventual +%% select message). Note that we only do this for the recv, +%% since its much more difficult to "arrange" for send. +%% We *also* test async for accept. +api_a_send_and_recv_tcp6(suite) -> + []; +api_a_send_and_recv_tcp6(doc) -> + []; +api_a_send_and_recv_tcp6(_Config) when is_list(_Config) -> + ?TT(?SECS(10)), + tc_try(api_a_send_and_recv_tcp6, + fun() -> has_support_ipv6() end, + fun() -> + Send = fun(Sock, Data) -> + socket:send(Sock, Data) + end, + Recv = fun(Sock) -> + socket:recv(Sock, 0, nowait) + end, + InitState = #{domain => inet6, + send => Send, + recv => Recv}, + ok = api_a_send_and_recv_tcp(InitState) + end). + + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + %% Basically send and receive using the msg functions (sendmsg and recvmsg) %% on an IPv4 TCP (stream) socket. But we try to be async. That is, we use %% the 'nowait' value for the Timeout argument (and await the eventual @@ -3815,7 +4039,7 @@ api_a_sendmsg_and_recvmsg_tcp4(_Config) when is_list(_Config) -> OK; {select, _} = SELECT -> SELECT; - {error, _} = ERROR -> + {error, _} = ERROR -> ERROR end end, @@ -3826,6 +4050,49 @@ api_a_sendmsg_and_recvmsg_tcp4(_Config) when is_list(_Config) -> end). + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +%% Basically send and receive using the msg functions (sendmsg and recvmsg) +%% on an IPv6 TCP (stream) socket. But we try to be async. That is, we use +%% the 'nowait' value for the Timeout argument (and await the eventual +%% select message). Note that we only do this for the recvmsg, +%% since its much more difficult to "arrange" for sendmsg. +%% We *also* test async for accept. +api_a_sendmsg_and_recvmsg_tcp6(suite) -> + []; +api_a_sendmsg_and_recvmsg_tcp6(doc) -> + []; +api_a_sendmsg_and_recvmsg_tcp6(_Config) when is_list(_Config) -> + ?TT(?SECS(10)), + tc_try(api_a_sendmsg_and_recvmsg_tcp6, + fun() -> has_support_ipv6() end, + fun() -> + Send = fun(Sock, Data) -> + MsgHdr = #{iov => [Data]}, + socket:sendmsg(Sock, MsgHdr) + end, + Recv = fun(Sock) -> + case socket:recvmsg(Sock, nowait) of + {ok, #{addr := undefined, + iov := [Data]}} -> + {ok, Data}; + {ok, _} = OK -> + OK; + {select, _} = SELECT -> + SELECT; + {error, _} = ERROR -> + ERROR + end + end, + InitState = #{domain => inet6, + send => Send, + recv => Recv}, + ok = api_a_send_and_recv_tcp(InitState) + end). + + + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% api_a_send_and_recv_tcp(InitState) -> @@ -4326,7 +4593,7 @@ api_a_send_and_recv_tcp(InitState) -> %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% Basically we make an async (Timeout = nowait) call to recvfrom, -%% wait some time and then cancel. +%% wait some time and then cancel. IPv4 %% api_a_recvfrom_cancel_udp4(suite) -> []; @@ -4355,8 +4622,39 @@ api_a_recvfrom_cancel_udp4(_Config) when is_list(_Config) -> %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% Basically we make an async (Timeout = nowait) call to recvfrom, +%% wait some time and then cancel. IPv6 +%% +api_a_recvfrom_cancel_udp6(suite) -> + []; +api_a_recvfrom_cancel_udp6(doc) -> + []; +api_a_recvfrom_cancel_udp6(_Config) when is_list(_Config) -> + ?TT(?SECS(10)), + tc_try(api_a_recvfrom_cancel_udp6, + fun() -> has_support_ipv6() end, + fun() -> + Recv = fun(Sock) -> + case socket:recvfrom(Sock, 0, nowait) of + {ok, _} = OK -> + OK; + {select, _} = SELECT -> + SELECT; + {error, _} = ERROR -> + ERROR + end + end, + InitState = #{domain => inet6, + recv => Recv}, + ok = api_a_recv_cancel_udp(InitState) + end). + + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + %% Basically we make an async (Timeout = nowait) call to recvmsg, -%% wait some time and then cancel. +%% wait some time and then cancel. IPv4 %% api_a_recvmsg_cancel_udp4(suite) -> []; @@ -4385,6 +4683,37 @@ api_a_recvmsg_cancel_udp4(_Config) when is_list(_Config) -> %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% Basically we make an async (Timeout = nowait) call to recvmsg, +%% wait some time and then cancel. IPv6 +%% +api_a_recvmsg_cancel_udp6(suite) -> + []; +api_a_recvmsg_cancel_udp6(doc) -> + []; +api_a_recvmsg_cancel_udp6(_Config) when is_list(_Config) -> + ?TT(?SECS(10)), + tc_try(api_a_recvmsg_cancel_udp6, + fun() -> has_support_ipv6() end, + fun() -> + Recv = fun(Sock) -> + case socket:recvmsg(Sock, nowait) of + {ok, _} = OK -> + OK; + {select, _} = SELECT -> + SELECT; + {error, _} = ERROR -> + ERROR + end + end, + InitState = #{domain => inet6, + recv => Recv}, + ok = api_a_recv_cancel_udp(InitState) + end). + + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + api_a_recv_cancel_udp(InitState) -> ServerSeq = [ @@ -4590,7 +4919,7 @@ api_a_recv_cancel_udp(InitState) -> %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% Basically we make an async (Timeout = nowait) call to accept, -%% wait some time and then cancel. +%% wait some time and then cancel. IPv4 %% api_a_accept_cancel_tcp4(suite) -> []; @@ -4620,6 +4949,38 @@ api_a_accept_cancel_tcp4(_Config) when is_list(_Config) -> %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% Basically we make an async (Timeout = nowait) call to accept, +%% wait some time and then cancel. IPv6 +%% +api_a_accept_cancel_tcp6(suite) -> + []; +api_a_accept_cancel_tcp6(doc) -> + []; +api_a_accept_cancel_tcp6(_Config) when is_list(_Config) -> + ?TT(?SECS(10)), + tc_try(api_a_accept_cancel_tcp6, + fun() -> has_support_ipv6() end, + fun() -> + Accept = fun(Sock) -> + case socket:accept(Sock, nowait) of + {ok, _} = OK -> + OK; + {select, _} = SELECT -> + SELECT; + {error, _} = ERROR -> + ERROR + end + end, + InitState = #{domain => inet6, + accept => Accept}, + ok = api_a_accept_cancel_tcp(InitState) + end). + + + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + api_a_accept_cancel_tcp(InitState) -> process_flag(trap_exit, true), ServerSeq = @@ -4820,7 +5181,7 @@ api_a_accept_cancel_tcp(InitState) -> %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% Basically we make an async (Timeout = nowait) call to recv, -%% wait some time and then cancel. +%% wait some time and then cancel. IPv4 %% api_a_recv_cancel_tcp4(suite) -> []; @@ -4842,8 +5203,32 @@ api_a_recv_cancel_tcp4(_Config) when is_list(_Config) -> %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% Basically we make an async (Timeout = nowait) call to recv, +%% wait some time and then cancel. IPv6 +%% +api_a_recv_cancel_tcp6(suite) -> + []; +api_a_recv_cancel_tcp6(doc) -> + []; +api_a_recv_cancel_tcp6(_Config) when is_list(_Config) -> + ?TT(?SECS(10)), + tc_try(api_a_recv_cancel_tcp6, + fun() -> has_support_ipv6() end, + fun() -> + Recv = fun(Sock) -> + socket:recv(Sock, 0, nowait) + end, + InitState = #{domain => inet6, + recv => Recv}, + ok = api_a_recv_cancel_tcp(InitState) + end). + + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + %% Basically we make an async (Timeout = nowait) call to recvmsg, -%% wait some time and then cancel. +%% wait some time and then cancel. IPv4 %% api_a_recvmsg_cancel_tcp4(suite) -> []; @@ -4865,6 +5250,30 @@ api_a_recvmsg_cancel_tcp4(_Config) when is_list(_Config) -> %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% Basically we make an async (Timeout = nowait) call to recvmsg, +%% wait some time and then cancel. IPv6 +%% +api_a_recvmsg_cancel_tcp6(suite) -> + []; +api_a_recvmsg_cancel_tcp6(doc) -> + []; +api_a_recvmsg_cancel_tcp6(_Config) when is_list(_Config) -> + ?TT(?SECS(10)), + tc_try(api_a_recvmsg_cancel_tcp6, + fun() -> has_support_ipv6() end, + fun() -> + Recv = fun(Sock) -> + socket:recvmsg(Sock, nowait) + end, + InitState = #{domain => inet6, + recv => Recv}, + ok = api_a_recv_cancel_tcp(InitState) + end). + + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + api_a_recv_cancel_tcp(InitState) -> process_flag(trap_exit, true), ServerSeq = @@ -5218,7 +5627,7 @@ api_a_recv_cancel_tcp(InitState) -> %% Basically we make multiple async (Timeout = nowait) call(s) to recvfrom %% (from *several* processes), wait some time and then cancel. -%% This should result in abort messages to the 'other' processes. +%% This should result in abort messages to the 'other' processes. IPv4 %% api_a_mrecvfrom_cancel_udp4(suite) -> []; @@ -5247,9 +5656,41 @@ api_a_mrecvfrom_cancel_udp4(_Config) when is_list(_Config) -> %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% Basically we make multiple async (Timeout = nowait) call(s) to recvfrom +%% (from *several* processes), wait some time and then cancel. +%% This should result in abort messages to the 'other' processes. IPv6 +%% +api_a_mrecvfrom_cancel_udp6(suite) -> + []; +api_a_mrecvfrom_cancel_udp6(doc) -> + []; +api_a_mrecvfrom_cancel_udp6(_Config) when is_list(_Config) -> + ?TT(?SECS(20)), + tc_try(api_a_mrecvfrom_cancel_udp6, + fun() -> has_support_ipv6() end, + fun() -> + Recv = fun(Sock) -> + case socket:recvfrom(Sock, 0, nowait) of + {ok, _} = OK -> + OK; + {select, _} = SELECT -> + SELECT; + {error, _} = ERROR -> + ERROR + end + end, + InitState = #{domain => inet6, + recv => Recv}, + ok = api_a_mrecv_cancel_udp(InitState) + end). + + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + %% Basically we make multiple async (Timeout = nowait) call(s) to recvmsg %% (from *several* processes), wait some time and then cancel. -%% This should result in abort messages to the 'other' processes. +%% This should result in abort messages to the 'other' processes. IPv4 %% api_a_mrecvmsg_cancel_udp4(suite) -> []; @@ -5278,6 +5719,38 @@ api_a_mrecvmsg_cancel_udp4(_Config) when is_list(_Config) -> %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% Basically we make multiple async (Timeout = nowait) call(s) to recvmsg +%% (from *several* processes), wait some time and then cancel. +%% This should result in abort messages to the 'other' processes. IPv6 +%% +api_a_mrecvmsg_cancel_udp6(suite) -> + []; +api_a_mrecvmsg_cancel_udp6(doc) -> + []; +api_a_mrecvmsg_cancel_udp6(_Config) when is_list(_Config) -> + ?TT(?SECS(20)), + tc_try(api_a_mrecvmsg_cancel_udp6, + fun() -> has_support_ipv6() end, + fun() -> + Recv = fun(Sock) -> + case socket:recvmsg(Sock, nowait) of + {ok, _} = OK -> + OK; + {select, _} = SELECT -> + SELECT; + {error, _} = ERROR -> + ERROR + end + end, + InitState = #{domain => inet6, + recv => Recv}, + ok = api_a_mrecv_cancel_udp(InitState) + end). + + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + api_a_mrecv_cancel_udp(InitState) -> ServerSeq = [ @@ -5649,7 +6122,7 @@ api_a_mrecv_cancel_udp(InitState) -> %% Basically we make multiple async (Timeout = nowait) call(s) to accept %% (from *several* processes), wait some time and then cancel, -%% This should result in abort messages to the 'other' processes. +%% This should result in abort messages to the 'other' processes. IPv4 %% api_a_maccept_cancel_tcp4(suite) -> []; @@ -5679,6 +6152,39 @@ api_a_maccept_cancel_tcp4(_Config) when is_list(_Config) -> %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% Basically we make multiple async (Timeout = nowait) call(s) to accept +%% (from *several* processes), wait some time and then cancel, +%% This should result in abort messages to the 'other' processes. IPv6 +%% +api_a_maccept_cancel_tcp6(suite) -> + []; +api_a_maccept_cancel_tcp6(doc) -> + []; +api_a_maccept_cancel_tcp6(_Config) when is_list(_Config) -> + ?TT(?SECS(20)), + tc_try(api_a_maccept_cancel_tcp6, + fun() -> has_support_ipv6() end, + fun() -> + Accept = fun(Sock) -> + case socket:accept(Sock, nowait) of + {ok, _} = OK -> + OK; + {select, _} = SELECT -> + SELECT; + {error, _} = ERROR -> + ERROR + end + end, + InitState = #{domain => inet6, + accept => Accept}, + ok = api_a_maccept_cancel_tcp(InitState) + end). + + + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + api_a_maccept_cancel_tcp(InitState) -> process_flag(trap_exit, true), ServerSeq = @@ -6047,7 +6553,7 @@ api_a_maccept_cancel_tcp(InitState) -> %% Basically we make multiple async (Timeout = nowait) call(s) to recv %% (from *several* processes), wait some time and then cancel, -%% This should result in abort messages to the 'other' processes. +%% This should result in abort messages to the 'other' processes. IPv4 %% api_a_mrecv_cancel_tcp4(suite) -> []; @@ -6069,9 +6575,34 @@ api_a_mrecv_cancel_tcp4(_Config) when is_list(_Config) -> %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% Basically we make multiple async (Timeout = nowait) call(s) to recv +%% (from *several* processes), wait some time and then cancel, +%% This should result in abort messages to the 'other' processes. IPv6 +%% +api_a_mrecv_cancel_tcp6(suite) -> + []; +api_a_mrecv_cancel_tcp6(doc) -> + []; +api_a_mrecv_cancel_tcp6(_Config) when is_list(_Config) -> + ?TT(?SECS(20)), + tc_try(api_a_mrecv_cancel_tcp6, + fun() -> has_support_ipv6() end, + fun() -> + Recv = fun(Sock) -> + socket:recv(Sock, 0, nowait) + end, + InitState = #{domain => inet6, + recv => Recv}, + ok = api_a_mrecv_cancel_tcp(InitState) + end). + + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + %% Basically we make multiple async (Timeout = nowait) call(s) to recvmsg %% (from *several* processes), wait some time and then cancel, -%% This should result in abort messages to the 'other' processes. +%% This should result in abort messages to the 'other' processes. IPv4 %% api_a_mrecvmsg_cancel_tcp4(suite) -> []; @@ -6093,6 +6624,31 @@ api_a_mrecvmsg_cancel_tcp4(_Config) when is_list(_Config) -> %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% Basically we make multiple async (Timeout = nowait) call(s) to recvmsg +%% (from *several* processes), wait some time and then cancel, +%% This should result in abort messages to the 'other' processes. IPv6 +%% +api_a_mrecvmsg_cancel_tcp6(suite) -> + []; +api_a_mrecvmsg_cancel_tcp6(doc) -> + []; +api_a_mrecvmsg_cancel_tcp6(_Config) when is_list(_Config) -> + ?TT(?SECS(20)), + tc_try(api_a_mrecvmsg_cancel_tcp6, + fun() -> has_support_ipv6() end, + fun() -> + Recv = fun(Sock) -> + socket:recvmsg(Sock, nowait) + end, + InitState = #{domain => inet6, + recv => Recv}, + ok = api_a_mrecv_cancel_tcp(InitState) + end). + + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + api_a_mrecv_cancel_tcp(InitState) -> process_flag(trap_exit, true), ServerSeq = @@ -7834,6 +8390,1695 @@ api_opt_simple_otp_controlling_process() -> %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% Tests the socket option acceptconn for UDP. +%% This should be possible to get but not set. + +api_opt_sock_acceptconn_udp(suite) -> + []; +api_opt_sock_acceptconn_udp(doc) -> + []; +api_opt_sock_acceptconn_udp(_Config) when is_list(_Config) -> + ?TT(?SECS(30)), + tc_try(api_opt_sock_acceptconn_udp, + fun() -> + has_support_sock_acceptconn() + end, + fun() -> api_opt_sock_acceptconn_udp() end). + + + +api_opt_sock_acceptconn_udp() -> + Opt = acceptconn, + Set = fun(S, Val) -> + socket:setopt(S, socket, Opt, Val) + end, + Get = fun(S) -> + socket:getopt(S, socket, Opt) + end, + + TesterSeq = + [ + #{desc => "which local address", + cmd => fun(#{domain := Domain} = State) -> + LSA = which_local_socket_addr(Domain), + {ok, State#{local_sa => LSA}} + end}, + #{desc => "create socket", + cmd => fun(#{domain := Domain} = State) -> + case socket:open(Domain, dgram, udp) of + {ok, Sock} -> + {ok, State#{sock => Sock}}; + {error, _} = ERROR -> + ERROR + end + end}, + + #{desc => "[get] verify socket (before bind)", + cmd => fun(#{sock := Sock} = _State) -> + case Get(Sock) of + {ok, false} -> + ?SEV_IPRINT("Expected Success: " + "Not accepting connections"), + ok; + {ok, true} -> + ?SEV_EPRINT("Unexpected Success: " + "Accepting connections"), + {error, {unexpected_success, {Opt, true}}}; + {error, enoprotoopt = Reason} -> + %% On some platforms this is not accepted + %% for UDP, so skip this part (UDP). + ?SEV_EPRINT("Expected Failure: " + "~p => SKIP", [Reason]), + (catch socket:close(Sock)), + {skip, Reason}; + {error, Reason} = ERROR -> + ?SEV_EPRINT("Unexpected Failure: ~p", + [Reason]), + ERROR + end + end}, + #{desc => "[set] verify socket (before bind)", + cmd => fun(#{sock := Sock} = _State) -> + case Set(Sock, true) of + {error, Reason} -> + ?SEV_IPRINT("Expected Failure: ~p", + [Reason]), + ok; + ok -> + ?SEV_EPRINT("Unexpected Success: " + "Set acceptconn (=true)"), + {error, unexpected_success} + end + end}, + + #{desc => "bind socket to local address", + cmd => fun(#{sock := Sock, local_sa := LSA} = _State) -> + case socket:bind(Sock, LSA) of + {ok, _} -> + ok; + {error, _} = ERROR -> + ERROR + end + end}, + + ?SEV_SLEEP(?SECS(1)), + + #{desc => "[get] verify socket (after bind)", + cmd => fun(#{sock := Sock} = _State) -> + case Get(Sock) of + {ok, false} -> + ?SEV_IPRINT("Expected Success: " + "Not accepting connections"), + ok; + {ok, true} -> + ?SEV_EPRINT("Unexpected Success: " + "Accepting connections"), + {error, {unexpected_success, {Opt, true}}}; + {error, Reason} = ERROR -> + ?SEV_EPRINT("Unexpected Failure: ~p", + [Reason]), + ERROR + end + end}, + #{desc => "[set] verify socket (after bind)", + cmd => fun(#{sock := Sock} = _State) -> + case Set(Sock, true) of + {error, Reason} -> + ?SEV_IPRINT("Expected Failure: ~p", + [Reason]), + ok; + ok -> + ?SEV_EPRINT("Unexpected Success: " + "Set acceptconn (=true)"), + {error, unexpected_success} + end + end}, + + %% *** Termination *** + #{desc => "close socket", + cmd => fun(#{sock := Sock} = State) -> + socket:close(Sock), + {ok, maps:remove(sock, State)} + end}, + + %% *** We are done *** + ?SEV_FINISH_NORMAL + ], + + Domain = inet, + + i("start tester evaluator"), + InitState = #{domain => Domain}, + Tester = ?SEV_START("tester", TesterSeq, InitState), + + i("await evaluator(s)"), + ok = ?SEV_AWAIT_FINISH([Tester]). + + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +%% Tests the socket option acceptconn for TCP. +%% This should be possible to get but not set. + +api_opt_sock_acceptconn_tcp(suite) -> + []; +api_opt_sock_acceptconn_tcp(doc) -> + []; +api_opt_sock_acceptconn_tcp(_Config) when is_list(_Config) -> + ?TT(?SECS(30)), + tc_try(api_opt_sock_acceptconn_tcp, + fun() -> + has_support_sock_acceptconn() + end, + fun() -> api_opt_sock_acceptconn_tcp() end). + + + +api_opt_sock_acceptconn_tcp() -> + Opt = acceptconn, + Set = fun(S, Val) -> + socket:setopt(S, socket, Opt, Val) + end, + Get = fun(S) -> + socket:getopt(S, socket, Opt) + end, + + TesterSeq = + [ + #{desc => "which local address", + cmd => fun(#{domain := Domain} = State) -> + LSA = which_local_socket_addr(Domain), + {ok, State#{local_sa => LSA}} + end}, + + #{desc => "create listen socket", + cmd => fun(#{domain := Domain} = State) -> + case socket:open(Domain, stream, tcp) of + {ok, Sock} -> + {ok, State#{lsock => Sock}}; + {error, _} = ERROR -> + ERROR + end + end}, + + #{desc => "[get] verify listen socket (before bind)", + cmd => fun(#{lsock := Sock} = _State) -> + case Get(Sock) of + {ok, false} -> + ?SEV_IPRINT("Expected Success: " + "Not accepting connections"), + ok; + {ok, true} -> + ?SEV_EPRINT("Unexpected Success: " + "Accepting connections"), + {error, {unexpected_success, {Opt, true}}}; + {error, enoprotoopt = Reason} -> + ?SEV_EPRINT("Expected Failure: " + "~p => SKIP", [Reason]), + (catch socket:close(Sock)), + {skip, Reason}; + {error, Reason} = ERROR -> + ?SEV_EPRINT("Unexpected Failure: ~p", + [Reason]), + ERROR + end + end}, + #{desc => "[set] verify listen socket (before bind)", + cmd => fun(#{lsock := Sock} = _State) -> + case Set(Sock, true) of + {error, Reason} -> + ?SEV_IPRINT("Expected Failure: ~p", [Reason]), + ok; + ok -> + ?SEV_EPRINT("Unexpected Success: " + "Set acceptconn (=true)"), + {error, unexpected_success} + end + end}, + + ?SEV_SLEEP(?SECS(1)), + + #{desc => "bind listen socket to local address", + cmd => fun(#{lsock := Sock, local_sa := LSA} = State) -> + case socket:bind(Sock, LSA) of + {ok, Port} -> + {ok, State#{server_sa => LSA#{port => Port}}}; + {error, _} = ERROR -> + ERROR + end + end}, + + #{desc => "[get] verify listen socket (after bind)", + cmd => fun(#{lsock := Sock} = _State) -> + case Get(Sock) of + {ok, false} -> + ?SEV_IPRINT("Expected Success: " + "Not accepting connections"), + ok; + {ok, true} -> + ?SEV_EPRINT("Unexpected Success: " + "Accepting connections"), + {error, {unexpected_success, {Opt, true}}}; + {error, Reason} = ERROR -> + ?SEV_EPRINT("Unexpected Failure: ~p", [Reason]), + ERROR + end + end}, + #{desc => "[set] verify listen socket (after bind)", + cmd => fun(#{lsock := Sock} = _State) -> + case Set(Sock, true) of + {error, Reason} -> + ?SEV_IPRINT("Expected Failure: ~p", [Reason]), + ok; + ok -> + ?SEV_EPRINT("Unexpected Success: " + "Set acceptconn (=true)"), + {error, unexpected_success} + end + end}, + + ?SEV_SLEEP(?SECS(1)), + + #{desc => "make listen socket accept connections", + cmd => fun(#{lsock := Sock} = _State) -> + case socket:listen(Sock) of + ok -> + ok; + {error, _} = ERROR -> + ERROR + end + end}, + + #{desc => "[get] verify listen socket (after listen)", + cmd => fun(#{lsock := Sock} = _State) -> + case Get(Sock) of + {ok, true} -> + ?SEV_IPRINT("Expected Success: " + "Accepting connections"), + ok; + {ok, false} -> + ?SEV_EPRINT("Unexpected Success: " + "Not accepting connections"), + {error, {unexpected_success, {Opt, false}}}; + {error, Reason} = ERROR -> + ?SEV_EPRINT("Unexpected Failure: ~p", [Reason]), + ERROR + end + end}, + #{desc => "[set] verify listen socket (after listen)", + cmd => fun(#{lsock := Sock} = _State) -> + case Set(Sock, false) of + {error, Reason} -> + ?SEV_IPRINT("Expected Failure: ~p", [Reason]), + ok; + ok -> + ?SEV_EPRINT("Unexpected Success: " + "Set acceptconn (=false)"), + {error, unexpected_success} + end + end}, + + ?SEV_SLEEP(?SECS(1)), + + #{desc => "create (connecting) socket", + cmd => fun(#{domain := Domain} = State) -> + case socket:open(Domain, stream, tcp) of + {ok, Sock} -> + {ok, State#{csockc => Sock}}; + {error, _} = ERROR -> + ERROR + end + end}, + + #{desc => "bind connecting socket to local address", + cmd => fun(#{csockc := Sock, local_sa := LSA} = _State) -> + case socket:bind(Sock, LSA) of + {ok, _Port} -> + ok; + {error, _} = ERROR -> + ERROR + end + end}, + + ?SEV_SLEEP(?SECS(1)), + + #{desc => "[get] verify connecting socket (before connect)", + cmd => fun(#{csockc := Sock} = _State) -> + case Get(Sock) of + {ok, false} -> + ?SEV_IPRINT("Expected Success: " + "Not accepting connections"), + ok; + {ok, true} -> + ?SEV_EPRINT("Unexpected Success: " + "Accepting connections"), + {error, {unexpected_success, {Opt, true}}}; + {error, Reason} = ERROR -> + ?SEV_EPRINT("Unexpected Failure: ~p", [Reason]), + ERROR + end + end}, + #{desc => "[set] verify connecting socket (before connect)", + cmd => fun(#{csockc := Sock} = _State) -> + case Set(Sock, true) of + {error, Reason} -> + ?SEV_IPRINT("Expected Failure: ~p", [Reason]), + ok; + ok -> + ?SEV_EPRINT("Unexpected Success: " + "Set acceptconn (=true)"), + {error, unexpected_success} + end + end}, + + ?SEV_SLEEP(?SECS(1)), + + #{desc => "connect to server", + cmd => fun(#{csockc := Sock, server_sa := SSA} = _State) -> + case socket:connect(Sock, SSA) of + ok -> + ok; + {error, _} = ERROR -> + ERROR + end + end}, + + #{desc => "accept connection", + cmd => fun(#{lsock := Sock} = State) -> + case socket:accept(Sock) of + {ok, CSock} -> + {ok, State#{csocks => CSock}}; + {error, _} = ERROR -> + ERROR + end + end}, + + #{desc => "[get] verify connecting socket (after connect)", + cmd => fun(#{csockc := Sock} = _State) -> + case Get(Sock) of + {ok, false} -> + ?SEV_IPRINT("Expected Success: " + "Not accepting connections"), + ok; + {ok, true} -> + ?SEV_EPRINT("Unexpected Success: " + "Accepting connections"), + {error, {unexpected_success, {Opt, true}}}; + {error, Reason} = ERROR -> + ?SEV_EPRINT("Unexpected Failure: ~p", [Reason]), + ERROR + end + end}, + #{desc => "[set] verify connecting socket (after connect)", + cmd => fun(#{csockc := Sock} = _State) -> + case Set(Sock, true) of + {error, Reason} -> + ?SEV_IPRINT("Expected Failure: ~p", [Reason]), + ok; + ok -> + ?SEV_EPRINT("Unexpected Success: " + "Set acceptconn (=true)"), + {error, unexpected_success} + end + end}, + + #{desc => "[get] verify connected socket", + cmd => fun(#{csocks := Sock} = _State) -> + case Get(Sock) of + {ok, false} -> + ?SEV_IPRINT("Expected Success: " + "Not accepting connections"), + ok; + {ok, true} -> + ?SEV_EPRINT("Unexpected Success: " + "Accepting connections"), + {error, {unexpected_success, {Opt, true}}}; + {error, Reason} = ERROR -> + ?SEV_EPRINT("Unexpected Failure: ~p", [Reason]), + ERROR + end + end}, + #{desc => "[set] verify connected socket", + cmd => fun(#{csocks := Sock} = _State) -> + case Set(Sock, true) of + {error, Reason} -> + ?SEV_IPRINT("Expected Failure: ~p", [Reason]), + ok; + ok -> + ?SEV_EPRINT("Unexpected Success: " + "Set acceptconn (=true)"), + {error, unexpected_success} + end + end}, + + #{desc => "[get] verify listen socket (after connect)", + cmd => fun(#{lsock := Sock} = _State) -> + case Get(Sock) of + {ok, true} -> + ?SEV_IPRINT("Expected Success: " + "Accepting connections"), + ok; + {ok, false} -> + ?SEV_EPRINT("Unexpected Success: " + "Not accepting connections"), + {error, {unexpected_success, {Opt, false}}}; + {error, Reason} = ERROR -> + ?SEV_EPRINT("Unexpected Failure: ~p", [Reason]), + ERROR + end + end}, + #{desc => "[set] verify listen socket (after connect)", + cmd => fun(#{lsock := Sock} = _State) -> + case Set(Sock, false) of + {error, Reason} -> + ?SEV_IPRINT("Expected Failure: ~p", [Reason]), + ok; + ok -> + ?SEV_EPRINT("Unexpected Success: " + "Set acceptconn (=false)"), + {error, unexpected_success} + end + end}, + + %% *** Termination *** + #{desc => "close connecting socket(s)", + cmd => fun(#{csockc := Sock} = State0) -> + socket:close(Sock), + State1 = maps:remove(csockc, State0), + State2 = maps:remove(csocks, State1), %% Auto-close + {ok, maps:remove(csockc, State2)} + end}, + #{desc => "close listen socket", + cmd => fun(#{lsock := Sock} = State) -> + socket:close(Sock), + {ok, maps:remove(lsock, State)} + end}, + + %% *** We are done *** + ?SEV_FINISH_NORMAL + ], + + + Domain = inet, + + i("start tester evaluator"), + InitState = #{domain => Domain}, + Tester = ?SEV_START("tester", TesterSeq, InitState), + + i("await evaluator(s)"), + ok = ?SEV_AWAIT_FINISH([Tester]). + + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +%% Tests the socket option acceptfilter. PLACEHOLDER! + +api_opt_sock_acceptfilter(suite) -> + []; +api_opt_sock_acceptfilter(doc) -> + []; +api_opt_sock_acceptfilter(_Config) when is_list(_Config) -> + ?TT(?SECS(30)), + tc_try(api_opt_sock_acceptfilter, + fun() -> not_yet_implemented() end, + fun() -> ok end). + + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +%% Tests the socket option bindtodevice. +%% It has not always been possible to 'get' this option +%% (atleast on linux). + +api_opt_sock_bindtodevice(suite) -> + []; +api_opt_sock_bindtodevice(doc) -> + []; +api_opt_sock_bindtodevice(_Config) when is_list(_Config) -> + ?TT(?SECS(30)), + tc_try(api_opt_sock_bindtodevice, + fun() -> has_support_sock_bindtodevice() end, + fun() -> api_opt_sock_bindtodevice() end). + + +api_opt_sock_bindtodevice() -> + Opt = bindtodevice, + Set = fun(S, Val) -> + socket:setopt(S, socket, Opt, Val) + end, + Get = fun(S) -> + socket:getopt(S, socket, Opt) + end, + + TesterSeq = + [ + #{desc => "which local address", + cmd => fun(#{domain := Domain} = State) -> + case ?LIB:which_local_host_info(Domain) of + {ok, #{name := Name, addr := Addr}} -> + ?SEV_IPRINT("local host info (~p): " + "~n Name: ~p" + "~n Addr: ~p", + [Domain, Name, Addr]), + LSA = #{family => Domain, + addr => Addr}, + {ok, State#{dev => Name, + local_sa => LSA}}; + {error, _} = ERROR -> + ERROR + end + end}, + #{desc => "create UDP socket 1", + cmd => fun(#{domain := Domain} = State) -> + case socket:open(Domain, dgram, udp) of + {ok, Sock} -> + {ok, State#{usock1 => Sock}}; + {error, _} = ERROR -> + ERROR + end + end}, + #{desc => "create UDP socket 2", + cmd => fun(#{domain := Domain} = State) -> + case socket:open(Domain, dgram, udp) of + {ok, Sock} -> + {ok, State#{usock2 => Sock}}; + {error, _} = ERROR -> + ERROR + end + end}, + #{desc => "create TCP socket 1", + cmd => fun(#{domain := Domain} = State) -> + case socket:open(Domain, stream, tcp) of + {ok, Sock} -> + {ok, State#{tsock1 => Sock}}; + {error, _} = ERROR -> + ERROR + end + end}, + #{desc => "create TCP socket 2", + cmd => fun(#{domain := Domain} = State) -> + case socket:open(Domain, stream, tcp) of + {ok, Sock} -> + {ok, State#{tsock2 => Sock}}; + {error, _} = ERROR -> + ERROR + end + end}, + + #{desc => "[get] verify UDP socket 1 (before bindtodevice)", + cmd => fun(#{usock1 := Sock} = _State) -> + case Get(Sock) of + {ok, Dev} -> + ?SEV_IPRINT("Expected Success: ~p", [Dev]), + ok; + {error, enoprotoopt = Reason} -> + ?SEV_EPRINT("Unexpected Failure: ~p => SKIP", + [Reason]), + {skip, Reason}; + {error, Reason} = ERROR -> + ?SEV_EPRINT("Unexpected Failure: ~p", + [Reason]), + ERROR + end + end}, + #{desc => "[get] verify UDP socket 2 (before bind)", + cmd => fun(#{usock2 := Sock} = _State) -> + case Get(Sock) of + {ok, Dev} -> + ?SEV_IPRINT("Expected Success: ~p", [Dev]), + ok; + {error, Reason} = ERROR -> + ?SEV_EPRINT("Unexpected Failure: ~p", [Reason]), + ERROR + end + end}, + #{desc => "[get] verify TCP socket 1 (before bindtodevice)", + cmd => fun(#{tsock1 := Sock} = _State) -> + case Get(Sock) of + {ok, Dev} -> + ?SEV_IPRINT("Expected Success: ~p", [Dev]), + ok; + {error, Reason} = ERROR -> + ?SEV_EPRINT("Unexpected Failure: ~p", [Reason]), + ERROR + end + end}, + #{desc => "[get] verify TCP socket 2 (before bind)", + cmd => fun(#{tsock2 := Sock} = _State) -> + case Get(Sock) of + {ok, Dev} -> + ?SEV_IPRINT("Expected Success: ~p", [Dev]), + ok; + {error, Reason} = ERROR -> + ?SEV_EPRINT("Unexpected Failure: ~p", [Reason]), + ERROR + end + end}, + + ?SEV_SLEEP(?SECS(1)), + + #{desc => "Bind UDP socket 1 to device", + cmd => fun(#{usock1 := Sock, dev := Dev} = State) -> + case Set(Sock, Dev) of + ok -> + ?SEV_IPRINT("Expected Success"), + ok; + {error, eperm = Reason} -> + ?SEV_IPRINT("Expected Failure: ~p", [Reason]), + (catch socket:close(Sock)), + {ok, State#{usock1 => skip}}; + {error, Reason} = ERROR -> + ?SEV_EPRINT("Unexpected Failure: ~p", [Reason]), + ERROR + end + end}, + #{desc => "Bind UDP socket 2 to local address", + cmd => fun(#{usock2 := Sock, local_sa := LSA} = _State) -> + case socket:bind(Sock, LSA) of + {ok, _Port} -> + ?SEV_IPRINT("Expected Success"), + ok; + {error, Reason} = ERROR -> + ?SEV_EPRINT("Unexpected Failure: ~p", [Reason]), + ERROR + end + end}, + #{desc => "Bind TCP socket 1 to device", + cmd => fun(#{usock1 := USock1, + tsock1 := Sock, dev := Dev} = State) -> + case Set(Sock, Dev) of + ok -> + ?SEV_IPRINT("Expected Success"), + ok; + {error, eperm = Reason} when (USock1 =:= skip) -> + ?SEV_IPRINT("Expected Failure: ~p", [Reason]), + {skip, Reason}; + {error, eperm = Reason} -> + ?SEV_IPRINT("Expected Failure: ~p", [Reason]), + (catch socket:close(Sock)), + {ok, State#{tsock1 => skip}}; + {error, Reason} = ERROR -> + ?SEV_EPRINT("Unexpected Failure: ~p", [Reason]), + ERROR + end + end}, + #{desc => "Bind TCP socket 2 to local address", + cmd => fun(#{tsock2 := Sock, local_sa := LSA} = _State) -> + case socket:bind(Sock, LSA) of + {ok, _Port} -> + ?SEV_IPRINT("Expected Success"), + ok; + {error, Reason} = ERROR -> + ?SEV_EPRINT("Unexpected Failure: ~p", [Reason]), + ERROR + end + end}, + + ?SEV_SLEEP(?SECS(1)), + + #{desc => "[get] verify UDP socket 1 (after bindtodevice)", + cmd => fun(#{usock1 := skip} = _State) -> + ?SEV_IPRINT("SKIP'ed (previous eperm)"), + ok; + (#{usock1 := Sock} = _State) -> + case Get(Sock) of + {ok, Dev} -> + ?SEV_IPRINT("Expected Success: ~p", [Dev]), + ok; + {error, Reason} = ERROR -> + ?SEV_EPRINT("Unexpected Failure: ~p", [Reason]), + ERROR + end + end}, + #{desc => "[get] verify UDP socket 2 (after bind)", + cmd => fun(#{usock2 := Sock} = _State) -> + case Get(Sock) of + {ok, Dev} -> + ?SEV_IPRINT("Expected Success: ~p", [Dev]), + ok; + {error, Reason} = ERROR -> + ?SEV_EPRINT("Unexpected Failure: ~p", [Reason]), + ERROR + end + end}, + #{desc => "[get] verify TCP socket 1 (after bindtodevice)", + cmd => fun(#{tsock1 := skip} = _State) -> + ?SEV_IPRINT("SKIP'ed (previous eperm)"), + ok; + (#{tsock1 := Sock} = _State) -> + case Get(Sock) of + {ok, Dev} -> + ?SEV_IPRINT("Expected Success: ~p", [Dev]), + ok; + {error, Reason} = ERROR -> + ?SEV_EPRINT("Unexpected Failure: ~p", [Reason]), + ERROR + end + end}, + #{desc => "[get] verify TCP socket 2 (after bind)", + cmd => fun(#{tsock2 := Sock} = _State) -> + case Get(Sock) of + {ok, Dev} -> + ?SEV_IPRINT("Expected Success: ~p", [Dev]), + ok; + {error, Reason} = ERROR -> + ?SEV_EPRINT("Unexpected Failure: ~p", [Reason]), + ERROR + end + end}, + + ?SEV_SLEEP(?SECS(1)), + + %% *** Termination *** + #{desc => "close UDP socket 1", + cmd => fun(#{usock1 := skip} = State) -> + ?SEV_IPRINT("SKIP'ed (already closed)"), + {ok, maps:remove(usock1, State)}; + (#{usock1 := Sock} = State) -> + socket:close(Sock), + {ok, maps:remove(usock1, State)} + end}, + #{desc => "close UDP socket 2", + cmd => fun(#{usock2 := Sock} = State) -> + socket:close(Sock), + {ok, maps:remove(usock2, State)} + end}, + #{desc => "close TCP socket 1", + cmd => fun(#{tsock1 := skip} = State) -> + ?SEV_IPRINT("SKIP'ed (already closed)"), + {ok, maps:remove(tsock1, State)}; + (#{tsock1 := Sock} = State) -> + socket:close(Sock), + {ok, maps:remove(tsock1, State)} + end}, + #{desc => "close TCP socket 2", + cmd => fun(#{tsock2 := Sock} = State) -> + socket:close(Sock), + {ok, maps:remove(tsock2, State)} + end}, + + %% *** We are done *** + ?SEV_FINISH_NORMAL + ], + + Domain = inet, + + i("start tester evaluator"), + InitState = #{domain => Domain}, + Tester = ?SEV_START("tester", TesterSeq, InitState), + + i("await evaluator(s)"), + ok = ?SEV_AWAIT_FINISH([Tester]). + + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +%% Tests the socket option broadcast. +%% Make it possible for datagram sockets to send packets to a broadcast +%% address (IPv4 only). + +api_opt_sock_broadcast(suite) -> + []; +api_opt_sock_broadcast(doc) -> + []; +api_opt_sock_broadcast(_Config) when is_list(_Config) -> + ?TT(?SECS(30)), + tc_try(api_opt_sock_broadcast, + fun() -> has_support_sock_broadcast() end, + fun() -> api_opt_sock_broadcast() end). + + +api_opt_sock_broadcast() -> + Opt = broadcast, + Set = fun(S, Val) when is_boolean(Val) -> + socket:setopt(S, socket, Opt, Val) + end, + Get = fun(S) -> + socket:getopt(S, socket, Opt) + end, + + TesterSeq = + [ + #{desc => "which local address", + cmd => fun(#{domain := Domain} = State) -> + case ?LIB:which_local_host_info(Domain) of + {ok, #{name := Name, + addr := Addr, + broadaddr := BAddr}} -> + ?SEV_IPRINT("local host info: " + "~n Name: ~p" + "~n Addr: ~p" + "~n Broadcast Addr: ~p", + [Name, Addr, BAddr]), + LSA = #{family => Domain, + addr => Addr}, + BSA = #{family => Domain, + addr => BAddr}, + {ok, State#{lsa => LSA, + bsa => BSA}}; + {error, _} = ERROR -> + ERROR + end + end}, + + #{desc => "[socket 1] create UDP socket (listening 1)", + cmd => fun(#{domain := Domain} = State) -> + case socket:open(Domain, dgram, udp) of + {ok, Sock} -> + {ok, State#{sock1 => Sock}}; + {error, _} = ERROR -> + ERROR + end + end}, + #{desc => "[socket 1] Bind UDP socket (to limited broadcast address)", + cmd => fun(#{sock1 := Sock} = State) -> + BSA = #{family => inet, + addr => broadcast}, + ?SEV_IPRINT("Try bind (socket 1) to: " + "~n ~p", [BSA]), + case socket:bind(Sock, BSA) of + {ok, Port} -> + ?SEV_IPRINT("Expected Success (bound): ~p", + [Port]), + {ok, State#{sa1 => BSA#{port => Port}}}; + {error, eaddrnotavail = Reason} -> + ?SEV_IPRINT("~p => " + "SKIP limited broadcast test", + [Reason]), + {ok, State#{sa1 => skip}}; + {error, Reason} = ERROR -> + ?SEV_EPRINT("Unexpected Failure: ~p", + [Reason]), + ERROR + end + end}, + #{desc => "[socket 1] UDP socket sockname", + cmd => fun(#{sa1 := skip} = _State) -> + ?SEV_IPRINT("SKIP limited broadcast test"), + ok; + (#{sock1 := Sock} = _State) -> + case socket:sockname(Sock) of + {ok, SA} -> + ?SEV_IPRINT("SA: ~p", [SA]), + ok; + {error, _} = ERROR -> + ERROR + end + end}, + + ?SEV_SLEEP(?SECS(1)), + + #{desc => "[socket 2] create UDP socket (listening 2)", + cmd => fun(#{domain := Domain} = State) -> + case socket:open(Domain, dgram, udp) of + {ok, Sock} -> + {ok, State#{sock2 => Sock}}; + {error, _} = ERROR -> + ERROR + end + end}, + #{desc => "[socket 2] Bind UDP socket (to subnet-directed broadcast address)", + cmd => fun(#{sock2 := Sock, + bsa := BSA} = State) -> + ?SEV_IPRINT("Try bind (socket 1) to: " + "~n ~p", [BSA]), + case socket:bind(Sock, BSA) of + {ok, Port} -> + ?SEV_IPRINT("Expected Success (bound): ~p", + [Port]), + {ok, State#{sa2 => BSA#{port => Port}}}; + {error, Reason} = ERROR -> + ?SEV_EPRINT("Unexpected Failure: ~p", + [Reason]), + ERROR + end + end}, + #{desc => "[socket 2] UDP socket sockname", + cmd => fun(#{sock2 := Sock} = _State) -> + case socket:sockname(Sock) of + {ok, SA} -> + ?SEV_IPRINT("SA: ~p", [SA]), + ok; + {error, _} = ERROR -> + ERROR + end + end}, + + ?SEV_SLEEP(?SECS(1)), + + #{desc => "[socket 3] create UDP socket (sender)", + cmd => fun(#{domain := Domain} = State) -> + case socket:open(Domain, dgram, udp) of + {ok, Sock} -> + {ok, State#{sock3 => Sock}}; + {error, _} = ERROR -> + ERROR + end + end}, + #{desc => "[socket 3][get] verify UDP socket (before bind and set)", + cmd => fun(#{sock3 := Sock} = _State) -> + case Get(Sock) of + {ok, false} -> + ?SEV_IPRINT("Expected Success: " + "broadcast not allowed"), + ok; + {ok, true} -> + ?SEV_IPRINT("Unexpected Success result: " + "broadcast already allowed"), + ok; + {error, Reason} = ERROR -> + ?SEV_EPRINT("Unexpected Failure: ~p", + [Reason]), + ERROR + end + end}, + #{desc => "[socket 3] Try make broadcast allowed", + cmd => fun(#{sock3 := Sock} = _State) -> + case Set(Sock, true) of + ok -> + ?SEV_IPRINT("Expected Success: " + "broadcast now allowed"), + ok; + {error, Reason} = ERROR -> + ?SEV_EPRINT("Unexpected Failure: ~p", + [Reason]), + ERROR + end + end}, + #{desc => "[socket 3] verify UDP socket broadcast allowed", + cmd => fun(#{sock3 := Sock} = _State) -> + case Get(Sock) of + {ok, true} -> + ?SEV_IPRINT("Expected Success: " + "broadcast allowed"), + ok; + {ok, false} -> + ?SEV_IPRINT("Unexpected Success result: " + "broadcast *not* allowed"), + ok; + {error, Reason} = ERROR -> + ?SEV_EPRINT("Unexpected Failure: ~p", + [Reason]), + ERROR + end + end}, + #{desc => "[socket 3] Bind UDP socket (to local address)", + cmd => fun(#{sock3 := Sock, lsa := LSA} = State) -> + ?SEV_IPRINT("Try bind (socket 2) to: " + "~n ~p", [LSA]), + case socket:bind(Sock, LSA) of + {ok, Port} -> + ?SEV_IPRINT("Expected Success (bound): ~p", + [Port]), + {ok, State#{sa3 => LSA#{port => Port}}}; + {error, Reason} = ERROR -> + ?SEV_EPRINT("Unexpected Failure: ~p", + [Reason]), + ERROR + end + end}, + #{desc => "[socket 3] verify UDP socket (after set)", + cmd => fun(#{sock3 := Sock} = _State) -> + case Get(Sock) of + {ok, true} -> + ?SEV_IPRINT("Expected Success: " + "broadcast allowed"), + ok; + {ok, false} -> + ?SEV_IPRINT("Unexpected Success result: " + "broadcast not allowed"), + {error, not_allowed}; + {error, Reason} = ERROR -> + ?SEV_EPRINT("Unexpected Failure: ~p", + [Reason]), + ERROR + end + end}, + + ?SEV_SLEEP(?SECS(1)), + + #{desc => "[socket 3] try send to limited broadcast address", + cmd => fun(#{sa1 := skip} = _State) -> + ?SEV_IPRINT("SKIP limited broadcast test"), + ok; + (#{sock3 := Sock, + sa1 := Dest} = _State) -> + Data = list_to_binary("hejsan"), + ?SEV_IPRINT("try send to bradcast address: " + "~n ~p", [Dest]), + case socket:sendto(Sock, Data, Dest) of + ok -> + ?SEV_IPRINT("Expected Success: " + "broadcast message sent"), + ok; + {error, Reason} = ERROR -> + ?SEV_EPRINT("Unexpected Failure: ~p", + [Reason]), + ERROR + end + end}, + #{desc => "[socket 1] try recv", + cmd => fun(#{sa1 := skip} = _State) -> + ?SEV_IPRINT("SKIP limited broadcast test"), + ok; + (#{sock1 := Sock} = State) -> + case socket:recvfrom(Sock, 0, 5000) of + {ok, _} -> + ?SEV_IPRINT("Expected Success: " + "received message"), + ok; + {error, timeout = Reason} -> + %% Some platforms seem to balk at this. + %% It spossible to bind to this, and + %% send to it, but no data is received. + %% At some point we should investigate... + %% For now, we just skip this part of + %% the test... + ?SEV_IPRINT("Unexpected Failure: ~p", + [Reason]), + {ok, State#{sa1 => skip}}; + {error, Reason} = ERROR -> + ?SEV_EPRINT("Unexpected Failure: ~p", + [Reason]), + ERROR + end + end}, + + ?SEV_SLEEP(?SECS(1)), + + #{desc => "[socket 3] try send to subnet-directed broadcast address", + cmd => fun(#{sock3 := Sock, + sa2 := Dest} = _State) -> + Data = list_to_binary("hejsan"), + ?SEV_IPRINT("try send to bradcast address: " + "~n ~p", [Dest]), + case socket:sendto(Sock, Data, Dest) of + ok -> + ?SEV_IPRINT("Expected Success: " + "broadcast message sent"), + ok; + {error, Reason} = ERROR -> + ?SEV_EPRINT("Unexpected Failure: ~p", + [Reason]), + ERROR + end + end}, + #{desc => "[socket 2] try recv", + cmd => fun(#{sock2 := Sock, sa1 := SA1} = _State) -> + case socket:recvfrom(Sock, 0, 5000) of + {ok, _} -> + ?SEV_IPRINT("Expected Success: " + "received message"), + ok; + {error, timeout = Reason} when (SA1 =:= skip) -> + ?SEV_IPRINT("Unexpected Failure: ~p", + [Reason]), + {skip, "receive timeout"}; + {error, Reason} = ERROR -> + ?SEV_EPRINT("Unexpected Failure: ~p", + [Reason]), + ERROR + end + end}, + + %% *** Termination *** + #{desc => "[socket 3] close UDP socket (sender)", + cmd => fun(#{sock3 := Sock} = State0) -> + socket:close(Sock), + State1 = maps:remove(sock3, State0), + State2 = maps:remove(sa3, State1), + {ok, State2} + end}, + #{desc => "[socket 2] close UDP socket (listener 2)", + cmd => fun(#{sock2 := Sock} = State0) -> + socket:close(Sock), + State1 = maps:remove(sock2, State0), + State2 = maps:remove(sa2, State1), + {ok, State2} + end}, + #{desc => "[socket 1] close UDP socket (listener 1)", + cmd => fun(#{sock1 := Sock} = State0) -> + socket:close(Sock), + State1 = maps:remove(sock1, State0), + State2 = maps:remove(sa1, State1), + {ok, State2} + end}, + + %% *** We are done *** + ?SEV_FINISH_NORMAL + ], + + Domain = inet, + + i("start tester evaluator"), + InitState = #{domain => Domain}, + Tester = ?SEV_START("tester", TesterSeq, InitState), + + i("await evaluator(s)"), + ok = ?SEV_AWAIT_FINISH([Tester]). + + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +%% Tests the socket option debug. +%% On linux, this test requires that the user running the test to have +%% CAP_NET_ADMIN capabilities or be root (effective user ID of 0), +%% therefor we explicitly test for the result eacces when attempting to +%% set, and skip if we get it. + +api_opt_sock_debug(suite) -> + []; +api_opt_sock_debug(doc) -> + []; +api_opt_sock_debug(_Config) when is_list(_Config) -> + ?TT(?SECS(10)), + tc_try(api_opt_sock_debug, + fun() -> has_support_sock_debug() end, + fun() -> api_opt_sock_debug() end). + + +api_opt_sock_debug() -> + Opt = debug, + Set = fun(S, Val) when is_integer(Val) -> + socket:setopt(S, socket, Opt, Val) + end, + Get = fun(S) -> + socket:getopt(S, socket, Opt) + end, + + TesterSeq = + [ + #{desc => "which local address", + cmd => fun(#{domain := Domain} = State) -> + case ?LIB:which_local_host_info(Domain) of + {ok, #{name := Name, + addr := Addr, + broadaddr := BAddr}} -> + ?SEV_IPRINT("local host info: " + "~n Name: ~p" + "~n Addr: ~p" + "~n Broadcast Addr: ~p", + [Name, Addr, BAddr]), + LSA = #{family => Domain, + addr => Addr}, + BSA = #{family => Domain, + addr => BAddr}, + {ok, State#{lsa => LSA, + bsa => BSA}}; + {error, _} = ERROR -> + ERROR + end + end}, + + #{desc => "create UDP socket", + cmd => fun(#{domain := Domain} = State) -> + case socket:open(Domain, dgram, udp) of + {ok, Sock} -> + {ok, State#{sock => Sock}}; + {error, _} = ERROR -> + ERROR + end + end}, + #{desc => "Get current debug value", + cmd => fun(#{sock := Sock} = State) -> + case Get(Sock) of + {ok, Debug} when is_integer(Debug) -> + ?SEV_IPRINT("Success: ~p", [Debug]), + {ok, State#{debug => Debug}}; + {error, Reason} = ERROR -> + ?SEV_EPRINT("Unexpected failure: ~p", + [Reason]), + ERROR + end + end}, + #{desc => "Try enable socket debug", + cmd => fun(#{sock := Sock, debug := Debug} = State) -> + NewDebug = Debug + 1, + case Set(Sock, NewDebug) of + ok -> + ?SEV_IPRINT("Expected Success"), + {ok, State#{debug => NewDebug}}; + {error, eacces = Reason} -> + ?SEV_EPRINT("NO ACCESS => SKIP"), + {skip, Reason}; + {error, Reason} = ERROR -> + ?SEV_EPRINT("Unexpected Failure: ~p", + [Reason]), + ERROR + end + end}, + #{desc => "Get current (new) debug value", + cmd => fun(#{sock := Sock, debug := Debug} = _State) -> + case Get(Sock) of + {ok, Debug} when is_integer(Debug) -> + ?SEV_IPRINT("Success: ~p", [Debug]), + ok; + {error, Reason} = ERROR -> + ?SEV_EPRINT("Unexpected failure: ~p", + [Reason]), + ERROR + end + end}, + + %% *** Termination *** + #{desc => "close UDP socket", + cmd => fun(#{sock := Sock} = State0) -> + socket:close(Sock), + State1 = maps:remove(sock, State0), + {ok, State1} + end}, + + %% *** We are done *** + ?SEV_FINISH_NORMAL + ], + + Domain = inet, + + i("start tester evaluator"), + InitState = #{domain => Domain}, + Tester = ?SEV_START("tester", TesterSeq, InitState), + + i("await evaluator(s)"), + ok = ?SEV_AWAIT_FINISH([Tester]). + + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +%% Tests the socket option domain. +%% This is a read only option. Also not available on all platforms. + +api_opt_sock_domain(suite) -> + []; +api_opt_sock_domain(doc) -> + []; +api_opt_sock_domain(_Config) when is_list(_Config) -> + ?TT(?SECS(10)), + tc_try(api_opt_sock_domain, + fun() -> has_support_sock_domain() end, + fun() -> api_opt_sock_domain() end). + + +api_opt_sock_domain() -> + Opt = domain, + Get = fun(S) -> + socket:getopt(S, socket, Opt) + end, + + TesterSeq = + [ + #{desc => "which local address", + cmd => fun(#{domain := Domain} = State) -> + case ?LIB:which_local_host_info(Domain) of + {ok, #{name := Name, + addr := Addr, + broadaddr := BAddr}} -> + ?SEV_IPRINT("local host info: " + "~n Name: ~p" + "~n Addr: ~p" + "~n Broadcast Addr: ~p", + [Name, Addr, BAddr]), + LSA = #{family => Domain, + addr => Addr}, + BSA = #{family => Domain, + addr => BAddr}, + {ok, State#{lsa => LSA, + bsa => BSA}}; + {error, _} = ERROR -> + ERROR + end + end}, + + #{desc => "create IPv4 UDP socket", + cmd => fun(#{domain := Domain} = State) -> + case socket:open(Domain, dgram, udp) of + {ok, Sock} -> + {ok, State#{usock => Sock}}; + {error, _} = ERROR -> + ERROR + end + end}, + #{desc => "Get domain for the UDP socket", + cmd => fun(#{domain := Domain, usock := Sock} = _State) -> + case Get(Sock) of + {ok, Domain} -> + ?SEV_IPRINT("Success: ~p", [Domain]), + ok; + {error, Reason} = ERROR -> + ?SEV_EPRINT("Unexpected failure: ~p", + [Reason]), + ERROR + end + end}, + #{desc => "create TCP socket", + cmd => fun(#{domain := Domain} = State) -> + case socket:open(Domain, stream, tcp) of + {ok, Sock} -> + {ok, State#{tsock => Sock}}; + {error, _} = ERROR -> + ERROR + end + end}, + #{desc => "Get domain for the TCP socket", + cmd => fun(#{domain := Domain, tsock := Sock} = _State) -> + case Get(Sock) of + {ok, Domain} -> + ?SEV_IPRINT("Success: ~p", [Domain]), + ok; + {error, Reason} = ERROR -> + ?SEV_EPRINT("Unexpected failure: ~p", + [Reason]), + ERROR + end + end}, + + %% *** Termination *** + #{desc => "close UDP socket", + cmd => fun(#{usock := Sock} = State0) -> + socket:close(Sock), + State1 = maps:remove(usock, State0), + {ok, State1} + end}, + #{desc => "close TCP socket", + cmd => fun(#{tsock := Sock} = State0) -> + socket:close(Sock), + State1 = maps:remove(tsock, State0), + {ok, State1} + end}, + + %% *** We are done *** + ?SEV_FINISH_NORMAL + ], + + Domain = inet, + + i("start tester evaluator"), + InitState = #{domain => Domain}, + Tester = ?SEV_START("tester", TesterSeq, InitState), + + i("await evaluator(s)"), + ok = ?SEV_AWAIT_FINISH([Tester]). + + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +%% Tests the socket option dontroute. +%% The man page has the following to say: +%% "Don't send via a gateway, send only to directly connected hosts. +%% The same effect can be achieved by setting the MSG_DONTROUTE +%% flag on a socket send(2) operation." +%% Since its "kind of" difficult to check if it actually takes an +%% effect (you would need a gateway for that and a machine "on the +%% other side"), we only test if we can set and get the value. +%% Better then nothing. + +api_opt_sock_dontroute(suite) -> + []; +api_opt_sock_dontroute(doc) -> + []; +api_opt_sock_dontroute(_Config) when is_list(_Config) -> + ?TT(?SECS(10)), + tc_try(api_opt_sock_dontroute, + fun() -> has_support_sock_dontroute() end, + fun() -> api_opt_sock_dontroute() end). + + +api_opt_sock_dontroute() -> + Opt = dontroute, + Set = fun(S, Val) when is_boolean(Val) -> + socket:setopt(S, socket, Opt, Val) + end, + Get = fun(S) -> + socket:getopt(S, socket, Opt) + end, + + TesterSeq = + [ + #{desc => "which local address", + cmd => fun(#{domain := Domain} = State) -> + case ?LIB:which_local_host_info(Domain) of + {ok, #{name := Name, + addr := Addr, + broadaddr := BAddr}} -> + ?SEV_IPRINT("local host info: " + "~n Name: ~p" + "~n Addr: ~p" + "~n Broadcast Addr: ~p", + [Name, Addr, BAddr]), + LSA = #{family => Domain, + addr => Addr}, + BSA = #{family => Domain, + addr => BAddr}, + {ok, State#{lsa => LSA, + bsa => BSA}}; + {error, _} = ERROR -> + ERROR + end + end}, + + #{desc => "create UDP socket", + cmd => fun(#{domain := Domain} = State) -> + case socket:open(Domain, dgram, udp) of + {ok, Sock} -> + {ok, State#{sock => Sock}}; + {error, _} = ERROR -> + ERROR + end + end}, + #{desc => "Get current value", + cmd => fun(#{sock := Sock} = State) -> + case Get(Sock) of + {ok, Val} when is_boolean(Val) -> + ?SEV_IPRINT("Success: ~p", [Val]), + {ok, State#{dontroute => Val}}; + {error, Reason} = ERROR -> + ?SEV_EPRINT("Unexpected failure: ~p", + [Reason]), + ERROR + end + end}, + #{desc => "Try change value", + cmd => fun(#{sock := Sock, dontroute := Current} = State) -> + New = not Current, + ?SEV_IPRINT("Change from ~p to ~p", [Current, New]), + case Set(Sock, New) of + ok -> + ?SEV_IPRINT("Expected Success"), + {ok, State#{dontroute => New}}; + {error, eopnotsupp = Reason} -> + ?SEV_EPRINT("Expected Failure: ~p", + [Reason]), + {skip, Reason}; + {error, Reason} = ERROR -> + ?SEV_EPRINT("Unexpected Failure: ~p", + [Reason]), + ERROR + end + end}, + #{desc => "Verify changed value", + cmd => fun(#{sock := Sock, dontroute := Val} = _State) -> + case Get(Sock) of + {ok, Val} -> + ?SEV_IPRINT("Expected Success"), + ok; + {error, Reason} = ERROR -> + ?SEV_EPRINT("Unexpected failure: ~p", + [Reason]), + ERROR + end + end}, + + %% *** Termination *** + #{desc => "close UDP socket", + cmd => fun(#{sock := Sock} = State0) -> + socket:close(Sock), + State1 = maps:remove(sock, State0), + {ok, State1} + end}, + + %% *** We are done *** + ?SEV_FINISH_NORMAL + ], + + Domain = inet, + + i("start tester evaluator"), + InitState = #{domain => Domain}, + Tester = ?SEV_START("tester", TesterSeq, InitState), + + i("await evaluator(s)"), + ok = ?SEV_AWAIT_FINISH([Tester]). + + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +%% Tests the socket option error. PLACEHOLDER! + +api_opt_sock_error(suite) -> + []; +api_opt_sock_error(doc) -> + []; +api_opt_sock_error(_Config) when is_list(_Config) -> + ?TT(?SECS(10)), + tc_try(api_opt_sock_error, + fun() -> not_yet_implemented() end, + fun() -> ok end). + + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +%% Tests the socket option keepalive. +%% This is bit tricky to test, partly because we have no control over +%% the underlying TCP timeouts. So, for now, we just test that we can +%% change the value. + +api_opt_sock_keepalive(suite) -> + []; +api_opt_sock_keepalive(doc) -> + []; +api_opt_sock_keepalive(_Config) when is_list(_Config) -> + ?TT(?SECS(10)), + tc_try(api_opt_sock_keepalive, + fun() -> has_support_sock_keepalive() end, + fun() -> api_opt_sock_keepalive() end). + + +api_opt_sock_keepalive() -> + Opt = keepalive, + Set = fun(S, Val) when is_boolean(Val) -> + socket:setopt(S, socket, Opt, Val) + end, + Get = fun(S) -> + socket:getopt(S, socket, Opt) + end, + + TesterSeq = + [ + #{desc => "which local address", + cmd => fun(#{domain := Domain} = State) -> + case ?LIB:which_local_host_info(Domain) of + {ok, #{name := Name, + addr := Addr, + broadaddr := BAddr}} -> + ?SEV_IPRINT("local host info: " + "~n Name: ~p" + "~n Addr: ~p" + "~n Broadcast Addr: ~p", + [Name, Addr, BAddr]), + LSA = #{family => Domain, + addr => Addr}, + BSA = #{family => Domain, + addr => BAddr}, + {ok, State#{lsa => LSA, + bsa => BSA}}; + {error, _} = ERROR -> + ERROR + end + end}, + + #{desc => "create TCP socket", + cmd => fun(#{domain := Domain} = State) -> + case socket:open(Domain, stream, tcp) of + {ok, Sock} -> + {ok, State#{sock => Sock}}; + {error, _} = ERROR -> + ERROR + end + end}, + #{desc => "Get current value", + cmd => fun(#{sock := Sock} = State) -> + case Get(Sock) of + {ok, Val} when is_boolean(Val) -> + ?SEV_IPRINT("Success: ~p", [Val]), + {ok, State#{keepalive => Val}}; + {error, Reason} = ERROR -> + ?SEV_EPRINT("Unexpected failure: ~p", + [Reason]), + ERROR + end + end}, + #{desc => "Try change the value", + cmd => fun(#{sock := Sock, keepalive := Current} = State) -> + New = not Current, + ?SEV_IPRINT("Try change value from ~p to ~p", + [Current, New]), + case Set(Sock, New) of + ok -> + ?SEV_IPRINT("Expected Success"), + {ok, State#{keepalive => New}}; + {error, Reason} = ERROR -> + ?SEV_EPRINT("Unexpected Failure: ~p", + [Reason]), + ERROR + end + end}, + #{desc => "Verify (new) current value", + cmd => fun(#{sock := Sock, keepalive := Val} = _State) -> + case Get(Sock) of + {ok, Val} -> + ?SEV_IPRINT("Expected Success (~p)", [Val]), + ok; + {ok, OtherVal} -> + ?SEV_IPRINT("Unexpected Success: ~p", + [OtherVal]), + {error, {unexpected_success_value, + Val, OtherVal}}; + {error, Reason} = ERROR -> + ?SEV_EPRINT("Unexpected failure: ~p", + [Reason]), + ERROR + end + end}, + + %% *** Termination *** + #{desc => "close UDP socket", + cmd => fun(#{sock := Sock} = State0) -> + socket:close(Sock), + State1 = maps:remove(sock, State0), + {ok, State1} + end}, + + %% *** We are done *** + ?SEV_FINISH_NORMAL + ], + + Domain = inet, + + i("start tester evaluator"), + InitState = #{domain => Domain}, + Tester = ?SEV_START("tester", TesterSeq, InitState), + + i("await evaluator(s)"), + ok = ?SEV_AWAIT_FINISH([Tester]). + + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +%% Tests the socket option linger. PLACEHOLDER! + +api_opt_sock_linger(suite) -> + []; +api_opt_sock_linger(doc) -> + []; +api_opt_sock_linger(_Config) when is_list(_Config) -> + ?TT(?SECS(10)), + tc_try(api_opt_sock_linger, + fun() -> not_yet_implemented() end, + fun() -> ok end). + + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + %% Tests that the add_mambership and drop_membership ip options work. %% We create one server and two clients. The server only send messages, %% the clients only receives messages. @@ -7853,9 +10098,9 @@ api_opt_ip_add_drop_membership(_Config) when is_list(_Config) -> ?TT(?SECS(30)), tc_try(api_opt_ip_add_drop_membership, fun() -> - has_ip_add_membership_support(), - has_ip_drop_membership_support(), - has_ip_multicast_support() + has_support_ip_add_membership(), + has_support_ip_drop_membership(), + has_support_ip_multicast() end, fun() -> api_opt_ip_add_drop_membership() end). @@ -8072,8 +10317,8 @@ api_opt_ip_add_drop_membership() -> ], - i("get multicast address"), Domain = inet, + i("get multicast address"), MAddr = which_ip_multicast_address(), MSA = #{family => Domain, addr => MAddr}, @@ -8106,6 +10351,7 @@ which_multicast_address(Domain) -> which_multicast_address2(Domain, WhichMAddr); Type -> + %% Actually, what is "not supported". is netstat! not_supported({multicast, Type}) end. @@ -8115,20 +10361,28 @@ which_multicast_address(Domain) -> which_multicast_address2(Domain, WhichMAddr) -> IfName = which_local_host_ifname(Domain), - try - begin - %% On some platforms the netstat barfs out some crap on stderr - %% before the actual info... - NetstatGroupsStr = os:cmd("netstat -g 2>/dev/null | grep " ++ IfName), - NetstatGroups0 = string:tokens(NetstatGroupsStr, [$\n]), - NetstatGroups = [string:tokens(G, [$ ]) || G <- NetstatGroups0], - MAddrs = [WhichMAddr(NetstatGroup) || NetstatGroup <- - NetstatGroups], - which_multicast_address3(Domain, MAddrs) - end - catch - C:E:S -> - not_supported({multicast, {C,E,S}}) + %% On some platforms the netstat barfs out some crap on stderr + %% before the actual info... + case os:cmd("netstat -g 2>/dev/null | grep " ++ IfName) of + [] -> + %% Can't figure out if we support multicast or not... + not_supported(no_netstat); + NetstatGroupsStr -> + try + begin + NetstatGroups0 = string:tokens(NetstatGroupsStr, [$\n]), + NetstatGroups = [string:tokens(G, [$ ]) || + G <- NetstatGroups0], + MAddrs = [WhichMAddr(NetstatGroup) || + NetstatGroup <- NetstatGroups], + which_multicast_address3(Domain, MAddrs) + end + catch + throw:E:_ -> + throw(E); + C:E:S -> + not_supported({multicast, {C,E,S}}) + end end. which_multicast_address3(_Domain, []) -> @@ -8146,8 +10400,8 @@ which_multicast_address3(Domain, [MAddrStr|MAddrs]) -> end. which_local_host_ifname(Domain) -> - case which_local_host_info(Domain) of - {ok, {Name, _Addr, _Flags}} -> + case ?LIB:which_local_host_info(Domain) of + {ok, #{name := Name}} -> Name; {error, Reason} -> not_supported({multicast, Reason}) @@ -9222,6 +11476,7 @@ api_to_send_tcp6(doc) -> []; api_to_send_tcp6(_Config) when is_list(_Config) -> tc_try(api_to_send_tcp6, + fun() -> has_support_ipv6() end, fun() -> not_yet_implemented()%% , %% ok = api_to_send_tcp(inet6) @@ -9254,6 +11509,7 @@ api_to_sendto_udp6(doc) -> []; api_to_sendto_udp6(_Config) when is_list(_Config) -> tc_try(api_to_sendto_udp6, + fun() -> has_support_ipv6() end, fun() -> not_yet_implemented()%% , %% ok = api_to_sendto_to_udp(inet6) @@ -9286,6 +11542,7 @@ api_to_sendmsg_tcp6(doc) -> []; api_to_sendmsg_tcp6(_Config) when is_list(_Config) -> tc_try(api_to_sendmsg_tcp6, + fun() -> has_support_ipv6() end, fun() -> not_yet_implemented()%% , %% ok = api_to_sendmsg_tcp(inet6) @@ -9320,6 +11577,7 @@ api_to_recv_udp6(doc) -> []; api_to_recv_udp6(_Config) when is_list(_Config) -> tc_try(api_to_recv_udp6, + fun() -> has_support_ipv6() end, fun() -> not_yet_implemented()%% , %% ok = api_to_recv_udp(inet6) @@ -9899,7 +12157,7 @@ sc_cpe_socket_cleanup_tcp4(suite) -> sc_cpe_socket_cleanup_tcp4(doc) -> []; sc_cpe_socket_cleanup_tcp4(_Config) when is_list(_Config) -> - ?TT(?SECS(5)), + ?TT(?SECS(30)), tc_try(sc_cpe_socket_cleanup_tcp4, fun() -> InitState = #{domain => inet, @@ -9919,7 +12177,7 @@ sc_cpe_socket_cleanup_tcp6(suite) -> sc_cpe_socket_cleanup_tcp6(doc) -> []; sc_cpe_socket_cleanup_tcp6(_Config) when is_list(_Config) -> - ?TT(?SECS(5)), + ?TT(?SECS(30)), tc_try(sc_cpe_socket_cleanup_tcp6, fun() -> has_support_ipv6() end, fun() -> @@ -9940,7 +12198,7 @@ sc_cpe_socket_cleanup_tcpL(suite) -> sc_cpe_socket_cleanup_tcpL(doc) -> []; sc_cpe_socket_cleanup_tcpL(_Config) when is_list(_Config) -> - ?TT(?SECS(5)), + ?TT(?SECS(30)), tc_try(sc_cpe_socket_cleanup_tcpL, fun() -> has_support_unix_domain_socket() end, fun() -> @@ -9961,7 +12219,7 @@ sc_cpe_socket_cleanup_udp4(suite) -> sc_cpe_socket_cleanup_udp4(doc) -> []; sc_cpe_socket_cleanup_udp4(_Config) when is_list(_Config) -> - ?TT(?SECS(5)), + ?TT(?SECS(30)), tc_try(sc_cpe_socket_cleanup_udp4, fun() -> InitState = #{domain => inet, @@ -9982,7 +12240,7 @@ sc_cpe_socket_cleanup_udp6(suite) -> sc_cpe_socket_cleanup_udp6(doc) -> []; sc_cpe_socket_cleanup_udp6(_Config) when is_list(_Config) -> - ?TT(?SECS(5)), + ?TT(?SECS(30)), tc_try(sc_cpe_socket_cleanup_udp6, fun() -> has_support_ipv6() end, fun() -> @@ -10003,7 +12261,7 @@ sc_cpe_socket_cleanup_udpL(suite) -> sc_cpe_socket_cleanup_udpL(doc) -> []; sc_cpe_socket_cleanup_udpL(_Config) when is_list(_Config) -> - ?TT(?SECS(5)), + ?TT(?SECS(30)), tc_try(sc_cpe_socket_cleanup_udpL, fun() -> has_support_unix_domain_socket() end, fun() -> @@ -10109,8 +12367,15 @@ sc_cpe_socket_cleanup(InitState) -> ERROR end end}, + + ?SEV_SLEEP(?SECS(5)), + %% The reason we get closed, is that as long as there is a ref to %% the resource (socket), then it will not be garbage collected. + %% Note that its still a race that the nif has processed that the + %% "controlling process" has terminated. There really is no + %% proper timeout for this, but the 5 seconds "should" be enough... + %% We should really have some way to subscribe to socket events... #{desc => "verify no socket (closed)", cmd => fun(#{owner := Pid, sock := Sock} = _State) -> case socket:getopt(Sock, otp, controlling_process) of @@ -13952,6 +16217,29 @@ traffic_send_and_recv_counters_tcp4(_Config) when is_list(_Config) -> %% This test case is intended to (simply) test that the counters %% for both read and write. %% So that its easy to extend, we use fun's for read and write. +%% We use TCP on IPv6. + +traffic_send_and_recv_counters_tcp6(suite) -> + []; +traffic_send_and_recv_counters_tcp6(doc) -> + []; +traffic_send_and_recv_counters_tcp6(_Config) when is_list(_Config) -> + ?TT(?SECS(15)), + tc_try(traffic_send_and_recv_counters_tcp6, + fun() -> has_support_ipv6() end, + fun() -> + InitState = #{domain => inet6, + proto => tcp, + recv => fun(S) -> socket:recv(S) end, + send => fun(S, D) -> socket:send(S, D) end}, + ok = traffic_send_and_recv_tcp(InitState) + end). + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% This test case is intended to (simply) test that the counters +%% for both read and write. +%% So that its easy to extend, we use fun's for read and write. %% We use default (TCP) on local. traffic_send_and_recv_counters_tcpL(suite) -> @@ -13961,6 +16249,7 @@ traffic_send_and_recv_counters_tcpL(doc) -> traffic_send_and_recv_counters_tcpL(_Config) when is_list(_Config) -> ?TT(?SECS(15)), tc_try(traffic_send_and_recv_counters_tcpL, + fun() -> has_support_unix_domain_socket() end, fun() -> InitState = #{domain => local, proto => default, @@ -14007,6 +16296,40 @@ traffic_sendmsg_and_recvmsg_counters_tcp4(_Config) when is_list(_Config) -> %% This test case is intended to (simply) test that the counters %% for both read and write. %% So that its easy to extend, we use fun's for read and write. +%% We use TCP on IPv6. + +traffic_sendmsg_and_recvmsg_counters_tcp6(suite) -> + []; +traffic_sendmsg_and_recvmsg_counters_tcp6(doc) -> + []; +traffic_sendmsg_and_recvmsg_counters_tcp6(_Config) when is_list(_Config) -> + ?TT(?SECS(15)), + tc_try(traffic_sendmsg_and_recvmsg_counters_tcp6, + fun() -> has_support_ipv6() end, + fun() -> + InitState = #{domain => inet6, + proto => tcp, + recv => fun(S) -> + case socket:recvmsg(S) of + {ok, #{addr := _Source, + iov := [Data]}} -> + {ok, Data}; + {error, _} = ERROR -> + ERROR + end + end, + send => fun(S, Data) -> + MsgHdr = #{iov => [Data]}, + socket:sendmsg(S, MsgHdr) + end}, + ok = traffic_send_and_recv_tcp(InitState) + end). + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% This test case is intended to (simply) test that the counters +%% for both read and write. +%% So that its easy to extend, we use fun's for read and write. %% We use default (TCP) on local. traffic_sendmsg_and_recvmsg_counters_tcpL(suite) -> @@ -14016,6 +16339,7 @@ traffic_sendmsg_and_recvmsg_counters_tcpL(doc) -> traffic_sendmsg_and_recvmsg_counters_tcpL(_Config) when is_list(_Config) -> ?TT(?SECS(15)), tc_try(traffic_sendmsg_and_recvmsg_counters_tcpL, + fun() -> has_support_unix_domain_socket() end, fun() -> InitState = #{domain => local, proto => default, @@ -14064,6 +16388,8 @@ traffic_send_and_recv_tcp(InitState) -> case socket:open(Domain, stream, Proto) of {ok, Sock} -> {ok, State#{lsock => Sock}}; + {error, eafnosupport = Reason} -> + {skip, Reason}; {error, _} = ERROR -> ERROR end @@ -14408,6 +16734,8 @@ traffic_send_and_recv_tcp(InitState) -> case socket:open(Domain, stream, Proto) of {ok, Sock} -> {ok, State#{sock => Sock}}; + {error, eafnosupport = Reason} -> + {skip, Reason}; {error, _} = ERROR -> ERROR end @@ -14928,6 +17256,33 @@ traffic_sendto_and_recvfrom_counters_udp4(_Config) when is_list(_Config) -> %% This test case is intended to (simply) test that the counters %% for both read and write. %% So that its easy to extend, we use fun's for read and write. +%% We use UDP on IPv6. + +traffic_sendto_and_recvfrom_counters_udp6(suite) -> + []; +traffic_sendto_and_recvfrom_counters_udp6(doc) -> + []; +traffic_sendto_and_recvfrom_counters_udp6(_Config) when is_list(_Config) -> + ?TT(?SECS(15)), + tc_try(traffic_sendto_and_recvfrom_counters_udp6, + fun() -> has_support_ipv6() end, + fun() -> + InitState = #{domain => inet6, + proto => udp, + recv => fun(S) -> + socket:recvfrom(S) + end, + send => fun(S, Data, Dest) -> + socket:sendto(S, Data, Dest) + end}, + ok = traffic_send_and_recv_udp(InitState) + end). + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% This test case is intended to (simply) test that the counters +%% for both read and write. +%% So that its easy to extend, we use fun's for read and write. %% We use default (UDP) on local. traffic_sendto_and_recvfrom_counters_udpL(suite) -> @@ -14937,6 +17292,7 @@ traffic_sendto_and_recvfrom_counters_udpL(doc) -> traffic_sendto_and_recvfrom_counters_udpL(_Config) when is_list(_Config) -> ?TT(?SECS(15)), tc_try(traffic_sendto_and_recvfrom_counters_udp4, + fun() -> has_support_unix_domain_socket() end, fun() -> InitState = #{domain => local, proto => default, @@ -14988,6 +17344,41 @@ traffic_sendmsg_and_recvmsg_counters_udp4(_Config) when is_list(_Config) -> %% This test case is intended to (simply) test that the counters %% for both read and write. %% So that its easy to extend, we use fun's for read and write. +%% We use UDP on IPv6. + +traffic_sendmsg_and_recvmsg_counters_udp6(suite) -> + []; +traffic_sendmsg_and_recvmsg_counters_udp6(doc) -> + []; +traffic_sendmsg_and_recvmsg_counters_udp6(_Config) when is_list(_Config) -> + ?TT(?SECS(15)), + tc_try(traffic_sendmsg_and_recvmsg_counters_udp6, + fun() -> has_support_ipv6() end, + fun() -> + InitState = #{domain => inet6, + proto => udp, + recv => fun(S) -> + case socket:recvmsg(S) of + {ok, #{addr := Source, + iov := [Data]}} -> + {ok, {Source, Data}}; + {error, _} = ERROR -> + ERROR + end + end, + send => fun(S, Data, Dest) -> + MsgHdr = #{addr => Dest, + iov => [Data]}, + socket:sendmsg(S, MsgHdr) + end}, + ok = traffic_send_and_recv_udp(InitState) + end). + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% This test case is intended to (simply) test that the counters +%% for both read and write. +%% So that its easy to extend, we use fun's for read and write. %% We use default (UDP) on local. traffic_sendmsg_and_recvmsg_counters_udpL(suite) -> @@ -14997,6 +17388,7 @@ traffic_sendmsg_and_recvmsg_counters_udpL(doc) -> traffic_sendmsg_and_recvmsg_counters_udpL(_Config) when is_list(_Config) -> ?TT(?SECS(15)), tc_try(traffic_sendmsg_and_recvmsg_counters_udpL, + fun() -> has_support_unix_domain_socket() end, fun() -> InitState = #{domain => local, proto => default, @@ -15455,7 +17847,7 @@ traffic_send_and_recv_udp(InitState) -> #{desc => "recv (1)", cmd => fun(#{sock := Sock, recv := Recv, - server_sa := ServerSA} = State) -> + server_sa := #{family := local} = ServerSA} = State) -> case Recv(Sock) of {ok, {ServerSA, Data}} -> ?SEV_IPRINT("recv ~p bytes", [size(Data)]), @@ -15463,6 +17855,17 @@ traffic_send_and_recv_udp(InitState) -> read_byte => size(Data)}}; {error, _} = ERROR -> ERROR + end; + (#{sock := Sock, + recv := Recv, + server_sa := #{addr := Addr, port := Port}} = State) -> + case Recv(Sock) of + {ok, {#{addr := Addr, port := Port}, Data}} -> + ?SEV_IPRINT("recv ~p bytes", [size(Data)]), + {ok, State#{read_pkg => 1, + read_byte => size(Data)}}; + {error, _} = ERROR -> + ERROR end end}, #{desc => "validate (recv 1)", @@ -15557,7 +17960,7 @@ traffic_send_and_recv_udp(InitState) -> end}, #{desc => "recv (2)", cmd => fun(#{sock := Sock, - server_sa := ServerSA, + server_sa := #{family := local} = ServerSA, recv := Recv, read_pkg := RPkg, read_byte := RByte} = State) -> @@ -15568,6 +17971,19 @@ traffic_send_and_recv_udp(InitState) -> read_byte => RByte + size(Data)}}; {error, _} = ERROR -> ERROR + end; + (#{sock := Sock, + server_sa := #{addr := Addr, port := Port}, + recv := Recv, + read_pkg := RPkg, + read_byte := RByte} = State) -> + case Recv(Sock) of + {ok, {#{addr := Addr, port := Port}, Data}} -> + ?SEV_IPRINT("recv ~p bytes", [size(Data)]), + {ok, State#{read_pkg => RPkg + 1, + read_byte => RByte + size(Data)}}; + {error, _} = ERROR -> + ERROR end end}, #{desc => "validate (recv 2)", @@ -17055,6 +19471,7 @@ traffic_ping_pong_large_send_and_recv_tcp4(_Config) when is_list(_Config) -> Msg = l2b(?TPP_LARGE), Num = ?TPP_LARGE_NUM, tc_try(traffic_ping_pong_large_send_and_recv_tcp4, + fun() -> is_old_fedora16() end, fun() -> InitState = #{domain => inet, proto => tcp, @@ -17081,7 +19498,8 @@ traffic_ping_pong_large_send_and_recv_tcp6(_Config) when is_list(_Config) -> Msg = l2b(?TPP_LARGE), Num = ?TPP_LARGE_NUM, tc_try(traffic_ping_pong_large_send_and_recv_tcp6, - fun() -> has_support_ipv6() end, + fun() -> is_old_fedora16(), + has_support_ipv6() end, fun() -> ?TT(?SECS(45)), InitState = #{domain => inet6, @@ -17130,9 +19548,28 @@ traffic_ping_pong_large_host_cond() -> traffic_ping_pong_large_host_cond({unix, sunos}, _) -> skip("TC does not work on platform"); +traffic_ping_pong_large_host_cond({unix, linux}, _) -> + traffic_ping_pong_large_host_cond2(string:trim(os:cmd("cat /etc/issue"))); traffic_ping_pong_large_host_cond(_, _) -> ok. +traffic_ping_pong_large_host_cond2("Welcome to SUSE Linux Enterprise Server 10 SP1 (i586)" ++ _) -> + skip("TC does not work on platform"); +traffic_ping_pong_large_host_cond2("Fedora release 16 " ++ _) -> + skip("Very slow VM"); +traffic_ping_pong_large_host_cond2(_) -> + ok. + + +is_old_fedora16() -> + is_old_fedora16(string:trim(os:cmd("cat /etc/issue"))). + +%% We actually only have one host running this, a slow VM. +is_old_fedora16("Fedora release 16 " ++ _) -> + skip("Very slow VM"); +is_old_fedora16(_) -> + ok. + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% This test case is intended to test that the sendto and recvfrom @@ -17175,12 +19612,12 @@ traffic_ping_pong_small_sendto_and_recvfrom_udp6(suite) -> traffic_ping_pong_small_sendto_and_recvfrom_udp6(doc) -> []; traffic_ping_pong_small_sendto_and_recvfrom_udp6(_Config) when is_list(_Config) -> - ?TT(?SECS(45)), Msg = l2b(?TPP_SMALL), Num = ?TPP_SMALL_NUM, tc_try(traffic_ping_pong_small_sendto_and_recvfrom_udp6, fun() -> has_support_ipv6() end, fun() -> + ?TT(?SECS(45)), InitState = #{domain => inet6, proto => udp, msg => Msg, @@ -17204,12 +19641,12 @@ traffic_ping_pong_small_sendto_and_recvfrom_udpL(suite) -> traffic_ping_pong_small_sendto_and_recvfrom_udpL(doc) -> []; traffic_ping_pong_small_sendto_and_recvfrom_udpL(_Config) when is_list(_Config) -> - ?TT(?SECS(45)), Msg = l2b(?TPP_SMALL), Num = ?TPP_SMALL_NUM, tc_try(traffic_ping_pong_small_sendto_and_recvfrom_udpL, fun() -> has_support_unix_domain_socket() end, fun() -> + ?TT(?SECS(45)), InitState = #{domain => local, proto => default, msg => Msg, @@ -17433,7 +19870,7 @@ traffic_ping_pong_medium_sendmsg_and_recvmsg_tcp6(_Config) when is_list(_Config) tc_try(traffic_ping_pong_medium_sendmsg_and_recvmsg_tcp6, fun() -> has_support_ipv6() end, fun() -> - ?TT(?SECS(20)), + ?TT(?SECS(30)), InitState = #{domain => inet6, proto => tcp, msg => Msg, @@ -17461,7 +19898,7 @@ traffic_ping_pong_medium_sendmsg_and_recvmsg_tcpL(_Config) when is_list(_Config) tc_try(traffic_ping_pong_medium_sendmsg_and_recvmsg_tcpL, fun() -> has_support_unix_domain_socket() end, fun() -> - ?TT(?SECS(20)), + ?TT(?SECS(30)), InitState = #{domain => local, proto => default, msg => Msg, @@ -17489,7 +19926,7 @@ traffic_ping_pong_large_sendmsg_and_recvmsg_tcp4(_Config) when is_list(_Config) tc_try(traffic_ping_pong_large_sendmsg_and_recvmsg_tcp4, fun() -> traffic_ping_pong_large_sendmsg_and_recvmsg_cond() end, fun() -> - ?TT(?SECS(30)), + ?TT(?SECS(60)), InitState = #{domain => inet, proto => tcp, msg => Msg, @@ -17530,7 +19967,7 @@ traffic_ping_pong_large_sendmsg_and_recvmsg_tcp6(_Config) when is_list(_Config) traffic_ping_pong_large_sendmsg_and_recvmsg_cond() end, fun() -> - ?TT(?SECS(30)), + ?TT(?SECS(60)), InitState = #{domain => inet6, proto => tcp, msg => Msg, @@ -17559,7 +19996,7 @@ traffic_ping_pong_large_sendmsg_and_recvmsg_tcpL(_Config) when is_list(_Config) tc_try(traffic_ping_pong_large_sendmsg_and_recvmsg_tcpL, fun() -> has_support_unix_domain_socket() end, fun() -> - ?TT(?SECS(30)), + ?TT(?SECS(60)), InitState = #{domain => local, proto => default, msg => Msg, @@ -17615,7 +20052,7 @@ traffic_ping_pong_small_sendmsg_and_recvmsg_udp6(_Config) when is_list(_Config) tc_try(traffic_ping_pong_small_sendmsg_and_recvmsg_udp6, fun() -> has_support_ipv6() end, fun() -> - ?TT(?SECS(30)), + ?TT(?SECS(60)), InitState = #{domain => inet6, proto => udp, msg => Msg, @@ -17643,7 +20080,7 @@ traffic_ping_pong_small_sendmsg_and_recvmsg_udpL(_Config) when is_list(_Config) tc_try(traffic_ping_pong_small_sendmsg_and_recvmsg_udpL, fun() -> has_support_unix_domain_socket() end, fun() -> - ?TT(?SECS(30)), + ?TT(?SECS(60)), InitState = #{domain => local, proto => default, msg => Msg, @@ -17670,7 +20107,7 @@ traffic_ping_pong_medium_sendmsg_and_recvmsg_udp4(_Config) when is_list(_Config) Num = ?TPP_MEDIUM_NUM, tc_try(traffic_ping_pong_medium_sendmsg_and_recvmsg_udp4, fun() -> - ?TT(?SECS(30)), + ?TT(?SECS(60)), InitState = #{domain => inet, proto => udp, msg => Msg, @@ -17698,7 +20135,7 @@ traffic_ping_pong_medium_sendmsg_and_recvmsg_udp6(_Config) when is_list(_Config) tc_try(traffic_ping_pong_medium_sendmsg_and_recvmsg_udp6, fun() -> has_support_ipv6() end, fun() -> - ?TT(?SECS(20)), + ?TT(?SECS(60)), InitState = #{domain => inet6, proto => udp, msg => Msg, @@ -17727,7 +20164,7 @@ traffic_ping_pong_medium_sendmsg_and_recvmsg_udpL(_Config) when is_list(_Config) tc_try(traffic_ping_pong_medium_sendmsg_and_recvmsg_udpL, fun() -> has_support_unix_domain_socket() end, fun() -> - ?TT(?SECS(20)), + ?TT(?SECS(60)), InitState = #{domain => local, proto => default, msg => Msg, @@ -17799,12 +20236,14 @@ traffic_ping_pong_send_and_receive_tcp(#{msg := Msg} = InitState) -> ?SEV_IPRINT("RcvBuf is ~p (needs atleast ~p)", [RcvSz, 16+size(Msg)]), if (RcvSz < size(Msg)) -> - case socket:setopt(Sock, - socket, rcvbuf, 1024+size(Msg)) of + NewRcvSz = 1024+size(Msg), + case socket:setopt(Sock, socket, rcvbuf, NewRcvSz) of ok -> ok; {error, enobufs} -> - skip({failed_change, rcvbuf}); + skip(?F("Change ~w buffer size (to ~w) " + "not allowed", + [rcvbuf, NewRcvSz])); {error, Reason1} -> ?FAIL({rcvbuf, Reason1}) end; @@ -17815,12 +20254,14 @@ traffic_ping_pong_send_and_receive_tcp(#{msg := Msg} = InitState) -> ?SEV_IPRINT("SndBuf is ~p (needs atleast ~p)", [SndSz, 16+size(Msg)]), if (SndSz < size(Msg)) -> - case socket:setopt(Sock, - socket, sndbuf, 1024+size(Msg)) of + NewSndSz = 1024+size(Msg), + case socket:setopt(Sock, socket, sndbuf, NewSndSz) of ok -> ok; {error, enobufs} -> - skip({failed_change, sndbuf}); + skip(?F("Change ~w buffer size (to ~w) " + "not allowed", + [sndbuf, NewSndSz])); {error, Reason2} -> ?FAIL({sndbuf, Reason2}) end; @@ -19408,7 +21849,9 @@ tpp_udp_client_handler_msg_exchange_loop(_Sock, _Dest, _Send, _Recv, _Msg, Start) -> Stop = ?LIB:timestamp(), {Sent, Received, Start, Stop}; -tpp_udp_client_handler_msg_exchange_loop(Sock, Dest, Send, Recv, Data, +tpp_udp_client_handler_msg_exchange_loop(Sock, + #{family := local} = Dest, + Send, Recv, Data, Num, N, Sent, Received, Start) -> case tpp_udp_send_req(Sock, Send, Data, Dest) of {ok, SendSz} -> @@ -19427,6 +21870,28 @@ tpp_udp_client_handler_msg_exchange_loop(Sock, Dest, Send, Recv, Data, {error, SReason} -> ?SEV_EPRINT("send (~w of ~w): ~p", [N, Num, SReason]), exit({send, SReason, N}) + end; +tpp_udp_client_handler_msg_exchange_loop(Sock, + #{addr := Addr, port := Port} = Dest0, + Send, Recv, Data, + Num, N, Sent, Received, Start) -> + case tpp_udp_send_req(Sock, Send, Data, Dest0) of + {ok, SendSz} -> + case tpp_udp_recv_rep(Sock, Recv) of + {ok, NewData, RecvSz, #{addr := Addr, port := Port} = Dest1} -> + tpp_udp_client_handler_msg_exchange_loop(Sock, Dest1, + Send, Recv, + NewData, Num, N+1, + Sent+SendSz, + Received+RecvSz, + Start); + {error, RReason} -> + ?SEV_EPRINT("recv (~w of ~w): ~p", [N, Num, RReason]), + exit({recv, RReason, N}) + end; + {error, SReason} -> + ?SEV_EPRINT("send (~w of ~w): ~p", [N, Num, SReason]), + exit({send, SReason, N}) end. @@ -25450,7 +27915,7 @@ ttest_tcp(TC, fun() -> if (Domain =:= local) -> has_support_unix_domain_socket(); - (Domain =:= inet6) -> has_support_ipv6(); + (Domain =:= inet6) -> has_support_ipv6(); true -> ok end end, @@ -25913,16 +28378,22 @@ ttest_tcp(InitState) -> ?SEV_FINISH_NORMAL ], + Domain = maps:get(domain, InitState), + LHost = local_host(), + LAddr = which_local_addr(Domain), + i("start server evaluator"), - ServerInitState = #{host => local_host(), - domain => maps:get(domain, InitState), + ServerInitState = #{host => LHost, + addr => LAddr, + domain => Domain, mod => maps:get(server_mod, InitState), active => maps:get(server_active, InitState)}, Server = ?SEV_START("server", ServerSeq, ServerInitState), i("start client evaluator"), - ClientInitState = #{host => local_host(), - domain => maps:get(domain, InitState), + ClientInitState = #{host => LHost, + addr => LAddr, + domain => Domain, mod => maps:get(client_mod, InitState), active => maps:get(client_active, InitState), msg_id => maps:get(msg_id, InitState), @@ -25931,9 +28402,14 @@ ttest_tcp(InitState) -> Client = ?SEV_START("client", ClientSeq, ClientInitState), i("start 'tester' evaluator"), - TesterInitState = #{domain => maps:get(domain, InitState), - server => Server#ev.pid, - client => Client#ev.pid}, + TesterInitState = #{domain => Domain, + msg_id => maps:get(msg_id, InitState), + client => Client#ev.pid, + client_mod => maps:get(client_mod, InitState), + client_active => maps:get(client_active, InitState), + server => Server#ev.pid, + server_mod => maps:get(server_mod, InitState), + server_active => maps:get(server_active, InitState)}, Tester = ?SEV_START("tester", TesterSeq, TesterInitState), i("await evaluator(s)"), @@ -25941,8 +28417,9 @@ ttest_tcp(InitState) -> -ttest_tcp_server_start(Node, _Domain, gen, Active) -> - Transport = socket_test_ttest_tcp_gen, +ttest_tcp_server_start(Node, Domain, gen, Active) -> + TransportMod = socket_test_ttest_tcp_gen, + Transport = {TransportMod, #{domain => Domain}}, socket_test_ttest_tcp_server:start_monitor(Node, Transport, Active); ttest_tcp_server_start(Node, Domain, sock, Active) -> TransportMod = socket_test_ttest_tcp_socket, @@ -25956,9 +28433,10 @@ ttest_tcp_server_stop(Pid) -> ttest_tcp_client_start(Node, Notify, - _Domain, gen, + Domain, gen, ServerInfo, Active, MsgID, MaxOutstanding, RunTime) -> - Transport = socket_test_ttest_tcp_gen, + TransportMod = socket_test_ttest_tcp_gen, + Transport = {TransportMod, #{domain => Domain}}, socket_test_ttest_tcp_client:start_monitor(Node, Notify, Transport, @@ -26253,39 +28731,6 @@ sock_sockname(Sock) -> ?FAIL({sockname, C, E, S}) end. - -%% sock_listen(Sock) -> -%% sock_listen2(fun() -> socket:listen(Sock) end). - -%% sock_listen(Sock, BackLog) -> -%% sock_listen2(fun() -> socket:listen(Sock, BackLog) end). - -%% sock_listen2(Listen) -> -%% try Listen() of -%% ok -> -%% ok; -%% {error, Reason} -> -%% ?FAIL({listen, Reason}) -%% catch -%% C:E:S -> -%% ?FAIL({listen, C, E, S}) -%% end. - - -%% sock_accept(LSock) -> -%% try socket:accept(LSock) of -%% {ok, Sock} -> -%% Sock; -%% {error, Reason} -> -%% i("sock_accept -> error: ~p", [Reason]), -%% ?FAIL({accept, Reason}) -%% catch -%% C:E:S -> -%% i("sock_accept -> failed: ~p, ~p, ~p", [C, E, S]), -%% ?FAIL({accept, C, E, S}) -%% end. - - sock_close(Sock) -> try socket:close(Sock) of ok -> @@ -26351,12 +28796,12 @@ which_local_socket_addr(local = Domain) -> #{family => Domain, path => mk_unique_path()}; -%% This gets the local address (not 127.0...) +%% This gets the local socket address (not 127.0...) %% We should really implement this using the (new) net module, %% but until that gets the necessary functionality... which_local_socket_addr(Domain) -> - case which_local_host_info(Domain) of - {ok, {_Name, _Flags, Addr}} -> + case ?LIB:which_local_host_info(Domain) of + {ok, #{addr := Addr}} -> #{family => Domain, addr => Addr}; {error, Reason} -> @@ -26364,55 +28809,15 @@ which_local_socket_addr(Domain) -> end. -%% Returns the interface (name), flags and address (not 127...) -%% of the local host. -which_local_host_info(Domain) -> - case inet:getifaddrs() of - {ok, IFL} -> - which_local_host_info(Domain, IFL); - {error, _} = ERROR -> - ERROR - end. -which_local_host_info(_Domain, []) -> - ?FAIL(no_address); -which_local_host_info(Domain, [{"lo" ++ _, _}|IFL]) -> - which_local_host_info(Domain, IFL); -which_local_host_info(Domain, [{"docker" ++ _, _}|IFL]) -> - which_local_host_info(Domain, IFL); -which_local_host_info(Domain, [{"br-" ++ _, _}|IFL]) -> - which_local_host_info(Domain, IFL); -which_local_host_info(Domain, [{Name, IFO}|IFL]) -> - case which_local_host_info2(Domain, IFO) of - {ok, {Flags, Addr}} -> - {ok, {Name, Flags, Addr}}; - {error, _} -> - which_local_host_info(Domain, IFL) - end; -which_local_host_info(Domain, [_|IFL]) -> - which_local_host_info(Domain, IFL). - -which_local_host_info2(Domain, IFO) -> - case lists:keysearch(flags, 1, IFO) of - {value, {flags, Flags}} -> - which_local_host_info2(Domain, IFO, Flags); - false -> - {error, no_flags} - end. - -which_local_host_info2(_Domain, [], _Flags) -> - {error, no_address}; -which_local_host_info2(inet = _Domain, [{addr, Addr}|_IFO], Flags) - when (size(Addr) =:= 4) andalso (element(1, Addr) =/= 127) -> - {ok, {Flags, Addr}}; -which_local_host_info2(inet6 = _Domain, [{addr, Addr}|_IFO], Flags) - when (size(Addr) =:= 8) andalso - (element(1, Addr) =/= 0) andalso - (element(1, Addr) =/= 16#fe80) -> - {ok, {Flags, Addr}}; -which_local_host_info2(Domain, [_|IFO], Flags) -> - which_local_host_info2(Domain, IFO, Flags). +which_local_addr(local = _Domain) -> + mk_unique_path(); +%% This gets the local address (not 127.0...) +%% We should really implement this using the (new) net module, +%% but until that gets the necessary functionality... +which_local_addr(Domain) -> + ?LIB:which_local_addr(Domain). @@ -26425,12 +28830,12 @@ which_local_host_info2(Domain, [_|IFO], Flags) -> %% We don't do that here, but since we can only do that (find a %% multicast address) for specific platforms, we check that we are %% on of those platforms here. -has_ip_multicast_support() -> +has_support_ip_multicast() -> case os:type() of {unix, OsName} when (OsName =:= linux) orelse (OsName =:= sunos) -> - case which_local_host_info(inet) of - {ok, {_Name, Flags, _Addr}} -> + case ?LIB:which_local_host_info(inet) of + {ok, #{flags := Flags}} -> case lists:member(multicast, Flags) of true -> ok; @@ -26440,26 +28845,64 @@ has_ip_multicast_support() -> {error, Reason} -> not_supported({multicast, Reason}) end; + {unix, OsName} -> + skip(?F("Not Supported: platform ~w", [OsName])); Type -> - not_supported({multicast, Type}) + skip(?F("Not Supported: platform ~p", [Type])) end. -has_ip_add_membership_support() -> - has_socket_option_ip_support(add_membership). +has_support_sock_acceptconn() -> + has_support_socket_option_sock(acceptconn). + +has_support_sock_bindtodevice() -> + has_support_socket_option_sock(bindtodevice). + +has_support_sock_broadcast() -> + has_support_socket_option_sock(broadcast), + case ?LIB:which_local_host_info(inet) of + {ok, #{flags := Flags}} -> + case lists:member(broadcast, Flags) of + true -> + ok; + false -> + not_supported({broadcast, Flags}) + end; + {error, Reason} -> + not_supported({broadcast, Reason}) + end. + +has_support_sock_debug() -> + has_support_socket_option_sock(debug). + +has_support_sock_domain() -> + has_support_socket_option_sock(domain). + +has_support_sock_dontroute() -> + has_support_socket_option_sock(dontroute). + +has_support_sock_keepalive() -> + has_support_socket_option_sock(keepalive). + + +has_support_ip_add_membership() -> + has_support_socket_option_ip(add_membership). + +has_support_ip_drop_membership() -> + has_support_socket_option_ip(drop_membership). -has_ip_drop_membership_support() -> - has_socket_option_ip_support(drop_membership). +has_support_socket_option_ip(Opt) -> + has_support_socket_option(ip, Opt). -has_socket_option_ip_support(Opt) -> - has_socket_option_support(ip, Opt). +has_support_socket_option_sock(Opt) -> + has_support_socket_option(socket, Opt). -has_socket_option_support(Level, Option) -> +has_support_socket_option(Level, Option) -> case socket:supports(options, Level, Option) of true -> ok; false -> - not_supported({options, Level, Option}) + skip(?F("Not Supported: ~w option ~w", [Level, Option])) end. @@ -26491,13 +28934,7 @@ has_support_unix_domain_socket() -> %% support for IPv6. If not, there is no point in running IPv6 tests. %% Currently we just skip. has_support_ipv6() -> - %% case socket:supports(ipv6) of - %% true -> - %% ok; - %% false -> - %% {error, not_supported} - %% end. - not_yet_implemented(). + ?LIB:has_support_ipv6(). diff --git a/erts/emulator/test/socket_test_lib.erl b/erts/emulator/test/socket_test_lib.erl index 4e65c4f3c0..39cbf0c79f 100644 --- a/erts/emulator/test/socket_test_lib.erl +++ b/erts/emulator/test/socket_test_lib.erl @@ -32,6 +32,12 @@ %% String and format f/2, + %% Generic 'has support' test function(s) + has_support_ipv6/0, + + which_local_host_info/1, + which_local_addr/1, + %% Skipping not_yet_implemented/0, skip/1 @@ -40,6 +46,11 @@ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +-define(FAIL(R), exit(R)). + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + pi(Item) when is_atom(Item) -> pi(self(), Item). @@ -88,6 +99,196 @@ f(F, A) -> %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +has_support_ipv6() -> + case socket:supports(ipv6) of + true -> + ok; + false -> + skip("IPv6 Not Supported") + end, + Domain = inet6, + LocalAddr = + case which_local_addr(Domain) of + {ok, Addr} -> + Addr; + {error, R1} -> + skip(f("Local Address eval failed: ~p", [R1])) + end, + ServerSock = + case socket:open(Domain, dgram, udp) of + {ok, SS} -> + SS; + {error, R2} -> + skip(f("(server) socket open failed: ~p", [R2])) + end, + LocalSA = #{family => Domain, addr => LocalAddr}, + ServerPort = + case socket:bind(ServerSock, LocalSA) of + {ok, P1} -> + P1; + {error, R3} -> + socket:close(ServerSock), + skip(f("(server) socket bind failed: ~p", [R3])) + end, + ServerSA = LocalSA#{port => ServerPort}, + ClientSock = + case socket:open(Domain, dgram, udp) of + {ok, CS} -> + CS; + {error, R4} -> + skip(f("(client) socket open failed: ~p", [R4])) + end, + case socket:bind(ClientSock, LocalSA) of + {ok, _} -> + ok; + {error, R5} -> + socket:close(ServerSock), + socket:close(ClientSock), + skip(f("(client) socket bind failed: ~p", [R5])) + end, + case socket:sendto(ClientSock, <<"hejsan">>, ServerSA) of + ok -> + ok; + {error, R6} -> + socket:close(ServerSock), + socket:close(ClientSock), + skip(f("failed socket sendto test: ~p", [R6])) + end, + case socket:recvfrom(ServerSock) of + {ok, {_, <<"hejsan">>}} -> + socket:close(ServerSock), + socket:close(ClientSock), + ok; + {error, R7} -> + socket:close(ServerSock), + socket:close(ClientSock), + skip(f("failed socket recvfrom test: ~p", [R7])) + end. + + + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +%% This gets the local address (not {127, _} or {0, ...} or {16#fe80, ...}) +%% We should really implement this using the (new) net module, +%% but until that gets the necessary functionality... +which_local_addr(Domain) -> + case which_local_host_info(Domain) of + {ok, #{addr := Addr}} -> + {ok, Addr}; + {error, _Reason} = ERROR -> + ERROR + end. + + +%% Returns the interface (name), flags and address (not 127...) +%% of the local host. +which_local_host_info(Domain) -> + case inet:getifaddrs() of + {ok, IFL} -> + which_local_host_info(Domain, IFL); + {error, _} = ERROR -> + ERROR + end. + +which_local_host_info(_Domain, []) -> + {error, no_address}; +which_local_host_info(Domain, [{"lo" ++ _, _}|IFL]) -> + which_local_host_info(Domain, IFL); +which_local_host_info(Domain, [{"docker" ++ _, _}|IFL]) -> + which_local_host_info(Domain, IFL); +which_local_host_info(Domain, [{"br-" ++ _, _}|IFL]) -> + which_local_host_info(Domain, IFL); +which_local_host_info(Domain, [{Name, IFO}|IFL]) -> + try which_local_host_info2(Domain, IFO) of + Info -> + {ok, Info#{name => Name}} + catch + throw:_:_ -> + which_local_host_info(Domain, IFL) + end; +which_local_host_info(Domain, [_|IFL]) -> + which_local_host_info(Domain, IFL). + +%% which_local_host_info2(Domain, IFO) -> +%% case lists:keysearch(flags, 1, IFO) of +%% {value, {flags, Flags}} -> +%% which_local_host_info2(Domain, IFO, Flags); +%% false -> +%% {error, no_flags} +%% end. + + +%% which_local_host_info2(_Domain, [], _Flags) -> +%% {error, no_address}; +%% which_local_host_info2(inet = _Domain, [{addr, Addr}|_IFO], Flags) +%% when (size(Addr) =:= 4) andalso (element(1, Addr) =/= 127) -> +%% {ok, {Flags, Addr}}; +%% which_local_host_info2(inet6 = _Domain, [{addr, Addr}|_IFO], Flags) +%% when (size(Addr) =:= 8) andalso +%% (element(1, Addr) =/= 0) andalso +%% (element(1, Addr) =/= 16#fe80) -> +%% {ok, {Flags, Addr}}; +%% which_local_host_info2(Domain, [_|IFO], Flags) -> +%% which_local_host_info2(Domain, IFO, Flags). + +%% foo(Info, inet = Domain, IFO) -> +%% foo(Info, Domain, IFO, [flags, addr, netmask, broadaddr, hwaddr]); +%% foo(Info, inet6 = Domain, IFO) -> +%% foo(Info, Domain, IFO, [flags, addr, netmask, hwaddr]). + +which_local_host_info2(inet = _Domain, IFO) -> + Addr = which_local_host_info3(addr, IFO, + fun({A, _, _, _}) when (A =/= 127) -> true; + (_) -> false + end), + NetMask = which_local_host_info3(netmask, IFO, + fun({_, _, _, _}) -> true; + (_) -> false + end), + BroadAddr = which_local_host_info3(broadaddr, IFO, + fun({_, _, _, _}) -> true; + (_) -> false + end), + Flags = which_local_host_info3(flags, IFO, fun(_) -> true end), + #{flags => Flags, + addr => Addr, + broadaddr => BroadAddr, + netmask => NetMask}; +which_local_host_info2(inet6 = _Domain, IFO) -> + Addr = which_local_host_info3(addr, IFO, + fun({A, _, _, _, _, _, _, _}) + when (A =/= 0) andalso + (A =/= 16#fe80) -> true; + (_) -> false + end), + NetMask = which_local_host_info3(netmask, IFO, + fun({_, _, _, _, _, _, _, _}) -> true; + (_) -> false + end), + Flags = which_local_host_info3(flags, IFO, fun(_) -> true end), + #{flags => Flags, + addr => Addr, + netmask => NetMask}. + +which_local_host_info3(_Key, [], _) -> + throw({error, no_address}); +which_local_host_info3(Key, [{Key, Val}|IFO], Check) -> + case Check(Val) of + true -> + Val; + false -> + which_local_host_info3(Key, IFO, Check) + end; +which_local_host_info3(Key, [_|IFO], Check) -> + which_local_host_info3(Key, IFO, Check). + + + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + not_yet_implemented() -> skip("not yet implemented"). diff --git a/erts/emulator/test/socket_test_ttest_tcp_client.erl b/erts/emulator/test/socket_test_ttest_tcp_client.erl index b5c5300fd0..f28819ca69 100644 --- a/erts/emulator/test/socket_test_ttest_tcp_client.erl +++ b/erts/emulator/test/socket_test_ttest_tcp_client.erl @@ -266,8 +266,9 @@ init(Quiet, (catch Mod:close(Sock)), exit(normal); {error, Reason} -> - ?E("connect failed: ~p", [Reason]), - exit({connect, Reason}) + ?E("connect failed: ~p" + "~n ~p", [Reason, ServerInfo]), + exit({connect, Reason, ServerInfo}) end. process_transport(Mod) when is_atom(Mod) -> diff --git a/erts/emulator/test/socket_test_ttest_tcp_client_socket.erl b/erts/emulator/test/socket_test_ttest_tcp_client_socket.erl index ca7eff4437..2fb1242028 100644 --- a/erts/emulator/test/socket_test_ttest_tcp_client_socket.erl +++ b/erts/emulator/test/socket_test_ttest_tcp_client_socket.erl @@ -34,24 +34,24 @@ start(Method, Async, Active, ServerInfo) when is_list(ServerInfo) -> Domain = local, socket_test_ttest_tcp_client:start_monitor(?MOD(Domain, Async, Method), - Active, ServerInfo); + ServerInfo, Active); start(Method, Async, Active, ServerInfo = {Addr, _}) when is_tuple(Addr) andalso (size(Addr) =:= 4) -> Domain = inet, socket_test_ttest_tcp_client:start_monitor(?MOD(Domain, Async, Method), - Active, ServerInfo); + ServerInfo, Active); start(Method, Async, Active, ServerInfo = {Addr, _}) when is_tuple(Addr) andalso (size(Addr) =:= 8) -> Domain = inet6, socket_test_ttest_tcp_client:start_monitor(?MOD(Domain, Async, Method), - Active, ServerInfo). + ServerInfo, Active). start(Method, Async, Active, ServerInfo, MsgID) when is_list(ServerInfo) -> %% This is just a simplification Domain = local, socket_test_ttest_tcp_client:start(?MOD(Domain, Async, Method), - Active, ServerInfo, MsgID); + ServerInfo, Active, MsgID); start(Method, Async, Active, ServerInfo = {Addr, _}, MsgID) when is_tuple(Addr) andalso (size(Addr) =:= 4) -> %% This is just a simplification @@ -62,14 +62,14 @@ start(Method, Async, Active, ServerInfo = {Addr, _}, MsgID) when is_tuple(Addr) andalso (size(Addr) =:= 8) -> Domain = inet6, socket_test_ttest_tcp_client:start(?MOD(Domain, Async, Method), - Active, ServerInfo, MsgID). + ServerInfo, Active, MsgID). start(Method, Async, Active, ServerInfo, MsgID, MaxOutstanding, RunTime) when is_list(ServerInfo) -> Domain = local, socket_test_ttest_tcp_client:start(false, ?MOD(Domain, Async, Method), - Active, ServerInfo, + ServerInfo, Active, MsgID, MaxOutstanding, RunTime); start(Method, Async, Active, ServerInfo = {Addr, _}, MsgID, MaxOutstanding, RunTime) @@ -77,7 +77,7 @@ start(Method, Async, Active, ServerInfo = {Addr, _}, Domain = inet, socket_test_ttest_tcp_client:start(false, ?MOD(Domain, Async, Method), - Active, ServerInfo, + ServerInfo, Active, MsgID, MaxOutstanding, RunTime); start(Method, Async, Active, ServerInfo = {Addr, _}, MsgID, MaxOutstanding, RunTime) @@ -85,7 +85,7 @@ start(Method, Async, Active, ServerInfo = {Addr, _}, Domain = inet6, socket_test_ttest_tcp_client:start(false, ?MOD(Domain, Async, Method), - Active, ServerInfo, + ServerInfo, Active, MsgID, MaxOutstanding, RunTime). start(Quiet, Async, Active, Method, ServerInfo, MsgID, MaxOutstanding, RunTime) @@ -93,7 +93,7 @@ start(Quiet, Async, Active, Method, ServerInfo, MsgID, MaxOutstanding, RunTime) Domain = local, socket_test_ttest_tcp_client:start(Quiet, ?MOD(Domain, Async, Method), - Active, ServerInfo, + ServerInfo, Active, MsgID, MaxOutstanding, RunTime); start(Quiet, Async, Active, Method, ServerInfo = {Addr, _}, MsgID, MaxOutstanding, RunTime) @@ -101,7 +101,7 @@ start(Quiet, Async, Active, Method, ServerInfo = {Addr, _}, Domain = inet, socket_test_ttest_tcp_client:start(Quiet, ?MOD(Domain, Async, Method), - Active, ServerInfo, + ServerInfo, Active, MsgID, MaxOutstanding, RunTime); start(Quiet, Async, Active, Method, ServerInfo = {Addr, _}, MsgID, MaxOutstanding, RunTime) @@ -109,7 +109,7 @@ start(Quiet, Async, Active, Method, ServerInfo = {Addr, _}, Domain = inet6, socket_test_ttest_tcp_client:start(Quiet, ?MOD(Domain, Async, Method), - Active, ServerInfo, + ServerInfo, Active, MsgID, MaxOutstanding, RunTime). stop(Pid) -> diff --git a/erts/emulator/test/socket_test_ttest_tcp_gen.erl b/erts/emulator/test/socket_test_ttest_tcp_gen.erl index 05b250e3d9..e59bd881e7 100644 --- a/erts/emulator/test/socket_test_ttest_tcp_gen.erl +++ b/erts/emulator/test/socket_test_ttest_tcp_gen.erl @@ -36,19 +36,7 @@ ]). -%% ========================================================================== - -%% getopt(Sock, Opt) when is_atom(Opt) -> -%% case inet:getopts(Sock, [Opt]) of -%% {ok, [{Opt, Value}]} -> -%% {ok, Value}; -%% {error, _} = ERROR -> -%% ERROR -%% end. - -%% setopt(Sock, Opt, Value) when is_atom(Opt) -> -%% inet:setopts(Sock, [{Opt, Value}]). - +-define(LIB, socket_test_lib). %% ========================================================================== @@ -106,12 +94,12 @@ listen(Port) -> listen(Port, #{domain => inet}). listen(Port, #{domain := Domain}) when is_integer(Port) andalso (Port >= 0) -> - Opts = [Domain, - binary, {ip, {0,0,0,0}}, {packet, raw}, {active, false}, - {buffer, 32*1024}], - case gen_tcp:listen(Port, Opts) of - {ok, Sock} -> - {ok, Sock}; + case ?LIB:which_local_host_info(Domain) of + {ok, {_, _, Addr}} -> + Opts = [Domain, + binary, {ip, Addr}, {packet, raw}, {active, false}, + {buffer, 32*1024}], + gen_tcp:listen(Port, Opts); {error, _} = ERROR -> ERROR end. diff --git a/erts/emulator/test/socket_test_ttest_tcp_server.erl b/erts/emulator/test/socket_test_ttest_tcp_server.erl index 27b561d4b7..2394dc7924 100644 --- a/erts/emulator/test/socket_test_ttest_tcp_server.erl +++ b/erts/emulator/test/socket_test_ttest_tcp_server.erl @@ -134,12 +134,18 @@ server_init(Starter, Parent, Transport, Active) -> if is_integer(PortOrPath) -> %% This is just for convenience - Addr = which_addr(), - ?I("listening on:" - "~n Addr: ~p (~s)" - "~n Port: ~w" - "~n", [Addr, inet:ntoa(Addr), PortOrPath]), - {Addr, PortOrPath}; + case Mod:sockname(LSock) of + {ok, {Addr, _}} -> + ?I("listening on:" + "~n Addr: ~p (~s)" + "~n Port: ~w" + "~n", [Addr, + inet:ntoa(Addr), + PortOrPath]), + {Addr, PortOrPath}; + {error, SNReason} -> + exit({sockname, SNReason}) + end; is_list(PortOrPath) -> ?I("listening on:" "~n Path: ~s" @@ -569,51 +575,51 @@ handler_maybe_activate(_, _, _) -> %% ========================================================================== -which_addr() -> - case inet:getifaddrs() of - {ok, IfAddrs} -> - which_addrs(inet, IfAddrs); - {error, Reason} -> - exit({getifaddrs, Reason}) - end. +%% which_addr() -> +%% case inet:getifaddrs() of +%% {ok, IfAddrs} -> +%% which_addrs(inet, IfAddrs); +%% {error, Reason} -> +%% exit({getifaddrs, Reason}) +%% end. -which_addrs(_Family, []) -> - exit({getifaddrs, not_found}); -which_addrs(Family, [{"lo", _} | IfAddrs]) -> - %% Skip - which_addrs(Family, IfAddrs); -which_addrs(Family, [{"docker" ++ _, _} | IfAddrs]) -> - %% Skip docker - which_addrs(Family, IfAddrs); -which_addrs(Family, [{"br-" ++ _, _} | IfAddrs]) -> - %% Skip docker - which_addrs(Family, IfAddrs); -which_addrs(Family, [{"en" ++ _, IfOpts} | IfAddrs]) -> - %% Maybe take this one - case which_addr(Family, IfOpts) of - {ok, Addr} -> - Addr; - error -> - which_addrs(Family, IfAddrs) - end; -which_addrs(Family, [{_IfName, IfOpts} | IfAddrs]) -> - case which_addr(Family, IfOpts) of - {ok, Addr} -> - Addr; - error -> - which_addrs(Family, IfAddrs) - end. +%% which_addrs(_Family, []) -> +%% exit({getifaddrs, not_found}); +%% which_addrs(Family, [{"lo", _} | IfAddrs]) -> +%% %% Skip +%% which_addrs(Family, IfAddrs); +%% which_addrs(Family, [{"docker" ++ _, _} | IfAddrs]) -> +%% %% Skip docker +%% which_addrs(Family, IfAddrs); +%% which_addrs(Family, [{"br-" ++ _, _} | IfAddrs]) -> +%% %% Skip docker +%% which_addrs(Family, IfAddrs); +%% which_addrs(Family, [{"en" ++ _, IfOpts} | IfAddrs]) -> +%% %% Maybe take this one +%% case which_addr(Family, IfOpts) of +%% {ok, Addr} -> +%% Addr; +%% error -> +%% which_addrs(Family, IfAddrs) +%% end; +%% which_addrs(Family, [{_IfName, IfOpts} | IfAddrs]) -> +%% case which_addr(Family, IfOpts) of +%% {ok, Addr} -> +%% Addr; +%% error -> +%% which_addrs(Family, IfAddrs) +%% end. -which_addr(_, []) -> - error; -which_addr(inet, [{addr, Addr}|_]) - when is_tuple(Addr) andalso (size(Addr) =:= 4) -> - {ok, Addr}; -which_addr(inet6, [{addr, Addr}|_]) - when is_tuple(Addr) andalso (size(Addr) =:= 8) -> - {ok, Addr}; -which_addr(Family, [_|IfOpts]) -> - which_addr(Family, IfOpts). +%% which_addr(_, []) -> +%% error; +%% which_addr(inet, [{addr, Addr}|_]) +%% when is_tuple(Addr) andalso (size(Addr) =:= 4) -> +%% {ok, Addr}; +%% which_addr(inet6, [{addr, Addr}|_]) +%% when is_tuple(Addr) andalso (size(Addr) =:= 8) -> +%% {ok, Addr}; +%% which_addr(Family, [_|IfOpts]) -> +%% which_addr(Family, IfOpts). %% ========================================================================== diff --git a/erts/emulator/test/socket_test_ttest_tcp_socket.erl b/erts/emulator/test/socket_test_ttest_tcp_socket.erl index 3aa3b2c504..9112748b4c 100644 --- a/erts/emulator/test/socket_test_ttest_tcp_socket.erl +++ b/erts/emulator/test/socket_test_ttest_tcp_socket.erl @@ -247,10 +247,16 @@ listen(Path, #{domain := local = Domain} = Opts) listen(Port, #{domain := Domain} = Opts) when is_integer(Port) andalso (Port >= 0) -> %% Bind fills in the rest - SA = #{family => Domain, - port => Port}, - Cleanup = fun() -> ok end, - do_listen(SA, Cleanup, Opts#{proto => tcp}). + case ?LIB:which_local_host_info(Domain) of + {ok, {_, _, Addr}} -> + SA = #{family => Domain, + addr => Addr, + port => Port}, + Cleanup = fun() -> ok end, + do_listen(SA, Cleanup, Opts#{proto => tcp}); + {error, _} = ERROR -> + ERROR + end. do_listen(SA, Cleanup, diff --git a/erts/emulator/test/trace_call_time_SUITE.erl b/erts/emulator/test/trace_call_time_SUITE.erl index 26f96a1766..9bab4cbbd8 100644 --- a/erts/emulator/test/trace_call_time_SUITE.erl +++ b/erts/emulator/test/trace_call_time_SUITE.erl @@ -254,8 +254,7 @@ combo(Config) when is_list(Config) -> 2 = erlang:trace_pattern({erlang, term_to_binary, '_'}, [], [local]), 2 = erlang:trace_pattern({erlang, term_to_binary, '_'}, true, [call_time]), 2 = erlang:trace_pattern({erlang, term_to_binary, '_'}, MetaMs, [{meta,MetaTracer}]), - %% not implemented - %2 = erlang:trace_pattern({erlang, term_to_binary, '_'}, true, [call_count]), + 2 = erlang:trace_pattern({erlang, term_to_binary, '_'}, true, [call_count]), 1 = erlang:trace(Self, true, [{tracer,LocalTracer} | Flags]), %% @@ -284,9 +283,7 @@ combo(Config) when is_list(Config) -> {value,{match_spec,[]}} = lists:keysearch(match_spec, 1, TraceInfoBif), {value,{meta, MetaTracer}} = lists:keysearch(meta, 1, TraceInfoBif), {value,{meta_match_spec,MetaMs}} = lists:keysearch(meta_match_spec, 1, TraceInfoBif), - %% not implemented - {value,{call_count,false}} = lists:keysearch(call_count, 1, TraceInfoBif), - %{value,{call_count,0}} = lists:keysearch(call_count, 1, TraceInfoBif), + {value,{call_count,0}} = lists:keysearch(call_count, 1, TraceInfoBif), {value,{call_time,[]}} = lists:keysearch(call_time, 1, TraceInfoBif), %% @@ -429,6 +426,8 @@ called_function(Config) when is_list(Config) -> %% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% dead_tracer(Config) when is_list(Config) -> + TracedMFAs = dead_tracer_mfas(), + Self = self(), FirstTracer = tracer(), StartTracing = fun() -> turn_on_tracing(Self) end, @@ -443,14 +442,14 @@ dead_tracer(Config) when is_list(Config) -> erlang:yield(), %% Collect and check that we only get call_time info for the current process. - Info1 = collect_all_info(), + Info1 = collect_all_info(TracedMFAs), [] = other_than_self(Info1), io:format("~p\n", [Info1]), %% Note that we have not turned off tracing for the current process, %% but that the tracer has terminated. No more call_time information should be recorded. [1,2,3] = seq(1, 3, fun(I) -> I + 1 end), - [] = collect_all_info(), + [] = collect_all_info(TracedMFAs), %% When we start a second tracer process, that tracer process must %% not inherit the tracing flags and the dead tracer (even though @@ -459,7 +458,7 @@ dead_tracer(Config) when is_list(Config) -> tell_tracer(SecondTracer, StartTracing), Seq20 = lists:seq(1, 20), Seq20 = seq(1, 20, fun(I) -> I + 1 end), - Info2 = collect_all_info(), + Info2 = collect_all_info(TracedMFAs), io:format("~p\n", [Info2]), [] = other_than_self(Info2), SecondTracer ! quit, @@ -495,9 +494,21 @@ turn_on_tracing(Pid) -> _ = now(), ok. -collect_all_info() -> - collect_all_info([{?MODULE,F,A} || {F,A} <- module_info(functions)] ++ - erlang:system_info(snifs)). +%% We want to trace functions local to this module as well as all BIFs, and for +%% the latter we need to ensure that their modules are loaded. +dead_tracer_mfas() -> + Modules = [M || {M,_F,_A} <- erlang:system_info(snifs)], + Whitelist0 = gb_sets:from_list(Modules), + Whitelist = case code:ensure_modules_loaded(Modules) of + {error, Reasons} -> + Blacklist = gb_sets:from_list([M || {M, _} <- Reasons]), + gb_sets:subtract(Whitelist0, Blacklist); + ok -> + Whitelist0 + end, + EligibleSNIFs = [MFA || {M,_F,_A}=MFA <- erlang:system_info(snifs), + gb_sets:is_element(M, Whitelist)], + [{?MODULE,F,A} || {F,A} <- module_info(functions)] ++ EligibleSNIFs. collect_all_info([MFA|T]) -> CallTime = erlang:trace_info(MFA, call_time), @@ -567,21 +578,29 @@ seq_r(Start, Stop, Succ, R) -> seq_r(Succ(Start), Stop, Succ, [Start | R]). % Check call time tracing data and print mismatches -check_trace_info(Mfa, [{Pid, C,_,_}] = Expect, Time) -> - case erlang:trace_info(Mfa, call_time) of - % Time tests are somewhat problematic. We want to know if Time (EXPECTED_TIME) and S*1000000 + Us (ACTUAL_TIME) - % is the same. - % If the ratio EXPECTED_TIME/ACTUAL_TIME is ~ 1 or if EXPECTED_TIME - ACTUAL_TIME is near zero, the test is ok. - {call_time,[{Pid,C,S,Us}]} when S >= 0, Us >= 0, abs(1 - Time/(S*1000000 + Us)) < ?R_ERROR; abs(Time - S*1000000 - Us) < ?US_ERROR -> +check_trace_info(Mfa, [{Pid, ExpectedC,_,_}] = Expect, Time) -> + {call_time,[{Pid,C,S,Us}]} = erlang:trace_info(Mfa, call_time), + {Mod, Name, Arity} = Mfa, + IsBuiltin = erlang:is_builtin(Mod, Name, Arity), + if + %% Call count on BIFs may exceed number of calls as they often trap to + %% themselves. + IsBuiltin, C >= ExpectedC, S >= 0, Us >= 0, + abs(1 - Time/(S*1000000 + Us)) < ?R_ERROR; + abs(Time - S*1000000 - Us) < ?US_ERROR -> ok; - {call_time,[{Pid,C,S,Us}]} -> + not IsBuiltin, C =:= ExpectedC, S >= 0, Us >= 0, + abs(1 - Time/(S*1000000 + Us)) < ?R_ERROR; + abs(Time - S*1000000 - Us) < ?US_ERROR -> + ok; + true -> Sum = S*1000000 + Us, - io:format("Expected ~p -> {call_time, ~p (Time ~p us)}~n - got ~w s. ~w us. = ~w us. - ~w -> delta ~w (ratio ~.2f, should be 1.0)~n", - [Mfa, Expect, Time, S, Us, Sum, Time, Sum - Time, Time/Sum]), - time_error; - Other -> - io:format("Expected ~p -> {call_time, ~p (Time ~p us)}~n - got ~p~n", [ Mfa, Expect, Time, Other]), - time_count_error + io:format("Expected ~p -> {call_time, ~p (Time ~p us)}~n - got ~w " + "s. ~w us. = ~w us. - ~w -> delta ~w (ratio ~.2f, " + "should be 1.0)~n", + [Mfa, Expect, Time, + S, Us, Sum, Time, Sum - Time, Time/Sum]), + time_error end; check_trace_info(Mfa, Expect, _) -> case erlang:trace_info(Mfa, call_time) of @@ -670,9 +689,12 @@ loop() -> quit -> ok; {Pid, execute, Fun } when is_function(Fun) -> + %% Make sure we always run with the same amount of reductions. + erlang:yield(), Pid ! {self(), answer, erlang:apply(Fun, [])}, loop(); {Pid, execute, {M, F, A}} -> + erlang:yield(), Pid ! {self(), answer, erlang:apply(M, F, A)}, loop() end. diff --git a/erts/emulator/utils/beam_makeops b/erts/emulator/utils/beam_makeops index 605a402f2a..cc21f9b5b4 100755 --- a/erts/emulator/utils/beam_makeops +++ b/erts/emulator/utils/beam_makeops @@ -1315,7 +1315,7 @@ sub combine_instruction_group { my $inc = 0; unless ($i == $#slots) { - $flags = "-no_next"; + $flags = "-micro_instruction"; my $next_offset = $label_to_offset{$next}; $inc = ($offset + $size) - $next_offset; $transfer_to_next = "I += $inc;\n" if $inc; @@ -1553,8 +1553,10 @@ sub code_gen { my $dispatch_next; my $instr_offset = $group_size + $offset + 1; - if ($flags =~ /-no_next/) { + if ($flags =~ /-micro_instruction/) { $dispatch_next = ""; + } elsif ($flags =~ /-no_next/) { + $dispatch_next = "ASSERT(!\"Fell through '$name' (-no_next)\");"; } elsif ($flags =~ /-no_prefetch/) { $dispatch_next = "\nI += $instr_offset;\n" . "ASSERT(VALID_INSTR(*I));\n" . diff --git a/erts/emulator/utils/make_tables b/erts/emulator/utils/make_tables index deee5c2344..ef0df28fc8 100755 --- a/erts/emulator/utils/make_tables +++ b/erts/emulator/utils/make_tables @@ -35,7 +35,6 @@ use File::Basename; # Output: # <-src>/erl_am.c # <-src>/erl_bif_table.c -# <-src>/erl_bif_wrap.c # <-src>/erl_dirty_bif_wrap.c # <-src>/erl_guard_bifs.c # <-src>/hipe_nbif_impl.c @@ -92,7 +91,7 @@ while (<>) { my($type, @args) = split; if ($type eq 'atom') { save_atoms(@args); - } elsif ($type eq 'bif' or $type eq 'ubif' or $type eq 'gcbif') { + } elsif ($type eq 'bif' or $type eq 'ubif' or $type eq 'hbif') { if (@args > 2) { error("$type only allows two arguments"); } @@ -124,14 +123,22 @@ while (<>) { error("invalid sched_type: $sched_type"); } - my $wrapper; - if ($type eq 'bif') { - $wrapper = "wrap_$alias"; - } else { - $wrapper = $alias; - } + my $kind; + if ($type eq 'bif') { + $kind = 'BIF_KIND_REGULAR'; + } + elsif ($type eq 'hbif') { + $kind = 'BIF_KIND_HEAVY'; + } + elsif ($type eq 'ubif') { + $kind = 'BIF_KIND_GUARD'; + } + else { + error("invalid bif_type: $type"); + } + push(@bif, ["am_$atom_alias{$mod}","am_$atom_alias{$name}",$arity, - $alias3,$wrapper,$alias]); + $alias3,$alias,$kind]); push(@bif_info, [$type, $sched_type, $alias3, $alias]); } elsif ($type eq 'dirty-cpu' or $type eq 'dirty-io' or $type eq 'dirty-cpu-test' or $type eq 'dirty-io-test') { @@ -196,7 +203,7 @@ open_file("$include/erl_bif_list.h"); my $i; for ($i = 0; $i < @bif; $i++) { # module atom, function atom, arity, C function, table index - print "BIF_LIST($bif[$i]->[0],$bif[$i]->[1],$bif[$i]->[2],$bif[$i]->[3],$bif[$i]->[5],$i)\n"; + print "BIF_LIST($bif[$i]->[0],$bif[$i]->[1],$bif[$i]->[2],$bif[$i]->[3],$bif[$i]->[4],$i)\n"; } # @@ -208,15 +215,24 @@ my $bif_size = @bif; print <<EOF; #ifndef __ERL_BIF_TABLE_H__ #define __ERL_BIF_TABLE_H__ + +#include "sys.h" + typedef void *BifFunction; +typedef enum { + BIF_KIND_REGULAR, + BIF_KIND_HEAVY, + BIF_KIND_GUARD +} BifKind; + typedef struct bif_entry { Eterm module; Eterm name; int arity; BifFunction f; - BifFunction traced; BifFunction impl; + BifKind kind; } BifEntry; typedef struct erts_gc_bif { @@ -232,7 +248,6 @@ typedef struct erts_u_bif { extern BifEntry bif_table[]; extern Export* bif_export[]; -extern const ErtsGcBif erts_gc_bifs[]; extern const ErtsUBif erts_u_bifs[]; #define BIF_SIZE $bif_size @@ -250,7 +265,6 @@ for ($i = 0; $i < @bif; $i++) { my $args = join(', ', 'Process*', 'Eterm*', 'UWord*'); my $name = $bif_info[$i]->[3]; print "Eterm $name($args);\n"; - print "Eterm wrap_$name($args);\n"; print "Eterm erts_gc_$name(Process* p, Eterm* reg, Uint live);\n" if $bif_info[$i]->[0] eq 'gcbif'; print "Eterm $bif_info[$i]->[2]($args);\n" @@ -283,25 +297,6 @@ for ($i = 0; $i < @bif; $i++) { print "};\n\n"; # -# Generate the bif wrappers file. -# - -open_file("$src/erl_bif_wrap.c"); -my $i; -includes("export.h", "sys.h", "erl_vm.h", "global.h", "erl_process.h", "bif.h", - "erl_bif_table.h", "erl_atom_table.h"); -for ($i = 0; $i < @bif; $i++) { - next if $bif[$i]->[3] eq $bif[$i]->[4]; # Skip unwrapped bifs - my $arity = $bif[$i]->[2]; - my $func = $bif_info[$i]->[3]; - print "Eterm\n"; - print "wrap_$func(Process* p, Eterm* args, UWord* I)\n"; - print "{\n"; - print " return erts_bif_trace($i, p, args, I);\n"; - print "}\n\n"; -} - -# # Generate erl_gc_bifs.c. # @@ -309,18 +304,11 @@ open_file("$src/erl_guard_bifs.c"); my $i; includes("export.h", "sys.h", "erl_vm.h", "global.h", "erl_process.h", "bif.h", "erl_bif_table.h"); -print "const ErtsGcBif erts_gc_bifs[] = {\n"; -for ($i = 0; $i < @bif; $i++) { - next unless $bif_info[$i]->[0] eq 'gcbif'; - print " {$bif[$i]->[3], erts_gc_$bif[$i]->[3], BIF_$bif[$i]->[5]},\n"; -} -print " {NULL, NULL, -1}\n"; -print "};\n"; print "const ErtsUBif erts_u_bifs[] = {\n"; for ($i = 0; $i < @bif; $i++) { next unless $bif_info[$i]->[0] eq 'ubif'; - print " {$bif[$i]->[3], BIF_$bif[$i]->[5]},\n"; + print " {$bif[$i]->[3], BIF_$bif[$i]->[4]},\n"; } print " {NULL, -1}\n"; print "};\n"; @@ -368,7 +356,7 @@ EOF my $i; for ($i = 0; $i < @bif; $i++) { print <<EOF; -Eterm nbif_impl_$bif[$i]->[5](Process *c_p, Eterm *regs); +Eterm nbif_impl_$bif[$i]->[4](Process *c_p, Eterm *regs); EOF } @@ -388,9 +376,9 @@ EOF for ($i = 0; $i < @bif; $i++) { print <<EOF; -Eterm nbif_impl_$bif[$i]->[5](Process *c_p, Eterm *regs) +Eterm nbif_impl_$bif[$i]->[4](Process *c_p, Eterm *regs) { - return $bif[$i]->[3](c_p, regs, (UWord *) bif_export\[BIF_$bif[$i]->[5]\]); + return $bif[$i]->[3](c_p, regs, (UWord *) bif_export\[BIF_$bif[$i]->[4]\]); } EOF |