-
Notifications
You must be signed in to change notification settings - Fork 18.4k
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 } }