Changeset View
Changeset View
Standalone View
Standalone View
head/sys/cddl/dev/profile/profile.c
Show First 20 Lines • Show All 260 Lines • ▼ Show 20 Lines | |||||
sbt_to_nsec(sbintime_t sbt) | sbt_to_nsec(sbintime_t sbt) | ||||
{ | { | ||||
return ((sbt >> 32) * NANOSEC + | return ((sbt >> 32) * NANOSEC + | ||||
(((uint32_t)sbt * (hrtime_t)NANOSEC) >> 32)); | (((uint32_t)sbt * (hrtime_t)NANOSEC) >> 32)); | ||||
} | } | ||||
static void | static void | ||||
profile_fire(void *arg) | profile_probe(profile_probe_t *prof, hrtime_t late) | ||||
{ | { | ||||
profile_probe_percpu_t *pcpu = arg; | struct thread *td; | ||||
profile_probe_t *prof = pcpu->profc_probe; | |||||
hrtime_t late; | |||||
struct trapframe *frame; | struct trapframe *frame; | ||||
uintfptr_t pc, upc; | uintfptr_t pc, upc; | ||||
#ifdef illumos | td = curthread; | ||||
late = gethrtime() - pcpu->profc_expected; | pc = upc = 0; | ||||
#else | |||||
late = sbt_to_nsec(sbinuptime() - pcpu->profc_expected); | |||||
#endif | |||||
pc = 0; | |||||
upc = 0; | |||||
/* | /* | ||||
* td_intr_frame can be unset if this is a catch up event | * td_intr_frame can be unset if this is a catch-up event upon waking up | ||||
* after waking up from idle sleep. | * from idle sleep. This can only happen on a CPU idle thread. Use a | ||||
* This can only happen on a CPU idle thread. | * representative arg0 value in this case so that one of the probe | ||||
* arguments is non-zero. | |||||
*/ | */ | ||||
frame = curthread->td_intr_frame; | frame = td->td_intr_frame; | ||||
if (frame != NULL) { | if (frame != NULL) { | ||||
if (TRAPF_USERMODE(frame)) | if (TRAPF_USERMODE(frame)) | ||||
upc = TRAPF_PC(frame); | upc = TRAPF_PC(frame); | ||||
else | else | ||||
pc = TRAPF_PC(frame); | pc = TRAPF_PC(frame); | ||||
} | } else if (TD_IS_IDLETHREAD(td)) | ||||
pc = (uintfptr_t)&cpu_idle; | |||||
dtrace_probe(prof->prof_id, pc, upc, late, 0, 0); | dtrace_probe(prof->prof_id, pc, upc, late, 0, 0); | ||||
} | |||||
static void | |||||
profile_fire(void *arg) | |||||
{ | |||||
profile_probe_percpu_t *pcpu = arg; | |||||
profile_probe_t *prof = pcpu->profc_probe; | |||||
hrtime_t late; | |||||
late = sbt_to_nsec(sbinuptime() - pcpu->profc_expected); | |||||
profile_probe(prof, late); | |||||
pcpu->profc_expected += pcpu->profc_interval; | pcpu->profc_expected += pcpu->profc_interval; | ||||
callout_schedule_sbt_curcpu(&pcpu->profc_cyclic, | callout_schedule_sbt_curcpu(&pcpu->profc_cyclic, | ||||
pcpu->profc_expected, 0, C_DIRECT_EXEC | C_ABSOLUTE); | pcpu->profc_expected, 0, C_DIRECT_EXEC | C_ABSOLUTE); | ||||
} | } | ||||
static void | static void | ||||
profile_tick(void *arg) | profile_tick(void *arg) | ||||
{ | { | ||||
profile_probe_t *prof = arg; | profile_probe_t *prof = arg; | ||||
struct trapframe *frame; | |||||
uintfptr_t pc, upc; | |||||
pc = 0; | profile_probe(prof, 0); | ||||
upc = 0; | |||||
/* | |||||
* td_intr_frame can be unset if this is a catch up event | |||||
* after waking up from idle sleep. | |||||
* This can only happen on a CPU idle thread. | |||||
*/ | |||||
frame = curthread->td_intr_frame; | |||||
if (frame != NULL) { | |||||
if (TRAPF_USERMODE(frame)) | |||||
upc = TRAPF_PC(frame); | |||||
else | |||||
pc = TRAPF_PC(frame); | |||||
} | |||||
dtrace_probe(prof->prof_id, pc, upc, 0, 0, 0); | |||||
prof->prof_expected += prof->prof_interval; | prof->prof_expected += prof->prof_interval; | ||||
callout_schedule_sbt(&prof->prof_cyclic, | callout_schedule_sbt(&prof->prof_cyclic, | ||||
prof->prof_expected, 0, C_DIRECT_EXEC | C_ABSOLUTE); | prof->prof_expected, 0, C_DIRECT_EXEC | C_ABSOLUTE); | ||||
} | } | ||||
static void | static void | ||||
profile_create(hrtime_t interval, char *name, int kind) | profile_create(hrtime_t interval, char *name, int kind) | ||||
{ | { | ||||
▲ Show 20 Lines • Show All 393 Lines • Show Last 20 Lines |