x86/x86asm: make x86asm.Decode thread-safe
Moves initialization of the decoderCover variable from happening
unconditionally to only being initialized by the test code using it so
that it does not cause a data race when not being used and Decode is
called in parallel.
Fixes golang/go#33532
Change-Id: I64d748f94d135f0c1f55f1456ff770ac5205c85a
GitHub-Last-Rev: 679e78ed1daf3ddbd03792155e3be90b7b498fc4
GitHub-Pull-Request: golang/arch#4
Reviewed-on: https://go-review.googlesource.com/c/arch/+/189919
Reviewed-by: Cherry Zhang <cherryyz@google.com>
Run-TryBot: Cherry Zhang <cherryyz@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
diff --git a/x86/x86asm/decode.go b/x86/x86asm/decode.go
index 250000e..8c98497 100644
--- a/x86/x86asm/decode.go
+++ b/x86/x86asm/decode.go
@@ -218,7 +218,6 @@
// decoderCover records coverage information for which parts
// of the byte code have been executed.
-// TODO(rsc): This is for testing. Only use this if a flag is given.
var decoderCover []bool
// Decode decodes the leading bytes in src as a single instruction.
@@ -462,9 +461,6 @@
// opshift gives the shift to use when saving the next
// opcode byte into inst.Opcode.
opshift = 24
- if decoderCover == nil {
- decoderCover = make([]bool, len(decoder))
- }
// Decode loop, executing decoder program.
var oldPC, prevPC int
@@ -476,7 +472,9 @@
println("run", pc)
}
x := decoder[pc]
- decoderCover[pc] = true
+ if decoderCover != nil {
+ decoderCover[pc] = true
+ }
pc++
// Read and decode ModR/M if needed by opcode.
diff --git a/x86/x86asm/ext_test.go b/x86/x86asm/ext_test.go
index 526ef5a..e63f113 100644
--- a/x86/x86asm/ext_test.go
+++ b/x86/x86asm/ext_test.go
@@ -100,6 +100,11 @@
generate func(f func([]byte)),
allowedMismatch func(text string, size int, inst *Inst, dec ExtInst) bool,
) {
+ decoderCover = make([]bool, len(decoder))
+ defer func() {
+ decoderCover = nil
+ }()
+
start := time.Now()
ext := &ExtDis{
Dec: make(chan ExtInst),