Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 11 Nov 2011 02:15:44 +0000 (UTC)
From:      Ryan Stone <rstone@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-8@freebsd.org
Subject:   svn commit: r227440 - stable/8/sys/kern
Message-ID:  <201111110215.pAB2FilL066357@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: rstone
Date: Fri Nov 11 02:15:44 2011
New Revision: 227440
URL: http://svn.freebsd.org/changeset/base/227440

Log:
  MFC 224156:
  
   Fix a LOR between hwpmc and the kernel linker.  When a system-wide
   sampling mode PMC is allocated, hwpmc calls linker_hwpmc_list_objects()
   while already holding an exclusive lock on pmc-sx lock.  list_objects()
   tries to acquire an exclusive lock on the kld_sx lock.  When a KLD module
   is loaded or unloaded successfully, kern_kld(un)load calls into the pmc
   hook while already holding an exclusive lock on the kld_sx lock.  Calling
   the pmc hook requires acquiring a shared lock on the pmc-sx lock.
  
   Fix this by only acquiring a shared lock on the kld_sx lock in
   linker_hwpmc_list_objects(), and also downgrading to a shared lock on the
   kld_sx lock in kern_kld(un)load before calling into the pmc hook.  In
   kern_kldload this required moving some modifications of the linker_file_t
   to happen before calling into the pmc hook.
  
   This fixes the deadlock by ensuring that the hwpmc -> list_objects() case
   is always able to proceed.  Without this patch, I was able to deadlock a
   multicore system within minutes by constantly loading and unloading an KLD
   module while I simultaneously started a sampling mode PMC in a loop.

Modified:
  stable/8/sys/kern/kern_linker.c
Directory Properties:
  stable/8/sys/   (props changed)
  stable/8/sys/amd64/include/xen/   (props changed)
  stable/8/sys/cddl/contrib/opensolaris/   (props changed)
  stable/8/sys/contrib/dev/acpica/   (props changed)
  stable/8/sys/contrib/pf/   (props changed)

Modified: stable/8/sys/kern/kern_linker.c
==============================================================================
--- stable/8/sys/kern/kern_linker.c	Fri Nov 11 02:13:35 2011	(r227439)
+++ stable/8/sys/kern/kern_linker.c	Fri Nov 11 02:15:44 2011	(r227440)
@@ -68,6 +68,9 @@ int kld_debug = 0;
 
 #define	KLD_LOCK()		sx_xlock(&kld_sx)
 #define	KLD_UNLOCK()		sx_xunlock(&kld_sx)
+#define	KLD_DOWNGRADE()		sx_downgrade(&kld_sx)
+#define	KLD_LOCK_READ()		sx_slock(&kld_sx)
+#define	KLD_UNLOCK_READ()	sx_sunlock(&kld_sx)
 #define	KLD_LOCKED()		sx_xlocked(&kld_sx)
 #define	KLD_LOCK_ASSERT() do {						\
 	if (!cold)							\
@@ -1014,18 +1017,24 @@ kern_kldload(struct thread *td, const ch
 
 	KLD_LOCK();
 	error = linker_load_module(kldname, modname, NULL, NULL, &lf);
-	if (error)
-		goto unlock;
+	if (error) {
+		KLD_UNLOCK();
+		goto done;
+	}
+	lf->userrefs++;
+	if (fileid != NULL)
+		*fileid = lf->id;
 #ifdef HWPMC_HOOKS
+	KLD_DOWNGRADE();
 	pkm.pm_file = lf->filename;
 	pkm.pm_address = (uintptr_t) lf->address;
 	PMC_CALL_HOOK(td, PMC_FN_KLD_LOAD, (void *) &pkm);
-#endif
-	lf->userrefs++;
-	if (fileid != NULL)
-		*fileid = lf->id;
-unlock:
+	KLD_UNLOCK_READ();
+#else
 	KLD_UNLOCK();
+#endif
+
+done:
 	CURVNET_RESTORE();
 	return (error);
 }
@@ -1097,10 +1106,14 @@ kern_kldunload(struct thread *td, int fi
 		error = ENOENT;
 
 #ifdef HWPMC_HOOKS
-	if (error == 0)
+	if (error == 0) {
+		KLD_DOWNGRADE();
 		PMC_CALL_HOOK(td, PMC_FN_KLD_UNLOAD, (void *) &pkm);
+		KLD_UNLOCK_READ();
+	} else
+#else
+		KLD_UNLOCK();
 #endif
-	KLD_UNLOCK();
 	CURVNET_RESTORE();
 	return (error);
 }
@@ -1919,7 +1932,7 @@ linker_hwpmc_list_objects(void)
 	int i, nmappings;
 
 	nmappings = 0;
-	KLD_LOCK();
+	KLD_LOCK_READ();
 	TAILQ_FOREACH(lf, &linker_files, link)
 		nmappings++;
 
@@ -1934,7 +1947,7 @@ linker_hwpmc_list_objects(void)
 		kobase[i].pm_address = (uintptr_t)lf->address;
 		i++;
 	}
-	KLD_UNLOCK();
+	KLD_UNLOCK_READ();
 
 	KASSERT(i > 0, ("linker_hpwmc_list_objects: no kernel objects?"));
 



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201111110215.pAB2FilL066357>