Commit af1dd56d authored by Shenghou Ma's avatar Shenghou Ma

misc/cgo/test: deflake TestParallelSleep once more

Fixes #5480.

R=golang-dev, iant
CC=golang-dev
https://golang.org/cl/9475043
parent a8484753
...@@ -3,6 +3,7 @@ ...@@ -3,6 +3,7 @@
// license that can be found in the LICENSE file. // license that can be found in the LICENSE file.
#include <sys/types.h> #include <sys/types.h>
#include <unistd.h>
#include "_cgo_export.h" #include "_cgo_export.h"
void void
...@@ -29,9 +30,30 @@ IntoC(void) ...@@ -29,9 +30,30 @@ IntoC(void)
BackIntoGo(); BackIntoGo();
} }
void #ifdef WIN32
#include <windows.h>
long long
mysleep(int seconds) {
long long st = GetTickCount();
sleep(seconds);
return st;
}
#else
#include <sys/time.h>
long long
mysleep(int seconds) {
long long st;
struct timeval tv;
gettimeofday(&tv, NULL);
st = tv.tv_sec * 1000 + tv.tv_usec / 1000;
sleep(seconds);
return st;
}
#endif
long long
twoSleep(int n) twoSleep(int n)
{ {
BackgroundSleep(n); BackgroundSleep(n);
sleep(n); return mysleep(n);
} }
...@@ -5,71 +5,46 @@ ...@@ -5,71 +5,46 @@
package cgotest package cgotest
/* /*
#include <unistd.h> // mysleep returns the absolute start time in ms.
long long mysleep(int seconds);
unsigned int sleep(unsigned int seconds); // twoSleep returns the absolute start time of the first sleep
// in ms.
extern void BackgroundSleep(int); long long twoSleep(int);
void twoSleep(int);
*/ */
import "C" import "C"
import ( import (
"runtime"
"testing" "testing"
"time" "time"
) )
var sleepDone = make(chan bool) var sleepDone = make(chan int64)
func parallelSleep(n int) { // parallelSleep returns the absolute difference between the start time
C.twoSleep(C.int(n)) // of the two sleeps.
<-sleepDone func parallelSleep(n int) int64 {
t := int64(C.twoSleep(C.int(n))) - <-sleepDone
if t < 0 {
return -t
}
return t
} }
//export BackgroundSleep //export BackgroundSleep
func BackgroundSleep(n int32) { func BackgroundSleep(n int32) {
go func() { go func() {
C.sleep(C.uint(n)) sleepDone <- int64(C.mysleep(C.int(n)))
sleepDone <- true
}()
}
// wasteCPU starts a background goroutine to waste CPU
// to cause the power management to raise the CPU frequency.
// On ARM this has the side effect of making sleep more accurate.
func wasteCPU() chan struct{} {
done := make(chan struct{})
go func() {
for {
select {
case <-done:
return
default:
}
}
}() }()
// pause for a short amount of time to allow the
// power management to recognise load has risen.
<-time.After(300 * time.Millisecond)
return done
} }
func testParallelSleep(t *testing.T) { func testParallelSleep(t *testing.T) {
if runtime.GOARCH == "arm" {
// on ARM, the 1.3s deadline is frequently missed,
// and burning cpu seems to help
defer runtime.GOMAXPROCS(runtime.GOMAXPROCS(2))
defer close(wasteCPU())
}
sleepSec := 1 sleepSec := 1
start := time.Now() dt := time.Duration(parallelSleep(sleepSec)) * time.Millisecond
parallelSleep(sleepSec) t.Logf("difference in start time for two sleep(%d) is %v", sleepSec, dt)
dt := time.Since(start)
t.Logf("sleep(%d) slept for %v", sleepSec, dt)
// bug used to run sleeps in serial, producing a 2*sleepSec-second delay. // bug used to run sleeps in serial, producing a 2*sleepSec-second delay.
if dt >= time.Duration(sleepSec)*1300*time.Millisecond { // we detect if the start times of those sleeps are > 0.5*sleepSec-second.
if dt >= time.Duration(sleepSec)*time.Second/2 {
t.Fatalf("parallel %d-second sleeps slept for %f seconds", sleepSec, dt.Seconds()) t.Fatalf("parallel %d-second sleeps slept for %f seconds", sleepSec, dt.Seconds())
} }
} }
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment