summaryrefslogtreecommitdiff
path: root/src/pkg/runtime/os_openbsd.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/pkg/runtime/os_openbsd.c')
-rw-r--r--src/pkg/runtime/os_openbsd.c38
1 files changed, 36 insertions, 2 deletions
diff --git a/src/pkg/runtime/os_openbsd.c b/src/pkg/runtime/os_openbsd.c
index 728cb88c4..7c9e478e8 100644
--- a/src/pkg/runtime/os_openbsd.c
+++ b/src/pkg/runtime/os_openbsd.c
@@ -54,6 +54,7 @@ getncpu(void)
return 1;
}
+#pragma textflag NOSPLIT
uintptr
runtime·semacreate(void)
{
@@ -111,22 +112,55 @@ runtime·semasleep(int64 ns)
return -1;
}
+static void badsemawakeup(void);
+
+#pragma textflag NOSPLIT
void
runtime·semawakeup(M *mp)
{
uint32 ret;
+ void *oldptr;
+ uint32 oldscalar;
+ void (*fn)(void);
// spin-mutex lock
while(runtime·xchg(&mp->waitsemalock, 1))
runtime·osyield();
mp->waitsemacount++;
ret = runtime·thrwakeup(&mp->waitsemacount, 1);
- if(ret != 0 && ret != ESRCH)
- runtime·printf("thrwakeup addr=%p sem=%d ret=%d\n", &mp->waitsemacount, mp->waitsemacount, ret);
+ if(ret != 0 && ret != ESRCH) {
+ // semawakeup can be called on signal stack.
+ // Save old ptrarg/scalararg so we can restore them.
+ oldptr = g->m->ptrarg[0];
+ oldscalar = g->m->scalararg[0];
+ g->m->ptrarg[0] = mp;
+ g->m->scalararg[0] = ret;
+ fn = badsemawakeup;
+ if(g == g->m->gsignal)
+ fn();
+ else
+ runtime·onM(&fn);
+ g->m->ptrarg[0] = oldptr;
+ g->m->scalararg[0] = oldscalar;
+ }
// spin-mutex unlock
runtime·atomicstore(&mp->waitsemalock, 0);
}
+static void
+badsemawakeup(void)
+{
+ M *mp;
+ int32 ret;
+
+ mp = g->m->ptrarg[0];
+ g->m->ptrarg[0] = nil;
+ ret = g->m->scalararg[0];
+ g->m->scalararg[0] = 0;
+
+ runtime·printf("thrwakeup addr=%p sem=%d ret=%d\n", &mp->waitsemacount, mp->waitsemacount, ret);
+}
+
void
runtime·newosproc(M *mp, void *stk)
{