Note that there are some explanatory texts on larger screens.

plurals
  1. POrdtsc's return value is _always_ mod 10 == 0 on Atom N450
    primarykey
    data
    text
    <p>On my E8200 box this doesn't occur, but on my Atom N450 netbook (both running OpenSuse 11.2), whenever I read the CPU's TSC, the returned value is <code>mod 10 == 0</code>, i. e. it is without remainder divisible by 10. I'm using the RDTSC value for measuring times that interesting pieces of code take, but for the purpose of demonstration I've made up this little program:</p> <pre><code> .text .global _start _start: xorl %ebx,%ebx xorl %ecx,%ecx xorl %r14d,%r14d movb $10,%cl loop: xchgq %rcx,%r15 # save to reg cpuid rdtsc shlq $32,%rdx xorq %rax,%rdx # full 64 bit of RDTSC movq %r14,%r13 # save the old value movq %rdx,%r14 # copy current movq %r14,%rsi # argv[1] of printf() subq %r13,%rdx # argv[2] (delta) leaq format(%rip),%rdi # argv[0] xorl %eax,%eax # no stack varargs call printf xchgq %rcx,%r15 loop loop 0: xorl %eax,%eax movb $0x3c,%al syscall .size _start, .-_start .data format: .asciz "rdtsc: %#018llx = %1$llu -- delta: %llu\n" </code></pre> <p>(I usually use my own routines for converting, but to prevent readers from suggesting that the error might be there, I'm just using printf() here.)</p> <p>With the above code, the output is (for example):</p> <pre><code>rdtsc: 0x000b88ef933ffd06 = 3246787292822790 -- delta: 3246787292822790 rdtsc: 0x000b88ef9342fcf4 = 3246787293019380 -- delta: 196590 rdtsc: 0x000b88ef93435dca = 3246787293044170 -- delta: 24790 rdtsc: 0x000b88ef9343b43c = 3246787293066300 -- delta: 22130 rdtsc: 0x000b88ef93440c34 = 3246787293088820 -- delta: 22520 rdtsc: 0x000b88ef9344604e = 3246787293110350 -- delta: 21530 rdtsc: 0x000b88ef9344b4d6 = 3246787293131990 -- delta: 21640 rdtsc: 0x000b88ef9345085a = 3246787293153370 -- delta: 21380 rdtsc: 0x000b88ef93455d96 = 3246787293175190 -- delta: 21820 rdtsc: 0x000b88ef9345b16a = 3246787293196650 -- delta: 21460 </code></pre> <p>As can be easily seen, the delta varies in reasonable amounts. But conspicuous (not to say conspired ;-) is that the least significant decimal digit is always 0.</p> <p>I've observed this phenomenon for more than two years now, and Stack Overflow is not the first address where I make this issue public. But nowhere I got a reasonable answer yet. The ideas we (me and other people out there) came up with, are that</p> <ul> <li>the TSC is incremented only every 10<sup>th</sup> cycle, but then by 10, or</li> <li>the TSC is internally updated correctly, but reflected to the outside only every 10<sup>th</sup> cycle, or</li> <li>the TSC is incremented by 10 each cycle.</li> </ul> <p>None of these points really make sense, however. I should have actually run a program like that on the E8200 (which is currently out of order) to see if the order of magnitude of the deltas is the same or only a tenth of those in the above output. (Any volunteers?)</p> <p>Googling didn't help, Intel's manuals did neither.</p> <p>When discussing with other people, there was no-one else who experienced the same behaviour. If it had to do with the kernel, then at least 3 versions were affected, but then... what does the kernel have to do with it?</p> <p>I've also had the netbook in service, and it came back with a new motherboard &mdash; implied a new CPU, so at least two individual entities of N450 must be affected.</p> <p>I've also took measures against clock frequency changes (and no matter what frequency I fixed the clock to, the values varied only in the expected range (the same as shown)), and switched off HT, though these should actually <em>help</em> to get some other least significant digits, rather than preventing them. But just to be sure.</p> <p>Well, if anyone wants to run the program on their machine, the command line is (provided you save the source in a file <code>rdtsc.s</code>):</p> <pre><code>as rdtsc.s -o rdtsc.o ld --dynamic-linker=/lib64/ld-linux-x86-64.so.2 rdtsc.o -L /lib64 -l c -o rdtsc </code></pre> <p>In order to build it with the gcc frontend, i. e.</p> <pre><code>gcc -l c rdtsc.s -o rdtsc </code></pre> <p>you must add (or replace the <code>_start:</code> label with) a <code>main:</code> label and make it global.</p> <p>[update (2012-09-15 ~21:15 UTC): Actually I could also have done <em>this</em> before: I just let it take the TSC before and after a <code>sleep(1)</code>, which gives a delta slightly greater than 1,666,000,000, which shows that the third point in the list above is wrong. But still I have no idea why I don't get the full precision. /update]</p>
    singulars
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload