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  }