On Zen5, even a 5-register cycle can be profitably implemented with
xchg when you have no spare register, a 4-register cycle even when
you have a spare register. For Zen4 and Zen3 cyc4 (for mem) and cyc3
(for reg) are borderline cases, and for shorter cycles xchg is
better.
On Intel processors, xchg is so slow that it never is profitable to
use it. The slowness takes on extreme values in the E-cores, with
slowdowns by a factor >10 for cyc4 and cyc5.
On Tue, 13 Oct 2026 08:43:47 GMT, Anton Ertl wrote:
On Zen5, even a 5-register cycle can be profitably implemented with
xchg when you have no spare register, a 4-register cycle even when
you have a spare register. For Zen4 and Zen3 cyc4 (for mem) and cyc3
(for reg) are borderline cases, and for shorter cycles xchg is
better.
On Intel processors, xchg is so slow that it never is profitable to
use it. The slowness takes on extreme values in the E-cores, with
slowdowns by a factor >10 for cyc4 and cyc5.
You’d think both companies would be running similar kinds of
instruction workloads to find the things worth optimizing in their CPU >architectures. But perhaps not ...
Microbenchmarks (and this text in HTML form) on <http://www.complang.tuwien.ac.at/anton/xchg/>.
In compilers, in particular in SSA destruction, or, more generally,
register allocation, you sometimes have situations where you want to
swap the contents of registers, e.g., when r1 contains a and r2
contains b on one path, while r1 contains b and r2 contains a on the
other path, and both paths join. This can be achieved with 3 mov instructions, but requires an extra register. The AMD64 instruction
set contains the instruction xchg, which swaps the registers without
extra register.
More generally, there may be more than two registers whose values have
to be moved in a cyclic way. This also requires an extra register and
(for an n-register cycle) n+1 mov instructions if performed using mov instructions, or it can be achieved with n-1 xchg instructions.
Mov instructions are supported very well in recent CPU cores, with the
cores usually being able to perform as many independent (and often
even dependent) moves as the register renamer accepts instructions
(e.g., if the register renamer accepts 8 instructions per cycle, 8
moves per cycle can be performed, usually even dependent moves).
But how do xchg instructions perform? Should a register allocator use
them where they are convenient, or prefer to use mov instructions and
an extra register?
<http://www.complang.tuwien.ac.at/anton/xchg/> contains
microbenchmarks and this posting presents results for them on various
cores from Intel and AMD. The first set of microbenchmarks perform 1G
xchg instructions in a loop containing 28 xchg instructions (plus two instructions for the loop).
One (independent) contains a sequence of 7 xchg instructions that are
fully independent of each other, all accessing different registers,
followed by the same sequence another three times. So the xchg
instructions are as independent as possible with 14 registers
involved.
The other (dependent) contains a sequence of 14 xchg instructions
where each subsequent instruction uses one register of the previous instruction, implementing a 15-register cycle. This sequence is
followed by the reversal of this sequence, resulting in performing the 15-register cycle in the other direction.
Here are the results in Gcycles on recent microarchitectures, i.e., a
result of 0.25 means that the microarchitecture performs 4 xchg
instructions per cycle. Smaller is better.
indep dep core family CPU
0.26 0.26 Zen5 AMD Ryzen AI Pro 350
0.35 0.35 Zen4 AMD Ryzen 8700G
0.35 0.35 Zen3 AMD Ryzen 5800X
0.61 1.50 Lion Cove Intel P Core Ultra 225
1.00 1.50 Golden Cove Intel P Core i3-1315U
0.82 1.50 Rocket Lake Intel P Xeon E-2388G
2.07 2.05 Skymont Intel E Core Ultra 225
3.45 3.45 Gracemont Intel E Core i3-1315U
Given the results of the dependent benchmark, it looks like the AMD processors perform xchg in the register renamer, consuming the
resources of two ordinary instructions there (probably because two
result registers are involved).
On Intel microarchitectures, whether P-cores or E-cores, but
especially the latter, xchg seems to have gotten little love.
Let's see how this affects cyclic moves between registers. The
following microbenchmarks perform cyclic moves through 2-5 registers (cyc2-cyc5) in three different ways:
mem Store the first register to memory, then perform n-1 moves among
registers, then load the memory location into the final register.
reg Move the first register into a spare register, then perform n-1
moves among the cycled registers, then move the spare register
into the final register.
xchg Use n-1 xchg instructions.
The benchmark loop contains 12 cycles, and cycles involving
non-overlapping sets of registers are benchmarked (6 sets for cyc2, 4
for cyc3, 3 for cyc4, 2 for cyc5). At least three different memory
locations are used for holding the value of the first register in
memory, but the same register is used as the spare register. Here are
the results (execution cycles per cyclic move (i.e., n+1 movs in case
of reg, n-1 xchgs in case of xchg).
cyc2 | cyc3 | cyc4 | cyc5 |core
mem reg xchg|mem reg xchg|mem reg xchg|mem reg xchg|
0.50 0.50 0.27|0.67 0.58 0.52|0.83 0.83 0.77|1.08 0.83 1.02|Zen5
1.00 0.51 0.36|1.00 0.68 0.69|1.00 0.85 1.03|1.01 1.01 1.36|Zen4
1.00 0.51 0.42|1.00 0.68 0.70|1.00 0.92 1.03|1.02 1.01 1.36|Zen3
0.50 0.40 0.68|0.54 0.56 1.28|0.67 0.66 1.97|0.81 0.81 4.21|Lion
Cove 0.61 0.53 1.00|0.70 0.70 2.00|0.89 0.90 3.00|1.06 1.08
4.41|Golden Cove 0.82 0.67 1.00|0.87 0.83 2.00|1.08 1.08 3.00|1.22
1.22 4.66|Rocket Lake 1.00 0.40 1.45|0.65 0.73 4.14|0.65 0.65
7.35|0.78 0.86 9.44|Skymont 0.67 0.67 3.08|0.83 0.83 6.73|1.03 1.03 10.63|1.23 1.23 13.77|Gracemont
On Zen5, even a 5-register cycle can be profitably implemented with
xchg when you have no spare register, a 4-register cycle even when you
have a spare register. For Zen4 and Zen3 cyc4 (for mem) and cyc3 (for
reg) are borderline cases, and for shorter cycles xchg is better.
On Intel processors, xchg is so slow that it never is profitable to
use it. The slowness takes on extreme values in the E-cores, with
slowdowns by a factor >10 for cyc4 and cyc5.
- anton
/ERROR "unexpected byte sequence starting at index 607: '\xE2'" while decoding/:
Lawrence =?iso-8859-13?q?D=FFOliveiro?= <[email protected]d> writes:
On Tue, 13 Oct 2026 08:43:47 GMT, Anton Ertl wrote:
On Zen5, even a 5-register cycle can be profitably implemented with
xchg when you have no spare register, a 4-register cycle even when
you have a spare register. For Zen4 and Zen3 cyc4 (for mem) and cyc3
(for reg) are borderline cases, and for shorter cycles xchg is
better.
On Intel processors, xchg is so slow that it never is profitable to
use it. The slowness takes on extreme values in the E-cores, with
slowdowns by a factor >10 for cyc4 and cyc5.
Youâd think both companies would be running similar kinds of >instruction workloads to find the things worth optimizing in their CPU >architectures. But perhaps not ...
Or maybe, given the structure of the renamer, an AMD engineer saw a relatively easy way to implement xchg efficiently, and did it, without
first looking at how often xchg occurs in benchmark programs. And at
Intel, either no engineer thought about this, or the structure of the
renamer makes an efficient implementation much harder.
It makes me wonder, however, why cyc2xchg is more expensive than--- Synchronet 3.22a-Linux NewsLink 1.2
cyc2reg, though. An easy implementation should be to decode xchg reg,
reg into three mov reg, reg (i.e., what cyc2reg implements), where the
spare register is a non-architectural register. But on every measured
Intel microarchitecture cyc2xchg is substantially slower than cyc2reg.
- anton
Unlike Mainframes where sort is bread-and-butter operation, on PCs
(and similar) it is not.
Unlike Mainframes where sort is bread-and-butter operation, on PCs
(and similar) it is not.
MitchAlsup <[email protected]d> writes:
Unlike Mainframes where sort is bread-and-butter operation, on PCs
(and similar) it is not.
And the relevance of that for "Performance of xchg reg,reg" is?
Microbenchmarks (and this text in HTML form) on <http://www.complang.tuwien.ac.at/anton/xchg/>.
In compilers, in particular in SSA destruction, or, more generally,
register allocation, you sometimes have situations where you want to
swap the contents of registers, e.g., when r1 contains a and r2
contains b on one path, while r1 contains b and r2 contains a on the
other path, and both paths join. This can be achieved with 3 mov instructions, but requires an extra register. The AMD64 instruction
set contains the instruction xchg, which swaps the registers without
extra register.
More generally, there may be more than two registers whose values have
to be moved in a cyclic way. This also requires an extra register and
(for an n-register cycle) n+1 mov instructions if performed using mov instructions, or it can be achieved with n-1 xchg instructions.
Mov instructions are supported very well in recent CPU cores, with the
cores usually being able to perform as many independent (and often
even dependent) moves as the register renamer accepts instructions
(e.g., if the register renamer accepts 8 instructions per cycle, 8
moves per cycle can be performed, usually even dependent moves).
But how do xchg instructions perform? Should a register allocator use
them where they are convenient, or prefer to use mov instructions and
an extra register?
<http://www.complang.tuwien.ac.at/anton/xchg/> contains
microbenchmarks and this posting presents results for them on various
cores from Intel and AMD. The first set of microbenchmarks perform 1G
xchg instructions in a loop containing 28 xchg instructions (plus two instructions for the loop).
One (independent) contains a sequence of 7 xchg instructions that are
fully independent of each other, all accessing different registers,
followed by the same sequence another three times. So the xchg
instructions are as independent as possible with 14 registers
involved.
The other (dependent) contains a sequence of 14 xchg instructions
where each subsequent instruction uses one register of the previous instruction, implementing a 15-register cycle. This sequence is
followed by the reversal of this sequence, resulting in performing the 15-register cycle in the other direction.
Here are the results in Gcycles on recent microarchitectures, i.e., a
result of 0.25 means that the microarchitecture performs 4 xchg
instructions per cycle. Smaller is better.
indep dep core family CPU
0.26 0.26 Zen5 AMD Ryzen AI Pro 350
0.35 0.35 Zen4 AMD Ryzen 8700G
0.35 0.35 Zen3 AMD Ryzen 5800X
0.61 1.50 Lion Cove Intel P Core Ultra 225
1.00 1.50 Golden Cove Intel P Core i3-1315U
0.82 1.50 Rocket Lake Intel P Xeon E-2388G
2.07 2.05 Skymont Intel E Core Ultra 225
3.45 3.45 Gracemont Intel E Core i3-1315U
Given the results of the dependent benchmark, it looks like the AMD processors perform xchg in the register renamer, consuming the
resources of two ordinary instructions there (probably because two
result registers are involved).
On Intel microarchitectures, whether P-cores or E-cores, but
especially the latter, xchg seems to have gotten little love.
Let's see how this affects cyclic moves between registers. The
following microbenchmarks perform cyclic moves through 2-5 registers (cyc2-cyc5) in three different ways:
mem Store the first register to memory, then perform n-1 moves among
registers, then load the memory location into the final register.
reg Move the first register into a spare register, then perform n-1
moves among the cycled registers, then move the spare register
into the final register.
xchg Use n-1 xchg instructions.
The benchmark loop contains 12 cycles, and cycles involving
non-overlapping sets of registers are benchmarked (6 sets for cyc2, 4
for cyc3, 3 for cyc4, 2 for cyc5). At least three different memory
locations are used for holding the value of the first register in
memory, but the same register is used as the spare register. Here are
the results (execution cycles per cyclic move (i.e., n+1 movs in case
of reg, n-1 xchgs in case of xchg).
cyc2 | cyc3 | cyc4 | cyc5 |core
mem reg xchg|mem reg xchg|mem reg xchg|mem reg xchg|
0.50 0.50 0.27|0.67 0.58 0.52|0.83 0.83 0.77|1.08 0.83 1.02|Zen5
1.00 0.51 0.36|1.00 0.68 0.69|1.00 0.85 1.03|1.01 1.01 1.36|Zen4
1.00 0.51 0.42|1.00 0.68 0.70|1.00 0.92 1.03|1.02 1.01 1.36|Zen3
0.50 0.40 0.68|0.54 0.56 1.28|0.67 0.66 1.97|0.81 0.81 4.21|Lion Cove
0.61 0.53 1.00|0.70 0.70 2.00|0.89 0.90 3.00|1.06 1.08 4.41|Golden Cove 0.82 0.67 1.00|0.87 0.83 2.00|1.08 1.08 3.00|1.22 1.22 4.66|Rocket Lake 1.00 0.40 1.45|0.65 0.73 4.14|0.65 0.65 7.35|0.78 0.86 9.44|Skymont
0.67 0.67 3.08|0.83 0.83 6.73|1.03 1.03 10.63|1.23 1.23 13.77|Gracemont
On Zen5, even a 5-register cycle can be profitably implemented with
xchg when you have no spare register, a 4-register cycle even when you
have a spare register. For Zen4 and Zen3 cyc4 (for mem) and cyc3 (for
reg) are borderline cases, and for shorter cycles xchg is better.
On Intel processors, xchg is so slow that it never is profitable to
use it. The slowness takes on extreme values in the E-cores, with
slowdowns by a factor >10 for cyc4 and cyc5.
- anton
Well, for some reason the LOCK prefix is implied for XCHG.
Well, for some reason the LOCK prefix is implied for XCHG.
"Chris M. Thomasson" <[email protected]> writes:No, it does not.
Well, for some reason the LOCK prefix is implied for XCHG.
According to <https://www.felixcloutier.com/x86/xchg> (which is based
on (I think) Intel's documentation):
|If a memory operand is referenced, the processor’s locking
protocol is |automatically implemented for the duration of the
exchange operation, |regardless of the presence or absence of the
LOCK prefix or of the |value of the IOPL.
This does not cover the "xchg reg, reg" case.
<https://www.felixcloutier.com/x86/lock> says:
|The XCHG instruction always asserts the LOCK# signal regardless of
the |presence or absence of the LOCK prefix.
This seems to include the "xchg reg, reg" case,
but asserting theIntel text (325383-060US September 2016):
LOCK# signal would make no difference, because: "the LOCK# signal
ensures that the processor has exclusive use of any shared memory
while the signal is asserted" and "the processor’s cache coherency mechanism ensures that the operation is carried out atomically with
regards to memory", but "xchg reg, reg" does not use memory at all,
and other processors have no access to a processor's registers.
- anton
On Thu, 15 Oct 2026 14:21:07 -0700, Chris M. Thomasson wrote:The implied LOCK only happens with a memory operand specified in the r/m byte. Terje
Well, for some reason the LOCK prefix is implied for XCHG.
I can imagine that being useful when accessing memory, but not just
for exchanging registers ...
[email protected] (Anton Ertl) writes:
MitchAlsup <[email protected]d> writes:
Unlike Mainframes where sort is bread-and-butter operation, on PCs
(and similar) it is not.
And the relevance of that for "Performance of xchg reg,reg" is?
To give you an idea what xchg reg,reg is good for:
long foo(long a, long b);
long bar(long a, long b)
{
return foo(b,a);
}
Both gcc-16 and clang-19 (even with -mtune=znver5) compile this to:
0000000000000000 <bar>:
0: 48 89 f8 mov %rdi,%rax
3: 48 89 f7 mov %rsi,%rdi
6: 48 89 c6 mov %rax,%rsi
9: e9 00 00 00 00 jmp e <bar+0xe> #actually jmp foo
This could be replaced with
xchg %rdi,%rsi
jmp foo
On 2026-Oct-15 03:06, Anton Ertl wrote:
Both gcc-16 and clang-19 (even with -mtune=znver5) compile this to:
0000000000000000 <bar>:
0: 48 89 f8 mov %rdi,%rax
3: 48 89 f7 mov %rsi,%rdi
6: 48 89 c6 mov %rax,%rsi
9: e9 00 00 00 00 jmp e <bar+0xe> #actually jmp foo
This could be replaced with
xchg %rdi,%rsi
jmp foo
There is also the xor swap which doesn't need an extra register
xor rax,rbx
xor rbx,rax
xor rax,rbx
On Fri, 16 Oct 2026 05:50:55 GMT
[email protected] (Anton Ertl) wrote:
"Chris M. Thomasson" <[email protected]> writes:
Well, for some reason the LOCK prefix is implied for XCHG.
According to <https://www.felixcloutier.com/x86/xchg> (which is based
on (I think) Intel's documentation):
|If a memory operand is referenced, the processor’s locking protocol is
|automatically implemented for the duration of the exchange operation,
|regardless of the presence or absence of the LOCK prefix or of the
|value of the IOPL.
This does not cover the "xchg reg, reg" case.
<https://www.felixcloutier.com/x86/lock> says:
|The XCHG instruction always asserts the LOCK# signal regardless of the
|presence or absence of the LOCK prefix.
This seems to include the "xchg reg, reg" case,
No, it does not.
In article <[email protected]>,
Michael S <[email protected]> wrote:
On Fri, 16 Oct 2026 05:50:55 GMT
[email protected] (Anton Ertl) wrote:
"Chris M. Thomasson" <[email protected]> writes:
Well, for some reason the LOCK prefix is implied for XCHG.
According to <https://www.felixcloutier.com/x86/xchg> (which is based
on (I think) Intel's documentation):
|If a memory operand is referenced, the processor’s locking protocol is
|automatically implemented for the duration of the exchange operation,
|regardless of the presence or absence of the LOCK prefix or of the
|value of the IOPL.
This does not cover the "xchg reg, reg" case.
<https://www.felixcloutier.com/x86/lock> says:
|The XCHG instruction always asserts the LOCK# signal regardless of the
|presence or absence of the LOCK prefix.
This seems to include the "xchg reg, reg" case,
No, it does not.
Unfortunately, the information is spread across two sections,
and they contradict. The description in the `LOCK` prefix
section in the latest version of the Intel SDM includes the text
Anton quoted, while the description of `XCHG` itself makes clear
that the destination operand must be a memory operand for the
locking protocol to automatically apply. Which is correct?
Dan Cross <[email protected]> schrieb:
In article <[email protected]>,
Michael S <[email protected]> wrote:
On Fri, 16 Oct 2026 05:50:55 GMT
[email protected] (Anton Ertl) wrote:
"Chris M. Thomasson" <[email protected]> writes:
Well, for some reason the LOCK prefix is implied for XCHG.
According to <https://www.felixcloutier.com/x86/xchg> (which is based
on (I think) Intel's documentation):
|If a memory operand is referenced, the processor’s locking protocol is
|automatically implemented for the duration of the exchange operation, >>>> |regardless of the presence or absence of the LOCK prefix or of the
|value of the IOPL.
This does not cover the "xchg reg, reg" case.
<https://www.felixcloutier.com/x86/lock> says:
|The XCHG instruction always asserts the LOCK# signal regardless of the >>>> |presence or absence of the LOCK prefix.
This seems to include the "xchg reg, reg" case,
No, it does not.
Unfortunately, the information is spread across two sections,
and they contradict. The description in the `LOCK` prefix
section in the latest version of the Intel SDM includes the text
Anton quoted, while the description of `XCHG` itself makes clear
that the destination operand must be a memory operand for the
locking protocol to automatically apply. Which is correct?
What would be the meaning of LOCK with memory operands? I can't
think of any.
Thomas Koenig <[email protected]> writes:
Dan Cross <[email protected]> schrieb:
In article <[email protected]>,
Michael S <[email protected]> wrote:
On Fri, 16 Oct 2026 05:50:55 GMT
[email protected] (Anton Ertl) wrote:
"Chris M. Thomasson" <[email protected]> writes:
Well, for some reason the LOCK prefix is implied for XCHG.
According to <https://www.felixcloutier.com/x86/xchg> (which is based >>>>> on (I think) Intel's documentation):
|If a memory operand is referenced, the processor’s locking protocol is
|automatically implemented for the duration of the exchange operation, >>>>> |regardless of the presence or absence of the LOCK prefix or of the
|value of the IOPL.
This does not cover the "xchg reg, reg" case.
<https://www.felixcloutier.com/x86/lock> says:
|The XCHG instruction always asserts the LOCK# signal regardless of the >>>>> |presence or absence of the LOCK prefix.
This seems to include the "xchg reg, reg" case,
No, it does not.
Unfortunately, the information is spread across two sections,
and they contradict. The description in the `LOCK` prefix
section in the latest version of the Intel SDM includes the text
Anton quoted, while the description of `XCHG` itself makes clear
that the destination operand must be a memory operand for the
locking protocol to automatically apply. Which is correct?
What would be the meaning of LOCK with memory operands? I can't
think of any.
Did you mean 'without memory operands'? It's clear that there
is no need to acquire the cache and/or system lock if there
are no memory operands, and a substantial performance penalty;
besides, which cache line would it use for the case where both
operands are registers?
Dan Cross <[email protected]> schrieb:
Unfortunately, the information is spread across two sections,
and they contradict. The description in the `LOCK` prefix
section in the latest version of the Intel SDM includes the text
Anton quoted, while the description of `XCHG` itself makes clear
that the destination operand must be a memory operand for the
locking protocol to automatically apply. Which is correct?
What would be the meaning of LOCK with memory operands? I can't
think of any.
There is also the xor swap which doesn't need an extra register
xor rax,rbx
xor rbx,rax
xor rax,rbx
Thomas Koenig <[email protected]> writes:
Dan Cross <[email protected]> schrieb:
In article <[email protected]>,
Michael S <[email protected]> wrote:
On Fri, 16 Oct 2026 05:50:55 GMT
[email protected] (Anton Ertl) wrote:
"Chris M. Thomasson" <[email protected]> writes:
Well, for some reason the LOCK prefix is implied for XCHG.
According to <https://www.felixcloutier.com/x86/xchg> (which is based >>>>> on (I think) Intel's documentation):
|If a memory operand is referenced, the processor’s locking protocol is
|automatically implemented for the duration of the exchange operation, >>>>> |regardless of the presence or absence of the LOCK prefix or of the
|value of the IOPL.
This does not cover the "xchg reg, reg" case.
<https://www.felixcloutier.com/x86/lock> says:
|The XCHG instruction always asserts the LOCK# signal regardless of the >>>>> |presence or absence of the LOCK prefix.
This seems to include the "xchg reg, reg" case,
No, it does not.
Unfortunately, the information is spread across two sections,
and they contradict. The description in the `LOCK` prefix
section in the latest version of the Intel SDM includes the text
Anton quoted, while the description of `XCHG` itself makes clear
that the destination operand must be a memory operand for the
locking protocol to automatically apply. Which is correct?
What would be the meaning of LOCK with memory operands? I can't
think of any.
Did you mean 'without memory operands'?
It's clear that there
is no need to acquire the cache and/or system lock if there
are no memory operands, and a substantial performance penalty;
besides, which cache line would it use for the case where both
operands are registers?
In article <11au1vu$3ks5m$[email protected]>,
Thomas Koenig <[email protected]> wrote:
Dan Cross <[email protected]> schrieb:
Unfortunately, the information is spread across two sections,
and they contradict. The description in the `LOCK` prefix
section in the latest version of the Intel SDM includes the text
Anton quoted, while the description of `XCHG` itself makes clear
that the destination operand must be a memory operand for the
locking protocol to automatically apply. Which is correct?
What would be the meaning of LOCK with memory operands? I can't
think of any.
Using the `LOCK` prefix without a destination operand that is a
memory operand is an error, and the SDM is quite explicit about
that. In fact, it says that an explicit `LOCK` prefix on an
`XCHG` a register destination operand is _not_ permitted and
"may" generate an `#UD` exception.
But sadly, when talking about an `XCHG` _without_ an explicit
operand, it is left ambiguous; all it says is that, "The `XCHG`
instruction always asserts the `LOCK#` signal regardless of the
presence or absence of the `LOCK` prefix." Devoid of the rest
of the surrounding context, one could interpret that to mean
that an `XCHG` _always_ forces a bus lock, irrespective of the
type of its desintation operand.
Why?
I have no idea; as I said, I'm in the camp of going with
what the description of `XCHG` itself says, and not the what the
description of the `LOCK` prefix says: that sentence is _not_
devoid of context, and besides, there has not been a physical
`LOCK#` signal coming out of an Intel Xeon package since
Nehalem.
I suppose one could imagine it forcing a poor-man's barrier to
prevent later loads from being reorderd before it (loads can't
migrate before locked instructions). But we've got explicit
fence instructions for that, so I don't buy it.
I suspect that sentence is just poorly phrased.
- Dan C.
In article <11au1vu$3ks5m$[email protected]>,
Thomas Koenig <[email protected]> wrote:
Dan Cross <[email protected]> schrieb:
Unfortunately, the information is spread across two sections,
and they contradict. The description in the `LOCK` prefix
section in the latest version of the Intel SDM includes the text
Anton quoted, while the description of `XCHG` itself makes clear
that the destination operand must be a memory operand for the
locking protocol to automatically apply. Which is correct?
What would be the meaning of LOCK with memory operands? I can't
think of any.
Using the `LOCK` prefix without a destination operand that is a
memory operand is an error, and the SDM is quite explicit about
that. In fact, it says that an explicit `LOCK` prefix on an
`XCHG` a register destination operand is _not_ permitted and
"may" generate an `#UD` exception.
But sadly, when talking about an `XCHG` _without_ an explicit
operand, it is left ambiguous; all it says is that, "The `XCHG`
instruction always asserts the `LOCK#` signal regardless of the
presence or absence of the `LOCK` prefix." Devoid of the rest
of the surrounding context, one could interpret that to mean
that an `XCHG` _always_ forces a bus lock, irrespective of the
type of its desintation operand.
Why?
Older machines performed the read, returned the read data to
a core and then sent the data to be written back to memory;
where the time between the read and the write was unknowable.
Some newer machines take the data to be written and package it
up in an interconnect transaction so the read and write happen
on back-to-back cycles with no possibility of interference.
These are ATOMIC even without any bus-locking. The data read
out is returned to the core.
I have no idea; as I said, I'm in the camp of going with
what the description of `XCHG` itself says, and not the what the
description of the `LOCK` prefix says: that sentence is _not_
devoid of context, and besides, there has not been a physical
`LOCK#` signal coming out of an Intel Xeon package since
Nehalem.
I suppose one could imagine it forcing a poor-man's barrier to
prevent later loads from being reorderd before it (loads can't
migrate before locked instructions). But we've got explicit
fence instructions for that, so I don't buy it.
I suspect that sentence is just poorly phrased.
In article <[email protected]>,
MitchAlsup <[email protected]d> wrote: >[email protected] (Dan Cross) posted:
In article <11au1vu$3ks5m$[email protected]>,
Thomas Koenig <[email protected]> wrote:
Dan Cross <[email protected]> schrieb:
Unfortunately, the information is spread across two sections,
and they contradict. The description in the `LOCK` prefix
section in the latest version of the Intel SDM includes the text
Anton quoted, while the description of `XCHG` itself makes clear
that the destination operand must be a memory operand for the
locking protocol to automatically apply. Which is correct?
What would be the meaning of LOCK with memory operands? I can't
think of any.
Using the `LOCK` prefix without a destination operand that is a
memory operand is an error, and the SDM is quite explicit about
that. In fact, it says that an explicit `LOCK` prefix on an
`XCHG` a register destination operand is _not_ permitted and
"may" generate an `#UD` exception.
But sadly, when talking about an `XCHG` _without_ an explicit
operand, it is left ambiguous; all it says is that, "The `XCHG`
instruction always asserts the `LOCK#` signal regardless of the
presence or absence of the `LOCK` prefix." Devoid of the rest
of the surrounding context, one could interpret that to mean
that an `XCHG` _always_ forces a bus lock, irrespective of the
type of its desintation operand.
Why?
Older machines performed the read, returned the read data to
a core and then sent the data to be written back to memory;
where the time between the read and the write was unknowable.
Some newer machines take the data to be written and package it
up in an interconnect transaction so the read and write happen
on back-to-back cycles with no possibility of interference.
These are ATOMIC even without any bus-locking. The data read
out is returned to the core.
No, I get that; I mean in the case where both operands to `XCHG`
are _register_ operands.
What I'm saying is that, as written, the bits in the `LOCK`
description above _could_ be interpreted to mean that _any_
`XCHG` will always assert the `LOCK#` signal, including an
`XCHG` that does not touch memory at all. The "Why?" was
rhetorical, as in, "Why would the system do that?" For example,
if one wrote, `xchg %ecx, %eax`, why should that assert `LOCK#`?
Truly I don't know, and I was just speculating.
But as I said, I don't think that is what the sentence in
question is _actually_ saying, and I really don't think that
`xchg %ecx, %eax` _actually_ asserts `LOCK#` (or, these days,
has anything to do with cache coherency and memory ordering).
I have no idea; as I said, I'm in the camp of going with
what the description of `XCHG` itself says, and not the what the
description of the `LOCK` prefix says: that sentence is _not_
devoid of context, and besides, there has not been a physical
`LOCK#` signal coming out of an Intel Xeon package since
Nehalem.
I suppose one could imagine it forcing a poor-man's barrier to
prevent later loads from being reorderd before it (loads can't
migrate before locked instructions). But we've got explicit
fence instructions for that, so I don't buy it.
I suspect that sentence is just poorly phrased.
- Dan C.
[email protected] (Dan Cross) posted:
In article <[email protected]>,
MitchAlsup <[email protected]d> wrote: >[email protected] (Dan Cross) posted:
In article <11au1vu$3ks5m$[email protected]>,
Thomas Koenig <[email protected]> wrote:
Dan Cross <[email protected]> schrieb:
Unfortunately, the information is spread across two sections,
and they contradict. The description in the `LOCK` prefix
section in the latest version of the Intel SDM includes the
text Anton quoted, while the description of `XCHG` itself
makes clear that the destination operand must be a memory
operand for the locking protocol to automatically apply.
Which is correct?
What would be the meaning of LOCK with memory operands? I can't
think of any.
Using the `LOCK` prefix without a destination operand that is a
memory operand is an error, and the SDM is quite explicit about
that. In fact, it says that an explicit `LOCK` prefix on an
`XCHG` a register destination operand is _not_ permitted and
"may" generate an `#UD` exception.
But sadly, when talking about an `XCHG` _without_ an explicit
operand, it is left ambiguous; all it says is that, "The `XCHG`
instruction always asserts the `LOCK#` signal regardless of the
presence or absence of the `LOCK` prefix." Devoid of the rest
of the surrounding context, one could interpret that to mean
that an `XCHG` _always_ forces a bus lock, irrespective of the
type of its desintation operand.
Why?
Older machines performed the read, returned the read data to
a core and then sent the data to be written back to memory;
where the time between the read and the write was unknowable.
Some newer machines take the data to be written and package it
up in an interconnect transaction so the read and write happen
on back-to-back cycles with no possibility of interference.
These are ATOMIC even without any bus-locking. The data read
out is returned to the core.
No, I get that; I mean in the case where both operands to `XCHG`
are _register_ operands.
What I'm saying is that, as written, the bits in the `LOCK`
description above _could_ be interpreted to mean that _any_
`XCHG` will always assert the `LOCK#` signal, including an
`XCHG` that does not touch memory at all. The "Why?" was
rhetorical, as in, "Why would the system do that?" For example,
if one wrote, `xchg %ecx, %eax`, why should that assert `LOCK#`?
Truly I don't know, and I was just speculating.
Writing high quality documentation is fundamentally hard. It took
me nearly 40 years of doing so to get to the point a mischievous
engineer could NOT misunderstand what I had written.
It is harder
wo write high quality documentation than perform circuit design.
What they wrote may have well been exactly what the HW did back then
but somewhere between then and now architects and designers figured
out other ways and nobody went back to fully scrub the documents.
But as I said, I don't think that is what the sentence in
question is _actually_ saying, and I really don't think that
`xchg %ecx, %eax` _actually_ asserts `LOCK#` (or, these days,
has anything to do with cache coherency and memory ordering).
I have no idea; as I said, I'm in the camp of going with
what the description of `XCHG` itself says, and not the what the
description of the `LOCK` prefix says: that sentence is _not_
devoid of context, and besides, there has not been a physical
`LOCK#` signal coming out of an Intel Xeon package since
Nehalem.
I suppose one could imagine it forcing a poor-man's barrier to
prevent later loads from being reorderd before it (loads can't
migrate before locked instructions). But we've got explicit
fence instructions for that, so I don't buy it.
I suspect that sentence is just poorly phrased.
- Dan C.
Writing high quality documentation is fundamentally hard.
It took me nearly 40 years of doing so to get to the point a
mischievous engineer could NOT misunderstand what I had written.
Writing high quality documentation is fundamentally hard. It took
me nearly 40 years of doing so to get to the point a mischievous
engineer could NOT misunderstand what I had written. It is harder
wo write high quality documentation than perform circuit design.
What they wrote may have well been exactly what the HW did back then
but somewhere between then and now architects and designers figured
out other ways and nobody went back to fully scrub the documents.
On Sat, 17 Oct 2026 19:39:42 GMT, MitchAlsup wrote:
Writing high quality documentation is fundamentally hard.
Isn’t that why formal specification languages were invented? For some >reason they never caught on.
For a classic example, look at the Algol-68 language spec. Yet many
people threw up their hands in horror at how it was written.
It took me nearly 40 years of doing so to get to the point a
mischievous engineer could NOT misunderstand what I had written.
Presumably you include lots of examples? I remember something Jerry
Pournelle said, critiquing the product documentation he had to read
for his columns in “BYTE” magazine, back in the day: “You can never >have too many examples”.
On Sat, 17 Oct 2026 20:54:44 -0000 (UTC), Lawrence D´Oliveiro ><[email protected]d> wrote:
Isn’t that why formal specification languages were invented? For some >>reason they never caught on.
For a classic example, look at the Algol-68 language spec. Yet many
people threw up their hands in horror at how it was written.
The problem with the original report was that they attempted with the
grammar turn [at least some kinds of] semantic errors into syntax
errors.
What I'm saying is that, as written, the bits in the `LOCK`
description above _could_ be interpreted to mean that _any_
`XCHG` will always assert the `LOCK#` signal, including an
`XCHG` that does not touch memory at all. The "Why?" was
rhetorical, as in, "Why would the system do that?" For example,
if one wrote, `xchg %ecx, %eax`, why should that assert `LOCK#`?
Truly I don't know, and I was just speculating.
Writing high quality documentation is fundamentally hard.
What they wrote may have well been exactly what the HW did back then
but somewhere between then and now architects and designers figured
out other ways and nobody went back to fully scrub the documents.
MitchAlsup <[email protected]d> writes: >[email protected] (Dan Cross) posted:
What I'm saying is that, as written, the bits in the `LOCK`
description above _could_ be interpreted to mean that _any_
`XCHG` will always assert the `LOCK#` signal, including an
`XCHG` that does not touch memory at all. The "Why?" was
rhetorical, as in, "Why would the system do that?" For example,
if one wrote, `xchg %ecx, %eax`, why should that assert `LOCK#`?
Truly I don't know, and I was just speculating.
Writing high quality documentation is fundamentally hard.
I don't think that's the issue here. They just did not limit the
sentence "The XCHG instruction always asserts the LOCK# signal
regardless of the presence or absence of the LOCK prefix." to XCHG instructions with memory operands. That would be easy to fix, but
they did not. And Chris M. Thomasson understood it as including
XCHG reg, reg.
My guess is that it is easy to fix in principle, but you have to deal
with all kinds of red tape for such a fix, so unless there is good
reason, you don't do it.
In article <[email protected]>,
MitchAlsup <[email protected]d> wrote:
[email protected] (Dan Cross) posted:
In article <11au1vu$3ks5m$[email protected]>,
Thomas Koenig <[email protected]> wrote:
Dan Cross <[email protected]> schrieb:
Unfortunately, the information is spread across two sections,
and they contradict. The description in the `LOCK` prefix
section in the latest version of the Intel SDM includes the text
Anton quoted, while the description of `XCHG` itself makes clear
that the destination operand must be a memory operand for the
locking protocol to automatically apply. Which is correct?
What would be the meaning of LOCK with memory operands? I can't
think of any.
Using the `LOCK` prefix without a destination operand that is a
memory operand is an error, and the SDM is quite explicit about
that. In fact, it says that an explicit `LOCK` prefix on an
`XCHG` a register destination operand is _not_ permitted and
"may" generate an `#UD` exception.
But sadly, when talking about an `XCHG` _without_ an explicit
operand, it is left ambiguous; all it says is that, "The `XCHG`
instruction always asserts the `LOCK#` signal regardless of the
presence or absence of the `LOCK` prefix." Devoid of the rest
of the surrounding context, one could interpret that to mean
that an `XCHG` _always_ forces a bus lock, irrespective of the
type of its desintation operand.
Why?
Older machines performed the read, returned the read data to
a core and then sent the data to be written back to memory;
where the time between the read and the write was unknowable.
Some newer machines take the data to be written and package it
up in an interconnect transaction so the read and write happen
on back-to-back cycles with no possibility of interference.
These are ATOMIC even without any bus-locking. The data read
out is returned to the core.
No, I get that; I mean in the case where both operands to `XCHG`
are _register_ operands.
What I'm saying is that, as written, the bits in the `LOCK`
description above _could_ be interpreted to mean that _any_
`XCHG` will always assert the `LOCK#` signal, including an
`XCHG` that does not touch memory at all. The "Why?" was
rhetorical, as in, "Why would the system do that?" For example,
if one wrote, `xchg %ecx, %eax`, why should that assert `LOCK#`?
Truly I don't know, and I was just speculating.
But as I said, I don't think that is what the sentence in
question is _actually_ saying, and I really don't think that
`xchg %ecx, %eax` _actually_ asserts `LOCK#` (or, these days,
has anything to do with cache coherency and memory ordering).
I have no idea; as I said, I'm in the camp of going with
what the description of `XCHG` itself says, and not the what the
description of the `LOCK` prefix says: that sentence is _not_
devoid of context, and besides, there has not been a physical
`LOCK#` signal coming out of an Intel Xeon package since
Nehalem.
I suppose one could imagine it forcing a poor-man's barrier to
prevent later loads from being reorderd before it (loads can't
migrate before locked instructions). But we've got explicit
fence instructions for that, so I don't buy it.
I suspect that sentence is just poorly phrased.
- Dan C.
In article <[email protected]>,
MitchAlsup <[email protected]d> wrote:
[email protected] (Dan Cross) posted:
In article <11au1vu$3ks5m$[email protected]>,
Thomas Koenig <[email protected]> wrote:
Dan Cross <[email protected]> schrieb:
Unfortunately, the information is spread across two sections,
and they contradict. The description in the `LOCK` prefix
section in the latest version of the Intel SDM includes the text
Anton quoted, while the description of `XCHG` itself makes clear
that the destination operand must be a memory operand for the
locking protocol to automatically apply. Which is correct?
What would be the meaning of LOCK with memory operands? I can't
think of any.
Using the `LOCK` prefix without a destination operand that is a
memory operand is an error, and the SDM is quite explicit about
that. In fact, it says that an explicit `LOCK` prefix on an
`XCHG` a register destination operand is _not_ permitted and
"may" generate an `#UD` exception.
But sadly, when talking about an `XCHG` _without_ an explicit
operand, it is left ambiguous; all it says is that, "The `XCHG`
instruction always asserts the `LOCK#` signal regardless of the
presence or absence of the `LOCK` prefix." Devoid of the rest
of the surrounding context, one could interpret that to mean
that an `XCHG` _always_ forces a bus lock, irrespective of the
type of its desintation operand.
Why?
Older machines performed the read, returned the read data to
a core and then sent the data to be written back to memory;
where the time between the read and the write was unknowable.
Some newer machines take the data to be written and package it
up in an interconnect transaction so the read and write happen
on back-to-back cycles with no possibility of interference.
These are ATOMIC even without any bus-locking. The data read
out is returned to the core.
No, I get that; I mean in the case where both operands to `XCHG`
are _register_ operands.
What I'm saying is that, as written, the bits in the `LOCK`
description above _could_ be interpreted to mean that _any_
`XCHG` will always assert the `LOCK#` signal, including an
`XCHG` that does not touch memory at all. The "Why?" was
rhetorical, as in, "Why would the system do that?" For example,
if one wrote, `xchg %ecx, %eax`, why should that assert `LOCK#`?
Truly I don't know, and I was just speculating.
Writing high quality documentation is fundamentally hard. It took
me nearly 40 years of doing so to get to the point a mischievous
engineer could NOT misunderstand what I had written. It is harder
wo write high quality documentation than perform circuit design.
What they wrote may have well been exactly what the HW did back then
but somewhere between then and now architects and designers figured
out other ways and nobody went back to fully scrub the documents.
On Sun, 18 Oct 2026 15:08:23 GMT...
[email protected] (Anton Ertl) wrote:
I don't think that's the issue here. They just did not limit the
sentence "The XCHG instruction always asserts the LOCK# signal
regardless of the presence or absence of the LOCK prefix." to XCHG
instructions with memory operands. That would be easy to fix, but
they did not. And Chris M. Thomasson understood it as including
XCHG reg, reg.
Frankly, I don't understand what both you and Dan Cross are talking
about.
I don't see how sentence from Intel's manual ("If a memory operand is >referenced, the processor=E2=80=99s locking protocol is automatically >implemented for the duration of the exchange operation, regardless of
the presence or absence of the LOCK prefix or of the value of the IOPL")
or sentence from AMD's manual ("If either operand references memory,
the processor locks automatically, whether or not the LOCK prefix is
used and independently of the value of IOPL.") can be pssibly
misunderstood.
On Sun, 18 Oct 2026 15:08:23 GMT
[email protected] (Anton Ertl) wrote:
MitchAlsup <[email protected]d> writes:
[email protected] (Dan Cross) posted:
What I'm saying is that, as written, the bits in the `LOCK`
description above _could_ be interpreted to mean that _any_
`XCHG` will always assert the `LOCK#` signal, including an
`XCHG` that does not touch memory at all. The "Why?" was
rhetorical, as in, "Why would the system do that?" For example,
if one wrote, `xchg %ecx, %eax`, why should that assert `LOCK#`?
Truly I don't know, and I was just speculating.
Writing high quality documentation is fundamentally hard.
I don't think that's the issue here. They just did not limit the
sentence "The XCHG instruction always asserts the LOCK# signal
regardless of the presence or absence of the LOCK prefix." to XCHG
instructions with memory operands. That would be easy to fix, but
they did not. And Chris M. Thomasson understood it as including
XCHG reg, reg.
My guess is that it is easy to fix in principle, but you have to deal
with all kinds of red tape for such a fix, so unless there is good
reason, you don't do it.
Frankly, I don't understand what both you and Dan Cross are talking
about.
I don't see how sentence from Intel's manual ("If a memory operand is >referenced, the processor’s locking protocol is automatically
implemented for the duration of the exchange operation, regardless of
the presence or absence of the LOCK prefix or of the value of the IOPL")
or sentence from AMD's manual ("If either operand references memory,
the processor locks automatically, whether or not the LOCK prefix is
used and independently of the value of IOPL.") can be pssibly
misunderstood.
Michael S <[email protected]> writes:
On Sun, 18 Oct 2026 15:08:23 GMT...
[email protected] (Anton Ertl) wrote:
I don't think that's the issue here. They just did not limit the
sentence "The XCHG instruction always asserts the LOCK# signal
regardless of the presence or absence of the LOCK prefix." to XCHG
instructions with memory operands. That would be easy to fix, but
they did not. And Chris M. Thomasson understood it as including
XCHG reg, reg.
Frankly, I don't understand what both you and Dan Cross are talking
about.
I don't see how sentence from Intel's manual ("If a memory operand is >referenced, the processor=E2=80=99s locking protocol is automatically >implemented for the duration of the exchange operation, regardless of
the presence or absence of the LOCK prefix or of the value of the
IOPL") or sentence from AMD's manual ("If either operand references
memory, the processor locks automatically, whether or not the LOCK
prefix is used and independently of the value of IOPL.") can be
pssibly misunderstood.
Chris M. Thomasson wrote in <11arg45$2p70p$[email protected]>:
|Well, for some reason the LOCK prefix is implied for XCHG.
Given that the thread up to that point was aboyt XCHG reg, reg (and
according to the subject it still is), he seems to be an example that
what Intel wrote about XCHG and LOCK can be misunderstood. I looked
at the documentation and cited the relevant sentences in <[email protected]>; most occurences clearly
refer only to XCHG where one operand is in memory. The exception is:
|The XCHG instruction always asserts the LOCK# signal regardless of
the |presence or absence of the LOCK prefix.
And actually all the stuff about XCHG with memory operands does not contradict this sentence. It could be understood as meaning that
while all the other aspects of locking don't apply to "XCHG reg, reg",
the assertion of the LOCK# signal still has to occur, and that's why
Intel processors implement a slow XCHG reg, reg. I don't think that's
what Intel intends and implements, but that's what a reading of their
manual implies.
- anton
On 2026-Oct-17 13:31, Dan Cross wrote:
[snip]
Intel Volume 3 System Programmers guide 10.1.2 Bus Locking
10.1.2.1 Automatic Locking is explicit:...
[snip]
On Sat, 17 Oct 2026 19:39:42 GMT, MitchAlsup wrote:
Writing high quality documentation is fundamentally hard.
Isn’t that why formal specification languages were invented? For some reason they never caught on.
For a classic example, look at the Algol-68 language spec. Yet many
people threw up their hands in horror at how it was written.
It took me nearly 40 years of doing so to get to the point a
mischievous engineer could NOT misunderstand what I had written.
Presumably you include lots of examples?
I remember something Jerry--- Synchronet 3.22a-Linux NewsLink 1.2
Pournelle said, critiquing the product documentation he had to read
for his columns in “BYTE” magazine, back in the day: “You can never have too many examples”.
In article <[email protected]>,
Michael S <[email protected]> wrote:
On Sun, 18 Oct 2026 15:08:23 GMT
[email protected] (Anton Ertl) wrote:
MitchAlsup <[email protected]d> writes:
[email protected] (Dan Cross) posted:
What I'm saying is that, as written, the bits in the `LOCK`
description above _could_ be interpreted to mean that _any_
`XCHG` will always assert the `LOCK#` signal, including an
`XCHG` that does not touch memory at all. The "Why?" was
rhetorical, as in, "Why would the system do that?" For example,
if one wrote, `xchg %ecx, %eax`, why should that assert `LOCK#`?
Truly I don't know, and I was just speculating.
Writing high quality documentation is fundamentally hard.
I don't think that's the issue here. They just did not limit the
sentence "The XCHG instruction always asserts the LOCK# signal
regardless of the presence or absence of the LOCK prefix." to XCHG
instructions with memory operands. That would be easy to fix, but
they did not. And Chris M. Thomasson understood it as including
XCHG reg, reg.
My guess is that it is easy to fix in principle, but you have to
deal with all kinds of red tape for such a fix, so unless there is
good reason, you don't do it.
Frankly, I don't understand what both you and Dan Cross are talking
about.
Because you are not reading the same thing we are.
I don't see how sentence from Intel's manual ("If a memory operand is >referenced, the processor’s locking protocol is automatically >implemented for the duration of the exchange operation, regardless of
the presence or absence of the LOCK prefix or of the value of the
IOPL") or sentence from AMD's manual ("If either operand references
memory, the processor locks automatically, whether or not the LOCK
prefix is used and independently of the value of IOPL.") can be
pssibly misunderstood.
Which part of the Intel and AMD manuals?
What Anton raised, and what I'm also referring to, is a a single
sentence in the SDM's description of the `LOCK` prefix. For
reference, I am looking at Volume 2A, order number 253666-093US,
published Sept 2026, page 3-565.
Tucked away in the "Description" section, at the end the third
paragraph, which describes what instructions can be prefaced by
`LOCK` and under what conditions, is the single sentence that
reads: "The `XCHG` instruction always asserts the `LOCK#` signal
regardless of the presence or absence of the `LOCK` prefix."
Note: that is a direct quote from the reference.
We know that `XCHG` with a memory destination operand is atomic
and affects memory ordering, etc, regardless of whether the
`LOCK` prefix is explicitly given or not. The issue is that
that sentence, taken in complete isolation, makes it sound like
this is _also_ the case for `xchg reg, reg`, where the
destination is a _register_ operand.
I claim that that is a misreading, and that a reader should
interpret that last sentence in the context of the first
sentence in that paragraph, that refers specifically to memory
operands; furthermore, other parts of the SDM are clear that
`xchg reg, reg` has no impact on memory ordering, bus locks,
etc.
Regardless, that sentence is ambiguous. References to the
description of `XCHG`, or to the locking protocols in volume 3,
does not change that.
The latest version of the entire Intel SDM is available online: https://www.intel.com/content/www/us/en/developer/articles/technical/intel-sdm.html
I had already quoted the paragarph in question in its entirely.
- Dan C.
MitchAlsup <[email protected]d> writes: >>[email protected] (Dan Cross) posted:
What I'm saying is that, as written, the bits in the `LOCK`
description above _could_ be interpreted to mean that _any_
`XCHG` will always assert the `LOCK#` signal, including an
`XCHG` that does not touch memory at all. The "Why?" was
rhetorical, as in, "Why would the system do that?" For example,
if one wrote, `xchg %ecx, %eax`, why should that assert `LOCK#`?
Truly I don't know, and I was just speculating.
Writing high quality documentation is fundamentally hard.
I don't think that's the issue here. They just did not limit the
sentence "The XCHG instruction always asserts the LOCK# signal
regardless of the presence or absence of the LOCK prefix." to XCHG >instructions with memory operands. That would be easy to fix, but
they did not. And Chris M. Thomasson understood it as including
XCHG reg, reg.
My guess is that it is easy to fix in principle, but you have to deal
with all kinds of red tape for such a fix, so unless there is good
reason, you don't do it.
This sentence already exists in my 1994-vintage Pentium Processor
User's Manual Vol. 3. There it is preceeded by:
|The LOCK prefix functions only with the following instructions:
|
|...
|XCHG reg, mem
|XCHG mem, reg
|...
With no occurence of XCHG reg, reg anywhere. But, OTOH, this is not
really a contradiction to the sentence "The XCHG instruction always
asserts the LOCK# signal regardless of the presence or absence of the
LOCK prefix."
What they wrote may have well been exactly what the HW did back then
but somewhere between then and now architects and designers figured
out other ways and nobody went back to fully scrub the documents.
Actually <https://www.felixcloutier.com/x86/lock> then says that
"Beginning with the P6 family processors, when [...], the LOCK# signal
is generally not asserted [...]" and still explains mechanism, finally
saying "the operation is carried out atomically with regards to
memory." If they wrote that as the description of the LOCK prefix,
much of the rest could be deleted.
Generally, an architecture manual should talk about architectural
effects, not about asserted signals.
The operational semantics given in
<https://www.felixcloutier.com/x86/lock> is:
| AssertLOCK#(DurationOfAccompaningInstruction);
Oh boy.
On Sun, 18 Oct 2026 15:08:23 GMT
[email protected] (Anton Ertl) wrote:
MitchAlsup <[email protected]d> writes: >[email protected] (Dan Cross) posted:
What I'm saying is that, as written, the bits in the `LOCK`
description above _could_ be interpreted to mean that _any_
`XCHG` will always assert the `LOCK#` signal, including an
`XCHG` that does not touch memory at all. The "Why?" was
rhetorical, as in, "Why would the system do that?" For example,
if one wrote, `xchg %ecx, %eax`, why should that assert `LOCK#`?
Truly I don't know, and I was just speculating.
Writing high quality documentation is fundamentally hard.
I don't think that's the issue here. They just did not limit the
sentence "The XCHG instruction always asserts the LOCK# signal
regardless of the presence or absence of the LOCK prefix." to XCHG instructions with memory operands. That would be easy to fix, but
they did not. And Chris M. Thomasson understood it as including
XCHG reg, reg.
My guess is that it is easy to fix in principle, but you have to deal
with all kinds of red tape for such a fix, so unless there is good
reason, you don't do it.
Frankly, I don't understand what both you and Dan Cross are talking
about.
I don't see how sentence from Intel's manual ("If a memory operand is referenced, the processor’s locking protocol is automatically
implemented for the duration of the exchange operation, regardless of
the presence or absence of the LOCK prefix or of the value of the IOPL")
or sentence from AMD's manual ("If either operand references memory,
the processor locks automatically, whether or not the LOCK prefix is
used and independently of the value of IOPL.") can be pssibly
misunderstood.
On Sun, 18 Oct 2026 16:57:26 GMT
[email protected] (Anton Ertl) wrote:
Michael S <[email protected]> writes:
On Sun, 18 Oct 2026 15:08:23 GMT...
[email protected] (Anton Ertl) wrote:
I don't think that's the issue here. They just did not limit the
sentence "The XCHG instruction always asserts the LOCK# signal
regardless of the presence or absence of the LOCK prefix." to XCHG
instructions with memory operands. That would be easy to fix, but
they did not. And Chris M. Thomasson understood it as including
XCHG reg, reg.
Frankly, I don't understand what both you and Dan Cross are talking
about.
I don't see how sentence from Intel's manual ("If a memory operand is
referenced, the processor=E2=80=99s locking protocol is automatically
implemented for the duration of the exchange operation, regardless of
the presence or absence of the LOCK prefix or of the value of the
IOPL") or sentence from AMD's manual ("If either operand references
memory, the processor locks automatically, whether or not the LOCK
prefix is used and independently of the value of IOPL.") can be
pssibly misunderstood.
Chris M. Thomasson wrote in <11arg45$2p70p$[email protected]>:
|Well, for some reason the LOCK prefix is implied for XCHG.
Given that the thread up to that point was aboyt XCHG reg, reg (and
according to the subject it still is), he seems to be an example that
what Intel wrote about XCHG and LOCK can be misunderstood. I looked
at the documentation and cited the relevant sentences in
<[email protected]>; most occurences clearly
refer only to XCHG where one operand is in memory. The exception is:
|The XCHG instruction always asserts the LOCK# signal regardless of
the |presence or absence of the LOCK prefix.
What is a source of this? Intel, AMD or somebody else?
And actually all the stuff about XCHG with memory operands does not
contradict this sentence. It could be understood as meaning that
while all the other aspects of locking don't apply to "XCHG reg, reg",
the assertion of the LOCK# signal still has to occur, and that's why
Intel processors implement a slow XCHG reg, reg. I don't think that's
what Intel intends and implements, but that's what a reading of their
manual implies.
Somehow, it does not imply it to me.
[snip]
When I want to know what particular insruction does I go to respective >section in Instruction Set Reference.
I can believe that there exist other methodes, but I prefere mine.
In article <11au1vu$3ks5m$[email protected]>,
Thomas Koenig <[email protected]> wrote:
Dan Cross <[email protected]> schrieb:
Unfortunately, the information is spread across two sections,
and they contradict. The description in the `LOCK` prefix
section in the latest version of the Intel SDM includes the text
Anton quoted, while the description of `XCHG` itself makes clear
that the destination operand must be a memory operand for the
locking protocol to automatically apply. Which is correct?
What would be the meaning of LOCK with memory operands? I can't
think of any.
Using the `LOCK` prefix without a destination operand that is a
memory operand is an error, and the SDM is quite explicit about
that. In fact, it says that an explicit `LOCK` prefix on an
`XCHG` a register destination operand is _not_ permitted and
"may" generate an `#UD` exception.
But sadly, when talking about an `XCHG` _without_ an explicit
operand, it is left ambiguous; all it says is that, "The `XCHG`
instruction always asserts the `LOCK#` signal regardless of the
presence or absence of the `LOCK` prefix." Devoid of the rest
of the surrounding context, one could interpret that to mean
that an `XCHG` _always_ forces a bus lock, irrespective of the
type of its desintation operand.
Why? I have no idea; as I said, I'm in the camp of going with
what the description of `XCHG` itself says, and not the what the
description of the `LOCK` prefix says: that sentence is _not_
devoid of context, and besides, there has not been a physical
`LOCK#` signal coming out of an Intel Xeon package since
Nehalem.
I suppose one could imagine it forcing a poor-man's barrier to
prevent later loads from being reorderd before it (loads can't
migrate before locked instructions). But we've got explicit
fence instructions for that, so I don't buy it.
I suspect that sentence is just poorly phrased.
- Dan C.
On Sun, 18 Oct 2026 16:57:26 GMT
[email protected] (Anton Ertl) wrote:
|The XCHG instruction always asserts the LOCK# signal regardless of
the |presence or absence of the LOCK prefix.
What is a source of this? Intel, AMD or somebody else?
The problem with the original report was that they attempted with the
grammar turn [at least some kinds of] semantic errors into syntax
errors.
I thought, though, that the main problem with Algol 68 was not that
it was described poorly, but that although people were still able to understand the language well enough despite an unconventional formal description language... it was a large and complicated language,
advancing the state of the art, and thus it was found difficult to
implement.
Hence, Pascal - a language which modernized Algol 60 without trying
to be a language on an entirely new level.
On Sun, 18 Oct 2026 09:45:00 -0400, George Neuner
<[email protected]> wrote:
The problem with the original report was that they attempted with the >>grammar turn [at least some kinds of] semantic errors into syntax
errors.
Obviously, there's no way one can enable a compiler to flag logic
errors in programs. A Turing-complete language can calculate anything,
so how can it tell you that you were calculating this when you wanted
to calculate that?
Of course, with AI, we might be able to do something there.
But already many modern languages do have strict type-checking.
So even if Algol 68 was over-ambitious in this regard, trying to have
the language help the programmer avoid more mistakes is basically a
sound idea.
Obviously, there's no way one can enable a compiler to flag logic
errors in programs. A Turing-complete language can calculate
anything, so how can it tell you that you were calculating this when
you wanted to calculate that?
A team at the IBM Lab in Vienna made a formal specification for PL/I;
I attended a lecture by Heinz Zemanek (the team leader) where he
mentioned something about an implementor disagreeing with the formal >specification for recursion (disagreements between implementor and >specification can also happen with specifications written in a natural >language, so that may not say much). Anyway, ><https://en.wikipedia.org/wiki/PL/I#Standardization> says "The
standard is couched as a formal definition[17] using a "PL/I
Machine"[21] to specify the semantics." This sounds like the
operational semantics that was developed by the IBM Lab Vienna, so
maybe the standardization committee picked up this work. But it seems
that the first standard never had a followon; was the definition too >unwieldy?
According to Anton Ertl <[email protected]>:
A team at the IBM Lab in Vienna made a formal specification for PL/I;
I attended a lecture by Heinz Zemanek (the team leader) where he
mentioned something about an implementor disagreeing with the formal >>specification for recursion (disagreements between implementor and >>specification can also happen with specifications written in a natural >>language, so that may not say much). Anyway, >><https://en.wikipedia.org/wiki/PL/I#Standardization> says "The
standard is couched as a formal definition[17] using a "PL/I
Machine"[21] to specify the semantics." This sounds like the
operational semantics that was developed by the IBM Lab Vienna, so
maybe the standardization committee picked up this work. But it seems
that the first standard never had a followon; was the definition too >>unwieldy?
I have a copy of the ANSI PL/I standard which uses VDL which I find close to impenetrable.
The syntax part is OK but the semantics are endless definitions of something >in terms of something else and I could never find the places where your program
actually did anything.
And actually all the stuff about XCHG with memory operands does not contradict this sentence. It could be understood as meaning that
while all the other aspects of locking don't apply to "XCHG reg, reg",
the assertion of the LOCK# signal still has to occur, and that's why
Intel processors implement a slow XCHG reg, reg.
My take is that BNF was a big success in formalizing a part of a
language. So what do you do when you are successful? You try to
follow up on that. So they wanted to formalize more of the language,
and go beyond the limits of BNF (context-free grammars) with Vw
grammars. This was technically successful, but from a usability POV
it was not.
Standard ML has been formally specified, and, given the audience of
this language, if any programming language may have success going
there, it should be a language like ML. There is a first revision
(1990) and a second revision (1997), and SML seems to have reached the
end of its evolution there.
Concerning terms like "semantic errors" or "static semantics" they
make it appear that there is a fundamental difference between syntax
and "static semantics" (the part that is not context-free and that is
checked by the compiler). It seems to me that that's just a matter of
what is expressed in the BNF.
E.g., in Algol 60 the computation of conditions for if-statements have special BNF rules, whereas some later programming languages have
a boolean type and putting a non-boolean between IF and THEN produces
a type error, not a syntax error.
On Sun, 18 Oct 2026 09:45:00 -0400, George Neuner
<[email protected]> wrote:
The problem with the original report was that they attempted with the >>grammar turn [at least some kinds of] semantic errors into syntax
errors.
Obviously, there's no way one can enable a compiler to flag logic
errors in programs.
A Turing-complete language can calculate anything,
so how can it tell you that you were calculating this when you wanted
to calculate that?
Try a LOCK RMW on memory that straddles a L2 cache line. That should trigger a full bus lock.
Anton Ertl [2026-10-18 16:57:26] wrote:
And actually all the stuff about XCHG with memory operands does not
contradict this sentence. It could be understood as meaning that
while all the other aspects of locking don't apply to "XCHG reg, reg",
the assertion of the LOCK# signal still has to occur, and that's why
Intel processors implement a slow XCHG reg, reg.
How could code witness the difference?
I believe AMD can claim that its behavior is consistent with the
behavior you'd get when asserting the LOCK# signal.
=== Stefan
In article <[email protected]>,
John Savard <[email protected]> wrote:
On Sun, 18 Oct 2026 09:45:00 -0400, George Neuner
<[email protected]> wrote:
The problem with the original report was that they attempted with the >>>grammar turn [at least some kinds of] semantic errors into syntax
errors.
Obviously, there's no way one can enable a compiler to flag logic
errors in programs. A Turing-complete language can calculate anything,
so how can it tell you that you were calculating this when you wanted
to calculate that?
With apologies, arguments like these always seem to me to miss
the forest for the trees a bit. Some constructs clearly violate
the documented semantics of e.g. a language.
Yes, these langauges are all Turing-complete and so on, and no,
we cannot solve _The_ Halting Problem, in all of its glorious
generality. But, we can solve any number of specific halting
_problems_. For example, I can see that, `for (;;);` is a loop
that does not terminate. With enough effort, I can take that
down some reasonably long paths.
So, too, one can spot a lot of logic errors. There's no reason
a compiler can't see this, for example:
? if (ptr == NULL) {
? int v = *ptr++;
? *ptr = v + 10;
? }
And flag it with a error: "you dereferenced a pointer right
after you asserted it was nil; did you invert the condition?"
Similarly, I posted about Rust a few days ago, which can do all
sorts of fun stuff with its borrow checker to assert that an
object is still alive while references to it exist, and so on,
and reject programs at compilation time that violate those
semantics.
Of course, with AI, we might be able to do something there.
But already many modern languages do have strict type-checking.
So even if Algol 68 was over-ambitious in this regard, trying to have
the language help the programmer avoid more mistakes is basically a
sound idea.
Agreed. Indeed, we've gone much farther than just mere type
checking.
- Dan C.
Obviously, there's no way one can enable a compiler to flag logic
errors in programs.
A Turing-complete language can calculate anything, so how can it tell
you that you were calculating this when you wanted to calculate that?
On 2026-Oct-18 15:27, Chris M. Thomasson wrote:
Try a LOCK RMW on memory that straddles a L2 cache line. That should
trigger a full bus lock.
FYI there is an article measuring the effects of cache line split locks
Investigating Split Locks on x86-64 https://chipsandcheese.com/p/investigating-split-locks-on-x86
I forgot the damn Linux thing. I think it might be sys_membarrier...
On Mon, 19 Oct 2026 14:08:53 -0700, Chris M. Thomasson wrote:
I forgot the damn Linux thing. I think it might be sys_membarrier...
<https://manpages.debian.org/membarrier(2)> ?
On 10/18/2026 8:43 PM, Stefan Monnier wrote:
Anton Ertl [2026-10-18 16:57:26] wrote:
And actually all the stuff about XCHG with memory operands does not
contradict this sentence. It could be understood as meaning that
while all the other aspects of locking don't apply to "XCHG reg, reg",
the assertion of the LOCK# signal still has to occur, and that's why
Intel processors implement a slow XCHG reg, reg.
How could code witness the difference?
I believe AMD can claim that its behavior is consistent with the
behavior you'd get when asserting the LOCK# signal.
=== Stefan
I believe this all started with empirical data from Anton showing
different performance between Intel and AMD processors for XCHG
reg,reg. There was some speculation that Intel asserted the lock
protocol and that was the cause. The discussion then moved to at best confusing, and perhaps contradictory documentation. But has anyone addressed the original question?
Specifically, do Intel processors actually do the lock stuff when it
isn't necessary? If so, is the cause of the difference? If not, what
is the cause?
On 10/19/2026 6:38 AM, EricP wrote:
On 2026-Oct-18 15:27, Chris M. Thomasson wrote:
Try a LOCK RMW on memory that straddles a L2 cache line. That should
trigger a full bus lock.
FYI there is an article measuring the effects of cache line split locks
Investigating Split Locks on x86-64
https://chipsandcheese.com/p/investigating-split-locks-on-x86
I see. Actually, a way to "abuse" it even further is to use a LOCK RMW,
say even LOCK XADD on something that straddles a cache line issues a bus lock. So, I have seen some papers on abusing QPI to gain a remote memory barrier or async sync for things like RCU. FlushProcessWriteBuffers
(windows way), I forgot the damn Linux thing. I think it might be sys_membarrier...
Anton Ertl [2026-10-18 16:57:26] wrote:
And actually all the stuff about XCHG with memory operands does not
contradict this sentence. It could be understood as meaning that
while all the other aspects of locking don't apply to "XCHG reg, reg",
the assertion of the LOCK# signal still has to occur, and that's why
Intel processors implement a slow XCHG reg, reg.
How could code witness the difference?
I believe AMD can claim that its behavior is consistent with the
behavior you'd get when asserting the LOCK# signal.
On Mon, 19 Oct 2026 01:52:51 -0000 (UTC),
[email protected] (Dan Cross) wrote:
In article <[email protected]>,
John Savard <[email protected]> wrote:
On Sun, 18 Oct 2026 09:45:00 -0400, George Neuner
<[email protected]> wrote:
The problem with the original report was that they attempted with the >>>>grammar turn [at least some kinds of] semantic errors into syntax >>>>errors.
Obviously, there's no way one can enable a compiler to flag logic
errors in programs. A Turing-complete language can calculate anything,
so how can it tell you that you were calculating this when you wanted
to calculate that?
With apologies, arguments like these always seem to me to miss
the forest for the trees a bit. Some constructs clearly violate
the documented semantics of e.g. a language.
Yes, these langauges are all Turing-complete and so on, and no,
we cannot solve _The_ Halting Problem, in all of its glorious
generality. But, we can solve any number of specific halting
_problems_. For example, I can see that, `for (;;);` is a loop
that does not terminate. With enough effort, I can take that
down some reasonably long paths.
So, too, one can spot a lot of logic errors. There's no reason
a compiler can't see this, for example:
? if (ptr == NULL) {
? int v = *ptr++;
? *ptr = v + 10;
? }
And flag it with a error: "you dereferenced a pointer right
after you asserted it was nil; did you invert the condition?"
Absolutely compiler analysis can catch (some) semantic errors ... that
never was in question.
The problem with the *original* Algol68 report was that they tried to
encode semantics using the syntax, the idea being that the parser then
could catch semantic errors as syntax errors.
The revised report changed direction: the syntax no longer tried to
encode the semantics ... but it still was hard to read because the
syntax definitions made copious /reference/ to semantics discussed in >accompanying text.
On 10/19/26 5:08 PM, Chris M. Thomasson wrote:
On 10/19/2026 6:38 AM, EricP wrote:
On 2026-Oct-18 15:27, Chris M. Thomasson wrote:
Try a LOCK RMW on memory that straddles a L2 cache line. That should
trigger a full bus lock.
FYI there is an article measuring the effects of cache line split locks
Investigating Split Locks on x86-64
https://chipsandcheese.com/p/investigating-split-locks-on-x86
I see. Actually, a way to "abuse" it even further is to use a LOCK
RMW, say even LOCK XADD on something that straddles a cache line
issues a bus lock. So, I have seen some papers on abusing QPI to gain
a remote memory barrier or async sync for things like RCU.
FlushProcessWriteBuffers (windows way), I forgot the damn Linux thing.
I think it might be sys_membarrier...
You are thinking of IPI (inter processsor interrupt) maybe? membarrier changed to that apparently because the quiesce points used by the RCU implementation of membarrier weren't frequent enough.
In article <[email protected]>,
Stefan Monnier <[email protected]> wrote:
Anton Ertl [2026-10-18 16:57:26] wrote:
And actually all the stuff about XCHG with memory operands does not
contradict this sentence. It could be understood as meaning that
while all the other aspects of locking don't apply to "XCHG reg, reg",
the assertion of the LOCK# signal still has to occur, and that's why
Intel processors implement a slow XCHG reg, reg.
How could code witness the difference?
I believe AMD can claim that its behavior is consistent with the
behavior you'd get when asserting the LOCK# signal.
The effects of a bus lock include disallowing memory operations
(except for instruction fetches or page table accesses) passing
a locked operation. If `XCHG reg,reg` where indeed treated as
though it asserted `LOCK#` for the duration of its execution, it
could be (ab)used to force that behavior: From sec 11.1.2.2 of
SDM Volume 3a (Sept 2026 version):
On 10/19/2026 4:17 PM, Joseph Seigh wrote:
On 10/19/26 5:08 PM, Chris M. Thomasson wrote:
On 10/19/2026 6:38 AM, EricP wrote:
On 2026-Oct-18 15:27, Chris M. Thomasson wrote:
Try a LOCK RMW on memory that straddles a L2 cache line. That should >>>> trigger a full bus lock.
FYI there is an article measuring the effects of cache line split locks >>>
Investigating Split Locks on x86-64
https://chipsandcheese.com/p/investigating-split-locks-on-x86
I see. Actually, a way to "abuse" it even further is to use a LOCK
RMW, say even LOCK XADD on something that straddles a cache line
issues a bus lock. So, I have seen some papers on abusing QPI to gain
a remote memory barrier or async sync for things like RCU.
FlushProcessWriteBuffers (windows way), I forgot the damn Linux thing.
I think it might be sys_membarrier...
You are thinking of IPI (inter processsor interrupt) maybe? membarrier changed to that apparently because the quiesce points used by the RCU implementation of membarrier weren't frequent enough.
I remember reading a paper from somebody, was it Dice? Damn! Cannot
remember right now. That abused the QPI, I think the quick path interconnect, to give them a "remote" membar to implement async algos.
Iirc they used misaligned LOCK RMW on something that straddled a l2
cache line to make the system assert a bus lock. I know I read the damn paper but it was way back. Iiirc around 2006-2008 ish? I cannot remember.
The IPI uses things like FlushProcessWriteBuffers over on Windows, Linux
has one to.
In article <[email protected]>,
Stefan Monnier <[email protected]> wrote:
How could code witness the difference?The effects of a bus lock include disallowing memory operations
(except for instruction fetches or page table accesses) passing
a locked operation.
On 10/18/2026 8:43 PM, Stefan Monnier wrote:
Anton Ertl [2026-10-18 16:57:26] wrote:I believe this all started with empirical data from Anton showing different performance between Intel and AMD processors for XCHG reg,reg.
And actually all the stuff about XCHG with memory operands does notHow could code witness the difference?
contradict this sentence. It could be understood as meaning that
while all the other aspects of locking don't apply to "XCHG reg, reg",
the assertion of the LOCK# signal still has to occur, and that's why
Intel processors implement a slow XCHG reg, reg.
I believe AMD can claim that its behavior is consistent with the
behavior you'd get when asserting the LOCK# signal.
=== Stefan
Dan Cross [2026-10-20 02:00:48] wrote:
In article <[email protected]>,
Stefan Monnier <[email protected]> wrote:
How could code witness the difference?The effects of a bus lock include disallowing memory operations
(except for instruction fetches or page table accesses) passing
a locked operation.
Ah, so it doesn't just make the operation atomic, but it additionally
imposes barrier-style restrictions on reordering surrounding memory >operations? I see, thanks.
[email protected] (Dan Cross) writes:
In article <[email protected]>,
Stefan Monnier <[email protected]> wrote:
Anton Ertl [2026-10-18 16:57:26] wrote:
And actually all the stuff about XCHG with memory operands does not
contradict this sentence. It could be understood as meaning that
while all the other aspects of locking don't apply to "XCHG reg, reg", >>>> the assertion of the LOCK# signal still has to occur, and that's why
Intel processors implement a slow XCHG reg, reg.
How could code witness the difference?
I believe AMD can claim that its behavior is consistent with the
behavior you'd get when asserting the LOCK# signal.
The effects of a bus lock include disallowing memory operations
(except for instruction fetches or page table accesses) passing
a locked operation. If `XCHG reg,reg` where indeed treated as
though it asserted `LOCK#` for the duration of its execution, it
could be (ab)used to force that behavior: From sec 11.1.2.2 of
SDM Volume 3a (Sept 2026 version):
It's worth noting that AMD processors (in the 2008 timeframe) would
assert the LOCK# signal if a highly contended cache line could not
be acquired in exclusive mode within a certain window of time,
even if the access was completely encapsulated in said cache line.
I suspect that is still the case.
Niklaus Wirth was possibly the biggest critic of the Algol 68 effort.
He and Tony Hoare had previously created Algol-W, which pioneered the
concept of record structures (taking a simpler form than COBOL’s
convoluted record structures). Pascal was basically the next step in
the evolution of that.
On Mon, 19 Oct 2026 01:46:21 -0000 (UTC), Lawrence =?iso-8859-13?q?D=FFOliveiro?= <[email protected]d> wrote:
Niklaus Wirth was possibly the biggest critic of the Algol 68 effort.
He and Tony Hoare had previously created Algol-W, which pioneered the
concept of record structures (taking a simpler form than COBOL’s
convoluted record structures). Pascal was basically the next step in
the evolution of that.
And, of course, one might mention MODULA-2, which took certain
advanced ideas seen in Ada and put them in a Pascal-like context.
My understanding is that the influences went from Modula-2 to Ada, and >Wikipedia agrees with me, saying that Modula-2 first appeared in 1978.
On Wed, 21 Oct 2026 18:34:46 +0300, Niklas Holsti <[email protected]d> wrote:
My understanding is that the influences went from Modula-2 to Ada, and >>Wikipedia agrees with me, saying that Modula-2 first appeared in 1978.
You're quite right. I searched for more information, and apparently Concurrent Pascal was "first", with MODULA-2 coming very shortly
after. And then, after the two competing models of those languages
were discussed for a while, Ada included the feature as well.
However, one source claimed that PL/I should really be given the
credit for including parallel constructs well before Concurrent
Pascal.
Anton Ertl [2026-10-18 16:57:26] wrote:
And actually all the stuff about XCHG with memory operands does not
contradict this sentence. It could be understood as meaning that
while all the other aspects of locking don't apply to "XCHG reg, reg",
the assertion of the LOCK# signal still has to occur, and that's why
Intel processors implement a slow XCHG reg, reg.
How could code witness the difference?
Stefan Monnier <[email protected]> writes:
Anton Ertl [2026-10-18 16:57:26] wrote:
And actually all the stuff about XCHG with memory operands does not
contradict this sentence. It could be understood as meaning that
while all the other aspects of locking don't apply to "XCHG reg,
reg", the assertion of the LOCK# signal still has to occur, and
that's why Intel processors implement a slow XCHG reg, reg.
How could code witness the difference?
Depends on the hardware. If there is some device connected t the
LOCK# signal (e.g., another CPU), and that behaves differently when
the signal is asserted, the code can measure that.
- anton
On Wed, 21 Oct 2026 18:34:46 +0300, Niklas Holsti <[email protected]d> wrote:
My understanding is that the influences went from Modula-2 to Ada, and
Wikipedia agrees with me, saying that Modula-2 first appeared in 1978.
You're quite right. I searched for more information, and apparently Concurrent Pascal was "first", with MODULA-2 coming very shortly
after. And then, after the two competing models of those languages
were discussed for a while, Ada included the feature as well.
However, one source claimed that PL/I should really be given the
credit for including parallel constructs well before Concurrent
Pascal.
On 10/21/2026 12:38 PM, John Savard wrote:
On Wed, 21 Oct 2026 18:34:46 +0300, Niklas Holsti
<[email protected]d> wrote:
My understanding is that the influences went from Modula-2 to Ada, and
Wikipedia agrees with me, saying that Modula-2 first appeared in 1978.
You're quite right. I searched for more information, and apparently
Concurrent Pascal was "first", with MODULA-2 coming very shortly
after. And then, after the two competing models of those languages
were discussed for a while, Ada included the feature as well.
However, one source claimed that PL/I should really be given the
credit for including parallel constructs well before Concurrent
Pascal.
I vaguely recall that there was an optional feature in the COBOL
standard for concurrent processing, or something like that. It wasn't >implemented in the compiler I used and I never investigated exactly what
it was. But it certainly predated Pascal, Ad and other such languages.
Does anyone else know anything about this?
| Sysop: | DaiTengu |
|---|---|
| Location: | Appleton, WI |
| Users: | 1,142 |
| Nodes: | 10 (0 / 10) |
| Uptime: | 93:07:25 |
| Calls: | 14,704 |
| Calls today: | 2 |
| Files: | 186,497 |
| D/L today: |
2,349 files (779M bytes) |
| Messages: | 2,551,657 |