summaryrefslogtreecommitdiff
path: root/src/pkg/runtime/darwin
diff options
context:
space:
mode:
Diffstat (limited to 'src/pkg/runtime/darwin')
-rw-r--r--src/pkg/runtime/darwin/386/defs.h29
-rw-r--r--src/pkg/runtime/darwin/386/signal.c57
-rw-r--r--src/pkg/runtime/darwin/386/sys.s5
-rw-r--r--src/pkg/runtime/darwin/amd64/defs.h34
-rw-r--r--src/pkg/runtime/darwin/amd64/signal.c57
-rw-r--r--src/pkg/runtime/darwin/amd64/sys.s13
-rw-r--r--src/pkg/runtime/darwin/defs.c6
-rw-r--r--src/pkg/runtime/darwin/os.h4
8 files changed, 160 insertions, 45 deletions
diff --git a/src/pkg/runtime/darwin/386/defs.h b/src/pkg/runtime/darwin/386/defs.h
index f9d874d85..bb70207fd 100644
--- a/src/pkg/runtime/darwin/386/defs.h
+++ b/src/pkg/runtime/darwin/386/defs.h
@@ -89,6 +89,9 @@ enum {
BUS_OBJERR = 0x3,
SEGV_MAPERR = 0x1,
SEGV_ACCERR = 0x2,
+ ITIMER_REAL = 0,
+ ITIMER_VIRTUAL = 0x1,
+ ITIMER_PROF = 0x2,
};
// Types
@@ -139,14 +142,14 @@ struct StackT {
typedef union Sighandler Sighandler;
union Sighandler {
- void *__sa_handler;
- void *__sa_sigaction;
+ uint32 __sa_handler;
+ uint32 __sa_sigaction;
};
typedef struct Sigaction Sigaction;
struct Sigaction {
Sighandler __sigaction_u;
- void *sa_tramp;
+ uint32 sa_tramp;
uint32 sa_mask;
int32 sa_flags;
};
@@ -171,14 +174,26 @@ struct Siginfo {
uint32 __pad[7];
};
+typedef struct Timeval Timeval;
+struct Timeval {
+ int32 tv_sec;
+ int32 tv_usec;
+};
+
+typedef struct Itimerval Itimerval;
+struct Itimerval {
+ Timeval it_interval;
+ Timeval it_value;
+};
+
typedef struct FPControl FPControl;
struct FPControl {
- byte pad0[2];
+ byte pad_godefs_0[2];
};
typedef struct FPStatus FPStatus;
struct FPStatus {
- byte pad0[2];
+ byte pad_godefs_0[2];
};
typedef struct RegMMST RegMMST;
@@ -214,7 +229,7 @@ struct Regs {
typedef struct FloatState FloatState;
struct FloatState {
- int32 fpu_reserved[2];
+ uint64 fpu_reserved;
FPControl fpu_fcw;
FPStatus fpu_fsw;
uint8 fpu_ftw;
@@ -267,7 +282,7 @@ struct Ucontext {
int32 uc_onstack;
uint32 uc_sigmask;
StackT uc_stack;
- Ucontext *uc_link;
+ uint32 uc_link;
uint32 uc_mcsize;
Mcontext *uc_mcontext;
};
diff --git a/src/pkg/runtime/darwin/386/signal.c b/src/pkg/runtime/darwin/386/signal.c
index aeef5de3f..35bbb178b 100644
--- a/src/pkg/runtime/darwin/386/signal.c
+++ b/src/pkg/runtime/darwin/386/signal.c
@@ -46,6 +46,11 @@ runtime·sighandler(int32 sig, Siginfo *info, void *context, G *gp)
mc = uc->uc_mcontext;
r = &mc->ss;
+ if(sig == SIGPROF) {
+ runtime·sigprof((uint8*)r->eip, (uint8*)r->esp, nil, gp);
+ return;
+ }
+
if(gp != nil && (runtime·sigtab[sig].flags & SigPanic)) {
// Work around Leopard bug that doesn't set FPE_INTDIV.
// Look at instruction to see if it is a divide.
@@ -126,31 +131,57 @@ runtime·signalstack(byte *p, int32 n)
runtime·sigaltstack(&st, nil);
}
+static void
+sigaction(int32 i, void (*fn)(int32, Siginfo*, void*, G*), bool restart)
+{
+ Sigaction sa;
+
+ runtime·memclr((byte*)&sa, sizeof sa);
+ sa.sa_flags = SA_SIGINFO|SA_ONSTACK;
+ if(restart)
+ sa.sa_flags |= SA_RESTART;
+ sa.sa_mask = ~0U;
+ sa.sa_tramp = (uintptr)runtime·sigtramp; // runtime·sigtramp's job is to call into real handler
+ sa.__sigaction_u.__sa_sigaction = (uintptr)fn;
+ runtime·sigaction(i, &sa, nil);
+}
+
void
runtime·initsig(int32 queue)
{
int32 i;
- static Sigaction sa;
+ void *fn;
runtime·siginit();
- sa.sa_flags |= SA_SIGINFO|SA_ONSTACK;
- sa.sa_mask = 0xFFFFFFFFU;
- sa.sa_tramp = runtime·sigtramp; // runtime·sigtramp's job is to call into real handler
for(i = 0; i<NSIG; i++) {
if(runtime·sigtab[i].flags) {
if((runtime·sigtab[i].flags & SigQueue) != queue)
continue;
- if(runtime·sigtab[i].flags & (SigCatch | SigQueue)) {
- sa.__sigaction_u.__sa_sigaction = runtime·sighandler;
- } else {
- sa.__sigaction_u.__sa_sigaction = runtime·sigignore;
- }
- if(runtime·sigtab[i].flags & SigRestart)
- sa.sa_flags |= SA_RESTART;
+ if(runtime·sigtab[i].flags & (SigCatch | SigQueue))
+ fn = runtime·sighandler;
else
- sa.sa_flags &= ~SA_RESTART;
- runtime·sigaction(i, &sa, nil);
+ fn = runtime·sigignore;
+ sigaction(i, fn, (runtime·sigtab[i].flags & SigRestart) != 0);
}
}
}
+
+void
+runtime·resetcpuprofiler(int32 hz)
+{
+ Itimerval it;
+
+ runtime·memclr((byte*)&it, sizeof it);
+ if(hz == 0) {
+ runtime·setitimer(ITIMER_PROF, &it, nil);
+ sigaction(SIGPROF, SIG_IGN, true);
+ } else {
+ sigaction(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);
+ }
+ m->profilehz = hz;
+}
diff --git a/src/pkg/runtime/darwin/386/sys.s b/src/pkg/runtime/darwin/386/sys.s
index 9d2caca0a..08eca9d5a 100644
--- a/src/pkg/runtime/darwin/386/sys.s
+++ b/src/pkg/runtime/darwin/386/sys.s
@@ -45,6 +45,11 @@ TEXT runtime·munmap(SB),7,$0
CALL runtime·notok(SB)
RET
+TEXT runtime·setitimer(SB),7,$0
+ MOVL $83, AX
+ INT $0x80
+ RET
+
// void gettime(int64 *sec, int32 *usec)
TEXT runtime·gettime(SB), 7, $32
LEAL 12(SP), AX // must be non-nil, unused
diff --git a/src/pkg/runtime/darwin/amd64/defs.h b/src/pkg/runtime/darwin/amd64/defs.h
index 09e595988..90f798e8a 100644
--- a/src/pkg/runtime/darwin/amd64/defs.h
+++ b/src/pkg/runtime/darwin/amd64/defs.h
@@ -89,6 +89,9 @@ enum {
BUS_OBJERR = 0x3,
SEGV_MAPERR = 0x1,
SEGV_ACCERR = 0x2,
+ ITIMER_REAL = 0,
+ ITIMER_VIRTUAL = 0x1,
+ ITIMER_PROF = 0x2,
};
// Types
@@ -135,19 +138,19 @@ struct StackT {
void *ss_sp;
uint64 ss_size;
int32 ss_flags;
- byte pad0[4];
+ byte pad_godefs_0[4];
};
typedef union Sighandler Sighandler;
union Sighandler {
- void *__sa_handler;
- void *__sa_sigaction;
+ uint64 __sa_handler;
+ uint64 __sa_sigaction;
};
typedef struct Sigaction Sigaction;
struct Sigaction {
Sighandler __sigaction_u;
- void *sa_tramp;
+ uint64 sa_tramp;
uint32 sa_mask;
int32 sa_flags;
};
@@ -172,14 +175,27 @@ struct Siginfo {
uint64 __pad[7];
};
+typedef struct Timeval Timeval;
+struct Timeval {
+ int64 tv_sec;
+ int32 tv_usec;
+ byte pad_godefs_0[4];
+};
+
+typedef struct Itimerval Itimerval;
+struct Itimerval {
+ Timeval it_interval;
+ Timeval it_value;
+};
+
typedef struct FPControl FPControl;
struct FPControl {
- byte pad0[2];
+ byte pad_godefs_0[2];
};
typedef struct FPStatus FPStatus;
struct FPStatus {
- byte pad0[2];
+ byte pad_godefs_0[2];
};
typedef struct RegMMST RegMMST;
@@ -220,7 +236,7 @@ struct Regs {
typedef struct FloatState FloatState;
struct FloatState {
- int32 fpu_reserved[2];
+ uint64 fpu_reserved;
FPControl fpu_fcw;
FPStatus fpu_fsw;
uint8 fpu_ftw;
@@ -274,7 +290,7 @@ struct Mcontext {
ExceptionState es;
Regs ss;
FloatState fs;
- byte pad0[4];
+ byte pad_godefs_0[4];
};
typedef struct Ucontext Ucontext;
@@ -282,7 +298,7 @@ struct Ucontext {
int32 uc_onstack;
uint32 uc_sigmask;
StackT uc_stack;
- Ucontext *uc_link;
+ uint64 uc_link;
uint64 uc_mcsize;
Mcontext *uc_mcontext;
};
diff --git a/src/pkg/runtime/darwin/amd64/signal.c b/src/pkg/runtime/darwin/amd64/signal.c
index 402ab33ca..3a99d2308 100644
--- a/src/pkg/runtime/darwin/amd64/signal.c
+++ b/src/pkg/runtime/darwin/amd64/signal.c
@@ -54,6 +54,11 @@ runtime·sighandler(int32 sig, Siginfo *info, void *context, G *gp)
mc = uc->uc_mcontext;
r = &mc->ss;
+ if(sig == SIGPROF) {
+ runtime·sigprof((uint8*)r->rip, (uint8*)r->rsp, nil, gp);
+ return;
+ }
+
if(gp != nil && (runtime·sigtab[sig].flags & SigPanic)) {
// Work around Leopard bug that doesn't set FPE_INTDIV.
// Look at instruction to see if it is a divide.
@@ -136,31 +141,57 @@ runtime·signalstack(byte *p, int32 n)
runtime·sigaltstack(&st, nil);
}
+static void
+sigaction(int32 i, void (*fn)(int32, Siginfo*, void*, G*), bool restart)
+{
+ Sigaction sa;
+
+ runtime·memclr((byte*)&sa, sizeof sa);
+ sa.sa_flags = SA_SIGINFO|SA_ONSTACK;
+ if(restart)
+ sa.sa_flags |= SA_RESTART;
+ sa.sa_mask = ~0ULL;
+ sa.sa_tramp = (uintptr)runtime·sigtramp; // runtime·sigtramp's job is to call into real handler
+ sa.__sigaction_u.__sa_sigaction = (uintptr)fn;
+ runtime·sigaction(i, &sa, nil);
+}
+
void
runtime·initsig(int32 queue)
{
int32 i;
- static Sigaction sa;
+ void *fn;
runtime·siginit();
- sa.sa_flags |= SA_SIGINFO|SA_ONSTACK;
- sa.sa_mask = 0xFFFFFFFFU;
- sa.sa_tramp = runtime·sigtramp; // runtime·sigtramp's job is to call into real handler
for(i = 0; i<NSIG; i++) {
if(runtime·sigtab[i].flags) {
if((runtime·sigtab[i].flags & SigQueue) != queue)
continue;
- if(runtime·sigtab[i].flags & (SigCatch | SigQueue)) {
- sa.__sigaction_u.__sa_sigaction = runtime·sighandler;
- } else {
- sa.__sigaction_u.__sa_sigaction = runtime·sigignore;
- }
- if(runtime·sigtab[i].flags & SigRestart)
- sa.sa_flags |= SA_RESTART;
+ if(runtime·sigtab[i].flags & (SigCatch | SigQueue))
+ fn = runtime·sighandler;
else
- sa.sa_flags &= ~SA_RESTART;
- runtime·sigaction(i, &sa, nil);
+ fn = runtime·sigignore;
+ sigaction(i, fn, (runtime·sigtab[i].flags & SigRestart) != 0);
}
}
}
+
+void
+runtime·resetcpuprofiler(int32 hz)
+{
+ Itimerval it;
+
+ runtime·memclr((byte*)&it, sizeof it);
+ if(hz == 0) {
+ runtime·setitimer(ITIMER_PROF, &it, nil);
+ sigaction(SIGPROF, SIG_IGN, true);
+ } else {
+ sigaction(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);
+ }
+ m->profilehz = hz;
+}
diff --git a/src/pkg/runtime/darwin/amd64/sys.s b/src/pkg/runtime/darwin/amd64/sys.s
index 4f9e0d77a..39398e065 100644
--- a/src/pkg/runtime/darwin/amd64/sys.s
+++ b/src/pkg/runtime/darwin/amd64/sys.s
@@ -38,11 +38,19 @@ TEXT runtime·write(SB),7,$0
SYSCALL
RET
+TEXT runtime·setitimer(SB), 7, $0
+ MOVL 8(SP), DI
+ MOVQ 16(SP), SI
+ MOVQ 24(SP), DX
+ MOVL $(0x2000000+83), AX // syscall entry
+ SYSCALL
+ RET
+
// void gettime(int64 *sec, int32 *usec)
TEXT runtime·gettime(SB), 7, $32
MOVQ SP, DI // must be non-nil, unused
MOVQ $0, SI
- MOVQ $(0x2000000+116), AX
+ MOVL $(0x2000000+116), AX
SYSCALL
MOVQ sec+0(FP), DI
MOVQ AX, (DI)
@@ -138,8 +146,7 @@ TEXT runtime·bsdthread_create(SB),7,$0
MOVQ mm+16(SP), SI // "arg"
MOVQ stk+8(SP), DX // stack
MOVQ gg+24(SP), R10 // "pthread"
-// TODO(rsc): why do we get away with 0 flags here but not on 386?
- MOVQ $0, R8 // flags
+ MOVQ $0x01000000, R8 // flags = PTHREAD_START_CUSTOM
MOVQ $0, R9 // paranoia
MOVQ $(0x2000000+360), AX // bsdthread_create
SYSCALL
diff --git a/src/pkg/runtime/darwin/defs.c b/src/pkg/runtime/darwin/defs.c
index 1a1cdf880..032a6bcbb 100644
--- a/src/pkg/runtime/darwin/defs.c
+++ b/src/pkg/runtime/darwin/defs.c
@@ -116,6 +116,10 @@ enum {
$SEGV_MAPERR = SEGV_MAPERR,
$SEGV_ACCERR = SEGV_ACCERR,
+
+ $ITIMER_REAL = ITIMER_REAL,
+ $ITIMER_VIRTUAL = ITIMER_VIRTUAL,
+ $ITIMER_PROF = ITIMER_PROF,
};
typedef mach_msg_body_t $MachBody;
@@ -130,6 +134,8 @@ typedef struct __sigaction $Sigaction; // used in syscalls
// typedef struct sigaction $Sigaction; // used by the C library
typedef union sigval $Sigval;
typedef siginfo_t $Siginfo;
+typedef struct timeval $Timeval;
+typedef struct itimerval $Itimerval;
typedef struct fp_control $FPControl;
typedef struct fp_status $FPStatus;
diff --git a/src/pkg/runtime/darwin/os.h b/src/pkg/runtime/darwin/os.h
index 35ef4e6d9..339768e51 100644
--- a/src/pkg/runtime/darwin/os.h
+++ b/src/pkg/runtime/darwin/os.h
@@ -2,6 +2,9 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
+#define SIG_DFL ((void*)0)
+#define SIG_IGN ((void*)1)
+
int32 runtime·bsdthread_create(void*, M*, G*, void(*)(void));
void runtime·bsdthread_register(void);
int32 runtime·mach_msg_trap(MachHeader*, int32, uint32, uint32, uint32, uint32, uint32);
@@ -23,3 +26,4 @@ struct StackT;
void runtime·sigaltstack(struct StackT*, struct StackT*);
void runtime·sigtramp(void);
void runtime·sigpanic(void);
+void runtime·setitimer(int32, Itimerval*, Itimerval*);