1
0
mirror of https://github.com/golang/go synced 2024-10-04 08:31:22 -06:00
go/src/pkg/runtime/thread_plan9.c
Russ Cox 6e2ae0a12c runtime/pprof: support OS X CPU profiling
Work around profiling kernel bug with signal masks.
Still broken on 64-bit Snow Leopard kernel,
but I think we can ignore that one and let people
upgrade to Lion.

Add new trivial tools addr2line and objdump to take
the place of the GNU tools of the same name, since
those are not installed on OS X.

Adapt pprof to invoke 'go tool addr2line' and
'go tool objdump' if the system tools do not exist.

Clean up disassembly of base register on amd64.

Fixes #2008.

R=golang-dev, bradfitz, mikioh.mikioh, r, iant
CC=golang-dev
https://golang.org/cl/5697066
2012-02-28 16:18:24 -05:00

250 lines
4.6 KiB
C

// Copyright 2010 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
#include "runtime.h"
#include "os_GOOS.h"
#include "arch_GOARCH.h"
int8 *goos = "plan9";
void
runtime·minit(void)
{
}
static int32
getproccount(void)
{
int32 fd, i, n, ncpu;
byte buf[2048];
fd = runtime·open((byte*)"/dev/sysstat", OREAD);
if(fd < 0)
return 1;
ncpu = 0;
for(;;) {
n = runtime·read(fd, buf, sizeof buf);
if(n <= 0)
break;
for(i = 0; i < n; i++) {
if(buf[i] == '\n')
ncpu++;
}
}
runtime·close(fd);
return ncpu > 0 ? ncpu : 1;
}
void
runtime·osinit(void)
{
runtime·ncpu = getproccount();
}
void
runtime·goenvs(void)
{
}
void
runtime·initsig(void)
{
}
void
runtime·osyield(void)
{
runtime·sleep(0);
}
void
runtime·usleep(uint32 µs)
{
uint32 ms;
ms = µs/1000;
if(ms == 0)
ms = 1;
runtime·sleep(ms);
}
int64
runtime·nanotime(void)
{
static int32 fd = -1;
byte b[8];
uint32 hi, lo;
// As long as all goroutines share the same file
// descriptor table we can get away with using
// just a static fd. Without a lock the file can
// be opened twice but that's okay.
//
// Using /dev/bintime gives us a latency on the
// order of ten microseconds between two calls.
//
// The naïve implementation (without the cached
// file descriptor) is roughly four times slower
// in 9vx on a 2.16 GHz Intel Core 2 Duo.
if(fd < 0 && (fd = runtime·open((byte*)"/dev/bintime", OREAD|OCEXEC)) < 0)
return 0;
if(runtime·pread(fd, b, sizeof b, 0) != sizeof b)
return 0;
hi = b[0]<<24 | b[1]<<16 | b[2]<<8 | b[3];
lo = b[4]<<24 | b[5]<<16 | b[6]<<8 | b[7];
return (int64)hi<<32 | (int64)lo;
}
void
time·now(int64 sec, int32 nsec)
{
int64 ns;
ns = runtime·nanotime();
sec = ns / 1000000000LL;
nsec = ns - sec * 1000000000LL;
FLUSH(&sec);
FLUSH(&nsec);
}
extern Tos *_tos;
void
runtime·exit(int32)
{
int32 fd;
uint8 buf[128];
uint8 tmp[16];
uint8 *p, *q;
int32 pid;
runtime·memclr(buf, sizeof buf);
runtime·memclr(tmp, sizeof tmp);
pid = _tos->pid;
/* build path string /proc/pid/notepg */
for(q=tmp; pid > 0;) {
*q++ = '0' + (pid%10);
pid = pid/10;
}
p = buf;
runtime·memmove((void*)p, (void*)"/proc/", 6);
p += 6;
for(q--; q >= tmp;)
*p++ = *q--;
runtime·memmove((void*)p, (void*)"/notepg", 7);
/* post interrupt note */
fd = runtime·open(buf, OWRITE);
runtime·write(fd, "interrupt", 9);
runtime·exits(nil);
}
void
runtime·newosproc(M *m, G *g, void *stk, void (*fn)(void))
{
m->tls[0] = m->id; // so 386 asm can find it
if(0){
runtime·printf("newosproc stk=%p m=%p g=%p fn=%p rfork=%p id=%d/%d ostk=%p\n",
stk, m, g, fn, runtime·rfork, m->id, m->tls[0], &m);
}
if(runtime·rfork(RFPROC|RFMEM|RFNOWAIT, stk, m, g, fn) < 0)
runtime·throw("newosproc: rfork failed");
}
uintptr
runtime·semacreate(void)
{
return 1;
}
int32
runtime·semasleep(int64 ns)
{
int32 ret;
int32 ms;
if(ns >= 0) {
// TODO: Plan 9 needs a new system call, tsemacquire.
// The kernel implementation is the same as semacquire
// except with a tsleep and check for timeout.
// It would be great if the implementation returned the
// value that was added to the semaphore, so that on
// timeout the return value would be 0, on success 1.
// Then the error string does not have to be parsed
// to detect timeout.
//
// If a negative time indicates no timeout, then
// semacquire can be implemented (in the kernel)
// as tsemacquire(p, v, -1).
runtime·throw("semasleep: timed sleep not implemented on Plan 9");
/*
if(ns < 0)
ms = -1;
else if(ns/1000 > 0x7fffffffll)
ms = 0x7fffffff;
else
ms = ns/1000;
ret = runtime·plan9_tsemacquire(&m->waitsemacount, 1, ms);
if(ret == 1)
return 0; // success
return -1; // timeout or interrupted
*/
}
while(runtime·plan9_semacquire(&m->waitsemacount, 1) < 0) {
/* interrupted; try again */
}
return 0; // success
}
void
runtime·semawakeup(M *mp)
{
runtime·plan9_semrelease(&mp->waitsemacount, 1);
}
void
os·sigpipe(void)
{
runtime·throw("too many writes on closed pipe");
}
/*
* placeholder - once notes are implemented,
* a signal generating a panic must appear as
* a call to this function for correct handling by
* traceback.
*/
void
runtime·sigpanic(void)
{
}
int32
runtime·read(int32 fd, void *buf, int32 nbytes)
{
return runtime·pread(fd, buf, nbytes, -1LL);
}
int32
runtime·write(int32 fd, void *buf, int32 nbytes)
{
return runtime·pwrite(fd, buf, nbytes, -1LL);
}
uintptr
runtime·memlimit(void)
{
return 0;
}
void
runtime·setprof(bool on)
{
USED(on);
}