hwpmc: fix performance issues

Differential revision:	https://reviews.freebsd.org/D32025

Avoid using atomics as it_wait is guarded by td_lock.

Report threshold calculation is done only if at least one PMC hook
is installed

Fixes:
* avoid unnecessary branching (if frame != null ...)
  by having PMC_HOOK_INSTALLED_ANY
  condition on the top of them, which should hint
  the core not to execute speculatively anything
  which us underneath;
* access intr_hwpmc_waiting_report_threshold cacheline
  only if at least one hook is loaded;
This commit is contained in:
Wojciech Macek 2021-09-20 13:08:32 +02:00
parent 319b150003
commit 7bc13692a2

View File

@ -107,6 +107,7 @@ static int intr_hwpmc_waiting_report_threshold = 1;
SYSCTL_INT(_hw, OID_AUTO, intr_hwpmc_waiting_report_threshold, CTLFLAG_RWTUN, SYSCTL_INT(_hw, OID_AUTO, intr_hwpmc_waiting_report_threshold, CTLFLAG_RWTUN,
&intr_hwpmc_waiting_report_threshold, 1, &intr_hwpmc_waiting_report_threshold, 1,
"Threshold for reporting number of events in a workq"); "Threshold for reporting number of events in a workq");
#define PMC_HOOK_INSTALLED_ANY() __predict_false(pmc_hook != NULL)
#endif #endif
static TAILQ_HEAD(, intr_event) event_list = static TAILQ_HEAD(, intr_event) event_list =
TAILQ_HEAD_INITIALIZER(event_list); TAILQ_HEAD_INITIALIZER(event_list);
@ -131,6 +132,14 @@ PMC_SOFT_DEFINE( , , intr, filter);
PMC_SOFT_DEFINE( , , intr, stray); PMC_SOFT_DEFINE( , , intr, stray);
PMC_SOFT_DEFINE( , , intr, schedule); PMC_SOFT_DEFINE( , , intr, schedule);
PMC_SOFT_DEFINE( , , intr, waiting); PMC_SOFT_DEFINE( , , intr, waiting);
#define PMC_SOFT_CALL_INTR_HLPR(event, frame) \
do { \
if (frame != NULL) \
PMC_SOFT_CALL_TF( , , intr, event, frame); \
else \
PMC_SOFT_CALL( , , intr, event); \
} while (0)
#endif #endif
/* Map an interrupt type to an ithread priority. */ /* Map an interrupt type to an ithread priority. */
@ -1005,11 +1014,9 @@ intr_event_schedule_thread(struct intr_event *ie, struct trapframe *frame)
thread_lock(td); thread_lock(td);
if (TD_AWAITING_INTR(td)) { if (TD_AWAITING_INTR(td)) {
#ifdef HWPMC_HOOKS #ifdef HWPMC_HOOKS
atomic_set_int(&it->it_waiting, 0); it->it_waiting = 0;
if (frame != NULL) if (PMC_HOOK_INSTALLED_ANY())
PMC_SOFT_CALL_TF( , , intr, schedule, frame); PMC_SOFT_CALL_INTR_HLPR(schedule, frame);
else
PMC_SOFT_CALL( , , intr, schedule);
#endif #endif
CTR3(KTR_INTR, "%s: schedule pid %d (%s)", __func__, td->td_proc->p_pid, CTR3(KTR_INTR, "%s: schedule pid %d (%s)", __func__, td->td_proc->p_pid,
td->td_name); td->td_name);
@ -1017,14 +1024,10 @@ intr_event_schedule_thread(struct intr_event *ie, struct trapframe *frame)
sched_add(td, SRQ_INTR); sched_add(td, SRQ_INTR);
} else { } else {
#ifdef HWPMC_HOOKS #ifdef HWPMC_HOOKS
atomic_add_int(&it->it_waiting, 1); it->it_waiting++;
if (PMC_HOOK_INSTALLED_ANY() &&
if (atomic_load_int(&it->it_waiting) >= intr_hwpmc_waiting_report_threshold) { (it->it_waiting >= intr_hwpmc_waiting_report_threshold))
if (frame != NULL) PMC_SOFT_CALL_INTR_HLPR(waiting, frame);
PMC_SOFT_CALL_TF( , , intr, waiting, frame);
else
PMC_SOFT_CALL( , , intr, waiting);
}
#endif #endif
CTR5(KTR_INTR, "%s: pid %d (%s): it_need %d, state %d", CTR5(KTR_INTR, "%s: pid %d (%s): it_need %d, state %d",
__func__, td->td_proc->p_pid, td->td_name, it->it_need, TD_GET_STATE(td)); __func__, td->td_proc->p_pid, td->td_name, it->it_need, TD_GET_STATE(td));