Hello!
I'm doing some work with v2lin library (
http://v2lin.sourceforge.net/). I have two Linux workstations to test the application I have ported from VxWorks OS. On one I have installed older OS Slackware 11 (Linux slackware 2.4.33.3) and on the other I have Ubuntu 7.10 (Linux desktop 2.6.22-14-generic).
I found out that ported application with v2lin library works on kernel version 2.4, but not on 2.6. On the 2.6 kernel the system gets overloaded in such an extreme that I cannot use the system anymore and have to reset PC. After some code testing I found out that all is working ok except timers. The problem arises because v2lin library calculates the clock resolution (ticks per second) and uses this value as an argument when starting timers. I wrote simple program to demonstrate this.
Code:
#include <time.h>
#include <iostream>
int main(void) {
struct timespec res;
clock_getres(CLOCK_REALTIME, &res);
std::cout << "res.tv_nsec: " << res.tv_nsec << std::endl;
std::cout << "res.tv_sec: " << res.tv_sec << std::endl;
int clkRate = 1e9 / res.tv_nsec;
std::cout << "clkRate: " << clkRate << std::endl;
return 0;
}
and
Code:
#include <time.h>
#include <iostream>
int main(void) {
clockid_t clocks[] = {
CLOCK_REALTIME,
CLOCK_MONOTONIC,
CLOCK_PROCESS_CPUTIME_ID,
CLOCK_THREAD_CPUTIME_ID,
(clockid_t) -1 };
int i;
for (i = 0; clocks[i] != (clockid_t) -1; i++) {
struct timespec res;
int ret;
ret = clock_getres (clocks[i], &res);
if (ret)
perror ("clock_getres");
else
printf ("clock=%d sec=%ld nsec=%ld\n", clocks[i], res.tv_sec, res.tv_nsec);
}
return 0;
}
Results on kernel 2.4 are:
Quote:
test1:
res.tv_nsec: 10000000
res.tv_sec: 0
clkRate: 100
tests2:
clock=0 sec=0 nsec=10000000
clock_getres: Invalid argument
clock_getres: Invalid argument
clock_getres: Invalid argument
|
Results on kernel 2.6 are:
Quote:
test1:
res.tv_nsec: 1
res.tv_sec: 0
clkRate: 1000000000
tests2:
clock=0 sec=0 nsec=1
clock=1 sec=0 nsec=1
clock=2 sec=0 nsec=1
clock=3 sec=0 nsec=1
|
I don't understand why res.tv_nsec value on the kernel 2.6 is 1? I read on the following page
http://kernelnewbies.org/Linux_2_6_21
Quote:
N (the number of times the timer interrupt is fired in each second, aka 'HZ') is a hard coded compile-time architecture-dependent constant. For Linux 2.4 (and Windows), HZ=100 (the timer interrupt fires 100 times per second). 2.6 increased HZ to 1000 for several reasons. 100 was the HZ value that x86 had been using since forever and it didn't really make a lot of sense in modern CPUs that run much faster. Higher HZ means smaller process time slices, which improves the minimum latency and interactivity. The downside is higher timer overhead (negligible in modern hardware, although some server-oriented distros package kernels with HZ=100 because of minor performance gains) and high pitch noises in some systems due to cheap, low-quality capacitors.
|
and in the book Linux System Programming by Robert Love
Quote:
On Linux, the frequency of the system timer is called HZ, because a preprocessor define of the same name represents it. The value of HZ is architecture-specific, and not part of the Linux ABI—that is, programs cannot depend on or expect any given value. Historically, the x86 architecture used a value of 100, meaning the system timer ran 100 times per second (that is, the system timer had a frequency of 100 hertz). This gave each jiffy a value of 0.01 seconds—1/HZ seconds. With the release of the 2.6 Linux kernel, the kernel developers bumped the value of HZ to 1000, giving each jiffy a value of 0.001 seconds. However, in version 2.6.13 and later, HZ is 250, providing each jiffy a value of 0.004 seconds.† There is a tradeoff inherent in the value of HZ: higher values provide higher resolution, but incur greater timer overhead.
|
According to the documentation the value of res.tv_nsec should be 1000000 (ticks per second is then 1000). So why do I get the value 1? In this case the value of ticks per second is 1000000000 and this value is enormous. The v2lin function, to start some timer, takes a signed integer value of ticks for how long timer should last. The size of signed integer is 2147483648. So imagine what happens when I want to start a timer lasting 5 seconds (5 * 1000000000). Signed integer does not even hold this value.
Has there been some lately change in kernel timer implementation? Can I do something about it besides recompiling the kernel or porting v2lin library?
Regards,