Author: attilio
Date: Thu Jun 25 20:59:37 2009
New Revision: 195005
URL: http://svn.freebsd.org/changeset/base/195005
Log:
  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

Modified:
  head/sys/dev/hwpmc/hwpmc_logging.c
  head/sys/dev/hwpmc/hwpmc_mod.c

Modified: head/sys/dev/hwpmc/hwpmc_logging.c
==============================================================================
--- head/sys/dev/hwpmc/hwpmc_logging.c  Thu Jun 25 20:57:53 2009        
(r195004)
+++ head/sys/dev/hwpmc/hwpmc_logging.c  Thu Jun 25 20:59:37 2009        
(r195005)
@@ -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
        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;

Modified: head/sys/dev/hwpmc/hwpmc_mod.c
==============================================================================
--- head/sys/dev/hwpmc/hwpmc_mod.c      Thu Jun 25 20:57:53 2009        
(r195004)
+++ head/sys/dev/hwpmc/hwpmc_mod.c      Thu Jun 25 20:59:37 2009        
(r195005)
@@ -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, v
        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, v
                 * 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, v
                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);
_______________________________________________
svn-src-all@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to