mirror of
https://github.com/golang/go
synced 2024-11-23 10:10:02 -07:00
runtime: delete cgo_allocate
This memory is untyped and can't be used anymore. The next version of SWIG won't need it. Change-Id: I592b287c5f5186975ee09a9b28d8efe3b57134e7 Reviewed-on: https://go-review.googlesource.com/8956 Reviewed-by: Ian Lance Taylor <iant@golang.org>
This commit is contained in:
parent
89b7c66d0d
commit
6a2b0c0b6d
@ -9,7 +9,6 @@ void callback(void *f);
|
|||||||
void callGoFoo(void);
|
void callGoFoo(void);
|
||||||
void callGoStackCheck(void);
|
void callGoStackCheck(void);
|
||||||
void callPanic(void);
|
void callPanic(void);
|
||||||
void callCgoAllocate(void);
|
|
||||||
int callGoReturnVal(void);
|
int callGoReturnVal(void);
|
||||||
int returnAfterGrow(void);
|
int returnAfterGrow(void);
|
||||||
int returnAfterGrowFromGo(void);
|
int returnAfterGrowFromGo(void);
|
||||||
@ -17,7 +16,6 @@ int returnAfterGrowFromGo(void);
|
|||||||
import "C"
|
import "C"
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"os"
|
|
||||||
"path"
|
"path"
|
||||||
"runtime"
|
"runtime"
|
||||||
"strings"
|
"strings"
|
||||||
@ -211,23 +209,6 @@ func testPanicFromC(t *testing.T) {
|
|||||||
C.callPanic()
|
C.callPanic()
|
||||||
}
|
}
|
||||||
|
|
||||||
func testAllocateFromC(t *testing.T) {
|
|
||||||
if strings.Contains(os.Getenv("GODEBUG"), "wbshadow=") {
|
|
||||||
// This test is writing pointers to Go heap objects from C.
|
|
||||||
// As such, those writes have no write barriers, and
|
|
||||||
// wbshadow=2 mode correctly discovers that and crashes.
|
|
||||||
// Disable test if any wbshadow mode is enabled.
|
|
||||||
// TODO(rsc): I am not sure whether the test is fundamentally
|
|
||||||
// incompatible with concurrent collection and should be
|
|
||||||
// turned off or rewritten entirely. The test is attempting to
|
|
||||||
// mimic some SWIG behavior, so it is important to work
|
|
||||||
// through what we expect before trying SWIG and C++
|
|
||||||
// with the concurrent collector.
|
|
||||||
t.Skip("test is incompatible with wbshadow=")
|
|
||||||
}
|
|
||||||
C.callCgoAllocate() // crashes or exits on failure
|
|
||||||
}
|
|
||||||
|
|
||||||
// Test that C code can return a value if it calls a Go function that
|
// Test that C code can return a value if it calls a Go function that
|
||||||
// causes a stack copy.
|
// causes a stack copy.
|
||||||
func testReturnAfterGrow(t *testing.T) {
|
func testReturnAfterGrow(t *testing.T) {
|
||||||
|
@ -23,58 +23,3 @@ callPanic(void)
|
|||||||
crosscall2(_cgo_panic, &a, sizeof a);
|
crosscall2(_cgo_panic, &a, sizeof a);
|
||||||
*(int*)1 = 1;
|
*(int*)1 = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Test calling cgo_allocate from C. This is what SWIG does. */
|
|
||||||
|
|
||||||
typedef struct List List;
|
|
||||||
struct List
|
|
||||||
{
|
|
||||||
List *next;
|
|
||||||
int x;
|
|
||||||
};
|
|
||||||
|
|
||||||
void
|
|
||||||
callCgoAllocate(void)
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
struct { size_t n; void *ret; } a;
|
|
||||||
List *l, *head, **tail;
|
|
||||||
|
|
||||||
// Make sure this doesn't crash.
|
|
||||||
// And make sure it returns non-nil.
|
|
||||||
a.n = 0;
|
|
||||||
a.ret = 0;
|
|
||||||
crosscall2(_cgo_allocate, &a, sizeof a);
|
|
||||||
if(a.ret == 0) {
|
|
||||||
fprintf(stderr, "callCgoAllocate: alloc 0 returned nil\n");
|
|
||||||
exit(2);
|
|
||||||
}
|
|
||||||
|
|
||||||
head = 0;
|
|
||||||
tail = &head;
|
|
||||||
for(i=0; i<100; i++) {
|
|
||||||
a.n = sizeof *l;
|
|
||||||
crosscall2(_cgo_allocate, &a, sizeof a);
|
|
||||||
l = a.ret;
|
|
||||||
l->x = i;
|
|
||||||
l->next = 0;
|
|
||||||
*tail = l;
|
|
||||||
tail = &l->next;
|
|
||||||
}
|
|
||||||
|
|
||||||
gc();
|
|
||||||
|
|
||||||
l = head;
|
|
||||||
for(i=0; i<100; i++) {
|
|
||||||
if(l->x != i) {
|
|
||||||
fprintf(stderr, "callCgoAllocate: lost memory\n");
|
|
||||||
exit(2);
|
|
||||||
}
|
|
||||||
l = l->next;
|
|
||||||
}
|
|
||||||
if(l != 0) {
|
|
||||||
fprintf(stderr, "callCgoAllocate: lost memory\n");
|
|
||||||
exit(2);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
@ -19,52 +19,3 @@ callPanic(void)
|
|||||||
{
|
{
|
||||||
_cgo_panic("panic from C");
|
_cgo_panic("panic from C");
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Test calling cgo_allocate from C. This is what SWIG does. */
|
|
||||||
|
|
||||||
typedef struct List List;
|
|
||||||
struct List
|
|
||||||
{
|
|
||||||
List *next;
|
|
||||||
int x;
|
|
||||||
};
|
|
||||||
|
|
||||||
void
|
|
||||||
callCgoAllocate(void)
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
List *l, *head, **tail;
|
|
||||||
|
|
||||||
// Make sure this doesn't crash.
|
|
||||||
// And make sure it returns non-nil.
|
|
||||||
if(_cgo_allocate(0) == 0) {
|
|
||||||
fprintf(stderr, "callCgoAllocate: alloc 0 returned nil\n");
|
|
||||||
exit(2);
|
|
||||||
}
|
|
||||||
|
|
||||||
head = 0;
|
|
||||||
tail = &head;
|
|
||||||
for(i=0; i<100; i++) {
|
|
||||||
l = _cgo_allocate(sizeof *l);
|
|
||||||
l->x = i;
|
|
||||||
l->next = 0;
|
|
||||||
*tail = l;
|
|
||||||
tail = &l->next;
|
|
||||||
}
|
|
||||||
|
|
||||||
gc();
|
|
||||||
|
|
||||||
l = head;
|
|
||||||
for(i=0; i<100; i++) {
|
|
||||||
if(l->x != i) {
|
|
||||||
fprintf(stderr, "callCgoAllocate: lost memory\n");
|
|
||||||
exit(2);
|
|
||||||
}
|
|
||||||
l = l->next;
|
|
||||||
}
|
|
||||||
if(l != 0) {
|
|
||||||
fprintf(stderr, "callCgoAllocate: lost memory\n");
|
|
||||||
exit(2);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
@ -23,7 +23,6 @@ func TestCallbackPanic(t *testing.T) { testCallbackPanic(t) }
|
|||||||
func TestCallbackPanicLoop(t *testing.T) { testCallbackPanicLoop(t) }
|
func TestCallbackPanicLoop(t *testing.T) { testCallbackPanicLoop(t) }
|
||||||
func TestCallbackPanicLocked(t *testing.T) { testCallbackPanicLocked(t) }
|
func TestCallbackPanicLocked(t *testing.T) { testCallbackPanicLocked(t) }
|
||||||
func TestPanicFromC(t *testing.T) { testPanicFromC(t) }
|
func TestPanicFromC(t *testing.T) { testPanicFromC(t) }
|
||||||
func TestAllocateFromC(t *testing.T) { testAllocateFromC(t) }
|
|
||||||
func TestZeroArgCallback(t *testing.T) { testZeroArgCallback(t) }
|
func TestZeroArgCallback(t *testing.T) { testZeroArgCallback(t) }
|
||||||
func TestBlocking(t *testing.T) { testBlocking(t) }
|
func TestBlocking(t *testing.T) { testBlocking(t) }
|
||||||
func Test1328(t *testing.T) { test1328(t) }
|
func Test1328(t *testing.T) { test1328(t) }
|
||||||
|
@ -22,32 +22,6 @@ func _runtime_cgocallback(unsafe.Pointer, unsafe.Pointer, uintptr)
|
|||||||
//go:cgo_export_static crosscall2
|
//go:cgo_export_static crosscall2
|
||||||
//go:cgo_export_dynamic crosscall2
|
//go:cgo_export_dynamic crosscall2
|
||||||
|
|
||||||
// Allocate memory. This allocates the requested number of bytes in
|
|
||||||
// memory controlled by the Go runtime. The allocated memory will be
|
|
||||||
// zeroed. You are responsible for ensuring that the Go garbage
|
|
||||||
// collector can see a pointer to the allocated memory for as long as
|
|
||||||
// it is valid, e.g., by storing a pointer in a local variable in your
|
|
||||||
// C function, or in memory allocated by the Go runtime. If the only
|
|
||||||
// pointers are in a C global variable or in memory allocated via
|
|
||||||
// malloc, then the Go garbage collector may collect the memory.
|
|
||||||
|
|
||||||
// Call like this in code compiled with gcc:
|
|
||||||
// struct { size_t len; void *ret; } a;
|
|
||||||
// a.len = /* number of bytes to allocate */;
|
|
||||||
// crosscall2(_cgo_allocate, &a, sizeof a);
|
|
||||||
// /* Here a.ret is a pointer to the allocated memory. */
|
|
||||||
|
|
||||||
//go:linkname _runtime_cgo_allocate_internal runtime._cgo_allocate_internal
|
|
||||||
var _runtime_cgo_allocate_internal byte
|
|
||||||
|
|
||||||
//go:linkname _cgo_allocate _cgo_allocate
|
|
||||||
//go:cgo_export_static _cgo_allocate
|
|
||||||
//go:cgo_export_dynamic _cgo_allocate
|
|
||||||
//go:nosplit
|
|
||||||
func _cgo_allocate(a unsafe.Pointer, n int32) {
|
|
||||||
_runtime_cgocallback(unsafe.Pointer(&_runtime_cgo_allocate_internal), a, uintptr(n))
|
|
||||||
}
|
|
||||||
|
|
||||||
// Panic. The argument is converted into a Go string.
|
// Panic. The argument is converted into a Go string.
|
||||||
|
|
||||||
// Call like this in code compiled with gcc:
|
// Call like this in code compiled with gcc:
|
||||||
|
@ -132,12 +132,6 @@ func cgocall_errno(fn, arg unsafe.Pointer) int32 {
|
|||||||
//go:nosplit
|
//go:nosplit
|
||||||
func endcgo(mp *m) {
|
func endcgo(mp *m) {
|
||||||
mp.ncgo--
|
mp.ncgo--
|
||||||
if mp.ncgo == 0 {
|
|
||||||
// We are going back to Go and are not in a recursive
|
|
||||||
// call. Let the GC collect any memory allocated via
|
|
||||||
// _cgo_allocate that is no longer referenced.
|
|
||||||
mp.cgomal = nil
|
|
||||||
}
|
|
||||||
|
|
||||||
if raceenabled {
|
if raceenabled {
|
||||||
raceacquire(unsafe.Pointer(&racecgosync))
|
raceacquire(unsafe.Pointer(&racecgosync))
|
||||||
|
@ -4,35 +4,8 @@
|
|||||||
|
|
||||||
package runtime
|
package runtime
|
||||||
|
|
||||||
import "unsafe"
|
|
||||||
|
|
||||||
// These functions are called from C code via cgo/callbacks.go.
|
// These functions are called from C code via cgo/callbacks.go.
|
||||||
|
|
||||||
// Allocate memory. This allocates the requested number of bytes in
|
|
||||||
// memory controlled by the Go runtime. The allocated memory will be
|
|
||||||
// zeroed. You are responsible for ensuring that the Go garbage
|
|
||||||
// collector can see a pointer to the allocated memory for as long as
|
|
||||||
// it is valid, e.g., by storing a pointer in a local variable in your
|
|
||||||
// C function, or in memory allocated by the Go runtime. If the only
|
|
||||||
// pointers are in a C global variable or in memory allocated via
|
|
||||||
// malloc, then the Go garbage collector may collect the memory.
|
|
||||||
//
|
|
||||||
// TODO(rsc,iant): This memory is untyped.
|
|
||||||
// Either we need to add types or we need to stop using it.
|
|
||||||
|
|
||||||
func _cgo_allocate_internal(len uintptr) unsafe.Pointer {
|
|
||||||
if len == 0 {
|
|
||||||
len = 1
|
|
||||||
}
|
|
||||||
ret := unsafe.Pointer(&make([]unsafe.Pointer, (len+ptrSize-1)/ptrSize)[0])
|
|
||||||
c := new(cgomal)
|
|
||||||
c.alloc = ret
|
|
||||||
gp := getg()
|
|
||||||
c.next = gp.m.cgomal
|
|
||||||
gp.m.cgomal = c
|
|
||||||
return ret
|
|
||||||
}
|
|
||||||
|
|
||||||
// Panic.
|
// Panic.
|
||||||
|
|
||||||
func _cgo_panic_internal(p *byte) {
|
func _cgo_panic_internal(p *byte) {
|
||||||
|
@ -127,15 +127,6 @@ const (
|
|||||||
_RootCount = 5
|
_RootCount = 5
|
||||||
)
|
)
|
||||||
|
|
||||||
//go:linkname weak_cgo_allocate go.weak.runtime._cgo_allocate_internal
|
|
||||||
var weak_cgo_allocate byte
|
|
||||||
|
|
||||||
// Is _cgo_allocate linked into the binary?
|
|
||||||
//go:nowritebarrier
|
|
||||||
func have_cgo_allocate() bool {
|
|
||||||
return &weak_cgo_allocate != nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// heapminimum is the minimum number of bytes in the heap.
|
// heapminimum is the minimum number of bytes in the heap.
|
||||||
// This cleans up the corner case of where we have a very small live set but a lot
|
// This cleans up the corner case of where we have a very small live set but a lot
|
||||||
// of allocations and collecting every GOGC * live set is expensive.
|
// of allocations and collecting every GOGC * live set is expensive.
|
||||||
|
@ -283,7 +283,6 @@ type m struct {
|
|||||||
fastrand uint32
|
fastrand uint32
|
||||||
ncgocall uint64 // number of cgo calls in total
|
ncgocall uint64 // number of cgo calls in total
|
||||||
ncgo int32 // number of cgo calls currently in progress
|
ncgo int32 // number of cgo calls currently in progress
|
||||||
cgomal *cgomal
|
|
||||||
park note
|
park note
|
||||||
alllink *m // on allm
|
alllink *m // on allm
|
||||||
schedlink *m
|
schedlink *m
|
||||||
@ -485,13 +484,6 @@ type lfnode struct {
|
|||||||
pushcnt uintptr
|
pushcnt uintptr
|
||||||
}
|
}
|
||||||
|
|
||||||
// Track memory allocated by code not written in Go during a cgo call,
|
|
||||||
// so that the garbage collector can see them.
|
|
||||||
type cgomal struct {
|
|
||||||
next *cgomal
|
|
||||||
alloc unsafe.Pointer
|
|
||||||
}
|
|
||||||
|
|
||||||
// Indicates to write barrier and sychronization task to preform.
|
// Indicates to write barrier and sychronization task to preform.
|
||||||
const (
|
const (
|
||||||
_GCoff = iota // GC not running, write barrier disabled
|
_GCoff = iota // GC not running, write barrier disabled
|
||||||
|
Loading…
Reference in New Issue
Block a user