summaryrefslogtreecommitdiff
path: root/misc/cgo/test/callback_c_gc.c
diff options
context:
space:
mode:
Diffstat (limited to 'misc/cgo/test/callback_c_gc.c')
-rw-r--r--misc/cgo/test/callback_c_gc.c59
1 files changed, 59 insertions, 0 deletions
diff --git a/misc/cgo/test/callback_c_gc.c b/misc/cgo/test/callback_c_gc.c
index 8953b74a6..28a62c6db 100644
--- a/misc/cgo/test/callback_c_gc.c
+++ b/misc/cgo/test/callback_c_gc.c
@@ -5,11 +5,15 @@
// +build gc
#include "_cgo_export.h"
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
/* Test calling panic from C. This is what SWIG does. */
extern void crosscall2(void (*fn)(void *, int), void *, int);
extern void _cgo_panic(void *, int);
+extern void _cgo_allocate(void *, int);
void
callPanic(void)
@@ -19,3 +23,58 @@ callPanic(void)
crosscall2(_cgo_panic, &a, sizeof a);
*(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);
+ }
+}
+