github.com/xushiwei/go@v0.0.0-20130601165731-2b9d83f45bc9/misc/cgo/test/issue1560.go (about) 1 // Copyright 2011 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 package cgotest 6 7 /* 8 #include <unistd.h> 9 10 unsigned int sleep(unsigned int seconds); 11 12 extern void BackgroundSleep(int); 13 void twoSleep(int); 14 */ 15 import "C" 16 17 import ( 18 "runtime" 19 "testing" 20 "time" 21 ) 22 23 var sleepDone = make(chan bool) 24 25 func parallelSleep(n int) { 26 C.twoSleep(C.int(n)) 27 <-sleepDone 28 } 29 30 //export BackgroundSleep 31 func BackgroundSleep(n int32) { 32 go func() { 33 C.sleep(C.uint(n)) 34 sleepDone <- true 35 }() 36 } 37 38 // wasteCPU starts a background goroutine to waste CPU 39 // to cause the power management to raise the CPU frequency. 40 // On ARM this has the side effect of making sleep more accurate. 41 func wasteCPU() chan struct{} { 42 done := make(chan struct{}) 43 go func() { 44 for { 45 select { 46 case <-done: 47 return 48 default: 49 } 50 } 51 }() 52 // pause for a short amount of time to allow the 53 // power management to recognise load has risen. 54 <-time.After(300 * time.Millisecond) 55 return done 56 } 57 58 func testParallelSleep(t *testing.T) { 59 if runtime.GOARCH == "arm" { 60 // on ARM, the 1.3s deadline is frequently missed, 61 // and burning cpu seems to help 62 defer runtime.GOMAXPROCS(runtime.GOMAXPROCS(2)) 63 defer close(wasteCPU()) 64 } 65 66 sleepSec := 1 67 start := time.Now() 68 parallelSleep(sleepSec) 69 dt := time.Since(start) 70 t.Logf("sleep(%d) slept for %v", sleepSec, dt) 71 // bug used to run sleeps in serial, producing a 2*sleepSec-second delay. 72 if dt >= time.Duration(sleepSec)*1300*time.Millisecond { 73 t.Fatalf("parallel %d-second sleeps slept for %f seconds", sleepSec, dt.Seconds()) 74 } 75 }