diff options
Diffstat (limited to 'src/pkg/runtime/os_netbsd.c')
-rw-r--r-- | src/pkg/runtime/os_netbsd.c | 70 |
1 files changed, 63 insertions, 7 deletions
diff --git a/src/pkg/runtime/os_netbsd.c b/src/pkg/runtime/os_netbsd.c index 29ea0cb42..cee96ebed 100644 --- a/src/pkg/runtime/os_netbsd.c +++ b/src/pkg/runtime/os_netbsd.c @@ -57,18 +57,23 @@ getncpu(void) return 1; } +#pragma textflag NOSPLIT uintptr runtime·semacreate(void) { return 1; } -#pragma textflag NOSPLIT -int32 -runtime·semasleep(int64 ns) +static void +semasleep(void) { + int64 ns; Timespec ts; + ns = (int64)(uint32)g->m->scalararg[0] | (int64)(uint32)g->m->scalararg[1]<<32; + g->m->scalararg[0] = 0; + g->m->scalararg[1] = 0; + // spin-mutex lock while(runtime·xchg(&g->m->waitsemalock, 1)) runtime·osyield(); @@ -115,7 +120,8 @@ runtime·semasleep(int64 ns) g->m->waitsemacount--; // spin-mutex unlock runtime·atomicstore(&g->m->waitsemalock, 0); - return 0; // semaphore acquired + g->m->scalararg[0] = 0; // semaphore acquired + return; } // semaphore not available. @@ -128,13 +134,36 @@ runtime·semasleep(int64 ns) // lock held but giving up // spin-mutex unlock runtime·atomicstore(&g->m->waitsemalock, 0); - return -1; + g->m->scalararg[0] = -1; + return; +} + +#pragma textflag NOSPLIT +int32 +runtime·semasleep(int64 ns) +{ + int32 r; + void (*fn)(void); + + g->m->scalararg[0] = (uint32)ns; + g->m->scalararg[1] = (uint32)(ns>>32); + fn = semasleep; + runtime·onM(&fn); + r = g->m->scalararg[0]; + g->m->scalararg[0] = 0; + return r; } +static void badsemawakeup(void); + +#pragma textflag NOSPLIT void runtime·semawakeup(M *mp) { uint32 ret; + void (*fn)(void); + void *oldptr; + uintptr oldscalar; // spin-mutex lock while(runtime·xchg(&mp->waitsemalock, 1)) @@ -143,12 +172,39 @@ runtime·semawakeup(M *mp) // TODO(jsing) - potential deadlock, see semasleep() for details. // Confirm that LWP is parked before unparking... ret = runtime·lwp_unpark(mp->procid, &mp->waitsemacount); - 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) { |