From 4c389ad3e373cf4bb6ae643e8a91b7104eb6c39a Mon Sep 17 00:00:00 2001 From: Kamil Rytarowski Date: Sun, 21 Feb 2016 05:36:03 +0100 Subject: [PATCH] Fix test issue on NetBSD: Walk-around getrusage(2) implementation nits The following code: int main(int argc, char **argv) { int i, j, k, total; struct rusage resUsage1, resUsage2; if (getrusage (RUSAGE_SELF, &resUsage1) == -1) errx(1, "getrusage"); /* simulate some activity */ for( i=0; i<1000; i++ ) { for( j=0; j<1000; j++ ) { total = j * i; for( k=0; k<1000; k++ ) { total += k + i; } } } if (getrusage (RUSAGE_SELF, &resUsage2) == -1) errx(1, "getrusage"); printf("kernel1 %ld.%06ld\n", resUsage1.ru_stime.tv_sec, resUsage1.ru_stime.tv_usec); printf("kernel2 %ld.%06ld\n", resUsage2.ru_stime.tv_sec, resUsage2.ru_stime.tv_usec); printf("user1 %ld.%06ld\n", resUsage1.ru_utime.tv_sec, resUsage1.ru_utime.tv_usec); printf("user2 %ld.%06ld\n", resUsage2.ru_utime.tv_sec, resUsage2.ru_utime.tv_usec); return 0; } Returns the following values: $ ./test kernel1 0.000262 kernel2 0.000000 user1 0.000262 user2 2.279965 The reason for it is as follows: The reason is that the scheduler keeps a precise total cpu time of a process but the systime/usertime is only sampled by a much slower clock. The ratio systime/usertime is then used to return an approximation so that systime and usertime sum up to the total time(*). As a result it is possible that usertime or systime go backwards. FreeBSD has implemented a workaround by remembering reported usertime/systime values for a process and clamping getrusage() against these values. As a result the usertime/systime value is usually too high but it is monotonic. Another approach would be to round down the usertime/systime values, by not approximating 'measurments' that do not exist. The result would be that usertime/systime values that are too low and don't sum up to the total CPU time but are again monotonic. The approximation is done in kern_resource/calc(). (*) The sampled interrupt time is also included. -- by Michael van Elst -- http://gnats.netbsd.org/cgi-bin/query-pr-single.pl?number=30115 Walkaround it by doing kernel-work with subsequent malloc(3) and free(3) calls. Note that doing these calls for smaller chunks (it looks like a compiler/libc can optimize it without going to the host kernel) or just 1000 times is not sufficient. --- .../tests/palsuite/threading/GetProcessTimes/test2/test2.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/src/pal/tests/palsuite/threading/GetProcessTimes/test2/test2.c b/src/pal/tests/palsuite/threading/GetProcessTimes/test2/test2.c index e2e7411..687facc 100644 --- a/src/pal/tests/palsuite/threading/GetProcessTimes/test2/test2.c +++ b/src/pal/tests/palsuite/threading/GetProcessTimes/test2/test2.c @@ -25,7 +25,7 @@ int __cdecl main( int argc, char **argv ) { int i, j, k; - int total = 0; + int *total; HANDLE hProcess; FILETIME createTime; @@ -76,11 +76,16 @@ int __cdecl main( int argc, char **argv ) { for( j=0; j<1000; j++ ) { - total = j * i; + /* do kernel work to increase system usage counters */ + total = malloc(1024 * 1024); + + *total = j * i; for( k=0; k<1000; k++ ) { - total += k + i; + *total += k + i; } + + free(total); } } -- 2.7.4