Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 4 additions & 3 deletions misc/cgo/test/cgo_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,7 @@ func TestThreadLock(t *testing.T) { testThreadLockFunc(t) }
func TestUnsignedInt(t *testing.T) { testUnsignedInt(t) }
func TestZeroArgCallback(t *testing.T) { testZeroArgCallback(t) }

func BenchmarkCgoCall(b *testing.B) { benchCgoCall(b) }
func BenchmarkGoString(b *testing.B) { benchGoString(b) }
func BenchmarkCGoCallback(b *testing.B) { benchCallback(b) }
func BenchmarkCgoCall(b *testing.B) { benchCgoCall(b) }
func BenchmarkGoString(b *testing.B) { benchGoString(b) }
func BenchmarkCGoCallback(b *testing.B) { benchCallback(b) }
func BenchmarkCGoInCThread(b *testing.B) { benchCGoInCthread(b) }
24 changes: 24 additions & 0 deletions misc/cgo/test/cthread_unix.c
Original file line number Diff line number Diff line change
Expand Up @@ -32,3 +32,27 @@ doAdd(int max, int nthread)
for(i=0; i<nthread; i++)
pthread_join(thread_id[i], 0);
}

static void*
goDummyCallbackThread(void* p)
{
int i, max;

max = *(int*)p;
for(i=0; i<max; i++)
goDummy();
return NULL;
}

int
callGoInCThread(int max)
{
pthread_t thread;

if (pthread_create(&thread, NULL, goDummyCallbackThread, (void*)(&max)) != 0)
return -1;
if (pthread_join(thread, NULL) != 0)
return -1;

return max;
}
22 changes: 22 additions & 0 deletions misc/cgo/test/cthread_windows.c
Original file line number Diff line number Diff line change
Expand Up @@ -35,3 +35,25 @@ doAdd(int max, int nthread)
CloseHandle((HANDLE)thread_id[i]);
}
}

__stdcall
static unsigned int
goDummyCallbackThread(void* p)
{
int i, max;

max = *(int*)p;
for(i=0; i<max; i++)
goDummy();
return 0;
}

int
callGoInCThread(int max)
{
uintptr_t thread_id;
thread_id = _beginthreadex(0, 0, goDummyCallbackThread, &max, 0, 0);
WaitForSingleObject((HANDLE)thread_id, INFINITE);
CloseHandle((HANDLE)thread_id);
return max;
}
14 changes: 14 additions & 0 deletions misc/cgo/test/testx.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import (
/*
// threads
extern void doAdd(int, int);
extern int callGoInCThread(int);

// issue 1328
void IntoC(void);
Expand Down Expand Up @@ -146,6 +147,10 @@ func Add(x int) {
*p = 2
}

//export goDummy
func goDummy() {
}

func testCthread(t *testing.T) {
if (runtime.GOOS == "darwin" || runtime.GOOS == "ios") && runtime.GOARCH == "arm64" {
t.Skip("the iOS exec wrapper is unable to properly handle the panic from Add")
Expand All @@ -159,6 +164,15 @@ func testCthread(t *testing.T) {
}
}

// Benchmark measuring overhead from C to Go in a C thread.
// Create a new C thread and invoke Go function repeatedly in the new C thread.
func benchCGoInCthread(b *testing.B) {
n := C.callGoInCThread(C.int(b.N))
if int(n) != b.N {
b.Fatal("unmatch loop times")
}
}

// issue 1328

//export BackIntoGo
Expand Down
54 changes: 54 additions & 0 deletions misc/cgo/testcarchive/carchive_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1247,3 +1247,57 @@ func TestPreemption(t *testing.T) {
t.Error(err)
}
}

// Issue 59294. Test calling Go function from C after using some
// stack space.
func TestDeepStack(t *testing.T) {
t.Parallel()

if !testWork {
defer func() {
os.Remove("testp9" + exeSuffix)
os.Remove("libgo9.a")
os.Remove("libgo9.h")
}()
}

cmd := exec.Command("go", "build", "-buildmode=c-archive", "-o", "libgo9.a", "./libgo9")
out, err := cmd.CombinedOutput()
t.Logf("%v\n%s", cmd.Args, out)
if err != nil {
t.Fatal(err)
}
checkLineComments(t, "libgo9.h")
checkArchive(t, "libgo9.a")

// build with -O0 so the C compiler won't optimize out the large stack frame
ccArgs := append(cc, "-O0", "-o", "testp9"+exeSuffix, "main9.c", "libgo9.a")
out, err = exec.Command(ccArgs[0], ccArgs[1:]...).CombinedOutput()
t.Logf("%v\n%s", ccArgs, out)
if err != nil {
t.Fatal(err)
}

argv := cmdToRun("./testp9")
cmd = exec.Command(argv[0], argv[1:]...)
sb := new(strings.Builder)
cmd.Stdout = sb
cmd.Stderr = sb
if err := cmd.Start(); err != nil {
t.Fatal(err)
}

timer := time.AfterFunc(time.Minute,
func() {
t.Error("test program timed out")
cmd.Process.Kill()
},
)
defer timer.Stop()

err = cmd.Wait()
t.Logf("%v\n%s", cmd.Args, sb)
if err != nil {
t.Error(err)
}
}
14 changes: 14 additions & 0 deletions misc/cgo/testcarchive/testdata/libgo9/a.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
// Copyright 2023 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 "runtime"

import "C"

func main() {}

//export GoF
func GoF() { runtime.GC() }
24 changes: 24 additions & 0 deletions misc/cgo/testcarchive/testdata/main9.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
// Copyright 2023 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.

#include "libgo9.h"

void use(int *x) { (*x)++; }

void callGoFWithDeepStack() {
int x[10000];

use(&x[0]);
use(&x[9999]);

GoF();

use(&x[0]);
use(&x[9999]);
}

int main() {
GoF(); // call GoF without using much stack
callGoFWithDeepStack(); // call GoF with a deep stack
}
53 changes: 53 additions & 0 deletions misc/cgo/testsanitizers/testdata/tsan14.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
// Copyright 2023 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

// This program failed when run under the C/C++ ThreadSanitizer.
//
// cgocallback on a new thread calls into runtime.needm -> _cgo_getstackbound
// to update gp.stack.lo with the stack bounds. If the G itself is passed to
// _cgo_getstackbound, then writes to the same G can be seen on multiple
// threads (when the G is reused after thread exit). This would trigger TSAN.

/*
#include <pthread.h>

void go_callback();

static void *thr(void *arg) {
go_callback();
return 0;
}

static void foo() {
pthread_t th;
pthread_attr_t attr;
pthread_attr_init(&attr);
pthread_attr_setstacksize(&attr, 256 << 10);
pthread_create(&th, &attr, thr, 0);
pthread_join(th, 0);
}
*/
import "C"

import (
"time"
)

//export go_callback
func go_callback() {
}

func main() {
for i := 0; i < 2; i++ {
go func() {
for {
C.foo()
}
}()
}

time.Sleep(1000*time.Millisecond)
}
1 change: 1 addition & 0 deletions misc/cgo/testsanitizers/tsan_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ func TestTSAN(t *testing.T) {
{src: "tsan11.go", needsRuntime: true},
{src: "tsan12.go", needsRuntime: true},
{src: "tsan13.go", needsRuntime: true},
{src: "tsan14.go", needsRuntime: true},
}
for _, tc := range cases {
tc := tc
Expand Down
2 changes: 1 addition & 1 deletion misc/wasm/go_wasip1_wasm_exec
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ case "$GOWASIRUNTIME" in
exec wasmtime run --dir=/ --env PWD="$PWD" --max-wasm-stack 1048576 "$1" -- "${@:2}"
;;
"wazero" | "")
exec wazero run -mount /:/ -env-inherit -cachedir "${TMPDIR}"/wazero "$1" "${@:2}"
exec wazero run -mount /:/ -env-inherit -cachedir "${TMPDIR:-/tmp}"/wazero "$1" "${@:2}"
;;
*)
echo "Unknown Go WASI runtime specified: $GOWASIRUNTIME"
Expand Down
11 changes: 0 additions & 11 deletions src/cmd/covdata/metamerge.go
Original file line number Diff line number Diff line change
Expand Up @@ -273,17 +273,6 @@ func (mm *metaMerge) emitCounters(outdir string, metaHash [16]byte) {
mm.astate = &argstate{}
}

// NumFuncs is used while writing the counter data files; it
// implements the 'NumFuncs' method required by the interface
// internal/coverage/encodecounter/CounterVisitor.
func (mm *metaMerge) NumFuncs() (int, error) {
rval := 0
for _, p := range mm.pkgs {
rval += len(p.ctab)
}
return rval, nil
}

// VisitFuncs is used while writing the counter data files; it
// implements the 'VisitFuncs' method required by the interface
// internal/coverage/encodecounter/CounterVisitor.
Expand Down
14 changes: 0 additions & 14 deletions src/cmd/go/internal/list/list.go
Original file line number Diff line number Diff line change
Expand Up @@ -624,20 +624,6 @@ func runList(ctx context.Context, cmd *base.Command, args []string) {
base.ExitIfErrors()
}

if cache.Default() == nil {
// These flags return file names pointing into the build cache,
// so the build cache must exist.
if *listCompiled {
base.Fatalf("go list -compiled requires build cache")
}
if *listExport {
base.Fatalf("go list -export requires build cache")
}
if *listTest {
base.Fatalf("go list -test requires build cache")
}
}

if *listTest {
c := cache.Default()
// Add test binaries to packages to be listed.
Expand Down
8 changes: 0 additions & 8 deletions src/cmd/go/internal/test/test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1537,14 +1537,6 @@ func (c *runCache) tryCacheWithID(b *work.Builder, a *work.Action, id string) bo
}
}

if cache.Default() == nil {
if cache.DebugTest {
fmt.Fprintf(os.Stderr, "testcache: GOCACHE=off\n")
}
c.disableCache = true
return false
}

// The test cache result fetch is a two-level lookup.
//
// First, we use the content hash of the test binary
Expand Down
Loading