summaryrefslogtreecommitdiff
path: root/src/pkg/runtime
diff options
context:
space:
mode:
Diffstat (limited to 'src/pkg/runtime')
-rw-r--r--src/pkg/runtime/cgocall.c6
-rw-r--r--src/pkg/runtime/proc.c20
-rw-r--r--src/pkg/runtime/runtime.h1
3 files changed, 21 insertions, 6 deletions
diff --git a/src/pkg/runtime/cgocall.c b/src/pkg/runtime/cgocall.c
index 7b2ec26f3..75d3850ef 100644
--- a/src/pkg/runtime/cgocall.c
+++ b/src/pkg/runtime/cgocall.c
@@ -234,14 +234,18 @@ void runtime·cgocallbackg1(void);
void
runtime·cgocallbackg(void)
{
+ uintptr pc, sp;
+
if(g != m->curg) {
runtime·prints("runtime: bad g in cgocallback");
runtime·exit(2);
}
+ pc = g->syscallpc;
+ sp = g->syscallsp;
runtime·exitsyscall(); // coming out of cgo call
runtime·cgocallbackg1();
- runtime·entersyscall(); // going back to cgo call
+ runtime·reentersyscall((void*)pc, sp); // going back to cgo call
}
void
diff --git a/src/pkg/runtime/proc.c b/src/pkg/runtime/proc.c
index 914a02e0b..de4f70153 100644
--- a/src/pkg/runtime/proc.c
+++ b/src/pkg/runtime/proc.c
@@ -1499,14 +1499,14 @@ save(void *pc, uintptr sp)
// entersyscall is going to return immediately after.
#pragma textflag NOSPLIT
void
-·entersyscall(int32 dummy)
+runtime·reentersyscall(void *pc, uintptr sp)
{
// Disable preemption because during this function g is in Gsyscall status,
// but can have inconsistent g->sched, do not let GC observe it.
m->locks++;
// Leave SP around for GC and traceback.
- save(runtime·getcallerpc(&dummy), runtime·getcallersp(&dummy));
+ save(pc, sp);
g->syscallsp = g->sched.sp;
g->syscallpc = g->sched.pc;
g->syscallstack = g->stackbase;
@@ -1525,7 +1525,7 @@ void
runtime·notewakeup(&runtime·sched.sysmonnote);
}
runtime·unlock(&runtime·sched);
- save(runtime·getcallerpc(&dummy), runtime·getcallersp(&dummy));
+ save(pc, sp);
}
m->mcache = nil;
@@ -1538,7 +1538,7 @@ void
runtime·notewakeup(&runtime·sched.stopnote);
}
runtime·unlock(&runtime·sched);
- save(runtime·getcallerpc(&dummy), runtime·getcallersp(&dummy));
+ save(pc, sp);
}
// Goroutines must not split stacks in Gsyscall status (it would corrupt g->sched).
@@ -1548,6 +1548,13 @@ void
m->locks--;
}
+#pragma textflag NOSPLIT
+void
+·entersyscall(int32 dummy)
+{
+ runtime·reentersyscall(runtime·getcallerpc(&dummy), runtime·getcallersp(&dummy));
+}
+
// The same as runtime·entersyscall(), but with a hint that the syscall is blocking.
#pragma textflag NOSPLIT
void
@@ -1588,10 +1595,13 @@ void
// from the low-level system calls used by the runtime.
#pragma textflag NOSPLIT
void
-runtime·exitsyscall(void)
+·exitsyscall(int32 dummy)
{
m->locks++; // see comment in entersyscall
+ if(runtime·getcallersp(&dummy) > g->syscallsp)
+ runtime·throw("exitsyscall: syscall frame is no longer valid");
+
if(g->isbackground) // do not consider blocked scavenger for deadlock detection
incidlelocked(-1);
diff --git a/src/pkg/runtime/runtime.h b/src/pkg/runtime/runtime.h
index 511550378..42fb3a47d 100644
--- a/src/pkg/runtime/runtime.h
+++ b/src/pkg/runtime/runtime.h
@@ -921,6 +921,7 @@ M* runtime·newm(void);
void runtime·goexit(void);
void runtime·asmcgocall(void (*fn)(void*), void*);
void runtime·entersyscall(void);
+void runtime·reentersyscall(void*, uintptr);
void runtime·entersyscallblock(void);
void runtime·exitsyscall(void);
G* runtime·newproc1(FuncVal*, byte*, int32, int32, void*);