From 6ad852755d40841e01ea8a1ce4dc7ef64f05d3dc Mon Sep 17 00:00:00 2001 From: malc Date: Sun, 8 Jul 2007 17:40:46 +0400 Subject: [PATCH] v1.00 --- Changes | 3 ++ OMakefile | 3 +- README.macosx | 2 +- README.windows | 23 ++++++++++++-- apc.ml | 8 +++-- ml_apc.c | 97 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++- 6 files changed, 127 insertions(+), 9 deletions(-) diff --git a/Changes b/Changes index 4bf1a0a..0dd617c 100644 --- a/Changes +++ b/Changes @@ -1,3 +1,6 @@ +10 + * Use RDPMC on NT/X86 or die trying + 9 * Do not show kernel-sampler CPU bar when not using kernel sampler diff --git a/OMakefile b/OMakefile index b06eacf..db045cb 100644 --- a/OMakefile +++ b/OMakefile @@ -1,4 +1,4 @@ -version = 0.99 +version = 1.00 .PHONY: all clean dist mod opt .DEFAULT: all @@ -6,7 +6,6 @@ version = 0.99 clibs = if $(equal $(shell uname), SunOS) value -cclib -lkstat - Mocamlcc (ml_apc, -Wall -Werror -g -I/usr/X11R6/include) Mocamlc (apc, -warn-error A -g -thread -I +lablGL) Mocamlopt (apc, -warn-error A -thread -I +lablGL) diff --git a/README.macosx b/README.macosx index 6e09a10..67ae730 100644 --- a/README.macosx +++ b/README.macosx @@ -1,4 +1,4 @@ Tested on Mac OS X Tiger (PPC) SMP - not tested -Kernel accounting appears to be rather chaotic +Kernel accounting appears to be rather chaotic (... and wrong ...) No kernel mode driver hence no workaround diff --git a/README.windows b/README.windows index dadd86c..fbb9a33 100644 --- a/README.windows +++ b/README.windows @@ -1,4 +1,23 @@ Tested on Windows XP SP2 (X86) SMP - tested (AMD X2 - i.e. 2 CPUs) -Kernel accounting _IS_ innaccurate -No kernel mode driver hence no workaround +Kernel accounting _IS_ inaccurate + +Apparently RMClock (http://cpu.rightmark.org/products/rmclock.shtml) +either somehow sets CR4.PCE or hooks to the #GP(0) handler so that +RDPMC works from userspace. + +Therefore if RMClock is running, APC can invoked with `-M' switch and +by sampling TSC/PMC0 one can estimate the idleness of the system. + +No idea how this behaves in presence of frequent (no pun intended) +CPU frequency changes. + +As it is now ml_apc.c must be compiled with the compiler supporting +Microsoft style inline assembly, in other words compilation will most +likely fail if trying to build with Mingw or Cygwin based OCaml +distribution. + + + CLOCKS IN UNHALTED STATE +Idle factor = 1 - ------------------------ + TOTAL CLOCKS diff --git a/apc.ml b/apc.ml index 2c01016..ea11e5c 100644 --- a/apc.ml +++ b/apc.ml @@ -287,7 +287,7 @@ end module Args = struct let banner = - [ "Amazing Piece of Code by insanely gifted programmer, Version 0.99" + [ "Amazing Piece of Code by insanely gifted programmer, Version 1.00" ; "Motivation by: gzh and afs" ; "usage: " ] |> String.concat "\n" @@ -403,7 +403,9 @@ struct in let add_windows opts = isampler := false; - opts + (fB "k" ksampler |< "kernel sampler (ZwQuerySystemInformation)") + :: (fB "M" isampler |< "idle sampler (PMC based)") + :: opts in let add_macosx opts = isampler := false; @@ -432,7 +434,7 @@ struct in let cpf {contents=v} s = if v <= 0.0 - then (prerr_string s; prerr_endline " must be pisitive"; exit 1) + then (prerr_string s; prerr_endline " must be positive"; exit 1) in cp w "Width"; cp h "Height"; diff --git a/ml_apc.c b/ml_apc.c index b6ad10a..2fe8665 100644 --- a/ml_apc.c +++ b/ml_apc.c @@ -190,8 +190,26 @@ static struct { HMODULE hmod; QuerySystemInformationProc QuerySystemInformation; ULONG nprocs; + double prevtime; + struct { + double clocks; + double unhalted; + double total; + } prev[64]; } glob; +static double gettime (void) +{ + FILETIME ft; + uint64 tmp; + + GetSystemTimeAsFileTime (&ft); + tmp = ft.dwHighDateTime; + tmp <<= 32; + tmp |= ft.dwLowDateTime; + return tmp * 1e-7; +} + static void init (void) { if (!glob.hmod) { @@ -207,6 +225,7 @@ static void init (void) "could not obtain ZwQuerySystemInformation entry point: %#lx", GetLastError ()); } + glob.prevtime = gettime (); } } @@ -239,12 +258,58 @@ CAMLprim value ml_waitalrm (value unit_v) CAMLreturn (Val_unit); } +static void pmc (int nproc, double *clocksp, double *unhaltedp) +{ + unsigned int h1, l1, h2, l2, p; + uint64 tmp; + DWORD prevmask; + + prevmask = SetThreadAffinityMask (GetCurrentThread (), 1 << nproc); + if (!prevmask) { + failwith_fmt ("SetThreadAffinityMask failed: %ld\n", GetLastError ()); + } + +#ifndef _MSC_VER +#error Not yet written +#endif + + _asm { + pushad; + mov eax, 1; + cpuid; + mov p, ebx; + rdtsc; + mov l1, eax; + mov h1, edx; + xor ecx, ecx; + rdpmc; + mov l2, eax; + mov h2, edx; + popad; + } + + tmp = h1; + tmp <<= 32; + tmp |= l1; + *clocksp = tmp; + + tmp = h2; + tmp <<= 32; + tmp |= l2; + *unhaltedp = tmp; + /* printf ("[%d] = %f %f %x\n", p >> 24, *clocksp, *unhaltedp, prevmask); */ +} + static void get_nprocs (void) { SYSTEM_BASIC_INFORMATION sbi; qsi (0, &sbi, sizeof (sbi)); glob.nprocs = sbi.NumberProcessors; + if (glob.nprocs > 64) { + failwith_fmt ("Hmm... the future is now, but i'm not ready %d", + glob.nprocs); + } } CAMLprim value ml_get_nprocs (value unit_v) @@ -340,6 +405,34 @@ CAMLprim value ml_os_type (value unit_v) CAMLreturn (Val_int (WINDOWS_TAG)); } +CAMLprim value ml_idletimeofday (value fd_v, value nprocs_v) +{ + CAMLparam2 (fd_v, nprocs_v); + CAMLlocal1 (res_v); + double now, delta; + int i; + + now = gettime (); + delta = now - glob.prevtime; + glob.prevtime = now; + + res_v = caml_alloc (glob.nprocs * Double_wosize, Double_array_tag); + for (i = 0; i < glob.nprocs; ++i) { + double d; + double clocks, unhalted; + double dc, du; + + pmc (i, &clocks, &unhalted); + dc = clocks - glob.prev[i].clocks; + du = unhalted - glob.prev[i].unhalted; + d = delta * (1.0 - du / dc); + glob.prev[i].clocks = clocks; + glob.prev[i].unhalted = unhalted; + glob.prev[i].total += d; + Store_double_field (res_v, i, glob.prev[i].total); + } + CAMLreturn (res_v); +} #elif defined __sun__ #define _POSIX_PTHREAD_SEMANTICS #include @@ -690,10 +783,12 @@ CAMLprim value ml_sysinfo (value unit_v) CAMLreturn (res_v); } +#ifndef _WIN32 CAMLprim value ml_idletimeofday (value fd_v, value nprocs_v) { CAMLparam2 (fd_v, nprocs_v); - failwith_fmt ("idletimeofday is not implemented on non-Linux"); + failwith_fmt ("idletimeofday is not implemented on non-Linux/Win32"); CAMLreturn (Val_unit); } #endif +#endif -- 2.11.4.GIT