Your message dated Sun, 21 Oct 2012 23:45:09 +0200 with message-id <[email protected]> and subject line Re: Bug#426565: /usr/share/man/man2/times.2.gz: interpretation of times(2) return value is based on HZ (obsolete?) value has caused the Debian Bug report #426565, regarding /usr/share/man/man2/times.2.gz: interpretation of times(2) return value is based on HZ (obsolete?) value to be marked as done.
This means that you claim that the problem has been dealt with. If this is not the case it is now your responsibility to reopen the Bug report if necessary, and/or fix the problem forthwith. (NB: If you are a system administrator and have no idea what this message is talking about, this may indicate a serious mail system misconfiguration somewhere. Please contact [email protected] immediately.) -- 426565: http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=426565 Debian Bug Tracking System Contact [email protected] with problems
--- Begin Message ---Package: manpages-dev Version: 2.49-1 Severity: normal File: /usr/share/man/man2/times.2.gz I have a problem with the following sentence in times(2) manual page, RETURN VALUE section: Since Linux 2.6, this point is (2^32/HZ) - 300 (i.e., about 429 million) seconds before system boot time. The problem is that in order to be able to use the return value (map it to my wall-clock) I have to know the value of HZ. It appears that the value of HZ depends on the kernel configuration option (recent Linux versions can have 100Hz, 250Hz, 1000Hz etc), so it's not possible to compile once and use the same binary on other machines. On Google I also found some discussion that HZ can be 1024 on some architectures So this HZ variable is a very bad idea. Google says that sysconf(_SC_CLK_TCK) should be used instead of HZ. This seems to be reasonable and works for time (jiffies) numbers in /proc, but it does NOT work for the return value, consider the following: 1) I compiled my kernel (2.6.20.11 with completely fair scheduler 14 on for Pentium 4) with the following options: CONFIG_HZ_1000=y CONFIG_HZ=1000 2) sysconf(_SC_CLK_TCK) returns 100, and it works correctly with timing numbers in the structure and /proc/#/stat (i.e. starttime field). 3) expression 2^32/sysconf(_SC_CLK_TCK)-300 evaluates to 42949372 this is about 42 million (not about 429 million as in manual) 4) I found the following formula to be useful to convert the returned ticks to milli seconds since boot: struct tms mytimes; uint64_t ms=(times(&mytimes)*1000/sysconf(_SC_CLK_TCK) - (1LLU<<32) + 951416); The idea is that times(&mytimes) returns the number of ticks since arbitrary point in time, I multiply it with 1000/sysconf(_SC_CLK_TCK) which is the number of milliseconds per one tick. Then the offset of the arbitrary point in time is adjusted. Interestingly, the constant 951416 is not firm (it seems to be shrinking by 100ms per hour or so), but (1LLU<<32) is not to be divided and the constant difference is far from 300 seconds as manual says. I just wonder what is really happening here. I used the following program to find out the formula and the difference between the values of times(2) and /proc/#/stat startime: #include <sys/times.h> #include <sys/types.h> #include <unistd.h> #include <iostream> #include <fstream> using namespace std; long long myStartTime(){ char statname[64] = ""; char info[64]; snprintf(statname, 64, "/proc/%d/stat", getpid()); ifstream stat(statname); stat.width(64); stat>>info; // PID if (atol(info)!=getpid()) { cout << "bad proc stat file" << endl; exit(EXIT_FAILURE); } stat.width(64); stat>>info; // filename of executable stat.width(64); stat>>info; // state stat.width(64); stat>>info; // parent PID stat.width(64); stat>>info; // process group stat.width(64); stat>>info; // session stat.width(64); stat>>info; // tty nr stat.width(64); stat>>info; // process group ID of tty owner stat.width(64); stat>>info; // flags stat.width(64); stat>>info; // No. minor faults stat.width(64); stat>>info; // No. minor faults in children stat.width(64); stat>>info; // No. major faults stat.width(64); stat>>info; // No. major faults in children stat.width(64); stat>>info; // No. jiffies in user mode stat.width(64); stat>>info; // No. jiffies in kernel mode stat.width(64); stat>>info; // children jiffies in user mode stat.width(64); stat>>info; // children jiffies in kernel mode stat.width(64); stat>>info; // priority stat.width(64); stat>>info; // nice value stat.width(64); stat>>info; // 0 (zero) stat.width(64); stat>>info; // jiffies before next SIGALARM stat.width(64); stat>>info; // jiffies since start after boot return (atoll(info)*1000/sysconf(_SC_CLK_TCK)); } long ticks_per_sec = sysconf(_SC_CLK_TCK); inline long long ticks2ms(long long &ticks) { return (ticks*1000/ticks_per_sec - (1LLU<<32) + 951416); } struct tms mytimes; long long start, before, after; int main(){ before = times(&mytimes); sleep(1); after = times(&mytimes); before = ticks2ms(before); after = ticks2ms(after); start = myStartTime(); long long diff; if (before>start) { diff = (before-start); cout << "Too late by " << diff << "ms" << endl; } else if (start>before) { diff = (start - before); cout << "TOO EARLY BY " << diff << "ms" << endl; cout << "startt="<<start<<"ms\nbefore=" << before << "ms after="<<after << "ms duration="<<(after-before)<<"ms" << endl; } else cout << "GOOD" << endl; } -- System Information: Debian Release: lenny/sid APT prefers testing APT policy: (990, 'testing'), (500, 'stable'), (50, 'unstable'), (1, 'experimental') Architecture: i386 (i686) Kernel: Linux 2.6.20.11-cfs-v13 (PREEMPT) Locale: LANG=lt_LT.UTF-8, LC_CTYPE=lt_LT.UTF-8 (charmap=UTF-8) Shell: /bin/sh linked to /bin/bash Versions of packages manpages-dev depends on: ii manpages 2.43-0 Manual pages about using a GNU/Lin manpages-dev recommends no packages. -- no debconf information
--- End Message ---
--- Begin Message ---Version: 2.74-1 On Tue, May 29, 2007 at 06:46:11PM +0200, Marius Mikucionis wrote: > Package: manpages-dev > Version: 2.49-1 > Severity: normal > File: /usr/share/man/man2/times.2.gz > > I have a problem with the following sentence in times(2) manual page, > RETURN VALUE section: > > Since Linux 2.6, this point is (2^32/HZ) - 300 (i.e., about 429 million) > seconds before system boot time. > > The problem is that in order to be able to use the return value (map it to my > wall-clock) I have to know the value of HZ. It appears that the value of HZ > depends on the kernel configuration option (recent Linux versions can have > 100Hz, 250Hz, 1000Hz etc), so it's not possible to compile once and use > the same binary on other machines. On Google I also found some discussion > that HZ can be 1024 on some architectures > So this HZ variable is a very bad idea. [..] A long time ago in a galaxy far .. manpages maintainer improved this and warns the reader how much he should probably not use times() because HZ is bad. http://git.kernel.org/?p=docs/man-pages/man-pages.git;a=commitdiff;h=5e27f149be682ba On Linux, the "arbitrary point in the past" from which the return value of times() is measured has varied across kernel versions. On Linux 2.4 and earlier this point is the moment the system was booted. Since Linux 2.6, this point is (2^32/HZ) - 300 (i.e., about 429 million) seconds before system boot time. This variability across kernel versions (and across UNIX implementations), combined with the fact that the returned value may overflow the range of clock_t, means that a portable application would be wise to avoid using this value. To measure changes in elapsed time, use gettimeofday(2) instead. -- Simon Paillard
--- End Message ---

