PreviousUpNext

15.4.1101  src/lib/std/src/internal-cpu-timer.pkg

## internal-cpu-timer.pkg
#
# See also:
#     src/lib/std/src/internal-wallclock-timer.pkg
#     src/lib/std/src/nj/set-sigalrm-frequency.pkg

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


###               "I have never let my schooling interfere with my education."
###
###                                               -- Mark Twain


stipulate
    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 f8b =  eight_byte_float_guts;                                                               # eight_byte_float_guts                 is from   src/lib/std/src/eight-byte-float-guts.pkg
    package int =  int_guts;                                                                            # int_guts                              is from   src/lib/std/src/int-guts.pkg
    package i1w =  one_word_int_guts;                                                                   # one_word_int_guts                     is from   src/lib/std/src/one-word-int-guts.pkg
    package pb  =  proto_basis;                                                                         # proto_basis                           is from   src/lib/std/src/proto-basis.pkg
    package tim =  time_guts;                                                                           # time_guts                             is from   src/lib/std/src/time-guts.pkg
    #
    Float       =  f8b::Float;
    #
    fun cfun  fun_name                                                                                  # For background see Note[1]            in   src/lib/std/src/unsafe/mythryl-callable-c-library-interface.pkg
        =
        ci::find_c_function'' { lib_name => "time", fun_name };
herein

    # This package is referenced (only) in:
    #
    #     src/lib/std/src/cpu-timer.pkg
    #     src/lib/std/src/nj/runtime-internals.pkg
    #
    package internal_cpu_timer: (weak)  api {
        #
        include api Cpu_Timer;                                                                          # Cpu_Timer                             is from   src/lib/std/src/cpu-timer.api
        #
        reset_timer:  Void -> Void;                                                                     # Reset global timer to zero elapsed time.
    }
    {

        Time = {   usermode_cpu_seconds:    pb::Time,                                                   # User-mode   CPU time consumption for this process.
                 kernelmode_cpu_seconds:    pb::Time                                                    # Kernel-mode CPU time consumption for this process.
               };

        Cpu_Timer
            =
            CPU_TIMER
              {
                program:          Time,
                heapcleaner:      Time,
                #
                last_program:     Ref Time,
                last_heapcleaner: Ref Time
              };

        Cpu_Times                                                                                       # This type is mainly for the convenience of client packages.
            =
            { program:     { usermode_cpu_seconds: Float,  kernelmode_cpu_seconds: Float },             # CPU time excluding that used by heapcleaner ("garbage collector").
              heapcleaner: { usermode_cpu_seconds: Float,  kernelmode_cpu_seconds: Float }              # CPU time                used by heapcleaner ("garbage collector").
            };

        (cfun "gettime")                                                                                # gettime       def in    src/c/lib/time/gettime.c
            ->
            (      gettime__syscall:    Void -> ( i1w::Int, Int,                                        # User-mode          seconds, microseconds.
                                                  i1w::Int, Int,                                        # Kernel-mode        seconds, microseconds.
                                                  i1w::Int, Int                                         # Garbage collection seconds, microseconds.
                                                ),
                   gettime__ref,
              set__gettime__ref
            );

        stipulate
            #
            fun make_time (seconds, microseconds)
                =
                tim::from_microseconds ((int::to_multiword_int 1000000) * i1w::to_multiword_int  seconds
                                        +                                 int::to_multiword_int  microseconds
                                        );
        herein

            fun get_time ()
                =
                {   (*gettime__ref ())
                        ->
                        (ts, tu, ss, su, gs, gu);

                    program     = {   usermode_cpu_seconds =>  make_time (ts, tu),
                                    kernelmode_cpu_seconds =>  make_time (ss, su)
                                  };

                    heapcleaner = {   usermode_cpu_seconds =>  make_time (gs, gu),
                                    kernelmode_cpu_seconds =>  tim::zero_time
                                  };

                    last_program     = REF program;
                    last_heapcleaner = REF heapcleaner;

                    { program, heapcleaner, last_program, last_heapcleaner };
                };

        end;

        fun make_cpu_timer ()
            =
            CPU_TIMER (get_time());


        stipulate
            init_cputime   =  REF (make_cpu_timer ());
        herein

            fun get_cpu_timer ()
                =
                *init_cputime;

            # This call is used (only) in
            #     src/lib/std/src/nj/runtime-internals.pkg
            # to clear timers when resuming a heap image
            # created by fork_to_disk():
            #
            fun reset_timer ()
                =
                init_cputime   :=  make_cpu_timer ();

        end;

        stipulate

            infix my  --- +++ ;

            fun usop timeop (t: Time, t': Time)                 # "usop" might be "microsecond op"
                =
                {   usermode_cpu_seconds => timeop (  t.usermode_cpu_seconds,   t'.usermode_cpu_seconds),
                  kernelmode_cpu_seconds => timeop (t.kernelmode_cpu_seconds, t'.kernelmode_cpu_seconds)
                };

            my (---) = usop tim::(-);
            my (+++) = usop tim::(+);

            fun to_float_seconds { usermode_cpu_seconds, kernelmode_cpu_seconds }
                =
                {   usermode_cpu_seconds =>  tim::to_float_seconds    usermode_cpu_seconds,
                  kernelmode_cpu_seconds =>  tim::to_float_seconds  kernelmode_cpu_seconds
                };
        herein

            fun get_elapsed_heapcleaner_and_program_usermode_and_kernelmode_cpu_seconds (CPU_TIMER t)
                =
                {   t' = get_time ();
                    #
                    { program =>  to_float_seconds (t'.program --- t.program),
                      heapcleaner    =>  to_float_seconds (t'.heapcleaner    --- t.heapcleaner   )
                    };
                };

            fun get_elapsed_usermode_and_kernelmode_cpu_seconds  timer
                =
                {   t = get_elapsed_heapcleaner_and_program_usermode_and_kernelmode_cpu_seconds  timer;
                    #
                    t.heapcleaner    -> { kernelmode_cpu_seconds => k1, usermode_cpu_seconds => u1 };   
                    t.program -> { kernelmode_cpu_seconds => k2, usermode_cpu_seconds => u2 };  
                    #
                    {   usermode_cpu_seconds =>  u1 + u2,
                      kernelmode_cpu_seconds =>  k1 + k2
                    };
                };

            fun get_elapsed_cpu_seconds  timer
                =
                {   (get_elapsed_usermode_and_kernelmode_cpu_seconds  timer)
                        ->
                        {   usermode_cpu_seconds,
                          kernelmode_cpu_seconds
                        };

                    usermode_cpu_seconds + kernelmode_cpu_seconds;
                };


            fun get_elapsed_heapcleaner_cpu_seconds  (CPU_TIMER t)
                =
                tim::to_float_seconds (tim::(-) (((get_time ()).heapcleaner).usermode_cpu_seconds, t.heapcleaner.usermode_cpu_seconds));



            fun get_added_heapcleaner_and_program_usermode_and_kernelmode_cpu_seconds  (CPU_TIMER t)
                =
                {   (get_time ())
                        ->
                        { program, heapcleaner, last_heapcleaner, last_program };

                    result =    { program     =>  to_float_seconds (program --- *t.last_program),
                                  heapcleaner =>  to_float_seconds (heapcleaner    --- *t.last_heapcleaner   )
                                };

                    t.last_program     :=  *last_program;
                    t.last_heapcleaner :=  *last_heapcleaner;

                    result;
                };

            fun get_added_usermode_and_kernelmode_cpu_seconds  timer
                =
                {   t = get_added_heapcleaner_and_program_usermode_and_kernelmode_cpu_seconds   timer;
                    #
                    t.heapcleaner -> { kernelmode_cpu_seconds => k1, usermode_cpu_seconds => u1 };      
                    t.program     -> { kernelmode_cpu_seconds => k2, usermode_cpu_seconds => u2 };      

                    {   usermode_cpu_seconds =>  u1 + u2,
                      kernelmode_cpu_seconds =>  k1 + k2
                    };
                };

            fun get_added_cpu_seconds  timer
                =
                {   (get_added_usermode_and_kernelmode_cpu_seconds  timer)
                        ->
                        {   usermode_cpu_seconds,
                          kernelmode_cpu_seconds
                        };

                    usermode_cpu_seconds + kernelmode_cpu_seconds;
                };


        end;                            # stipulate
    };
end;


Comments and suggestions to: bugs@mythryl.org

PreviousUpNext