aboutsummaryrefslogtreecommitdiff
path: root/src/pkg/runtime
diff options
context:
space:
mode:
authorRuss Cox <rsc@golang.org>2012-02-28 16:18:24 -0500
committerRuss Cox <rsc@golang.org>2012-02-28 16:18:24 -0500
commit6e2ae0a12c0f73da56d4f465e68208731b4b16be (patch)
tree97b35b94a6880d7eb9a458663e1bfe432e4731e9 /src/pkg/runtime
parentc10f50859ead8f1578e86e65d5f376ae6a3a32df (diff)
downloadgo-6e2ae0a12c0f73da56d4f465e68208731b4b16be.tar.xz
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
Diffstat (limited to 'src/pkg/runtime')
-rw-r--r--src/pkg/runtime/lock_futex.c12
-rw-r--r--src/pkg/runtime/lock_sema.c11
-rw-r--r--src/pkg/runtime/os_darwin.h3
-rw-r--r--src/pkg/runtime/os_freebsd.h1
-rw-r--r--src/pkg/runtime/os_netbsd.h1
-rw-r--r--src/pkg/runtime/os_openbsd.h1
-rw-r--r--src/pkg/runtime/pprof/pprof.go6
-rw-r--r--src/pkg/runtime/pprof/pprof_test.go12
-rw-r--r--src/pkg/runtime/proc.c9
-rw-r--r--src/pkg/runtime/runtime.h10
-rw-r--r--src/pkg/runtime/signal_darwin_386.c5
-rw-r--r--src/pkg/runtime/signal_darwin_amd64.c9
-rw-r--r--src/pkg/runtime/signal_unix.c6
-rw-r--r--src/pkg/runtime/sys_darwin_386.s4
-rw-r--r--src/pkg/runtime/sys_darwin_amd64.s2
-rw-r--r--src/pkg/runtime/thread_darwin.c49
-rw-r--r--src/pkg/runtime/thread_freebsd.c6
-rw-r--r--src/pkg/runtime/thread_linux.c8
-rw-r--r--src/pkg/runtime/thread_netbsd.c6
-rw-r--r--src/pkg/runtime/thread_openbsd.c6
-rw-r--r--src/pkg/runtime/thread_plan9.c8
-rw-r--r--src/pkg/runtime/thread_windows.c8
22 files changed, 153 insertions, 30 deletions
diff --git a/src/pkg/runtime/lock_futex.c b/src/pkg/runtime/lock_futex.c
index 6ec4aee7bf..b4465bff18 100644
--- a/src/pkg/runtime/lock_futex.c
+++ b/src/pkg/runtime/lock_futex.c
@@ -118,8 +118,12 @@ runtime·notewakeup(Note *n)
void
runtime·notesleep(Note *n)
{
+ if(m->profilehz > 0)
+ runtime·setprof(false);
while(runtime·atomicload(&n->key) == 0)
runtime·futexsleep(&n->key, 0, -1);
+ if(m->profilehz > 0)
+ runtime·setprof(true);
}
void
@@ -135,14 +139,18 @@ runtime·notetsleep(Note *n, int64 ns)
if(runtime·atomicload(&n->key) != 0)
return;
+ if(m->profilehz > 0)
+ runtime·setprof(false);
deadline = runtime·nanotime() + ns;
for(;;) {
runtime·futexsleep(&n->key, 0, ns);
if(runtime·atomicload(&n->key) != 0)
- return;
+ break;
now = runtime·nanotime();
if(now >= deadline)
- return;
+ break;
ns = deadline - now;
}
+ if(m->profilehz > 0)
+ runtime·setprof(true);
}
diff --git a/src/pkg/runtime/lock_sema.c b/src/pkg/runtime/lock_sema.c
index 28d2c3281e..1d9c37fdb6 100644
--- a/src/pkg/runtime/lock_sema.c
+++ b/src/pkg/runtime/lock_sema.c
@@ -154,7 +154,11 @@ runtime·notesleep(Note *n)
return;
}
// Queued. Sleep.
+ if(m->profilehz > 0)
+ runtime·setprof(false);
runtime·semasleep(-1);
+ if(m->profilehz > 0)
+ runtime·setprof(true);
}
void
@@ -178,12 +182,16 @@ runtime·notetsleep(Note *n, int64 ns)
return;
}
+ if(m->profilehz > 0)
+ runtime·setprof(false);
deadline = runtime·nanotime() + ns;
for(;;) {
// Registered. Sleep.
if(runtime·semasleep(ns) >= 0) {
// Acquired semaphore, semawakeup unregistered us.
// Done.
+ if(m->profilehz > 0)
+ runtime·setprof(true);
return;
}
@@ -196,6 +204,9 @@ runtime·notetsleep(Note *n, int64 ns)
ns = deadline - now;
}
+ if(m->profilehz > 0)
+ runtime·setprof(true);
+
// Deadline arrived. Still registered. Semaphore not acquired.
// Want to give up and return, but have to unregister first,
// so that any notewakeup racing with the return does not
diff --git a/src/pkg/runtime/os_darwin.h b/src/pkg/runtime/os_darwin.h
index 071a547177..eb5d2daa38 100644
--- a/src/pkg/runtime/os_darwin.h
+++ b/src/pkg/runtime/os_darwin.h
@@ -38,4 +38,7 @@ void runtime·raisesigpipe(void);
#define NSIG 32
#define SI_USER 0 /* empirically true, but not what headers say */
+#define SIG_BLOCK 1
+#define SIG_UNBLOCK 2
#define SIG_SETMASK 3
+
diff --git a/src/pkg/runtime/os_freebsd.h b/src/pkg/runtime/os_freebsd.h
index da1d8de2eb..5e8de5434a 100644
--- a/src/pkg/runtime/os_freebsd.h
+++ b/src/pkg/runtime/os_freebsd.h
@@ -9,7 +9,6 @@ struct sigaction;
void runtime·sigaction(int32, struct sigaction*, struct sigaction*);
void runtime·sigprocmask(Sigset *, Sigset *);
void runtime·setsig(int32, void(*)(int32, Siginfo*, void*, G*), bool);
-void runtiem·setitimerval(int32, Itimerval*, Itimerval*);
void runtime·setitimer(int32, Itimerval*, Itimerval*);
int32 runtime·sysctl(uint32*, uint32, byte*, uintptr*, byte*, uintptr);
diff --git a/src/pkg/runtime/os_netbsd.h b/src/pkg/runtime/os_netbsd.h
index 67c58ecb2a..4ecf78d882 100644
--- a/src/pkg/runtime/os_netbsd.h
+++ b/src/pkg/runtime/os_netbsd.h
@@ -12,7 +12,6 @@ void runtime·sigaltstack(Sigaltstack*, Sigaltstack*);
void runtime·sigaction(int32, struct sigaction*, struct sigaction*);
void runtime·setsig(int32, void(*)(int32, Siginfo*, void*, G*), bool);
void runtime·sighandler(int32 sig, Siginfo *info, void *context, G *gp);
-void runtime·setitimerval(int32, Itimerval*, Itimerval*);
void runtime·setitimer(int32, Itimerval*, Itimerval*);
int32 runtime·sysctl(uint32*, uint32, byte*, uintptr*, byte*, uintptr);
diff --git a/src/pkg/runtime/os_openbsd.h b/src/pkg/runtime/os_openbsd.h
index 67c58ecb2a..4ecf78d882 100644
--- a/src/pkg/runtime/os_openbsd.h
+++ b/src/pkg/runtime/os_openbsd.h
@@ -12,7 +12,6 @@ void runtime·sigaltstack(Sigaltstack*, Sigaltstack*);
void runtime·sigaction(int32, struct sigaction*, struct sigaction*);
void runtime·setsig(int32, void(*)(int32, Siginfo*, void*, G*), bool);
void runtime·sighandler(int32 sig, Siginfo *info, void *context, G *gp);
-void runtime·setitimerval(int32, Itimerval*, Itimerval*);
void runtime·setitimer(int32, Itimerval*, Itimerval*);
int32 runtime·sysctl(uint32*, uint32, byte*, uintptr*, byte*, uintptr);
diff --git a/src/pkg/runtime/pprof/pprof.go b/src/pkg/runtime/pprof/pprof.go
index 099bb6a92f..f67e8a8f9a 100644
--- a/src/pkg/runtime/pprof/pprof.go
+++ b/src/pkg/runtime/pprof/pprof.go
@@ -20,8 +20,8 @@ import (
"text/tabwriter"
)
-// BUG(rsc): CPU profiling is broken on OS X, due to an Apple kernel bug.
-// For details, see http://code.google.com/p/go/source/detail?r=35b716c94225.
+// BUG(rsc): A bug in the OS X Snow Leopard 64-bit kernel prevents
+// CPU profiling from giving accurate results on that system.
// A Profile is a collection of stack traces showing the call sequences
// that led to instances of a particular event, such as allocation.
@@ -156,7 +156,7 @@ func (p *Profile) Count() int {
}
// Add adds the current execution stack to the profile, associated with value.
-// Add stores value in an internal map, so value must be suitable for use as
+// Add stores value in an internal map, so value must be suitable for use as
// a map key and will not be garbage collected until the corresponding
// call to Remove. Add panics if the profile already contains a stack for value.
//
diff --git a/src/pkg/runtime/pprof/pprof_test.go b/src/pkg/runtime/pprof/pprof_test.go
index 5f128c01cf..994ec9dde4 100644
--- a/src/pkg/runtime/pprof/pprof_test.go
+++ b/src/pkg/runtime/pprof/pprof_test.go
@@ -7,6 +7,7 @@ package pprof_test
import (
"bytes"
"hash/crc32"
+ "os/exec"
"runtime"
. "runtime/pprof"
"strings"
@@ -17,8 +18,15 @@ import (
func TestCPUProfile(t *testing.T) {
switch runtime.GOOS {
case "darwin":
- // see Apple Bug Report #9177434 (copied into change description)
- return
+ out, err := exec.Command("uname", "-a").CombinedOutput()
+ if err != nil {
+ t.Fatal(err)
+ }
+ vers := string(out)
+ t.Logf("uname -a: %v", vers)
+ if strings.Contains(vers, "Darwin Kernel Version 10.8.0") && strings.Contains(vers, "root:xnu-1504.15.3~1/RELEASE_X86_64") {
+ t.Logf("skipping test on known-broken kernel (64-bit Snow Leopard)")
+ }
case "plan9":
// unimplemented
return
diff --git a/src/pkg/runtime/proc.c b/src/pkg/runtime/proc.c
index d94bec8855..ddac048a00 100644
--- a/src/pkg/runtime/proc.c
+++ b/src/pkg/runtime/proc.c
@@ -338,7 +338,7 @@ mcommoninit(M *m)
m->mcache = runtime·allocmcache();
runtime·callers(1, m->createstack, nelem(m->createstack));
-
+
// Add to runtime·allm so garbage collector doesn't free m
// when it is just in a register or thread-local storage.
m->alllink = runtime·allm;
@@ -728,7 +728,6 @@ runtime·mstart(void)
// so other calls can reuse this stack space.
runtime·gosave(&m->g0->sched);
m->g0->sched.pc = (void*)-1; // make sure it is never used
-
runtime·asminit();
runtime·minit();
schedule(nil);
@@ -916,6 +915,9 @@ runtime·entersyscall(void)
{
uint32 v;
+ if(m->profilehz > 0)
+ runtime·setprof(false);
+
// Leave SP around for gc and traceback.
runtime·gosave(&g->sched);
g->gcsp = g->sched.sp;
@@ -979,6 +981,9 @@ runtime·exitsyscall(void)
// Garbage collector isn't running (since we are),
// so okay to clear gcstack.
g->gcstack = nil;
+
+ if(m->profilehz > 0)
+ runtime·setprof(true);
return;
}
diff --git a/src/pkg/runtime/runtime.h b/src/pkg/runtime/runtime.h
index 3b0f505e72..f2669fdb7e 100644
--- a/src/pkg/runtime/runtime.h
+++ b/src/pkg/runtime/runtime.h
@@ -730,3 +730,13 @@ bool runtime·showframe(Func*);
void runtime·ifaceE2I(struct InterfaceType*, Eface, Iface*);
uintptr runtime·memlimit(void);
+
+// If appropriate, ask the operating system to control whether this
+// thread should receive profiling signals. This is only necessary on OS X.
+// An operating system should not deliver a profiling signal to a
+// thread that is not actually executing (what good is that?), but that's
+// what OS X prefers to do. When profiling is turned on, we mask
+// away the profiling signal when threads go to sleep, so that OS X
+// is forced to deliver the signal to a thread that's actually running.
+// This is a no-op on other systems.
+void runtime·setprof(bool);
diff --git a/src/pkg/runtime/signal_darwin_386.c b/src/pkg/runtime/signal_darwin_386.c
index 1844f68a63..9e986352b4 100644
--- a/src/pkg/runtime/signal_darwin_386.c
+++ b/src/pkg/runtime/signal_darwin_386.c
@@ -40,7 +40,8 @@ runtime·sighandler(int32 sig, Siginfo *info, void *context, G *gp)
r = &mc->ss;
if(sig == SIGPROF) {
- runtime·sigprof((uint8*)r->eip, (uint8*)r->esp, nil, gp);
+ if(gp != m->g0 && gp != m->gsignal)
+ runtime·sigprof((uint8*)r->eip, (uint8*)r->esp, nil, gp);
return;
}
@@ -58,7 +59,7 @@ runtime·sighandler(int32 sig, Siginfo *info, void *context, G *gp)
if(pc[0] == 0xF6 || pc[0] == 0xF7)
info->si_code = FPE_INTDIV;
}
-
+
// Make it look like a call to the signal func.
// Have to pass arguments out of band since
// augmenting the stack frame would break
diff --git a/src/pkg/runtime/signal_darwin_amd64.c b/src/pkg/runtime/signal_darwin_amd64.c
index 32c73081c1..d9c5f48e7c 100644
--- a/src/pkg/runtime/signal_darwin_amd64.c
+++ b/src/pkg/runtime/signal_darwin_amd64.c
@@ -48,7 +48,8 @@ runtime·sighandler(int32 sig, Siginfo *info, void *context, G *gp)
r = &mc->ss;
if(sig == SIGPROF) {
- runtime·sigprof((uint8*)r->rip, (uint8*)r->rsp, nil, gp);
+ if(gp != m->g0 && gp != m->gsignal)
+ runtime·sigprof((uint8*)r->rip, (uint8*)r->rsp, nil, gp);
return;
}
@@ -68,7 +69,7 @@ runtime·sighandler(int32 sig, Siginfo *info, void *context, G *gp)
if(pc[0] == 0xF6 || pc[0] == 0xF7)
info->si_code = FPE_INTDIV;
}
-
+
// Make it look like a call to the signal func.
// Have to pass arguments out of band since
// augmenting the stack frame would break
@@ -77,7 +78,7 @@ runtime·sighandler(int32 sig, Siginfo *info, void *context, G *gp)
gp->sigcode0 = info->si_code;
gp->sigcode1 = (uintptr)info->si_addr;
gp->sigpc = r->rip;
-
+
// Only push runtime·sigpanic if r->rip != 0.
// If r->rip == 0, probably panicked because of a
// call to a nil func. Not pushing that onto sp will
@@ -92,7 +93,7 @@ runtime·sighandler(int32 sig, Siginfo *info, void *context, G *gp)
r->rip = (uintptr)runtime·sigpanic;
return;
}
-
+
if(info->si_code == SI_USER || (t->flags & SigNotify))
if(runtime·sigsend(sig))
return;
diff --git a/src/pkg/runtime/signal_unix.c b/src/pkg/runtime/signal_unix.c
index 13708415b9..0b9d2a55a1 100644
--- a/src/pkg/runtime/signal_unix.c
+++ b/src/pkg/runtime/signal_unix.c
@@ -55,17 +55,17 @@ void
runtime·resetcpuprofiler(int32 hz)
{
Itimerval it;
-
+
runtime·memclr((byte*)&it, sizeof it);
if(hz == 0) {
runtime·setitimer(ITIMER_PROF, &it, nil);
- runtime·setsig(SIGPROF, SIG_IGN, true);
+ runtime·setprof(false);
} else {
- runtime·setsig(SIGPROF, runtime·sighandler, true);
it.it_interval.tv_sec = 0;
it.it_interval.tv_usec = 1000000 / hz;
it.it_value = it.it_interval;
runtime·setitimer(ITIMER_PROF, &it, nil);
+ runtime·setprof(true);
}
m->profilehz = hz;
}
diff --git a/src/pkg/runtime/sys_darwin_386.s b/src/pkg/runtime/sys_darwin_386.s
index e235a8473d..c2dab8931c 100644
--- a/src/pkg/runtime/sys_darwin_386.s
+++ b/src/pkg/runtime/sys_darwin_386.s
@@ -100,14 +100,14 @@ TEXT runtime·nanotime(SB), 7, $32
IMULL $1000, BX
ADDL BX, AX
ADCL $0, DX
-
+
MOVL ret+0(FP), DI
MOVL AX, 0(DI)
MOVL DX, 4(DI)
RET
TEXT runtime·sigprocmask(SB),7,$0
- MOVL $48, AX
+ MOVL $329, AX // pthread_sigmask (on OS X, sigprocmask==entire process)
INT $0x80
JAE 2(PC)
CALL runtime·notok(SB)
diff --git a/src/pkg/runtime/sys_darwin_amd64.s b/src/pkg/runtime/sys_darwin_amd64.s
index 13882c8524..4b215d04d4 100644
--- a/src/pkg/runtime/sys_darwin_amd64.s
+++ b/src/pkg/runtime/sys_darwin_amd64.s
@@ -96,7 +96,7 @@ TEXT runtime·sigprocmask(SB),7,$0
MOVL 8(SP), DI
MOVQ 16(SP), SI
MOVQ 24(SP), DX
- MOVL $(0x2000000+48), AX // syscall entry
+ MOVL $(0x2000000+329), AX // pthread_sigmask (on OS X, sigprocmask==entire process)
SYSCALL
JCC 2(PC)
CALL runtime·notok(SB)
diff --git a/src/pkg/runtime/thread_darwin.c b/src/pkg/runtime/thread_darwin.c
index d170dfb3d3..556fb67e84 100644
--- a/src/pkg/runtime/thread_darwin.c
+++ b/src/pkg/runtime/thread_darwin.c
@@ -11,6 +11,7 @@ extern SigTab runtime·sigtab[];
static Sigset sigset_all = ~(Sigset)0;
static Sigset sigset_none;
+static Sigset sigset_prof = 1<<(SIGPROF-1);
static void
unimplemented(int8 *name)
@@ -23,7 +24,14 @@ unimplemented(int8 *name)
int32
runtime·semasleep(int64 ns)
{
- return runtime·mach_semacquire(m->waitsema, ns);
+ int32 v;
+
+ if(m->profilehz > 0)
+ runtime·setprof(false);
+ v = runtime·mach_semacquire(m->waitsema, ns);
+ if(m->profilehz > 0)
+ runtime·setprof(true);
+ return v;
}
void
@@ -84,7 +92,7 @@ runtime·newosproc(M *m, G *g, void *stk, void (*fn)(void))
runtime·sigprocmask(SIG_SETMASK, &sigset_all, &oset);
errno = runtime·bsdthread_create(stk, m, g, fn);
runtime·sigprocmask(SIG_SETMASK, &oset, nil);
-
+
if(errno < 0) {
runtime·printf("runtime: failed to create new OS thread (have %d already; errno=%d)\n", runtime·mcount(), -errno);
runtime·throw("runtime.newosproc");
@@ -98,7 +106,11 @@ runtime·minit(void)
// Initialize signal handling.
m->gsignal = runtime·malg(32*1024); // OS X wants >=8K, Linux >=2K
runtime·signalstack(m->gsignal->stackguard - StackGuard, 32*1024);
- runtime·sigprocmask(SIG_SETMASK, &sigset_none, nil);
+
+ if(m->profilehz > 0)
+ runtime·sigprocmask(SIG_SETMASK, &sigset_none, nil);
+ else
+ runtime·sigprocmask(SIG_SETMASK, &sigset_prof, nil);
}
// Mach IPC, to get at semaphores
@@ -434,3 +446,34 @@ runtime·memlimit(void)
// the limit.
return 0;
}
+
+// NOTE(rsc): On OS X, when the CPU profiling timer expires, the SIGPROF
+// signal is not guaranteed to be sent to the thread that was executing to
+// cause it to expire. It can and often does go to a sleeping thread, which is
+// not interesting for our profile. This is filed Apple Bug Report #9177434,
+// copied to http://code.google.com/p/go/source/detail?r=35b716c94225.
+// To work around this bug, we disable receipt of the profiling signal on
+// a thread while in blocking system calls. This forces the kernel to deliver
+// the profiling signal to an executing thread.
+//
+// The workaround fails on OS X machines using a 64-bit Snow Leopard kernel.
+// In that configuration, the kernel appears to want to deliver SIGPROF to the
+// sleeping threads regardless of signal mask and, worse, does not deliver
+// the signal until the thread wakes up on its own.
+//
+// If necessary, we can switch to using ITIMER_REAL for OS X and handle
+// the kernel-generated SIGALRM by generating our own SIGALRMs to deliver
+// to all the running threads. SIGALRM does not appear to be affected by
+// the 64-bit Snow Leopard bug. However, as of this writing Mountain Lion
+// is in preview, making Snow Leopard two versions old, so it is unclear how
+// much effort we need to spend on one buggy kernel.
+
+// Control whether profiling signal can be delivered to this thread.
+void
+runtime·setprof(bool on)
+{
+ if(on)
+ runtime·sigprocmask(SIG_UNBLOCK, &sigset_prof, nil);
+ else
+ runtime·sigprocmask(SIG_BLOCK, &sigset_prof, nil);
+}
diff --git a/src/pkg/runtime/thread_freebsd.c b/src/pkg/runtime/thread_freebsd.c
index 7871827a97..77e8bb3dac 100644
--- a/src/pkg/runtime/thread_freebsd.c
+++ b/src/pkg/runtime/thread_freebsd.c
@@ -189,3 +189,9 @@ runtime·memlimit(void)
return rl.rlim_cur - used;
}
+
+void
+runtime·setprof(bool on)
+{
+ USED(on);
+}
diff --git a/src/pkg/runtime/thread_linux.c b/src/pkg/runtime/thread_linux.c
index d406a71240..6b428440e0 100644
--- a/src/pkg/runtime/thread_linux.c
+++ b/src/pkg/runtime/thread_linux.c
@@ -228,7 +228,7 @@ runtime·memlimit(void)
Rlimit rl;
extern byte text[], end[];
uintptr used;
-
+
if(runtime·getrlimit(RLIMIT_AS, &rl) != 0)
return 0;
if(rl.rlim_cur >= 0x7fffffff)
@@ -249,3 +249,9 @@ runtime·memlimit(void)
return rl.rlim_cur - used;
}
+
+void
+runtime·setprof(bool on)
+{
+ USED(on);
+}
diff --git a/src/pkg/runtime/thread_netbsd.c b/src/pkg/runtime/thread_netbsd.c
index 7d14e5c68b..62e133c449 100644
--- a/src/pkg/runtime/thread_netbsd.c
+++ b/src/pkg/runtime/thread_netbsd.c
@@ -207,3 +207,9 @@ runtime·memlimit(void)
{
return 0;
}
+
+void
+runtime·setprof(bool on)
+{
+ USED(on);
+}
diff --git a/src/pkg/runtime/thread_openbsd.c b/src/pkg/runtime/thread_openbsd.c
index 704d95a3c6..bee0c5755f 100644
--- a/src/pkg/runtime/thread_openbsd.c
+++ b/src/pkg/runtime/thread_openbsd.c
@@ -207,3 +207,9 @@ runtime·memlimit(void)
{
return 0;
}
+
+void
+runtime·setprof(bool on)
+{
+ USED(on);
+}
diff --git a/src/pkg/runtime/thread_plan9.c b/src/pkg/runtime/thread_plan9.c
index 7d5c38fc9a..aaed5050bb 100644
--- a/src/pkg/runtime/thread_plan9.c
+++ b/src/pkg/runtime/thread_plan9.c
@@ -87,7 +87,7 @@ runtime·nanotime(void)
// 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)
@@ -241,3 +241,9 @@ runtime·memlimit(void)
{
return 0;
}
+
+void
+runtime·setprof(bool on)
+{
+ USED(on);
+}
diff --git a/src/pkg/runtime/thread_windows.c b/src/pkg/runtime/thread_windows.c
index 8feac9711d..8a448bc37c 100644
--- a/src/pkg/runtime/thread_windows.c
+++ b/src/pkg/runtime/thread_windows.c
@@ -226,7 +226,7 @@ void
time·now(int64 sec, int32 usec)
{
int64 ns;
-
+
ns = runtime·nanotime();
sec = ns / 1000000000LL;
usec = ns - sec * 1000000000LL;
@@ -431,3 +431,9 @@ runtime·memlimit(void)
{
return 0;
}
+
+void
+runtime·setprof(bool on)
+{
+ USED(on);
+}