I'm reading preshing's blog Memory Reordering Caught in the Act, and reproduced memory-reordering by his example code
Then I wonder if I could reproduce memory-reordering by Go, so I wrote the example code in go, but memory-reordering is not shown in Go.
I'm writing to share some findings.
And could you help explain why Go could not get memory-reordering? Thanks.
Example code in Go:
package main
import (
"fmt"
"math/rand"
)
var x, y, r1, r2 int
var detected = 0
func randWait() {
for rand.Intn(8) != 0 {
}
}
func main() {
beginSig1 := make(chan bool, 1)
beginSig2 := make(chan bool, 1)
endSig1 := make(chan bool, 1)
endSig2 := make(chan bool, 1)
go func() {
for {
<-beginSig1
randWait()
x = 1
r1 = y
endSig1 <- true
}
}()
go func() {
for {
<-beginSig2
randWait()
y = 1
r2 = x
endSig2 <- true
}
}()
for i := 1; ; i = i + 1 {
x = 0
y = 0
beginSig1 <- true
beginSig2 <- true
<-endSig1
<-endSig2
if r1 == 0 && r2 == 0 {
detected = detected + 1
fmt.Println(detected, "reorders detected after ", i, "iterations")
}
}
}
The assembly code (by "ndisasm -b 32") show different between C++ vs Go
Assembly code from C++
00000CF0 C705520300000100 mov dword [0x352],0x1 //X=1
-0000
00000CFA 8B0550030000 mov eax,[0x350]
00000D00 89054E030000 mov [0x34e],eax //r1=Y
Assembly code from Go
000013EA 48 dec eax
000013EB C70425787F170001 mov dword [0x177f78],0x1 //x=1
-000000
000013F6 48 dec eax
000013F7 8B1C25807F1700 mov ebx,[0x177f80]
000013FE 48 dec eax
000013FF 891C25687F1700 mov [0x177f68],ebx //r1=Y
00001406 48 dec eax
it seems Go uses dec eax
around access of shared memory, but it make no sense that dec eax
can prevent memory-reordering
The Intel® 64 and IA-32 Architectures Software Developer Manuals Volume 3, Section 8.2 shows the cases that could prevent memory-reordering, but dec eax
isn't included...
I tried to add dec eax
as margin of shared-memory-access in C code, and memory-reordering is still there.
By now, I have no clue about the reason. Please help me on it, thank you.
I don't see a call to set GOMAXPROCs anywhere? If you don't call it you'll be running on just one CPU which won't ever show re-ordering: http://golang.org/pkg/runtime/#GOMAXPROCS
Update: In Go 1.5 (Released 2015/08/19) and later you no longer need to set GOMAXPROCS - Go defaults to using all your CPUs.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With