svn commit: r196915 - in stable/7/sys: dev/hwpmc kern

Attilio Rao attilio at FreeBSD.org
Mon Sep 7 08:52:16 UTC 2009


Author: attilio
Date: Mon Sep  7 08:52:15 2009
New Revision: 196915
URL: http://svn.freebsd.org/changeset/base/196915

Log:
  MFC r195159 and r195005:
  
  * Don't assume a fixed number of preloaded KLDs but calculate at runtime.
    This avoind ending up into an endless loop.
  * Fix a LOR between pmc_sx and allproc/proctree locks
  
  Sponsored by:	Sandvine Incorporated

Modified:
  stable/7/sys/dev/hwpmc/hwpmc_logging.c
  stable/7/sys/dev/hwpmc/hwpmc_mod.c
  stable/7/sys/kern/kern_linker.c

Modified: stable/7/sys/dev/hwpmc/hwpmc_logging.c
==============================================================================
--- stable/7/sys/dev/hwpmc/hwpmc_logging.c	Mon Sep  7 08:46:26 2009	(r196914)
+++ stable/7/sys/dev/hwpmc/hwpmc_logging.c	Mon Sep  7 08:52:15 2009	(r196915)
@@ -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: stable/7/sys/dev/hwpmc/hwpmc_mod.c
==============================================================================
--- stable/7/sys/dev/hwpmc/hwpmc_mod.c	Mon Sep  7 08:46:26 2009	(r196914)
+++ stable/7/sys/dev/hwpmc/hwpmc_mod.c	Mon Sep  7 08:52:15 2009	(r196915)
@@ -2666,7 +2666,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;
 
@@ -2675,6 +2675,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;
 
@@ -2723,9 +2724,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) {
@@ -3776,10 +3779,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);

Modified: stable/7/sys/kern/kern_linker.c
==============================================================================
--- stable/7/sys/kern/kern_linker.c	Mon Sep  7 08:46:26 2009	(r196914)
+++ stable/7/sys/kern/kern_linker.c	Mon Sep  7 08:52:15 2009	(r196915)
@@ -1882,62 +1882,41 @@ linker_basename(const char *path)
 }
 
 #ifdef HWPMC_HOOKS
-
-struct hwpmc_context {
-	int	nobjects;
-	int	nmappings;
-	struct pmckern_map_in *kobase;
-};
-
-static int
-linker_hwpmc_list_object(linker_file_t lf, void *arg)
-{
-	struct hwpmc_context *hc;
-
-	hc = arg;
-
-	/* If we run out of mappings, fail. */
-	if (hc->nobjects >= hc->nmappings)
-		return (1);
-
-	/* Save the info for this linker file. */
-	hc->kobase[hc->nobjects].pm_file = lf->filename;
-	hc->kobase[hc->nobjects].pm_address = (uintptr_t)lf->address;
-	hc->nobjects++;
-	return (0);
-}
-
 /*
  * Inform hwpmc about the set of kernel modules currently loaded.
  */
 void *
 linker_hwpmc_list_objects(void)
 {
-	struct hwpmc_context hc;
+	linker_file_t lf;
+	struct pmckern_map_in *kobase;
+	int i, nmappings;
 
-	hc.nmappings = 15;	/* a reasonable default */
+	nmappings = 0;
+	KLD_LOCK();
+	TAILQ_FOREACH(lf, &linker_files, link)
+		nmappings++;
 
- retry:
-	/* allocate nmappings+1 entries */
-	MALLOC(hc.kobase, struct pmckern_map_in *,
-	    (hc.nmappings + 1) * sizeof(struct pmckern_map_in), M_LINKER,
-	    M_WAITOK | M_ZERO);
-
-	hc.nobjects = 0;
-	if (linker_file_foreach(linker_hwpmc_list_object, &hc) != 0) {
-		hc.nmappings = hc.nobjects;
-		FREE(hc.kobase, M_LINKER);
-		goto retry;
+	/* Allocate nmappings + 1 entries. */
+	kobase = malloc((nmappings + 1) * sizeof(struct pmckern_map_in),
+	    M_LINKER, M_WAITOK | M_ZERO);
+	i = 0;
+	TAILQ_FOREACH(lf, &linker_files, link) {
+
+		/* Save the info for this linker file. */
+		kobase[i].pm_file = lf->filename;
+		kobase[i].pm_address = (uintptr_t)lf->address;
+		i++;
 	}
+	KLD_UNLOCK();
 
-	KASSERT(hc.nobjects > 0, ("linker_hpwmc_list_objects: no kernel "
-		"objects?"));
+	KASSERT(i > 0, ("linker_hwpmc_list_objects: no kernel objects?"));
 
 	/* The last entry of the malloced area comprises of all zeros. */
-	KASSERT(hc.kobase[hc.nobjects].pm_file == NULL,
+	KASSERT(kobase[i].pm_file == NULL,
 	    ("linker_hwpmc_list_objects: last object not NULL"));
 
-	return ((void *)hc.kobase);
+	return ((void *)kobase);
 }
 #endif
 


More information about the svn-src-all mailing list