## save-heap-to-disk.pkg
# Compiled by:
#
src/lib/std/src/standard-core.sublibstipulate
package at = run_at__premicrothread; # run_at__premicrothread is from
src/lib/std/src/nj/run-at--premicrothread.pkg package ci = mythryl_callable_c_library_interface; # mythryl_callable_c_library_interface is from
src/lib/std/src/unsafe/mythryl-callable-c-library-interface.pkg package fil = file__premicrothread; # file__premicrothread is from
src/lib/std/src/posix/file--premicrothread.pkg package is = interprocess_signals; # interprocess_signals is from
src/lib/std/src/nj/interprocess-signals.pkg package rt = runtime; # runtime is from
src/lib/core/init/runtime.pkg package wp = winix_process__premicrothread; # winix_process__premicrothread is from
src/lib/std/src/posix/winix-process--premicrothread.pkg package wt = winix_types; # winix_types is from
src/lib/std/src/posix/winix-types.pkg #
Pair(X,Y) = PAIR (X, Y);
#
run_functions_scheduled_to_run = at::run_functions_scheduled_to_run;
herein
package save_heap_to_disk
: (weak) Save_Heap_To_Disk # Save_Heap_To_Disk is from
src/lib/std/src/nj/save-heap-to-disk.api {
Fork_Result = AM_PARENT
| AM_CHILD;
#
package process = winix_process__premicrothread;
fun cfun fun_name
=
ci::find_c_function { lib_name => "heap", fun_name };
#
###############################################################
# The functions in this package should be called only on a
# quiescient system with only one active posix thread, so
# our usual latency-minimization reasons for indirecting
# syscalls through other posix threads do not apply.
#
# Consequently I'm not taking the time and effort to switch it
# over from using find_c_function() to using find_c_function'().
# -- 2012-04-21 CrT
##############################################################
# Actually, we may need to revisit this issue -- shutting down
# the support hostthreads may be nontrivial, and it is not clear
# that it matters.
# -- 2012-06-04 CrT
##############################################################
export_heap
=
cfun "export_heap" # "export_heap" def in src/c/lib/heap/export-heap.c
:
String -> Bool;
# We need the pair wrapper type to make sure that the second argument will
# be fully wrapped when it is passed to the run-time system.
# [also see wrap-export.pkg]
#
Cmdt = Pair( String, List( String ) ) -> wt::process::Status; # "Cmdt" may be "Command_Type"
spawn_to_disk'
=
cfun "spawn_to_disk" # "spawn_to_disk" def in src/c/lib/heap/libmythryl-heap.c
:
(String, Cmdt) -> Void;
fun raise_null_filename_exception ()
=
raise exception rt::RUNTIME_EXCEPTION ("empty heap file name", NULL);
fun fork_to_disk file_name # In practice this is currently called only in
src/lib/core/internal/make-mythryld-executable.pkg = # unless you count
src/lib/tk/src/njml.pkg {
# file__premicrothread::say {. "fork_to_disk/AAA (save-heap-to-disk.pkg)\n"; };
# print "fork_to_disk/AAA (save-heap-to-disk.pkg)\n";
if (file_name == "") raise_null_filename_exception (); fi; # Does not return.
#
log::note {. "fork_to_disk doing at::FORK_TO_DISK"; };
run_functions_scheduled_to_run at::FORK_TO_DISK; # Shutting down system prior to writing heap image.
log::note {. "fork_to_disk (NOT) doing at::SHUTDOWN_PHASE_1_USER_HOOKS"; };
# run_functions_scheduled_to_run at::SHUTDOWN_PHASE_1_USER_HOOKS; # We don't do this because we're not shutting down -- main thread will continue execution.
# print "fork_to_disk turning off log::note by doing log::log_note__hook := NULL; --save-heap-to-disk.pkg\n";
log::note {. "fork_to_disk turning off log::note by doing log::log_note__hook := NULL;"; };
log::log_note__hook := NULL; # We do this early because user-supplied thunks passed to log::note may start crashing
log::log_warn__hook := NULL; # about this point due to dependence on facilities being shut down.
# log::log_fatal__hook := NULL; # Commented out because log_fatal__hook is no longer Null_Or().
# We're going to need to unredirect system calls because when the forked image
# initially comes up our support hostthreads will not yet be running and consequently
# redirected system calls won't be working at that point.
# log::note {. "fork_to_disk doing SHUTDOWN_PHASE_2_UNREDIRECT_SYSCALLS"; };
# run_functions_scheduled_to_run at::SHUTDOWN_PHASE_2_UNREDIRECT_SYSCALLS;
# I don't see any need to actually shut down our support hostthreads however:
# log::note {. "fork_to_disk doing at::SHUTDOWN_PHASE_4_STOP_SUPPORT_HOSTTHREADS"; };
run_functions_scheduled_to_run at::SHUTDOWN_PHASE_4_STOP_SUPPORT_HOSTTHREADS; # Threadkit uses this to shut down its hostthreads etc.
log::note {. "fork_to_disk doing at::SHUTDOWN_PHASE_5_ZERO_COMPILE_STATISTICS"; };
# run_functions_scheduled_to_run at::SHUTDOWN_PHASE_5_ZERO_COMPILE_STATISTICS; #
run_functions_scheduled_to_run at::SHUTDOWN_PHASE_6_FLUSH_OPEN_FILES;
#
if (not (export_heap file_name))
#
AM_PARENT; # We're the parent process, back from saving the heap to disk.
else
# # We're the "child" process, just woken up from the on-disk heap image.
#
fil::current_thread_info__hook := NULL; # We do this as early as practical because if a log::note() call creeps in before we do this
# we are liable due to segfault due to get_current_microthread() accessing an uninitialized register.
run_functions_scheduled_to_run at::STARTUP_PHASE_1_RESET_STATE_VARIABLES;
run_functions_scheduled_to_run at::STARTUP_PHASE_2_REOPEN_MYTHRYL_LOG;
# I think this crashes us: log::note {. "fork_to_disk doing STARTUP_PHASE_3_REOPEN_USER_LOGS -- save-heap-to-disk.pkg"; };
run_functions_scheduled_to_run at::STARTUP_PHASE_3_REOPEN_USER_LOGS;
# I think this crashes us: log::note {. "fork_to_disk doing STARTUP_PHASE_4_MAKE_STDIN_STDOUT_AND_STDERR -- save-heap-to-disk.pkg"; };
run_functions_scheduled_to_run at::STARTUP_PHASE_4_MAKE_STDIN_STDOUT_AND_STDERR;
# I think this crashes us: log::note {. "fork_to_disk doing STARTUP_PHASE_5_CLOSE_STALE_OUTPUT_STREAMS -- save-heap-to-disk.pkg"; };
run_functions_scheduled_to_run at::STARTUP_PHASE_5_CLOSE_STALE_OUTPUT_STREAMS;
log::note {. "fork_to_disk doing STARTUP_PHASE_6_INITIALIZE_POSIX_INTERPROCESS_SIGNAL_HANDLER_TABLE -- save-heap-to-disk.pkg"; };
run_functions_scheduled_to_run at::STARTUP_PHASE_6_INITIALIZE_POSIX_INTERPROCESS_SIGNAL_HANDLER_TABLE; # (interprocess-signals.pkg)
log::note {. "fork_to_disk doing STARTUP_PHASE_7_RESET_POSIX_INTERPROCESS_SIGNAL_HANDLER_TABLE -- save-heap-to-disk.pkg"; };
run_functions_scheduled_to_run at::STARTUP_PHASE_7_RESET_POSIX_INTERPROCESS_SIGNAL_HANDLER_TABLE; # (interprocess-signals.pkg)
log::note {. "fork_to_disk doing STARTUP_PHASE_8_RESET_COMPILER_STATISTICS -- save-heap-to-disk.pkg"; };
run_functions_scheduled_to_run at::STARTUP_PHASE_8_RESET_COMPILER_STATISTICS; # (compile-statistics.pkg)
log::note {. "fork_to_disk doing STARTUP_PHASE_9_RESET_CPU_AND_WALLCLOCK_TIMERS -- save-heap-to-disk.pkg"; };
run_functions_scheduled_to_run at::STARTUP_PHASE_9_RESET_CPU_AND_WALLCLOCK_TIMERS; # (runtime-internals.pkg)
log::note {. "fork_to_disk doing STARTUP_PHASE_10_START_NEW_DLOPEN_ERA -- save-heap-to-disk.pkg"; };
run_functions_scheduled_to_run at::STARTUP_PHASE_10_START_NEW_DLOPEN_ERA; # (linkage-dlopen.pkg)
# print "fork_to_disk doing at::STARTUP_PHASE_11_START_SUPPORT_HOSTTHREADS; --save-heap-to-disk.pkg\n";
log::note {. "fork_to_disk doing STARTUP_PHASE_11_START_SUPPORT_HOSTTHREADS -- save-heap-to-disk.pkg"; };
run_functions_scheduled_to_run at::STARTUP_PHASE_11_START_SUPPORT_HOSTTHREADS;
log::note {. "fork_to_disk doing STARTUP_PHASE_12_START_THREAD_SCHEDULER -- save-heap-to-disk.pkg"; };
run_functions_scheduled_to_run at::STARTUP_PHASE_12_START_THREAD_SCHEDULER;
log::note {. "fork_to_disk doing STARTUP_PHASE_13_REDIRECT_SYSCALLS -- save-heap-to-disk.pkg"; };
run_functions_scheduled_to_run at::STARTUP_PHASE_13_REDIRECT_SYSCALLS;
log::note {. "fork_to_disk doing STARTUP_PHASE_14_START_BASE_IMPS -- save-heap-to-disk.pkg"; };
run_functions_scheduled_to_run at::STARTUP_PHASE_14_START_BASE_IMPS;
log::note {. "fork_to_disk doing STARTUP_PHASE_15_START_XKIT_IMPS -- save-heap-to-disk.pkg"; };
run_functions_scheduled_to_run at::STARTUP_PHASE_15_START_XKIT_IMPS;
log::note {. "fork_to_disk doing STARTUP_PHASE_16_OF_HEAP_MADE_BY_FORK_TO_DISK -- save-heap-to-disk.pkg"; };
run_functions_scheduled_to_run at::STARTUP_PHASE_16_OF_HEAP_MADE_BY_FORK_TO_DISK; # This runs user hooks specific to fork-to-disk images.
log::note {. "fork_to_disk doing STARTUP_PHASE_15_STARTUP_PHASE_17_USER_HOOKS -- save-heap-to-disk.pkg"; };
run_functions_scheduled_to_run at::STARTUP_PHASE_17_USER_HOOKS; # unused by default, available for users
#
AM_CHILD;
fi;
};
stipulate
#
# This is the wrapper for executable heap images.
#
# We need the PAIR wrapper to make sure that
# the second argument will be fully wrapped
# when it is passed to the run-time system:
#
fun wrap f (PAIR args) # We will arrive here (only) when starting up a heap image created by spawn_to_disk() from
src/lib/std/src/nj/save-heap-to-disk.pkg = # where spawn_to_disk() is mainly called from sh/_build-an-executable-mythryl-heap-image
{
fil::current_thread_info__hook := NULL; # We do this as early as practical because if a log::note() call creeps in before we do this
# we are liable due to segfault due to get_current_microthread() accessing an uninitialized register.
# I think this crashes us: log::note {. print "wrap doing STARTUP_PHASE_1_RESET_STATE_VARIABLES -- save-heap-to-disk.pkg"; };
run_functions_scheduled_to_run at::STARTUP_PHASE_1_RESET_STATE_VARIABLES;
# I think this crashes us: log::note {. "wrap doing STARTUP_PHASE_2_REOPEN_MYTHRYL_LOG -- save-heap-to-disk.pkg"; };
run_functions_scheduled_to_run at::STARTUP_PHASE_2_REOPEN_MYTHRYL_LOG;
# I think this crashes us: log::note {. "wrap doing STARTUP_PHASE_3_REOPEN_USER_LOGS -- save-heap-to-disk.pkg"; };
run_functions_scheduled_to_run at::STARTUP_PHASE_3_REOPEN_USER_LOGS;
# I think this crashes us: log::note {. "wrap doing STARTUP_PHASE_4_MAKE_STDIN_STDOUT_AND_STDERR -- save-heap-to-disk.pkg"; };
run_functions_scheduled_to_run at::STARTUP_PHASE_4_MAKE_STDIN_STDOUT_AND_STDERR;
# I think this crashes us: log::note {. "wrap doing STARTUP_PHASE_5_CLOSE_STALE_OUTPUT_STREAMS -- save-heap-to-disk.pkg"; };
run_functions_scheduled_to_run at::STARTUP_PHASE_5_CLOSE_STALE_OUTPUT_STREAMS;
log::note {. "wrap doing STARTUP_PHASE_6_INITIALIZE_POSIX_INTERPROCESS_SIGNAL_HANDLER_TABLE -- save-heap-to-disk.pkg"; };
run_functions_scheduled_to_run at::STARTUP_PHASE_6_INITIALIZE_POSIX_INTERPROCESS_SIGNAL_HANDLER_TABLE; # (interprocess-signals.pkg)
log::note {. "wrap doing STARTUP_PHASE_7_RESET_POSIX_INTERPROCESS_SIGNAL_HANDLER_TABLE -- save-heap-to-disk.pkg"; };
run_functions_scheduled_to_run at::STARTUP_PHASE_7_RESET_POSIX_INTERPROCESS_SIGNAL_HANDLER_TABLE; # (interprocess-signals.pkg)
log::note {. "wrap doing STARTUP_PHASE_8_RESET_COMPILER_STATISTICS -- save-heap-to-disk.pkg"; };
run_functions_scheduled_to_run at::STARTUP_PHASE_8_RESET_COMPILER_STATISTICS; # (compile-statistics.pkg)
log::note {. "wrap doing STARTUP_PHASE_9_RESET_CPU_AND_WALLCLOCK_TIMERS -- save-heap-to-disk.pkg"; };
run_functions_scheduled_to_run at::STARTUP_PHASE_9_RESET_CPU_AND_WALLCLOCK_TIMERS; # (runtime-internals.pkg)
log::note {. "wrap doing STARTUP_PHASE_10_START_NEW_DLOPEN_ERA -- save-heap-to-disk.pkg"; };
run_functions_scheduled_to_run at::STARTUP_PHASE_10_START_NEW_DLOPEN_ERA;
log::note {. "wrap doing STARTUP_PHASE_11_START_SUPPORT_HOSTTHREADS -- save-heap-to-disk.pkg"; };
# print "wrap doing at::STARTUP_PHASE_11_START_SUPPORT_HOSTTHREADS; --save-heap-to-disk.pkg\n";
run_functions_scheduled_to_run at::STARTUP_PHASE_11_START_SUPPORT_HOSTTHREADS;
log::note {. "wrap doing STARTUP_PHASE_12_START_THREAD_SCHEDULER -- save-heap-to-disk.pkg"; };
run_functions_scheduled_to_run at::STARTUP_PHASE_12_START_THREAD_SCHEDULER;
log::note {. "wrap doing STARTUP_PHASE_13_REDIRECT_SYSCALLS -- save-heap-to-disk.pkg"; };
run_functions_scheduled_to_run at::STARTUP_PHASE_13_REDIRECT_SYSCALLS;
log::note {. "wrap doing STARTUP_PHASE_14_START_BASE_IMPS -- save-heap-to-disk.pkg"; };
run_functions_scheduled_to_run at::STARTUP_PHASE_14_START_BASE_IMPS;
log::note {. "wrap doing STARTUP_PHASE_15_START_XKIT_IMPS -- save-heap-to-disk.pkg"; };
run_functions_scheduled_to_run at::STARTUP_PHASE_15_START_XKIT_IMPS;
log::note {. "wrap doing STARTUP_PHASE_16_OF_HEAP_MADE_BY_SPAWN_TO_DISK -- save-heap-to-disk.pkg\n"; };
run_functions_scheduled_to_run at::STARTUP_PHASE_16_OF_HEAP_MADE_BY_SPAWN_TO_DISK; # This runs user hooks specific to spawn-to-disk images.
log::note {. "wrap doing STARTUP_PHASE_17_USER_HOOKS -- save-heap-to-disk.pkg\n"; };
run_functions_scheduled_to_run at::STARTUP_PHASE_17_USER_HOOKS; # unused by default, available for users
#
wp::exit_x( (f args)
except
exn = wp::failure
);
};
herein
fun spawn_to_disk (file_name, f)
=
{ if (file_name == "") raise_null_filename_exception (); fi; # Does not return.
#
is::mask_signals is::MASK_ALL;
#
log::note {. "spawn_to_disk doing SPAWN_TO_DISK"; };
run_functions_scheduled_to_run at::SPAWN_TO_DISK; # Shutting down system prior to writing heap image.
log::note {. "spawn_to_disk doing SHUTDOWN_PHASE_1_USER_HOOKS"; };
# print "spawn_to_disk doing at::SHUTDOWN_PHASE_1_USER_HOOKS; --save-heap-to-disk.pkg\n";
run_functions_scheduled_to_run at::SHUTDOWN_PHASE_1_USER_HOOKS;
# print "spawn_to_disk turning off log::note by doing log::log_note__hook := NULL; --save-heap-to-disk.pkg\n";
log::note {. "spawn_to_disk turning off log::note by doing log::log_note__hook := NULL;"; };
# Following stuff commented out because I'm not convinced the game is worth the candle: -- 2012-09-23 CrT
# log::log_note__hook := NULL; # We do this early because user-supplied thunks passed to log::note may start crashing
# log::log_warn__hook := NULL; # about this point due to dependence on facilities being shut down.
# log::log_fatal__hook := NULL;
# log::note {. "spawn_to_disk doing SHUTDOWN_PHASE_2_UNREDIRECT_SYSCALLS"; };
# run_functions_scheduled_to_run at::SHUTDOWN_PHASE_2_UNREDIRECT_SYSCALLS;
# log::note {. "spawn_to_disk doing SHUTDOWN_PHASE_3_STOP_THREAD_SCHEDULER"; };
# run_functions_scheduled_to_run at::SHUTDOWN_PHASE_3_STOP_THREAD_SCHEDULER;
# log::note {. "spawn_to_disk doing SHUTDOWN_PHASE_4_STOP_SUPPORT_HOSTTHREADS"; };
# run_functions_scheduled_to_run at::SHUTDOWN_PHASE_4_STOP_SUPPORT_HOSTTHREADS; # Threadkit uses this to shut down its hostthreads etc.
# log::note {. "spawn_to_disk doing at::SHUTDOWN_PHASE_5_ZERO_COMPILE_STATISTICS"; };
# run_functions_scheduled_to_run at::SHUTDOWN_PHASE_5_ZERO_COMPILE_STATISTICS;
# run_functions_scheduled_to_run at::SHUTDOWN_PHASE_6_CLOSE_OPEN_FILES;
# run_functions_scheduled_to_run at::SHUTDOWN_PHASE_7_CLEAR_POSIX_INTERPROCESS_SIGNAL_HANDLER_TABLE;
# #
# rt::pervasive_package_pickle_list__global
# :=
# inline_t::cast (); # inline_t is from
src/lib/core/init/built-in.pkg spawn_to_disk' (file_name, wrap f); # Never returns.
};
end;
}; # package save_heap_to_disk
end;
## COPYRIGHT (c) 1995 AT&T Bell Laboratories.
## Subsequent changes by Jeff Prothero Copyright (c) 2010-2015,
## released per terms of SMLNJ-COPYRIGHT.