Java's Atomic and volatile, under the hood on x86
brooker.co.za
brooker.co.za
For example, take this C program which uses the GCC atomic builtin __sync_add_and_fetch():
void f(int *x) { __sync_add_and_fetch(x, 1); }
This compiles into: lock add DWORD PTR [rdi],0x1
ret
cmpxchg is also vulnerable to the ABA problem (http://en.wikipedia.org/wiki/ABA_problem), which the "lock add" approach is not."inc" is also an instruction best avoided these days, since it doesn't update all of the flags and can therefore cause an EFLAGS stall (http://stackoverflow.com/questions/12163610/why-inc-and-add-...)
How is that accomplished? Isn't the stall required by definition, since the partial flags update creates extra data dependencies?
One simple and common optimization is to perform register rename on the flags register. More often than not, the flags updated by INC or DEC are simply overwritten by a later arithmetic instruction without ever being used; simple rename can eliminate the stall in these cases.
Another simple optimization would be for the front-end perform macro-op fusion of an INC or DEC with a following branch that is known to only use the flag bits written by the INC; then the fused macro-op can issue without waiting on the other flag bits, and avoid stalling control flow.
However, I have no inside knowledge about what particular changes Intel made or didn't made to remove this particular hazard; I only know that it seems to have been nearly entirely eliminated.
http://securitysauce.blogspot.com/2009/04/snort-30-beta-3-re...
Edit: to clarify, snort can run across multiple threads, but a single stream is handled by a single thread. When they tried to process the same data in multiple threads at once, cache synching killed performance.
Flow affinity, locking "streams" to cores, is the way to go. Relevant linux kernel support: http://git.kernel.org/?p=linux/kernel/git/torvalds/linux.git...
Apparently this is a register that was added with AMD64. I guess that's what I get for not keeping up with x86 assembly over the last five years.
Edit: It is not valid according to http://www.codeproject.com/Articles/45788/The-Real-Protected... - so headlining with "x86" is misleading at best.
from http://en.wikipedia.org/wiki/X86-64
>> The first AMD64-based processor, the Opteron, was released in April 2003.
>> The first processor to implement Intel 64 was the multi-socket processor Xeon code-named Nocona in June 2004.
>> Intel's official launch of Intel 64 (under the name EM64T at that time) in mainstream desktop processors was the N0 Stepping Prescott-2M. All 9xx, 8xx, 6xx, 5x9, 5x6, 5x1, 3x6, and 3x1 series CPUs have Intel 64 enabled, as do the Core 2 CPUs, as will future Intel CPUs for workstations or servers. Intel 64 is also present in the last members of the Celeron D line.
>> The first Intel mobile processor implementing Intel 64 is the Merom version of the Core 2 processor, which was released on 27 July 2006.
What I was trying to get across is that, in the trivial implementation, visibility and atomicity are required. There are obviously better ways for threads to correctly count in parallel with much better performance - but not ones that Java will automatically recognize based on the obvious implementation of the code.