summaryrefslogtreecommitdiffstats
path: root/sys/dev/hwpmc
diff options
context:
space:
mode:
authorattilio <attilio@FreeBSD.org>2009-06-25 20:59:37 +0000
committerattilio <attilio@FreeBSD.org>2009-06-25 20:59:37 +0000
commitb5fb3d044ba3871b3ea31f6b6f1586de46c3d2b3 (patch)
tree2f657c3284423777a3c940226dc585a9d867603a /sys/dev/hwpmc
parent26f635f51fa012eb580d6a06f40c81be3eeb2e57 (diff)
downloadFreeBSD-src-b5fb3d044ba3871b3ea31f6b6f1586de46c3d2b3.zip
FreeBSD-src-b5fb3d044ba3871b3ea31f6b6f1586de46c3d2b3.tar.gz
Fix a LOR between pmc_sx and proctree/allproc when creating a new thread
for the pmclog. Reported by: Ryan Stone <rstone at sandvine dot com> Tested by: Ryan Stone <rstone at sandvine dot com> Sponsored by: Sandvine Incorporated
Diffstat (limited to 'sys/dev/hwpmc')
-rw-r--r--sys/dev/hwpmc/hwpmc_logging.c7
-rw-r--r--sys/dev/hwpmc/hwpmc_mod.c19
2 files changed, 19 insertions, 7 deletions
diff --git a/sys/dev/hwpmc/hwpmc_logging.c b/sys/dev/hwpmc/hwpmc_logging.c
index 6612203..cfb055b 100644
--- a/sys/dev/hwpmc/hwpmc_logging.c
+++ b/sys/dev/hwpmc/hwpmc_logging.c
@@ -44,6 +44,7 @@ __FBSDID("$FreeBSD$");
#include <sys/module.h>
#include <sys/mutex.h>
#include <sys/pmc.h>
+#include <sys/pmckern.h>
#include <sys/pmclog.h>
#include <sys/proc.h>
#include <sys/signalvar.h>
@@ -552,6 +553,12 @@ pmclog_configure_log(struct pmc_mdep *md, struct pmc_owner *po, int logfd)
int error;
struct proc *p;
+ /*
+ * As long as it is possible to get a LOR between pmc_sx lock and
+ * proctree/allproc sx locks used for adding a new process, assure
+ * the former is not held here.
+ */
+ sx_assert(&pmc_sx, SA_UNLOCKED);
PMCDBG(LOG,CFG,1, "config po=%p logfd=%d", po, logfd);
p = po->po_owner;
diff --git a/sys/dev/hwpmc/hwpmc_mod.c b/sys/dev/hwpmc/hwpmc_mod.c
index c239a69..482db0e 100644
--- a/sys/dev/hwpmc/hwpmc_mod.c
+++ b/sys/dev/hwpmc/hwpmc_mod.c
@@ -2663,7 +2663,7 @@ static const char *pmc_op_to_name[] = {
static int
pmc_syscall_handler(struct thread *td, void *syscall_args)
{
- int error, is_sx_downgraded, op;
+ int error, is_sx_downgraded, is_sx_locked, op;
struct pmc_syscall_args *c;
void *arg;
@@ -2672,6 +2672,7 @@ pmc_syscall_handler(struct thread *td, void *syscall_args)
DROP_GIANT();
is_sx_downgraded = 0;
+ is_sx_locked = 1;
c = (struct pmc_syscall_args *) syscall_args;
@@ -2720,9 +2721,11 @@ pmc_syscall_handler(struct thread *td, void *syscall_args)
* a log file configured, flush its buffers and
* de-configure it.
*/
- if (cl.pm_logfd >= 0)
+ if (cl.pm_logfd >= 0) {
+ sx_xunlock(&pmc_sx);
+ is_sx_locked = 0;
error = pmclog_configure_log(md, po, cl.pm_logfd);
- else if (po->po_flags & PMC_PO_OWNS_LOGFILE) {
+ } else if (po->po_flags & PMC_PO_OWNS_LOGFILE) {
pmclog_process_closelog(po);
error = pmclog_flush(po);
if (error == 0) {
@@ -3772,10 +3775,12 @@ pmc_syscall_handler(struct thread *td, void *syscall_args)
break;
}
- if (is_sx_downgraded)
- sx_sunlock(&pmc_sx);
- else
- sx_xunlock(&pmc_sx);
+ if (is_sx_locked != 0) {
+ if (is_sx_downgraded)
+ sx_sunlock(&pmc_sx);
+ else
+ sx_xunlock(&pmc_sx);
+ }
if (error)
atomic_add_int(&pmc_stats.pm_syscall_errors, 1);
OpenPOWER on IntegriCloud