## 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;