-
Notifications
You must be signed in to change notification settings - Fork 18.7k
Closed
Labels
Milestone
Description
14574:2c2052f38c3c tip
Add the following test to math/big tests:
func TestScanPiParallel(t *testing.T) {
c := make(chan bool)
for i := 0; i < 2; i++ {
go func() {
TestScanPi(t)
c <- true
}()
}
for i := 0; i < 2; i++ {
<-c
}
}
ThreadSanitizer says:
WARNING: DATA RACE at 0x000000ac6ab0
Read by goroutine 4:
math/big.divisors()
src/pkg/math/big/nat.go:956 +0x1aa
math/big.nat.string()
src/pkg/math/big/nat.go:807 +0x84d
math/big.nat.decimalString()
src/pkg/math/big/nat.go:731 +0x7e
math/big.TestScanPi()
src/pkg/math/big/nat_test.go:407 +0x1d6
math/big.func·006()
src/pkg/math/big/nat_test.go:416 +0x3a
Previous write by goroutine 3:
math/big.divisors()
src/pkg/math/big/nat.go:970 +0xa90
math/big.nat.string()
src/pkg/math/big/nat.go:807 +0x84d
math/big.nat.decimalString()
src/pkg/math/big/nat.go:731 +0x7e
math/big.TestScanPi()
src/pkg/math/big/nat_test.go:407 +0x1d6
math/big.func·006()
src/pkg/math/big/nat_test.go:416 +0x3a
Goroutine 4 (running) created at:
math/big.TestScanPiParallel()
src/pkg/math/big/nat_test.go:418 +0xac
testing.tRunner()
src/pkg/testing/testing.go:301 +0x86
Goroutine 3 (finished) created at:
math/big.TestScanPiParallel()
src/pkg/math/big/nat_test.go:418 +0xac
testing.tRunner()
src/pkg/testing/testing.go:301 +0x86
The issue is in the following code. If table[k-1].ndigits != 0 it does not mean that the
table is fully initialized. Occasionally I see "div by zero" crashes when
running in parallel.
// extend table
if table[k-1].ndigits == 0 {
if cached {
cacheLock.Lock() // begin critical section
}
// add new entries as needed
var larger nat
for i := 0; i < k; i++ {
if table[i].ndigits == 0 {
if i == 0 {
table[i].bbb = nat(nil).expWW(bb, Word(leafSize))
table[i].ndigits = ndigits * leafSize
} else {
table[i].bbb = nat(nil).mul(table[i-1].bbb, table[i-1].bbb)
table[i].ndigits = 2 * table[i-1].ndigits
}
// optimization: exploit aggregated extra bits in macro blocks
larger = nat(nil).set(table[i].bbb)
for mulAddVWW(larger, larger, b, 0) == 0 {
table[i].bbb = table[i].bbb.set(larger)
table[i].ndigits++
}
table[i].nbits = table[i].bbb.bitLen()
}
}
if cached {
cacheLock.Unlock() // end critical section
}
}