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:
Joel Sing 2011-08-08 09:56:38 -04:00 committed by Russ Cox
parent 604b91a43e
commit 21ac258e07
10 changed files with 977 additions and 0 deletions

View 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);
}