mirror of
https://github.com/golang/go.git
synced 2025-12-08 06:10:04 +00:00
runtime: openbsd amd64 runtime support
Add support for the go runtime on openbsd/amd64. This is based on the existing freebsd runtime. Threads are implemented using OpenBSD's rthreads, which are currently disabled by default, however can be enabled via the kern.rthreads sysctl. For now, cgo is disabled. R=rsc CC=golang-dev https://golang.org/cl/4815067
This commit is contained in:
parent
604b91a43e
commit
21ac258e07
10 changed files with 977 additions and 0 deletions
156
src/pkg/runtime/openbsd/thread.c
Normal file
156
src/pkg/runtime/openbsd/thread.c
Normal file
|
|
@ -0,0 +1,156 @@
|
|||
// Use of this source file is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.`
|
||||
|
||||
#include "runtime.h"
|
||||
#include "defs.h"
|
||||
#include "os.h"
|
||||
#include "stack.h"
|
||||
|
||||
extern SigTab runtime·sigtab[];
|
||||
|
||||
extern int64 runtime·rfork_thread(int32 flags, void *stack, M *m, G *g, void (*fn)(void));
|
||||
extern void runtime·sys_sched_yield(void);
|
||||
|
||||
// Basic spinlocks using CAS. We can improve on these later.
|
||||
static void
|
||||
lock(Lock *l)
|
||||
{
|
||||
uint32 v;
|
||||
int32 ret;
|
||||
|
||||
for(;;) {
|
||||
if(runtime·cas(&l->key, 0, 1))
|
||||
return;
|
||||
runtime·sys_sched_yield();
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
unlock(Lock *l)
|
||||
{
|
||||
uint32 v;
|
||||
int32 ret;
|
||||
|
||||
for (;;) {
|
||||
v = l->key;
|
||||
if((v&1) == 0)
|
||||
runtime·throw("unlock of unlocked lock");
|
||||
if(runtime·cas(&l->key, v, 0))
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
runtime·lock(Lock *l)
|
||||
{
|
||||
if(m->locks < 0)
|
||||
runtime·throw("lock count");
|
||||
m->locks++;
|
||||
lock(l);
|
||||
}
|
||||
|
||||
void
|
||||
runtime·unlock(Lock *l)
|
||||
{
|
||||
m->locks--;
|
||||
if(m->locks < 0)
|
||||
runtime·throw("lock count");
|
||||
unlock(l);
|
||||
}
|
||||
|
||||
// Event notifications.
|
||||
void
|
||||
runtime·noteclear(Note *n)
|
||||
{
|
||||
n->lock.key = 0;
|
||||
lock(&n->lock);
|
||||
}
|
||||
|
||||
void
|
||||
runtime·notesleep(Note *n)
|
||||
{
|
||||
lock(&n->lock);
|
||||
unlock(&n->lock);
|
||||
}
|
||||
|
||||
void
|
||||
runtime·notewakeup(Note *n)
|
||||
{
|
||||
unlock(&n->lock);
|
||||
}
|
||||
|
||||
// From OpenBSD's sys/param.h
|
||||
#define RFPROC (1<<4) /* change child (else changes curproc) */
|
||||
#define RFMEM (1<<5) /* share `address space' */
|
||||
#define RFNOWAIT (1<<6) /* parent need not wait() on child */
|
||||
#define RFTHREAD (1<<13) /* create a thread, not a process */
|
||||
|
||||
void
|
||||
runtime·newosproc(M *m, G *g, void *stk, void (*fn)(void))
|
||||
{
|
||||
int32 flags;
|
||||
int32 ret;
|
||||
|
||||
flags = RFPROC | RFTHREAD | RFMEM | RFNOWAIT;
|
||||
|
||||
if (0) {
|
||||
runtime·printf(
|
||||
"newosproc stk=%p m=%p g=%p fn=%p id=%d/%d ostk=%p\n",
|
||||
stk, m, g, fn, m->id, m->tls[0], &m);
|
||||
}
|
||||
|
||||
m->tls[0] = m->id; // so 386 asm can find it
|
||||
|
||||
if((ret = runtime·rfork_thread(flags, stk, m, g, fn)) < 0) {
|
||||
runtime·printf("runtime: failed to create new OS thread (have %d already; errno=%d)\n", runtime·mcount() - 1, -ret);
|
||||
runtime·printf("runtime: is kern.rthreads disabled?\n");
|
||||
|
||||
runtime·throw("runtime.newosproc");
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
runtime·osinit(void)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
runtime·goenvs(void)
|
||||
{
|
||||
runtime·goenvs_unix();
|
||||
}
|
||||
|
||||
// Called to initialize a new m (including the bootstrap m).
|
||||
void
|
||||
runtime·minit(void)
|
||||
{
|
||||
// Initialize signal handling
|
||||
m->gsignal = runtime·malg(32*1024);
|
||||
runtime·signalstack(m->gsignal->stackguard - StackGuard, 32*1024);
|
||||
}
|
||||
|
||||
void
|
||||
runtime·sigpanic(void)
|
||||
{
|
||||
switch(g->sig) {
|
||||
case SIGBUS:
|
||||
if(g->sigcode0 == BUS_ADRERR && g->sigcode1 < 0x1000)
|
||||
runtime·panicstring("invalid memory address or nil pointer dereference");
|
||||
runtime·printf("unexpected fault address %p\n", g->sigcode1);
|
||||
runtime·throw("fault");
|
||||
case SIGSEGV:
|
||||
if((g->sigcode0 == 0 || g->sigcode0 == SEGV_MAPERR || g->sigcode0 == SEGV_ACCERR) && g->sigcode1 < 0x1000)
|
||||
runtime·panicstring("invalid memory address or nil pointer dereference");
|
||||
runtime·printf("unexpected fault address %p\n", g->sigcode1);
|
||||
runtime·throw("fault");
|
||||
case SIGFPE:
|
||||
switch(g->sigcode0) {
|
||||
case FPE_INTDIV:
|
||||
runtime·panicstring("integer divide by zero");
|
||||
case FPE_INTOVF:
|
||||
runtime·panicstring("integer overflow");
|
||||
}
|
||||
runtime·panicstring("floating point error");
|
||||
}
|
||||
runtime·panicstring(runtime·sigtab[g->sig].name);
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue