PERFORCE change 97634 for review

John Birrell jb at FreeBSD.org
Mon May 22 20:16:29 UTC 2006


http://perforce.freebsd.org/chv.cgi?CH=97634

Change 97634 by jb at jb_freebsd2 on 2006/05/22 20:15:14

	Change the kernel linker to use an sx lock instead of a mutex so that
	DTrace can list all linker files while holding the lock and still be
	able to malloc with wait to create probes.
	
	Add a function to list the function names and their values. This function
	assumes that the lock is held while listing the files, so no additional
	locking is attempted.

Affected files ...

.. //depot/projects/dtrace/src/sys/kern/kern_linker.c#8 edit
.. //depot/projects/dtrace/src/sys/sys/linker.h#6 edit

Differences ...

==== //depot/projects/dtrace/src/sys/kern/kern_linker.c#8 (text+ko) ====

@@ -49,6 +49,7 @@
 #include <sys/libkern.h>
 #include <sys/namei.h>
 #include <sys/vnode.h>
+#include <sys/sx.h>
 #include <sys/sysctl.h>
 
 #include "linker_if.h"
@@ -74,7 +75,7 @@
 
 linker_file_t linker_kernel_file;
 
-static struct mtx kld_mtx;	/* kernel linker mutex */
+static struct sx kld_sx;	/* kernel linker lock */
 
 static linker_class_list_t classes;
 static linker_file_list_t linker_files;
@@ -85,16 +86,16 @@
 	linker_file_t lftmp;						\
 									\
 retry:									\
-	mtx_lock(&kld_mtx);						\
+	sx_xlock(&kld_sx);						\
 	TAILQ_FOREACH(lftmp, &linker_files, link) {			\
 		if (next_file_id == lftmp->id) {			\
 			next_file_id++;					\
-			mtx_unlock(&kld_mtx);				\
+			sx_xunlock(&kld_sx);				\
 			goto retry;					\
 		}							\
 	}								\
 	(a) = next_file_id;						\
-	mtx_unlock(&kld_mtx);	/* Hold for safe read of id variable */	\
+	sx_xunlock(&kld_sx);	/* Hold for safe read of id variable */	\
 } while(0)
 
 
@@ -126,7 +127,7 @@
 linker_init(void *arg)
 {
 
-	mtx_init(&kld_mtx, "kernel linker", NULL, MTX_DEF);
+	sx_init(&kld_sx, "kernel linker");
 	TAILQ_INIT(&classes);
 	TAILQ_INIT(&linker_files);
 }
@@ -424,14 +425,14 @@
 		goto out;
 	sprintf(koname, "%s.ko", filename);
 
-	mtx_lock(&kld_mtx);
+	sx_xlock(&kld_sx);
 	TAILQ_FOREACH(lf, &linker_files, link) {
 		if (strcmp(lf->filename, koname) == 0)
 			break;
 		if (strcmp(lf->filename, filename) == 0)
 			break;
 	}
-	mtx_unlock(&kld_mtx);
+	sx_xunlock(&kld_sx);
 out:
 	if (koname)
 		free(koname, M_LINKER);
@@ -443,11 +444,11 @@
 {
 	linker_file_t lf = 0;
 	
-	mtx_lock(&kld_mtx);
+	sx_xlock(&kld_sx);
 	TAILQ_FOREACH(lf, &linker_files, link)
 		if (lf->id == fileid)
 			break;
-	mtx_unlock(&kld_mtx);
+	sx_xunlock(&kld_sx);
 	return (lf);
 }
 
@@ -474,9 +475,9 @@
 	lf->deps = NULL;
 	STAILQ_INIT(&lf->common);
 	TAILQ_INIT(&lf->modules);
-	mtx_lock(&kld_mtx);
+	sx_xlock(&kld_sx);
 	TAILQ_INSERT_TAIL(&linker_files, lf, link);
-	mtx_unlock(&kld_mtx);
+	sx_xunlock(&kld_sx);
 out:
 	return (lf);
 }
@@ -546,9 +547,9 @@
 		linker_file_sysuninit(file);
 		linker_file_unregister_sysctls(file);
 	}
-	mtx_lock(&kld_mtx);
+	sx_xlock(&kld_sx);
 	TAILQ_REMOVE(&linker_files, file, link);
-	mtx_unlock(&kld_mtx);
+	sx_xunlock(&kld_sx);
 
 	if (file->deps) {
 		for (i = 0; i < file->ndeps; i++)
@@ -618,18 +619,28 @@
 	linker_file_t lf;
 	int error = 0;
 
-	mtx_lock(&kld_mtx);
+	sx_xlock(&kld_sx);
 
 	TAILQ_FOREACH(lf, &linker_files, link) {
 		if ((error = callback_func(lf, arg)) != 0)
 			break;
 	}
 
-	mtx_unlock(&kld_mtx);
+	sx_xunlock(&kld_sx);
 
 	return (error);
 }
 
+/*
+ * List all functions in a file.
+ */
+int
+linker_file_function_listall(linker_file_t lf,
+    int (*callback_func)(linker_file_t, linker_symval_t *, void *), void *arg)
+{
+	return (LINKER_EACH_FUNCTION_NAMEVAL(lf, callback_func, arg));
+}
+
 caddr_t
 linker_file_lookup_value(const char *name)
 {
@@ -639,7 +650,7 @@
 
 	symval.value = 0;
 
-	mtx_lock(&kld_mtx);
+	sx_xlock(&kld_sx);
 
 	TAILQ_FOREACH(lf, &linker_files, link) {
 		if (LINKER_LOOKUP_SYMBOL(lf, name, &sym) == 0 &&
@@ -647,7 +658,7 @@
 			break;
 	}
 
-	mtx_unlock(&kld_mtx);
+	sx_xunlock(&kld_sx);
 
 	return (symval.value);
 }
@@ -988,12 +999,12 @@
 	mtx_lock(&Giant);
 
 	if (uap->fileid == 0) {
-		mtx_lock(&kld_mtx);
+		sx_xlock(&kld_sx);
 		if (TAILQ_FIRST(&linker_files))
 			td->td_retval[0] = TAILQ_FIRST(&linker_files)->id;
 		else
 			td->td_retval[0] = 0;
-		mtx_unlock(&kld_mtx);
+		sx_xunlock(&kld_sx);
 		goto out;
 	}
 	lf = linker_find_file_by_id(uap->fileid);
@@ -1159,7 +1170,7 @@
 		} else
 			error = ENOENT;
 	} else {
-		mtx_lock(&kld_mtx);
+		sx_xlock(&kld_sx);
 		TAILQ_FOREACH(lf, &linker_files, link) {
 			if (LINKER_LOOKUP_SYMBOL(lf, symstr, &sym) == 0 &&
 			    LINKER_SYMBOL_VALUES(lf, sym, &symval) == 0) {
@@ -1170,7 +1181,7 @@
 				break;
 			}
 		}
-		mtx_unlock(&kld_mtx);
+		sx_xunlock(&kld_sx);
 		if (lf == NULL)
 			error = ENOENT;
 	}
@@ -1772,7 +1783,7 @@
 	    M_WAITOK | M_ZERO);
 
 	nobjects = 0;
-	mtx_lock(&kld_mtx);
+	sx_xlock(&kld_sx);
 	TAILQ_FOREACH(lf, &linker_files, link)
 		nobjects++;
 
@@ -1782,7 +1793,7 @@
 	if (nobjects > nmappings) {
 		nmappings = nobjects;
 		FREE(kobase, M_LINKER);
-		mtx_unlock(&kld_mtx);
+		sx_xunlock(&kld_sx);
 		goto retry;
 	}
 
@@ -1797,7 +1808,7 @@
 	KASSERT(ko->pm_file == NULL,
 	    ("linker_hwpmc_list_objects: last object not NULL"));
 
-	mtx_unlock(&kld_mtx);
+	sx_xunlock(&kld_sx);
 
 	return ((void *) kobase);
 }
@@ -1990,16 +2001,16 @@
 	error = sysctl_wire_old_buffer(req, 0);
 	if (error != 0)
 		return (error);
-	mtx_lock(&kld_mtx);
+	sx_xlock(&kld_sx);
 	TAILQ_FOREACH(lf, &linker_files, link) {
 		error = LINKER_EACH_FUNCTION_NAME(lf,
 		    sysctl_kern_function_list_iterate, req);
 		if (error) {
-			mtx_unlock(&kld_mtx);
+			sx_xunlock(&kld_sx);
 			return (error);
 		}
 	}
-	mtx_unlock(&kld_mtx);
+	sx_xunlock(&kld_sx);
 	return (SYSCTL_OUT(req, "", 1));
 }
 

==== //depot/projects/dtrace/src/sys/sys/linker.h#6 (text+ko) ====

@@ -59,6 +59,8 @@
     size_t		size;
 } linker_symval_t;
 
+typedef int (*linker_function_nameval_callback_t)(linker_file_t, linker_symval_t *, void *);
+
 struct common_symbol {
     STAILQ_ENTRY(common_symbol) link;
     char*		name;
@@ -82,6 +84,9 @@
     STAILQ_HEAD(, common_symbol) common; /* list of common symbols */
     TAILQ_HEAD(, module) modules;	/* modules in this file */
     TAILQ_ENTRY(linker_file) loaded;	/* preload dependency support */
+
+    /* Function Boundary Tracing (FBT) fields. */
+    int			fbt_nentries;	/* number of fbt entries created. */
 };
 
 /*
@@ -169,6 +174,12 @@
 int linker_file_listall(int (*)(linker_file_t,void *),void *);
 
 /*
+ * List all functions in a file.
+ */
+int linker_file_function_listall(linker_file_t, int (*)(linker_file_t,
+    linker_symval_t *, void *), void *);
+
+/*
  * This routine is responsible for finding dependencies of userland
  * initiated kldload(2)'s of files.
  */


More information about the p4-projects mailing list