PreviousUpNext

15.4.1138  src/lib/std/src/nj/save-heap-to-disk.pkg

## save-heap-to-disk.pkg

# Compiled by:
#     src/lib/std/src/standard-core.sublib

stipulate
    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.


Comments and suggestions to: bugs@mythryl.org

PreviousUpNext