From 5fc6439c88655cdeacbbc892b45dc66701cd9aa3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?John=20H=C3=B6gberg?= Date: Tue, 17 Dec 2024 13:47:35 +0100 Subject: [PATCH] erts: Introduce hibernate/0 and simplify hibernate/3 Co-authored-by: Kiko Fernandez-Reyes --- erts/emulator/beam/beam_common.c | 82 ++--------- erts/emulator/beam/bif.c | 63 ++++++-- erts/emulator/beam/emu/ops.tab | 11 +- erts/emulator/beam/emu/trace_instrs.tab | 19 ++- erts/emulator/beam/erl_gc.c | 164 +++++++-------------- erts/emulator/beam/global.h | 2 +- erts/emulator/beam/jit/arm/instr_trace.cpp | 19 +-- erts/emulator/beam/jit/arm/ops.tab | 8 +- erts/emulator/beam/jit/x86/instr_trace.cpp | 27 ++-- erts/emulator/beam/jit/x86/ops.tab | 8 +- erts/emulator/test/hibernate_SUITE.erl | 87 ++++++++++- erts/preloaded/ebin/erlang.beam | Bin 40368 -> 40420 bytes erts/preloaded/src/erlang.erl | 19 ++- 13 files changed, 264 insertions(+), 245 deletions(-) diff --git a/erts/emulator/beam/beam_common.c b/erts/emulator/beam/beam_common.c index bc25fb280c9c..be305fb65828 100644 --- a/erts/emulator/beam/beam_common.c +++ b/erts/emulator/beam/beam_common.c @@ -1612,54 +1612,19 @@ fixed_apply(Process* p, Eterm* reg, Uint arity, return ep; } -int -erts_hibernate(Process* c_p, Eterm* reg) -{ - int arity; - Eterm tmp; - Eterm module = reg[0]; - Eterm function = reg[1]; - Eterm args = reg[2]; - - if (is_not_atom(module) || is_not_atom(function)) { - /* - * No need to test args here -- done below. - */ - error: - c_p->freason = BADARG; - - error2: - reg[0] = module; - reg[1] = function; - reg[2] = args; - return 0; - } +void erts_hibernate(Process *c_p, Eterm *regs, int arity) { + const Uint max_default_arg_reg = + sizeof(c_p->def_arg_reg) / sizeof(c_p->def_arg_reg[0]); - arity = 0; - tmp = args; - while (is_list(tmp)) { - if (arity < MAX_REG) { - tmp = CDR(list_val(tmp)); - arity++; - } else { - c_p->freason = SYSTEM_LIMIT; - goto error2; - } - } - if (is_not_nil(tmp)) { /* Must be well-formed list */ - goto error; + /* Save some memory if possible. */ + if (arity <= max_default_arg_reg && c_p->arg_reg != c_p->def_arg_reg) { + erts_free(ERTS_ALC_T_ARG_REG, c_p->arg_reg); + c_p->max_arg_reg = max_default_arg_reg; + c_p->arg_reg = c_p->def_arg_reg; } - /* - * At this point, arguments are known to be good. - */ - - if (c_p->arg_reg != c_p->def_arg_reg) { - /* Save some memory */ - erts_free(ERTS_ALC_T_ARG_REG, c_p->arg_reg); - c_p->arg_reg = c_p->def_arg_reg; - c_p->max_arg_reg = sizeof(c_p->def_arg_reg)/sizeof(c_p->def_arg_reg[0]); - } + sys_memcpy(c_p->arg_reg, regs, arity * sizeof(Eterm)); + c_p->arity = arity; #ifdef USE_VM_PROBES if (DTRACE_ENABLED(process_hibernate)) { @@ -1670,30 +1635,6 @@ erts_hibernate(Process* c_p, Eterm* reg) DTRACE2(process_hibernate, process_name, mfa_buf); } #endif - /* - * Arrange for the process to be resumed at the given MFA with - * the stack cleared. - */ - c_p->arity = 3; - c_p->arg_reg[0] = module; - c_p->arg_reg[1] = function; - c_p->arg_reg[2] = args; - c_p->stop = c_p->hend - CP_SIZE; /* Keep first continuation pointer */ - - switch(erts_frame_layout) { - case ERTS_FRAME_LAYOUT_RA: - ASSERT(c_p->stop[0] == make_cp(beam_normal_exit)); - break; - case ERTS_FRAME_LAYOUT_FP_RA: - FRAME_POINTER(c_p) = &c_p->stop[0]; - ASSERT(c_p->stop[0] == make_cp(NULL)); - ASSERT(c_p->stop[1] == make_cp(beam_normal_exit)); - break; - } - - c_p->catches = 0; - c_p->return_trace_frames = 0; - c_p->i = beam_run_process; /* * If there are no waiting messages, garbage collect and @@ -1712,10 +1653,9 @@ erts_hibernate(Process* c_p, Eterm* reg) erts_atomic32_read_band_relb(&c_p->state, ~ERTS_PSFLG_ACTIVE); ASSERT(!ERTS_PROC_IS_EXITING(c_p)); } + erts_proc_unlock(c_p, ERTS_PROC_LOCK_MSGQ|ERTS_PROC_LOCK_STATUS); - c_p->current = &BIF_TRAP_EXPORT(BIF_hibernate_3)->info.mfa; c_p->flags |= F_HIBERNATE_SCHED; /* Needed also when woken! */ - return 1; } ErtsCodePtr diff --git a/erts/emulator/beam/bif.c b/erts/emulator/beam/bif.c index 5709df04b2eb..74356f5d6074 100644 --- a/erts/emulator/beam/bif.c +++ b/erts/emulator/beam/bif.c @@ -54,6 +54,7 @@ #include "jit/beam_asm.h" #include "erl_global_literals.h" #include "beam_load.h" +#include "beam_common.h" Export *erts_await_result; static Export await_exit_trap; @@ -1189,26 +1190,56 @@ BIF_RETTYPE unlink_1(BIF_ALIST_1) BIF_RETTYPE hibernate_3(BIF_ALIST_3) { - /* - * hibernate/3 is usually translated to an instruction; therefore - * this function is only called when the call could not be translated. - */ - Eterm reg[3]; + Eterm module = BIF_ARG_1, function = BIF_ARG_2, args = BIF_ARG_3; + Uint arity = 0; + + /* Check for obvious errors as a courtesy to the user; while apply/3 will + * fail later on if there's anything wrong with the arguments (e.g. the + * callee does not exist), we have more helpful context now than after + * discarding the stack. */ + if (is_not_atom(module) || is_not_atom(function)) { + BIF_ERROR(BIF_P, BADARG); + } - reg[0] = BIF_ARG_1; - reg[1] = BIF_ARG_2; - reg[2] = BIF_ARG_3; + while (is_list(args) && arity <= MAX_ARG) { + args = CDR(list_val(args)); + arity++; + } - if (erts_hibernate(BIF_P, reg)) { - /* - * If hibernate succeeded, TRAP. The process will be wait in a - * hibernated state if its state is inactive (!ERTS_PSFLG_ACTIVE); - * otherwise, continue executing (if any message was in the queue). - */ - BIF_TRAP_CODE_PTR(BIF_P, BIF_P->i, 3); + if (is_not_nil(args)) { + if (arity > MAX_ARG) { + BIF_ERROR(BIF_P, SYSTEM_LIMIT); + } + + BIF_ERROR(BIF_P, BADARG); } - return THE_NON_VALUE; + /* Discard our execution state and prepare to resume with apply/3 after + * waking up from hibernation. + * + * Note that BIF_P->current has already been set to hibernate/3 as this is + * a heavy BIF. */ + BIF_P->stop = BIF_P->hend - CP_SIZE; + BIF_P->return_trace_frames = 0; + BIF_P->catches = 0; + + switch(erts_frame_layout) { + case ERTS_FRAME_LAYOUT_RA: + ASSERT(BIF_P->stop[0] == make_cp(beam_normal_exit)); + break; + case ERTS_FRAME_LAYOUT_FP_RA: + FRAME_POINTER(BIF_P) = &BIF_P->stop[0]; + ASSERT(BIF_P->stop[0] == make_cp(NULL)); + ASSERT(BIF_P->stop[1] == make_cp(beam_normal_exit)); + break; + } + + /* Normally, the X register array is filled when trapping out. We do NOT do + * this here as there is special magic involved when trapping out after + * hibernation; `erts_hibernate` populates the process' argument registers + * and then the BIF epilogue jumps straight into do_schedule. */ + erts_hibernate(BIF_P, BIF__ARGS, 3); + BIF_TRAP_CODE_PTR(BIF_P, beam_run_process, 3); } /**********************************************************************/ diff --git a/erts/emulator/beam/emu/ops.tab b/erts/emulator/beam/emu/ops.tab index 0a5606d82948..b0f5cea82acc 100644 --- a/erts/emulator/beam/emu/ops.tab +++ b/erts/emulator/beam/emu/ops.tab @@ -877,12 +877,13 @@ call_ext u==0 u$func:erlang:yield/0 => i_yield call_ext_last u==0 u$func:erlang:yield/0 D => i_yield | deallocate_return D call_ext_only u==0 u$func:erlang:yield/0 => i_yield | return + +# The hibernate/0 BIF is an instruction # -# The hibernate/3 BIF is an instruction. -# -call_ext u==3 u$func:erlang:hibernate/3 => i_hibernate -call_ext_last u==3 u$func:erlang:hibernate/3 _D => i_hibernate -call_ext_only u==3 u$func:erlang:hibernate/3 => i_hibernate + +call_ext u==0 u$func:erlang:hibernate/0 => i_hibernate +call_ext_last u==0 u$func:erlang:hibernate/0 D => i_hibernate | deallocate_return D +call_ext_only u==0 u$func:erlang:hibernate/0 => i_hibernate | return call_ext u==0 u$func:os:perf_counter/0 => i_perf_counter diff --git a/erts/emulator/beam/emu/trace_instrs.tab b/erts/emulator/beam/emu/trace_instrs.tab index 4f109bde602f..3a4b21898e0c 100644 --- a/erts/emulator/beam/emu/trace_instrs.tab +++ b/erts/emulator/beam/emu/trace_instrs.tab @@ -120,16 +120,15 @@ i_yield() { i_hibernate() { HEAVY_SWAPOUT; - if (erts_hibernate(c_p, reg)) { - FCALLS = c_p->fcalls; - c_p->flags &= ~F_HIBERNATE_SCHED; - goto do_schedule; - } else { - HEAVY_SWAPIN; - I = handle_error(c_p, I, reg, &BIF_TRAP_EXPORT(BIF_hibernate_3)->info.mfa); - goto post_error_handling; - } - //| -no_next + + erts_hibernate(c_p, reg, 0); + + c_p->arg_reg[0] = am_ok; + c_p->arity = 1; + + $SET_CP_I_ABS($NEXT_INSTRUCTION); + c_p->current = NULL; + goto do_schedule; } // This is optimised as an instruction because diff --git a/erts/emulator/beam/erl_gc.c b/erts/emulator/beam/erl_gc.c index 20585d75f78a..b464efaa721d 100644 --- a/erts/emulator/beam/erl_gc.c +++ b/erts/emulator/beam/erl_gc.c @@ -968,22 +968,18 @@ erts_garbage_collect(Process* p, Uint need, Eterm* objv, int nobj) static int garbage_collect_hibernate(Process* p, int check_long_gc) { - Uint heap_size; - Eterm* heap; - Eterm* htop; - Uint actual_size; - char* area; + Eterm *collection_heap, *collection_htop, *final_heap; + Uint final_size, heap_size, stack_size; + Sint stack_offset, heap_offset; + char *area; Uint area_sz; - Sint offs; - int reds; - if (p->flags & F_DISABLE_GC) - ERTS_INTERNAL_ERROR("GC disabled"); + ERTS_ASSERT(!(p->flags & F_DISABLE_GC)); if (p->sig_qs.flags & FS_ON_HEAP_MSGQ) { erts_proc_lock(p, ERTS_PROC_LOCK_MSGQ); erts_proc_sig_fetch(p); - erts_proc_unlock(p, ERTS_PROC_LOCK_MSGQ); + erts_proc_unlock(p, ERTS_PROC_LOCK_MSGQ); } if (ERTS_SCHEDULER_IS_DIRTY(erts_proc_sched_data(p))) { @@ -1004,131 +1000,85 @@ garbage_collect_hibernate(Process* p, int check_long_gc) p->flags = flags; } - /* - * Preliminaries. - */ erts_atomic32_read_bor_nob(&p->state, ERTS_PSFLG_GC); ErtsGcQuickSanityCheck(p); - /* Only allow one continuation pointer. */ - ASSERT(p->stop == p->hend - CP_SIZE); - - switch (erts_frame_layout) { - case ERTS_FRAME_LAYOUT_RA: - ASSERT(p->stop[0] == make_cp(beam_normal_exit)); - break; - case ERTS_FRAME_LAYOUT_FP_RA: - ASSERT(p->stop[0] == make_cp(NULL)); - ASSERT(p->stop[1] == make_cp(beam_normal_exit)); - ASSERT(FRAME_POINTER(p) == &p->stop[0]); - break; - } - - /* - * Do it. - */ heap_size = p->heap_sz + (p->old_htop - p->old_heap) + p->mbuf_sz; - - /* Reserve place for continuation pointer and redzone */ - heap_size += S_RESERVED; - - heap = (Eterm*) ERTS_HEAP_ALLOC(ERTS_ALC_T_TMP_HEAP, - sizeof(Eterm)*heap_size); - htop = heap; - - htop = full_sweep_heaps(p, - ERTS_INVALID_HFRAG_PTR, - 1, - heap, - htop, - (char *) p->old_heap, - (char *) p->old_htop - (char *) p->old_heap, - p->arg_reg, - p->arity); + stack_size = STACK_START(p) - STACK_TOP(p); + + /* Allocate a new heap and move all living terms to it. Note that this + * temporary heap does not need to include space for the stack. */ + collection_heap = (Eterm*)ERTS_HEAP_ALLOC(ERTS_ALC_T_TMP_HEAP, + heap_size * sizeof(Eterm)); + collection_htop = full_sweep_heaps(p, + ERTS_INVALID_HFRAG_PTR, + 1, + collection_heap, + collection_heap, + (char*)p->old_heap, + (char*)p->old_htop - (char*)p->old_heap, + p->arg_reg, + p->arity); #ifdef HARDDEBUG disallow_heap_frag_ref_in_heap(p, heap, htop); #endif - erts_deallocate_young_generation(p); - - p->heap = heap; - p->high_water = htop; - p->htop = htop; - p->hend = p->heap + heap_size; - p->stop = p->hend - CP_SIZE; - p->heap_sz = heap_size; - - heap_size = actual_size = p->htop - p->heap; + heap_size = collection_htop - collection_heap; + final_size = heap_size + S_RESERVED + stack_size; - /* Reserve place for continuation pointer and redzone */ - heap_size += S_RESERVED; + /* Move the heap to its final destination, compacting it together with the + * stack. + * + * IMPORTANT: We have garbage collected to a temporary heap and then copy + * the result to a newly allocated heap of exact size. + * + * !! This is intentional !! Garbage collecting as usual and then shrinking + * the heap by reallocating it caused serious fragmentation problems when + * large amounts of processes were hibernated. */ + final_heap = ERTS_HEAP_ALLOC(ERTS_ALC_T_HEAP, sizeof(Eterm) * final_size); + sys_memcpy(final_heap, collection_heap, heap_size * sizeof(Eterm)); + sys_memcpy(&final_heap[final_size - stack_size], + p->stop, + stack_size * sizeof(Eterm)); - FLAGS(p) &= ~F_FORCE_GC; - p->live_hf_end = ERTS_INVALID_HFRAG_PTR; + stack_offset = final_heap - p->stop; + heap_offset = final_heap - collection_heap; - /* - * Move the heap to its final destination. - * - * IMPORTANT: We have garbage collected to a temporary heap and - * then copy the result to a newly allocated heap of exact size. - * This is intentional and important! Garbage collecting as usual - * and then shrinking the heap by reallocating it caused serious - * fragmentation problems when large amounts of processes were - * hibernated. - */ + area = (char *) collection_heap; + area_sz = heap_size * sizeof(Eterm); - ASSERT(actual_size < p->heap_sz); + erts_deallocate_young_generation(p); + erts_free(ERTS_ALC_T_TMP_HEAP, collection_heap); - 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->heap = final_heap; + p->heap_sz = final_size; + p->high_water = &final_heap[heap_size]; + p->htop = &final_heap[heap_size]; + p->hend = &final_heap[final_size]; + p->stop = &p->heap[final_size - stack_size]; - p->hend = heap + heap_size; - p->stop = p->hend - CP_SIZE; - - switch (erts_frame_layout) { - case ERTS_FRAME_LAYOUT_RA: - p->stop[0] = make_cp(beam_normal_exit); - break; - case ERTS_FRAME_LAYOUT_FP_RA: - p->stop[0] = make_cp(NULL); - p->stop[1] = make_cp(beam_normal_exit); - FRAME_POINTER(p) = &p->stop[0]; - break; - } - - offs = heap - p->heap; - area = (char *) p->heap; - area_sz = ((char *) p->htop) - area; - offset_heap(heap, actual_size, offs, area, area_sz); - p->high_water = heap + (p->high_water - p->heap); - offset_rootset(p, offs, 0, area, area_sz, p->arg_reg, p->arity); - p->htop = heap + actual_size; - p->heap = heap; - p->heap_sz = heap_size; + FLAGS(p) &= ~F_FORCE_GC; + p->live_hf_end = ERTS_INVALID_HFRAG_PTR; + offset_heap(final_heap, heap_size, heap_offset, area, area_sz); + offset_rootset(p, heap_offset, stack_offset, area, area_sz, + p->arg_reg, p->arity); #ifdef CHECK_FOR_HOLES p->last_htop = p->htop; - p->last_mbuf = 0; -#endif + p->last_mbuf = NULL; +#endif #ifdef DEBUG p->last_old_htop = NULL; #endif - /* - * Finishing. - */ - ErtsGcQuickSanityCheck(p); p->flags |= F_HIBERNATED; - erts_atomic32_read_band_nob(&p->state, ~ERTS_PSFLG_GC); - reds = gc_cost(actual_size, actual_size); - return reds; + return gc_cost(final_size, final_size); } void diff --git a/erts/emulator/beam/global.h b/erts/emulator/beam/global.h index d7bb35378d1c..921bc112442b 100644 --- a/erts/emulator/beam/global.h +++ b/erts/emulator/beam/global.h @@ -1552,7 +1552,7 @@ Uint erts_current_reductions(Process* current, Process *p); int erts_print_system_version(fmtfn_t to, void *arg, Process *c_p); -int erts_hibernate(Process* c_p, Eterm* reg); +void erts_hibernate(Process *c_p, Eterm *regs, int arity); ERTS_GLB_FORCE_INLINE int erts_is_literal(Eterm tptr, Eterm *ptr); diff --git a/erts/emulator/beam/jit/arm/instr_trace.cpp b/erts/emulator/beam/jit/arm/instr_trace.cpp index f60dda7619a4..9c78432b3547 100644 --- a/erts/emulator/beam/jit/arm/instr_trace.cpp +++ b/erts/emulator/beam/jit/arm/instr_trace.cpp @@ -201,26 +201,19 @@ void BeamModuleAssembler::emit_i_return_to_trace() { } void BeamModuleAssembler::emit_i_hibernate() { - Label error = a.newLabel(); - - emit_enter_runtime(3); + emit_enter_runtime(0); a.mov(ARG1, c_p); load_x_reg_array(ARG2); - runtime_call<2>(erts_hibernate); + mov_imm(ARG3, 0); + runtime_call<3>(erts_hibernate); - emit_leave_runtime(3); - - a.cbz(ARG1, error); + emit_leave_runtime(0); a.ldr(TMP1.w(), arm::Mem(c_p, offsetof(Process, flags))); a.and_(TMP1, TMP1, imm(~F_HIBERNATE_SCHED)); a.str(TMP1.w(), arm::Mem(c_p, offsetof(Process, flags))); - a.b(resolve_fragment(ga->get_do_schedule(), disp128MB)); - a.bind(error); - emit_raise_exception(&BIF_TRAP_EXPORT(BIF_hibernate_3)->info.mfa); - mark_unreachable(); + mov_imm(XREG0, am_ok); + fragment_call(ga->get_dispatch_return()); } diff --git a/erts/emulator/beam/jit/arm/ops.tab b/erts/emulator/beam/jit/arm/ops.tab index bfd23151c99e..fb75fc3ccb04 100644 --- a/erts/emulator/beam/jit/arm/ops.tab +++ b/erts/emulator/beam/jit/arm/ops.tab @@ -656,11 +656,11 @@ call_ext_last u==0 u$func:erlang:yield/0 D => i_yield | deallocate D | return call_ext_only u==0 u$func:erlang:yield/0 => i_yield | return # -# The hibernate/3 BIF is an instruction. +# The hibernate/0 BIF is an instruction. # -call_ext u==3 u$func:erlang:hibernate/3 => i_hibernate -call_ext_last u==3 u$func:erlang:hibernate/3 _D => i_hibernate -call_ext_only u==3 u$func:erlang:hibernate/3 => i_hibernate +call_ext u==0 u$func:erlang:hibernate/0 => i_hibernate +call_ext_last u==0 u$func:erlang:hibernate/0 D => i_hibernate | deallocate D | return +call_ext_only u==0 u$func:erlang:hibernate/0 => i_hibernate | return call_ext u==0 u$func:os:perf_counter/0 => i_perf_counter diff --git a/erts/emulator/beam/jit/x86/instr_trace.cpp b/erts/emulator/beam/jit/x86/instr_trace.cpp index 7a867679b3fa..8c0e652ba435 100644 --- a/erts/emulator/beam/jit/x86/instr_trace.cpp +++ b/erts/emulator/beam/jit/x86/instr_trace.cpp @@ -234,23 +234,28 @@ void BeamModuleAssembler::emit_i_return_to_trace() { } void BeamModuleAssembler::emit_i_hibernate() { - Label error = a.newLabel(); - - emit_enter_runtime(); + emit_enter_runtime(); a.mov(ARG1, c_p); load_x_reg_array(ARG2); - runtime_call<2>(erts_hibernate); + mov_imm(ARG3, 0); + runtime_call<3>(erts_hibernate); - emit_leave_runtime(); - - a.test(RET, RET); - a.je(error); + emit_leave_runtime(); a.and_(x86::dword_ptr(c_p, offsetof(Process, flags)), imm(~F_HIBERNATE_SCHED)); - a.jmp(resolve_fragment(ga->get_do_schedule())); - a.bind(error); - emit_raise_exception(&BIF_TRAP_EXPORT(BIF_hibernate_3)->info.mfa); + a.mov(getXRef(0), imm(am_ok)); +#ifdef NATIVE_ERLANG_STACK + fragment_call(resolve_fragment(ga->get_dispatch_return())); +#else + Label next = a.newLabel(); + + a.lea(ARG3, x86::qword_ptr(next)); + a.jmp(resolve_fragment(ga->get_dispatch_return())); + + a.align(AlignMode::kCode, 8); + a.bind(next); +#endif } diff --git a/erts/emulator/beam/jit/x86/ops.tab b/erts/emulator/beam/jit/x86/ops.tab index 1d6e0b726de0..48f4a0b29d79 100644 --- a/erts/emulator/beam/jit/x86/ops.tab +++ b/erts/emulator/beam/jit/x86/ops.tab @@ -602,11 +602,11 @@ call_ext_last u==0 u$func:erlang:yield/0 D => i_yield | deallocate D | return call_ext_only u==0 u$func:erlang:yield/0 => i_yield | return # -# The hibernate/3 BIF is an instruction. +# The hibernate/0 BIF is an instruction. # -call_ext u==3 u$func:erlang:hibernate/3 => i_hibernate -call_ext_last u==3 u$func:erlang:hibernate/3 _D => i_hibernate -call_ext_only u==3 u$func:erlang:hibernate/3 => i_hibernate +call_ext u==0 u$func:erlang:hibernate/0 => i_hibernate +call_ext_last u==0 u$func:erlang:hibernate/0 D => i_hibernate | deallocate D | return +call_ext_only u==0 u$func:erlang:hibernate/0 => i_hibernate | return call_ext u==0 u$func:os:perf_counter/0 => i_perf_counter diff --git a/erts/emulator/test/hibernate_SUITE.erl b/erts/emulator/test/hibernate_SUITE.erl index 81b56ba7f84b..6155408cb947 100644 --- a/erts/emulator/test/hibernate_SUITE.erl +++ b/erts/emulator/test/hibernate_SUITE.erl @@ -25,7 +25,7 @@ -export([all/0, suite/0, basic/1,dynamic_call/1,min_heap_size/1,bad_args/1, messages_in_queue/1,undefined_mfa/1,no_heap/1, - wake_up_and_bif_trap/1]). + wake_up_and_bif_trap/1,in_place/1]). %% Used by test cases. -export([basic_hibernator/1,dynamic_call_hibernator/2,messages_in_queue_restart/2, @@ -37,7 +37,7 @@ suite() -> all() -> [basic, dynamic_call, min_heap_size, bad_args, messages_in_queue, - undefined_mfa, no_heap, wake_up_and_bif_trap]. + undefined_mfa, no_heap, wake_up_and_bif_trap, in_place]. %%% %%% Testing the basic functionality of erlang:hibernate/3. @@ -372,6 +372,89 @@ characters_to_list_trap(Parent) -> unicode:characters_to_list(Bin), Parent ! {ok, self()}. +%% Tests the in-place variant, hibernate/0 +in_place(_Config) -> + in_place_helper("Minimal test", + fun(F) -> F() end, 16), + + in_place_helper("Deep stack test", + fun(F) -> + (fun S(0) -> F(); S(N) -> S(N - 1), ok end)(512) + end, 530), + + in_place_helper("Heavy data test", + fun(F) -> + Data = lists:seq(1, 1024), + F(), + lists:foreach(fun(_) -> ok end, Data) + end, 2100), + + in_place_helper("Heavy data and stack test", + fun(F) -> + Data = lists:seq(1, 1024), + (fun S(0) -> F(); S(N) -> S(N - 1), ok end)(512), + lists:foreach(fun(_) -> ok end, Data) + end, 2600), + + ok. + +in_place_helper(Description, Fun, Limit) -> + Parent = self(), + Token = make_ref(), + + {Reference, RefMon} = + spawn_opt(fun() -> + Fun(fun() -> + Parent ! {ready, Token}, + receive {done, Token} -> ok end + end) + end, [link, monitor]), + {Hibernator, HibMon} = + spawn_opt(fun() -> + Fun(fun() -> + Parent ! {ready, Token}, + erlang:hibernate(), + Parent ! {awoken, Token}, + receive {done, Token} -> ok end + end) + end, [link, monitor]), + + receive {ready, Token} -> ok end, + [{status, waiting}, {_, RefSize}] = + process_info(Reference, [status, total_heap_size]), + Reference ! {done, Token}, + receive {'DOWN', RefMon, _, _, _} -> ok end, + + receive {ready, Token} -> ok end, + [{status, waiting}, {_, HiberSize}] = + process_info(Hibernator, [status, total_heap_size]), + + %% Sleep a while, we have a small race between the ready message and + %% hibernation. + ct:sleep(1000), + + %% If we did not succeed in hibernating, the hibernator will have sent a + %% message saying it has awoken before we poke it with a done message. + receive + {awoken, Token} -> + ct:fail("Failed to sleep on hibernate/0") + after + 0 -> ok + end, + + Hibernator ! {done, Token}, + receive {awoken, Token} -> ok end, + + receive {'DOWN', HibMon, _, _, _} -> ok end, + + ct:log("~ts~n\tReference size ~p~n\tHibernated size ~p~n", + [Description, RefSize, HiberSize]), + + true = HiberSize < Limit, %Assertion, whitebox. + true = HiberSize =< RefSize, %Assertion. + + ok. + %% %% Misc %% diff --git a/erts/preloaded/ebin/erlang.beam b/erts/preloaded/ebin/erlang.beam index 2315ec378407aa3bc81f90fa042e2233e70b8263..3e5a61d6d4a956781fab1294cb47e4faf2d874ed 100644 GIT binary patch delta 22078 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 M(5`LU?VnHjKmA?|Bme*a delta 22458 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 diff --git a/erts/preloaded/src/erlang.erl b/erts/preloaded/src/erlang.erl index 304f6bdcc7db..508c7660cd4e 100644 --- a/erts/preloaded/src/erlang.erl +++ b/erts/preloaded/src/erlang.erl @@ -441,7 +441,7 @@ A list of binaries. This datatype is useful to use together with -export([get_module_info/1, group_leader/0]). -export([group_leader/2]). -export([halt/0, halt/1, halt/2, - has_prepared_code_on_load/1, hibernate/3]). + has_prepared_code_on_load/1, hibernate/0, hibernate/3]). -export([insert_element/3]). -export([integer_to_binary/1, integer_to_list/1]). -export([iolist_size/1, iolist_to_binary/1, iolist_to_iovec/1]). @@ -3304,6 +3304,23 @@ halt(_, _) -> has_prepared_code_on_load(_PreparedCode) -> erlang:nif_error(undefined). +%% hibernate/0 +-doc """ +Puts the calling process into a wait state where its memory allocation has been +reduced as much as possible. This is useful if the process does not expect to +receive any messages soon. + +The process is awakened when a message is sent to it, and control resumes +normally to the caller. It does not discard the call stack like +`erlang:hibernate/3`. +""". +-doc #{ group => processes }. +-spec hibernate() -> ok. +hibernate() -> + %% This function is a fallback used on apply/3; the loader turns this + %% remote call of ourselves into a special instruction. + erlang:hibernate(). + %% hibernate/3 -doc """ Puts the calling process into a wait state where its memory allocation has been