/* * Convert interrupt statistics from CPU ticks to nanoseconds and * update kstat. */ int cpu_kstat_intrstat_update(kstat_t *ksp, int rw) { kstat_named_t *knp = ksp->ks_data; cpu_t *cpup = (cpu_t *)ksp->ks_private; int i; if (rw == KSTAT_WRITE) return (EACCES); /* * We use separate passes to copy and convert the statistics to * nanoseconds. This assures that the snapshot of the data is as * self-consistent as possible. */ for (i = 0; i < PIL_MAX; i++) { knp[i * 2].value.ui64 = cpup->cpu_m.intrstat[i + 1][0]; knp[(i * 2) + 1].value.ui64 = cpup->cpu_stats.sys.intr[i]; } for (i = 0; i < PIL_MAX; i++) { knp[i * 2].value.ui64 = (uint64_t)tick2ns((hrtime_t)knp[i * 2].value.ui64, cpup->cpu_id); } return (0); }
static void px_ib_cpu_ticks_to_ih_nsec(px_ib_t *ib_p, px_ih_t *ih_p, uint32_t cpu_id) { extern kmutex_t pxintr_ks_template_lock; hrtime_t ticks; /* * Because we are updating two fields in ih_t we must lock * pxintr_ks_template_lock to prevent someone from reading the * kstats after we set ih_ticks to 0 and before we increment * ih_nsec to compensate. * * We must also protect against the interrupt arriving and incrementing * ih_ticks between the time we read it and when we reset it to 0. * To do this we use atomic_swap. */ ASSERT(MUTEX_HELD(&ib_p->ib_ino_lst_mutex)); mutex_enter(&pxintr_ks_template_lock); ticks = atomic_swap_64(&ih_p->ih_ticks, 0); ih_p->ih_nsec += (uint64_t)tick2ns(ticks, cpu_id); mutex_exit(&pxintr_ks_template_lock); }