// run // Copyright 2015 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. package main import ( "fmt" "runtime" ) const N = 100000 func main() { // Allocate more Ps than processors. This raises // the chance that we get interrupted by the OS // in exactly the right (wrong!) place. p := runtime.NumCPU() runtime.GOMAXPROCS(2 * p) // Allocate some pointers. ptrs := make([]*int, p) for i := 0; i < p; i++ { ptrs[i] = new(int) } // Arena where we read and write pointers like crazy. collider := make([]*int, p) done := make(chan struct{}, 2*p) // Start writers. They alternately write a pointer // and nil to a slot in the collider. for i := 0; i < p; i++ { i := i go func() { for j := 0; j < N; j++ { // Write a pointer using memmove. copy(collider[i:i+1], ptrs[i:i+1]) // Write nil using memclr. // (This is a magic loop that gets lowered to memclr.) r := collider[i : i+1] for k := range r { r[k] = nil } } done <- struct{}{} }() } // Start readers. They read pointers from slots // and make sure they are valid. for i := 0; i < p; i++ { i := i go func() { for j := 0; j < N; j++ { var ptr [1]*int copy(ptr[:], collider[i:i+1]) if ptr[0] != nil && ptr[0] != ptrs[i] { panic(fmt.Sprintf("bad pointer read %p!", ptr[0])) } } done <- struct{}{} }() } for i := 0; i < 2*p; i++ { <-done } }