/* signal handler */ static void sampler_sample(int sig) { ScmVM *vm = Scm_VM(); if (vm->prof == NULL) return; if (vm->prof->state != SCM_PROFILER_RUNNING) return; if (vm->prof->currentSample >= SCM_PROF_SAMPLES_IN_BUFFER) { ITIMER_STOP(); sampler_flush(vm); ITIMER_START(); } int i = vm->prof->currentSample++; if (vm->base) { /* If vm->pc is RET and val0 is a subr, it is pretty likely that we're actually executing that subr. */ if (vm->pc && SCM_VM_INSN_CODE(*vm->pc) == SCM_VM_RET && SCM_SUBRP(vm->val0)) { vm->prof->samples[i].func = vm->val0; vm->prof->samples[i].pc = NULL; } else { vm->prof->samples[i].func = SCM_OBJ(vm->base); vm->prof->samples[i].pc = vm->pc; } } else { vm->prof->samples[i].func = SCM_FALSE; vm->prof->samples[i].pc = NULL; } vm->prof->totalSamples++; }
/*============================================================= * External API */ void Scm_ProfilerStart(void) { ScmVM *vm = Scm_VM(); ScmObj templat = Scm_StringAppendC(SCM_STRING(Scm_TmpDir()), "/gauche-profXXXXXX", -1, -1); char *templat_buf = Scm_GetString(SCM_STRING(templat)); /*mutable copy*/ if (!vm->prof) { vm->prof = SCM_NEW(ScmVMProfiler); vm->prof->state = SCM_PROFILER_INACTIVE; vm->prof->samplerFd = Scm_Mkstemp(templat_buf); vm->prof->currentSample = 0; vm->prof->totalSamples = 0; vm->prof->errorOccurred = 0; vm->prof->currentCount = 0; vm->prof->statHash = SCM_HASH_TABLE(Scm_MakeHashTableSimple(SCM_HASH_EQ, 0)); #if defined(GAUCHE_WINDOWS) vm->prof->hTargetThread = NULL; vm->prof->hObserverThread = NULL; vm->prof->hTimerEvent = NULL; vm->prof->samplerFileName = templat_buf; #else /* !GAUCHE_WINDOWS */ unlink(templat_buf); /* keep anonymous tmpfile */ #endif /* !GAUCHE_WINDOWS */ } else if (vm->prof->samplerFd < 0) { vm->prof->samplerFd = Scm_Mkstemp(templat_buf); #if defined(GAUCHE_WINDOWS) vm->prof->samplerFileName = templat_buf; #else /* !GAUCHE_WINDOWS */ unlink(templat_buf); #endif /* !GAUCHE_WINDOWS */ } if (vm->prof->state == SCM_PROFILER_RUNNING) return; vm->prof->state = SCM_PROFILER_RUNNING; vm->profilerRunning = TRUE; /* NB: this should be done globally!!! */ #if defined(GAUCHE_WINDOWS) if (!DuplicateHandle(GetCurrentProcess(), GetCurrentThread(), GetCurrentProcess(), &vm->prof->hTargetThread, 0, FALSE, DUPLICATE_SAME_ACCESS)) { vm->prof->hTargetThread = NULL; Scm_SysError("DuplicateHandle failed"); } #else /* !GAUCHE_WINDOWS */ struct sigaction act; act.sa_handler = sampler_sample; sigfillset(&act.sa_mask); act.sa_flags = SA_RESTART; if (sigaction(SIGPROF, &act, NULL) < 0) { Scm_SysError("sigaction failed"); } #endif /* !GAUCHE_WINDOWS */ ITIMER_START(); }
/*============================================================= * External API */ void Scm_ProfilerStart(void) { ScmVM *vm = Scm_VM(); ScmObj templat = Scm_StringAppendC(SCM_STRING(Scm_TmpDir()), "/gauche-profXXXXXX", -1, -1); char *templat_buf = Scm_GetString(SCM_STRING(templat)); /*mutable copy*/ if (!vm->prof) { vm->prof = SCM_NEW(ScmVMProfiler); vm->prof->state = SCM_PROFILER_INACTIVE; vm->prof->samplerFd = Scm_Mkstemp(templat_buf); vm->prof->currentSample = 0; vm->prof->totalSamples = 0; vm->prof->errorOccurred = 0; vm->prof->currentCount = 0; vm->prof->statHash = SCM_HASH_TABLE(Scm_MakeHashTableSimple(SCM_HASH_EQ, 0)); unlink(templat_buf); /* keep anonymous tmpfile */ } else if (vm->prof->samplerFd < 0) { vm->prof->samplerFd = Scm_Mkstemp(templat_buf); unlink(templat_buf); } if (vm->prof->state == SCM_PROFILER_RUNNING) return; vm->prof->state = SCM_PROFILER_RUNNING; vm->profilerRunning = TRUE; /* NB: this should be done globally!!! */ struct sigaction act; act.sa_handler = sampler_sample; sigfillset(&act.sa_mask); act.sa_flags = SA_RESTART; if (sigaction(SIGPROF, &act, NULL) < 0) { Scm_SysError("sigaction failed"); } ITIMER_START(); }