From 96fe691712a6b249efdb91f6053a72c3124f8578 Mon Sep 17 00:00:00 2001 From: malc Date: Sun, 8 Jul 2007 17:38:34 +0400 Subject: [PATCH] v0.97c --- FILES | 1 + OMakefile | 2 +- README | 65 +++++++++++++++++++++++--------------------------- apc.ml | 2 +- build.sh | 1 + hog.c | 81 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 6 files changed, 115 insertions(+), 37 deletions(-) create mode 100644 hog.c diff --git a/FILES b/FILES index 9e1539e..ef48d9e 100644 --- a/FILES +++ b/FILES @@ -11,3 +11,4 @@ README Thanks FILES Changes +hog.c diff --git a/OMakefile b/OMakefile index 2c5cc7b..47a41c1 100644 --- a/OMakefile +++ b/OMakefile @@ -1,4 +1,4 @@ -version = 0.97b +version = 0.97c ocaml-includes = -I +lablGL diff --git a/README b/README index a29cd59..e5a6d01 100644 --- a/README +++ b/README @@ -3,11 +3,12 @@ WARNING The kernel module part of this program messes with internal affairs of the kernel, while best effort was put into making it safe, there are: - NO GUARANTEES WHATSOEVER -Furthermore removing the previous versions of the module (via -rmmod(8)) caused one particular kernel version to panic -(2.6.8-2-686-SMP form Debian), to the best of my current knowledge + NO GUARANTEES WHATSOEVER + +Furthermore removing the previous versions of the module (via +rmmod(8)) caused one particular kernel version to panic +(2.6.8-2-686-SMP form Debian), to the best of my current knowledge panics are only possible on SMP machines (and with maxcpus > 1). Pair of safety nets were added and this particular kernel no longer panics upon module removal, but, again, three words in caps above apply. @@ -27,42 +28,36 @@ This is APC - graphical CPU load meter. It is more suitable/accurate in situations where applications generate "short" periodic bursts of activity. -It works by timing the time spent in the kernels idle handler. CPU +It works by measuring the time spent in the kernels idle handler. CPU load time is taken to mean: + time spent in idle handler 1 - -------------------------- total time elapsed -Kernel can use variety of values for HZ (most frequent: 100 250 1000) - -PAL/SECAM video frame grabbers do so with 25/50 FPS frequency, if the -pulse leads to some application deciding to burn CPU (putting the -frame on the screen, encoding it, etc) chances are good that the load -you will see in top(1) (or anything `/proc/stat' based) would not -represent reality accurately. Ditto for plain video clips playing at -25 fps. - -When frequency of aforementioned bursts divides HZ value evenly -reading `/proc/stat' or `/proc/uptime' can make an impression that -sometimes machine gets loaded for a brief period of time but then goes -idle again (for a while) then the cycle repeats. This is not the case, -the machine is constantly loaded (well according to ad-hoc measuring -via background "niced" process and/or APC) - -If this line of thinking is correct one can not notice any load at all -while watching NTSC content (30fps - does not divide 100/250/1000 -evenly) - -Furthermore `/proc/stat' exports monotonically increasing load times -but _NOT_ real time[1], so there's omni-present sub-jiffy error. Not -to mention that jiffy resolution is somewhat low. - -If you depend on sorta-kinda semi-correct load meter in those -conditions APC might present a better choice. - -The kernel module part of APC measures how much time is spent -executing idle kernel function - this information is represented by -yellow color, values obtained via `/proc/stat' are represented by red. +Con Kolivas in his post on LKML (http://lkml.org/lkml/2007/2/12/7) +described the way Linux gathers information that it exports to +`/proc/stat' (at least for "boring" architectures), this method is by +no means accurate. + +You can witness this by running the `hog' example and, if stars are +aligned correctly, you will notice that something is wrong with what +`/proc/stat' claims. Since most of the CPU monitoring applications use +`/proc/stat' they will produce incorrect results too. + +Apart from being inaccurate, `/proc/stat' exports monotonically +increasing load times but _NOT_ real time[1], so there's omni-present +sub-jiffy error. Not to mention that jiffy resolution is somewhat low. + +If you depend on sorta-kinda semi-correct load meter in situation when +`/proc/stat' is disconnected with reality APC might present a better +choice. + +The kernel module part of APC tries to insert itself as a power +management idle handler and when invoked measure how much time is +spent executing previous/default one - this information is represented +by yellow color, values obtained via `/proc/stat' are represented by +red. You can use `-help' command line option to get a brief overview of tunable parameters. diff --git a/apc.ml b/apc.ml index 93a7331..a44451c 100644 --- a/apc.ml +++ b/apc.ml @@ -135,7 +135,7 @@ end module Args = struct let banner = - [ "Amazing Piece of Code by insanely gifted programmer, Version 0.97b" + [ "Amazing Piece of Code by insanely gifted programmer, Version 0.97c" ; "Motivation by: gzh and afs" ; "usage: " ] |> String.concat "\n" diff --git a/build.sh b/build.sh index 528abcf..3174bac 100755 --- a/build.sh +++ b/build.sh @@ -6,5 +6,6 @@ libs="unix.cma lablgl.cma lablglut.cma threads.cma" flags="-custom -thread -I +lablGL" test -z "$comp" && comp=ocamlc $comp -o apc $flags $libs apc.ml ml_apc.c +cc -o hog -Wall -Werror -pedantic -W hog.c (cd mod && make) diff --git a/hog.c b/hog.c new file mode 100644 index 0000000..4544fdd --- /dev/null +++ b/hog.c @@ -0,0 +1,81 @@ +/* gcc -o hog hog.c */ +#define _GNU_SOURCE +#include +#include +#include +#include +#include +#include +#include +#include + +#define HIST 10 + +static sig_atomic_t stop; + +static void sighandler (int signr) +{ + (void) signr; + stop = 1; +} + +static unsigned long hog (unsigned long niters) +{ + stop = 0; + while (!stop && --niters) + ; + return niters; +} + +int main (void) +{ + unsigned int i; + struct itimerval it; + sigset_t set; + unsigned long v[HIST]; + double tmp = 0.0; + unsigned long n; + + it.it_interval.tv_sec = 0; + it.it_interval.tv_usec = 1; + it.it_value.tv_sec = 0; + it.it_value.tv_usec = 1; + + if (signal (SIGALRM, &sighandler)) { + err (EXIT_FAILURE, "failed to set signal handler"); + } + + if (setitimer (ITIMER_REAL, &it, NULL)) { + err (EXIT_FAILURE, "failed to set interval timer"); + } + + for (i = 0; i < HIST; ++i) { + v[i] = ULONG_MAX - hog (ULONG_MAX); + } + + for (i = 0; i < HIST; ++i) { + printf ("%d = %ld\n", i, v[i]); + tmp += v[i]; + } + tmp /= HIST; + n = tmp - (tmp / 3); + + if (sigemptyset (&set)) { + err (EXIT_FAILURE, "failed to empty sigset"); + } + + if (sigaddset (&set, SIGALRM)) { + err (EXIT_FAILURE, "failed to add to sigset"); + } + + for (;;) { + int signr; + + hog (n); + if (sigwait (&set, &signr)) { + err (EXIT_FAILURE, "failed to wait for a signal"); + } + } + + return 0; +} -- 2.11.4.GIT