aboutsummaryrefslogtreecommitdiff
path: root/sys/dev/hwpmc/hwpmc_mod.c
diff options
context:
space:
mode:
authorMitchell Horne <mhorne@FreeBSD.org>2023-06-14 16:32:11 +0000
committerMitchell Horne <mhorne@FreeBSD.org>2023-06-14 16:34:21 +0000
commita133f64239cdbefa374cf6df134f3581f9b9f147 (patch)
treea00b9596b8fd35525ffabcc07d8ed3051c7288c5 /sys/dev/hwpmc/hwpmc_mod.c
parentc498169442f3ebf769eb0157260c592729e48dc1 (diff)
downloadsrc-a133f64239cdbefa374cf6df134f3581f9b9f147.tar.gz
src-a133f64239cdbefa374cf6df134f3581f9b9f147.zip
Diffstat (limited to 'sys/dev/hwpmc/hwpmc_mod.c')
-rw-r--r--sys/dev/hwpmc/hwpmc_mod.c190
1 files changed, 103 insertions, 87 deletions
diff --git a/sys/dev/hwpmc/hwpmc_mod.c b/sys/dev/hwpmc/hwpmc_mod.c
index 987184b7fae8..24cd3ba0fc0f 100644
--- a/sys/dev/hwpmc/hwpmc_mod.c
+++ b/sys/dev/hwpmc/hwpmc_mod.c
@@ -3282,6 +3282,103 @@ static const char *pmc_op_to_name[] = {
is_sx_downgraded = true; \
} while (0)
+/*
+ * Main body of PMC_OP_PMCATTACH.
+ */
+static int
+pmc_do_op_pmcattach(struct thread *td, struct pmc_op_pmcattach a)
+{
+ struct pmc *pm;
+ struct proc *p;
+ int error;
+
+ sx_assert(&pmc_sx, SX_XLOCKED);
+
+ if (a.pm_pid < 0) {
+ return (EINVAL);
+ } else if (a.pm_pid == 0) {
+ a.pm_pid = td->td_proc->p_pid;
+ }
+
+ error = pmc_find_pmc(a.pm_pmc, &pm);
+ if (error != 0)
+ return (error);
+
+ if (PMC_IS_SYSTEM_MODE(PMC_TO_MODE(pm)))
+ return (EINVAL);
+
+ /* PMCs may be (re)attached only when allocated or stopped */
+ if (pm->pm_state == PMC_STATE_RUNNING) {
+ return (EBUSY);
+ } else if (pm->pm_state != PMC_STATE_ALLOCATED &&
+ pm->pm_state != PMC_STATE_STOPPED) {
+ return (EINVAL);
+ }
+
+ /* lookup pid */
+ if ((p = pfind(a.pm_pid)) == NULL)
+ return (ESRCH);
+
+ /*
+ * Ignore processes that are working on exiting.
+ */
+ if ((p->p_flag & P_WEXIT) != 0) {
+ PROC_UNLOCK(p); /* pfind() returns a locked process */
+ return (ESRCH);
+ }
+
+ /*
+ * We are allowed to attach a PMC to a process if we can debug it.
+ */
+ error = p_candebug(curthread, p);
+
+ PROC_UNLOCK(p);
+
+ if (error == 0)
+ error = pmc_attach_process(p, pm);
+
+ return (error);
+}
+
+/*
+ * Main body of PMC_OP_PMCDETACH.
+ */
+static int
+pmc_do_op_pmcdetach(struct thread *td, struct pmc_op_pmcattach a)
+{
+ struct pmc *pm;
+ struct proc *p;
+ int error;
+
+ if (a.pm_pid < 0) {
+ return (EINVAL);
+ } else if (a.pm_pid == 0)
+ a.pm_pid = td->td_proc->p_pid;
+
+ error = pmc_find_pmc(a.pm_pmc, &pm);
+ if (error != 0)
+ return (error);
+
+ if ((p = pfind(a.pm_pid)) == NULL)
+ return (ESRCH);
+
+ /*
+ * Treat processes that are in the process of exiting as if they were
+ * not present.
+ */
+ if ((p->p_flag & P_WEXIT) != 0) {
+ PROC_UNLOCK(p);
+ return (ESRCH);
+ }
+
+ PROC_UNLOCK(p); /* pfind() returns a locked process */
+
+ if (error == 0)
+ error = pmc_detach_process(p, pm);
+
+ return (error);
+}
+
static int
pmc_syscall_handler(struct thread *td, void *syscall_args)
{
@@ -4004,114 +4101,33 @@ pmc_syscall_handler(struct thread *td, void *syscall_args)
}
break;
-
/*
* Attach a PMC to a process.
*/
-
case PMC_OP_PMCATTACH:
{
- struct pmc *pm;
- struct proc *p;
struct pmc_op_pmcattach a;
- sx_assert(&pmc_sx, SX_XLOCKED);
-
- if ((error = copyin(arg, &a, sizeof(a))) != 0)
- break;
-
- if (a.pm_pid < 0) {
- error = EINVAL;
- break;
- } else if (a.pm_pid == 0)
- a.pm_pid = td->td_proc->p_pid;
-
- if ((error = pmc_find_pmc(a.pm_pmc, &pm)) != 0)
- break;
-
- if (PMC_IS_SYSTEM_MODE(PMC_TO_MODE(pm))) {
- error = EINVAL;
- break;
- }
-
- /* PMCs may be (re)attached only when allocated or stopped */
- if (pm->pm_state == PMC_STATE_RUNNING) {
- error = EBUSY;
- break;
- } else if (pm->pm_state != PMC_STATE_ALLOCATED &&
- pm->pm_state != PMC_STATE_STOPPED) {
- error = EINVAL;
- break;
- }
-
- /* lookup pid */
- if ((p = pfind(a.pm_pid)) == NULL) {
- error = ESRCH;
- break;
- }
-
- /*
- * Ignore processes that are working on exiting.
- */
- if (p->p_flag & P_WEXIT) {
- error = ESRCH;
- PROC_UNLOCK(p); /* pfind() returns a locked process */
+ error = copyin(arg, &a, sizeof(a));
+ if (error != 0)
break;
- }
- /*
- * we are allowed to attach a PMC to a process if
- * we can debug it.
- */
- error = p_candebug(curthread, p);
-
- PROC_UNLOCK(p);
-
- if (error == 0)
- error = pmc_attach_process(p, pm);
+ error = pmc_do_op_pmcattach(td, a);
}
break;
-
/*
* Detach an attached PMC from a process.
*/
-
case PMC_OP_PMCDETACH:
{
- struct pmc *pm;
- struct proc *p;
struct pmc_op_pmcattach a;
- if ((error = copyin(arg, &a, sizeof(a))) != 0)
- break;
-
- if (a.pm_pid < 0) {
- error = EINVAL;
- break;
- } else if (a.pm_pid == 0)
- a.pm_pid = td->td_proc->p_pid;
-
- if ((error = pmc_find_pmc(a.pm_pmc, &pm)) != 0)
- break;
-
- if ((p = pfind(a.pm_pid)) == NULL) {
- error = ESRCH;
+ error = copyin(arg, &a, sizeof(a));
+ if (error != 0)
break;
- }
- /*
- * Treat processes that are in the process of exiting
- * as if they were not present.
- */
-
- if (p->p_flag & P_WEXIT)
- error = ESRCH;
-
- PROC_UNLOCK(p); /* pfind() returns a locked process */
-
- if (error == 0)
- error = pmc_detach_process(p, pm);
+ error = pmc_do_op_pmcdetach(td, a);
}
break;