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 -- To UNSUBSCRIBE, email to [EMAIL PROTECTED] with a subject of "unsubscribe". Trouble? Contact [EMAIL PROTECTED]