goname = "_cgoexpwrap" + cPrefix + "_" + fn.Recv.List[0].Names[0].Name + "_" + goname
}
fmt.Fprintf(fc, "#pragma dynexport %s %s\n", goname, goname)
- fmt.Fprintf(fc, "extern void ·%s();\n", goname)
- fmt.Fprintf(fc, "\nvoid\n")
+ fmt.Fprintf(fc, "extern void ·%s();\n\n", goname)
+ fmt.Fprintf(fc, "#pragma textflag 7\n") // no split stack, so no use of m or g
+ fmt.Fprintf(fc, "void\n")
fmt.Fprintf(fc, "_cgoexp%s_%s(void *a, int32 n)\n", cPrefix, exp.ExpName)
fmt.Fprintf(fc, "{\n")
fmt.Fprintf(fc, "\truntime·cgocallback(·%s, a, n);\n", goname)
// Save current m->g0->sched.sp on stack and then set it to SP.
get_tls(CX)
MOVL m(CX), BP
+
+ // If m is nil, it is almost certainly because we have been called
+ // on a thread that Go did not create. We're going to crash as
+ // soon as we try to use m; instead, try to print a nice error and exit.
+ CMPL BP, $0
+ JNE 2(PC)
+ CALL runtime·badcallback(SB)
+
MOVL m_g0(BP), SI
PUSHL (g_sched+gobuf_sp)(SI)
MOVL SP, (g_sched+gobuf_sp)(SI)
// Save current m->g0->sched.sp on stack and then set it to SP.
get_tls(CX)
MOVQ m(CX), BP
+
+ // If m is nil, it is almost certainly because we have been called
+ // on a thread that Go did not create. We're going to crash as
+ // soon as we try to use m; instead, try to print a nice error and exit.
+ CMPQ BP, $0
+ JNE 2(PC)
+ CALL runtime·badcallback(SB)
+
MOVQ m_g0(BP), SI
PUSHQ (g_sched+gobuf_sp)(SI)
MOVQ SP, (g_sched+gobuf_sp)(SI)
else
runtime·sigprocmask(SIG_BLOCK, &sigset_prof, nil);
}
+
+static int8 badcallback[] = "runtime: cgo callback on thread not created by Go.\n";
+
+// This runs on a foreign stack, without an m or a g. No stack split.
+#pragma textflag 7
+void
+runtime·badcallback(void)
+{
+ runtime·write(2, badcallback, sizeof badcallback - 1);
+}
{
USED(on);
}
+
+static int8 badcallback[] = "runtime: cgo callback on thread not created by Go.\n";
+
+// This runs on a foreign stack, without an m or a g. No stack split.
+#pragma textflag 7
+void
+runtime·badcallback(void)
+{
+ runtime·write(2, badcallback, sizeof badcallback - 1);
+}
{
USED(on);
}
+
+static int8 badcallback[] = "runtime: cgo callback on thread not created by Go.\n";
+
+// This runs on a foreign stack, without an m or a g. No stack split.
+#pragma textflag 7
+void
+runtime·badcallback(void)
+{
+ runtime·write(2, badcallback, sizeof badcallback - 1);
+}
{
USED(on);
}
+
+static int8 badcallback[] = "runtime: cgo callback on thread not created by Go.\n";
+
+// This runs on a foreign stack, without an m or a g. No stack split.
+#pragma textflag 7
+void
+runtime·badcallback(void)
+{
+ runtime·write(2, badcallback, sizeof badcallback - 1);
+}
{
USED(on);
}
+
+static int8 badcallback[] = "runtime: cgo callback on thread not created by Go.\n";
+
+// This runs on a foreign stack, without an m or a g. No stack split.
+#pragma textflag 7
+void
+runtime·badcallback(void)
+{
+ runtime·write(2, badcallback, sizeof badcallback - 1);
+}
{
USED(on);
}
+
+static int8 badcallback[] = "runtime: cgo callback on thread not created by Go.\n";
+
+// This runs on a foreign stack, without an m or a g. No stack split.
+#pragma textflag 7
+void
+runtime·badcallback(void)
+{
+ runtime·pwrite(2, badcallback, sizeof badcallback - 1, -1LL);
+}
{
USED(on);
}
+
+static int8 badcallback[] = "runtime: cgo callback on thread not created by Go.\n";
+
+// This runs on a foreign stack, without an m or a g. No stack split.
+#pragma textflag 7
+void
+runtime·badcallback(void)
+{
+ uint32 written;
+
+ runtime·stdcall(
+ runtime·WriteFile, 5,
+ runtime·stdcall(runtime·GetStdHandle, 1, (uintptr)-12), // stderr
+ badcallback,
+ (uintptr)(sizeof badcallback - 1),
+ &written,
+ nil
+ );
+}