github.com/riscv/riscv-go@v0.0.0-20200123204226-124ebd6fcc8e/src/runtime/testdata/testprogcgo/cgo.go (about)

     1  // Copyright 2015 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 main
     6  
     7  /*
     8  void foo1(void) {}
     9  void foo2(void* p) {}
    10  */
    11  import "C"
    12  import (
    13  	"fmt"
    14  	"os"
    15  	"runtime"
    16  	"strconv"
    17  	"time"
    18  	"unsafe"
    19  )
    20  
    21  func init() {
    22  	register("CgoSignalDeadlock", CgoSignalDeadlock)
    23  	register("CgoTraceback", CgoTraceback)
    24  	register("CgoCheckBytes", CgoCheckBytes)
    25  }
    26  
    27  func CgoSignalDeadlock() {
    28  	runtime.GOMAXPROCS(100)
    29  	ping := make(chan bool)
    30  	go func() {
    31  		for i := 0; ; i++ {
    32  			runtime.Gosched()
    33  			select {
    34  			case done := <-ping:
    35  				if done {
    36  					ping <- true
    37  					return
    38  				}
    39  				ping <- true
    40  			default:
    41  			}
    42  			func() {
    43  				defer func() {
    44  					recover()
    45  				}()
    46  				var s *string
    47  				*s = ""
    48  			}()
    49  		}
    50  	}()
    51  	time.Sleep(time.Millisecond)
    52  	for i := 0; i < 64; i++ {
    53  		go func() {
    54  			runtime.LockOSThread()
    55  			select {}
    56  		}()
    57  		go func() {
    58  			runtime.LockOSThread()
    59  			select {}
    60  		}()
    61  		time.Sleep(time.Millisecond)
    62  		ping <- false
    63  		select {
    64  		case <-ping:
    65  		case <-time.After(time.Second):
    66  			fmt.Printf("HANG\n")
    67  			return
    68  		}
    69  	}
    70  	ping <- true
    71  	select {
    72  	case <-ping:
    73  	case <-time.After(time.Second):
    74  		fmt.Printf("HANG\n")
    75  		return
    76  	}
    77  	fmt.Printf("OK\n")
    78  }
    79  
    80  func CgoTraceback() {
    81  	C.foo1()
    82  	buf := make([]byte, 1)
    83  	runtime.Stack(buf, true)
    84  	fmt.Printf("OK\n")
    85  }
    86  
    87  func CgoCheckBytes() {
    88  	try, _ := strconv.Atoi(os.Getenv("GO_CGOCHECKBYTES_TRY"))
    89  	if try <= 0 {
    90  		try = 1
    91  	}
    92  	b := make([]byte, 1e6*try)
    93  	start := time.Now()
    94  	for i := 0; i < 1e3*try; i++ {
    95  		C.foo2(unsafe.Pointer(&b[0]))
    96  		if time.Since(start) > time.Second {
    97  			break
    98  		}
    99  	}
   100  }