| // 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 | |
| } | |
| } |