Index: subr_percpu.c =================================================================== RCS file: /cvs/src/sys/kern/subr_percpu.c,v retrieving revision 1.9 diff -u -p -r1.9 subr_percpu.c --- subr_percpu.c 10 Mar 2021 10:21:47 -0000 1.9 +++ subr_percpu.c 14 Mar 2022 01:26:17 -0000 @@ -16,6 +16,8 @@ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ +#include "kstat.h" + #include #include #include @@ -26,9 +28,103 @@ #ifdef MULTIPROCESSOR struct pool cpumem_pl; +#if NKSTAT > 0 +#include +#include +#include + +struct pinger { + struct cpu_info *ci; + struct taskq *tq; + struct kstat *ks; + struct task peg; +}; + +static struct pinger *pingers; + +static int +pinger_kstat(struct kstat *ks) +{ + struct kstat_kv *kvs = ks->ks_data; + struct cond c; + struct task t = TASK_INITIALIZER((void *)cond_signal, &c); + unsigned int i; + + getnanouptime(&ks->ks_updated); + + for (i = 0; i < ncpus; i++) { + struct kstat_kv *kv = &kvs[i]; + struct pinger *p = &pingers[i]; + uint64_t tic, toc; + + cond_init(&c); + + tic = rdtsc(); + task_add(p->tq, &t); + cond_wait(&c, "pinger"); + toc = rdtsc(); + + kstat_kv_u64(kv) = toc - tic; + } + + return (0); +} + +static void +pinger_init(struct pinger *p, struct cpu_info *ci) +{ + struct kstat *ks; + struct kstat_kv *kvs; + unsigned int i; + + KASSERT(p->ci == NULL); + + p->ci = ci; + p->tq = taskq_create(ci->ci_dev->dv_xname, 1, + IPL_SOFTNET, TASKQ_MPSAFE); + + task_set(&p->peg, (void *)sched_peg_curproc, ci); + task_add(p->tq, &p->peg); + + ks = kstat_create("pinger", 0, "cpu", ci->ci_cpuid, KSTAT_T_KV, 0); + if (ks == NULL) + panic("%s kstat_create", __func__); + + kvs = mallocarray(sizeof(*kvs), ncpus, M_DEVBUF, + M_WAITOK|M_ZERO); + for (i = 0; i < ncpus; i++) { + struct kstat_kv *kv = &kvs[i]; + + snprintf(kv->kv_key, sizeof(kv->kv_key), "cpu%u", i); + kv->kv_type = KSTAT_KV_T_UINT64; + kv->kv_unit = KSTAT_KV_U_CYCLES; + } + + ks->ks_data = kvs; + ks->ks_datalen = sizeof(*kvs) * ncpus; + ks->ks_read = pinger_kstat; + + kstat_install(ks); + + p->ks = ks; +} +#endif /* NKSTAT > 0 */ + void percpu_init(void) { +#if NKSTAT > 0 + CPU_INFO_ITERATOR cii; + struct cpu_info *ci; + + pingers = mallocarray(sizeof(*pingers), ncpus, M_DEVBUF, + M_WAITOK|M_ZERO); + CPU_INFO_FOREACH(cii, ci) { + KASSERT(ci->ci_cpuid < ncpus); + pinger_init(&pingers[ci->ci_cpuid], ci); + } +#endif /* NKSTAT > 0 */ + pool_init(&cpumem_pl, sizeof(struct cpumem) * ncpusfound, 0, IPL_NONE, PR_WAITOK, "percpumem", &pool_allocator_single); }