Re: [ACPI] Re: Linux 2.4.26-rc1 (cmpxchg vs 80386 build)

From: Richard B. Johnson
Date: Thu Apr 01 2004 - 08:22:11 EST


On Thu, 1 Apr 2004, Maciej W. Rozycki wrote:

> On Wed, 31 Mar 2004, Jamie Lokier wrote:
>
> > > Well, "cmpxchg", "xadd", etc. can be easily emulated with an aid of a
> > > spinlock. With SMP operation included.
> >
> > Nope. Len Brown wrote:
> >
> > > Linux uses this locking mechanism to coordinate shared access
> > > to hardware registers with embedded controllers,
> > > which is true also on uniprocessors too.
> >
> > You can't do that with a spinlock. The embedded controllers would
> > need to know about the spinlock.
>
> Hmm, does it mean we support x86 systems where an iomem resource has to
> be atomically accessible by a CPU and a peripheral controller?
>
> --
> + Maciej W. Rozycki, Technical University of Gdansk, Poland +
> +--------------------------------------------------------------+
> + e-mail: macro@xxxxxxxxxxxxx, PGP key available +


Of course they all can be emulated. And some "embedded
controllers" don't care and won't have a clue.

The whole idea of atomic operations is to have the specific
operation complete entirely so there is no intermediate
state that can catch you with your pants down.

For instance, If I code something in 'C' as:

x++;

I would expect that the value of x after the sequence-
point is exactly one more than it was before. However,
if x happens to be a long long in ix86 machines, you
are screwed because the operation occurs in two stages.

addl $1,(x) # Low word
adcl $0,4(x) # CY into high word

If you got interrupted between the first and second operation,
AND if the result of the operation was used before it was
completed, the user gets the wrong value.

In Intel machines ALL memory operations are atomic. What
the means is that if I make code that does:

addl %eax,(memory)

... what's in memory will always be the sum of what it was
before and the value in the EAX register. However, if I
made code that did:

movl (memory), %ecx # Get value from memory
addl %eax, %ecx # Add from EAX
movl %ecx, (memory) # Put value back into memory

... such operations are not atomic even though they do the
same thing.

A long time ago, somebody invented the 'lock' instruction
for Intel machines. It turns out that the first ones locked
the whole bus during an operation. Eventually somebody looked
at that, and by the time the '486 came out, they no longer
locked the whole bus. Then somebody else said; "WTF...
Why do we even need this stuff". It was a throw-back to
early primitive machines where there were only load and
store operations in memory. All arithmetic had to be done
in registers. Now, there are only a couple instructions you
can use the lock prefix with, or you get an invalid opcode
trap, and they are really no-ops because the instruction
itself is atomic.

To make the:

movl (memory), %ecx # Get value from memory
addl %eax, %ecx # Add from EAX
movl %ecx, (memory) # Put value back into memory

... code atomic, you need only to prevent it from being
interrupted. On a non-SMP machine, it's easy.

pushf # Save flags
cli # Clear interrupt bit
movl (memory), %ecx # Get value from memory
addl %eax, %ecx # Add from EAX
movl %ecx, (memory) # Put value back into memory
popf # Restore flags (and interrupt bit)

It's a bit more complicated on SMP machines because CLI only
affects the CPU that fetched it. You need a spin-lock for
that.

Now, if my memory operand happens to be some bits that
control a machine, we are not talking about atomic operations
at all, but the order of operations. This could take a
whole chapter in a book.

Cheers,
Dick Johnson
Penguin : Linux version 2.4.24 on an i686 machine (797.90 BogoMips).
Note 96.31% of all statistics are fiction.


-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/