diff options
Diffstat (limited to 'src/pkg/runtime/darwin')
-rw-r--r-- | src/pkg/runtime/darwin/386/defs.h | 29 | ||||
-rw-r--r-- | src/pkg/runtime/darwin/386/signal.c | 57 | ||||
-rw-r--r-- | src/pkg/runtime/darwin/386/sys.s | 5 | ||||
-rw-r--r-- | src/pkg/runtime/darwin/amd64/defs.h | 34 | ||||
-rw-r--r-- | src/pkg/runtime/darwin/amd64/signal.c | 57 | ||||
-rw-r--r-- | src/pkg/runtime/darwin/amd64/sys.s | 13 | ||||
-rw-r--r-- | src/pkg/runtime/darwin/defs.c | 6 | ||||
-rw-r--r-- | src/pkg/runtime/darwin/os.h | 4 |
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*); |