Skip site navigation (1)Skip section navigation (2)
Date:      02 Apr 2002 16:45:05 +0200
From:      Dag-Erling Smorgrav <des@ofug.org>
To:        Poul-Henning Kamp <phk@critter.freebsd.dk>
Cc:        Marcel Moolenaar <marcel@FreeBSD.org>, cvs-committers@FreeBSD.org, cvs-all@FreeBSD.org
Subject:   Re: cvs commit: src/sys/ia64/ia64 ia64dump.c
Message-ID:  <xzp7knqupla.fsf@flood.ping.uio.no>
In-Reply-To: <51854.1017754714@critter.freebsd.dk>
References:  <51854.1017754714@critter.freebsd.dk>

index | next in thread | previous in thread | raw e-mail

[-- Attachment #1 --]
I *had* patches, but nuked them when you committed your code.
Remnants can be found in the attached garbage file.  I even blew a
partition working on this (by setting dumplo too high).

DES
-- 
Dag-Erling Smorgrav - des@ofug.org


[-- Attachment #2 --]
Index: sys/alpha/alpha/machdep.c
===================================================================
RCS file: /home/ncvs/src/sys/alpha/alpha/machdep.c,v
retrieving revision 1.170
diff -u -r1.170 machdep.c
--- sys/alpha/alpha/machdep.c	27 Mar 2002 09:23:37 -0000	1.170
+++ sys/alpha/alpha/machdep.c	30 Mar 2002 15:05:25 -0000
@@ -192,7 +192,6 @@
 struct msgbuf *msgbufp=0;
 
 int Maxmem = 0;
-long dumplo;
 
 int	totalphysmem;		/* total amount of physical memory in system */
 int	physmem;		/* physical memory used by NetBSD + some rsvd */
Index: sys/conf/options.i386
===================================================================
RCS file: /home/ncvs/src/sys/conf/options.i386,v
retrieving revision 1.169
diff -u -r1.169 options.i386
--- sys/conf/options.i386	27 Feb 2002 09:51:31 -0000	1.169
+++ sys/conf/options.i386	23 Mar 2002 18:04:45 -0000
@@ -188,6 +188,9 @@
 # SMB/CIFS filesystem
 SMBFS
 
+# Mutex profiling
+TRACE_MUTEX_TIME	opt_global.h
+
 # -------------------------------
 # EOF
 # -------------------------------
Index: sys/i386/i386/machdep.c
===================================================================
RCS file: /home/ncvs/src/sys/i386/i386/machdep.c,v
retrieving revision 1.507
diff -u -r1.507 machdep.c
--- sys/i386/i386/machdep.c	27 Mar 2002 09:23:37 -0000	1.507
+++ sys/i386/i386/machdep.c	30 Mar 2002 15:06:12 -0000
@@ -196,7 +196,6 @@
 	0, 0, sysctl_hw_availpages, "I", "");
 
 int Maxmem = 0;
-long dumplo;
 
 vm_offset_t phys_avail[10];
 
Index: sys/ia64/ia64/machdep.c
===================================================================
RCS file: /home/ncvs/src/sys/ia64/ia64/machdep.c,v
retrieving revision 1.85
diff -u -r1.85 machdep.c
--- sys/ia64/ia64/machdep.c	30 Mar 2002 23:25:22 -0000	1.85
+++ sys/ia64/ia64/machdep.c	31 Mar 2002 00:36:27 -0000
@@ -142,7 +142,6 @@
 struct msgbuf *msgbufp=0;
 
 int Maxmem = 0;
-long dumplo;
 
 int	totalphysmem;		/* total amount of physical memory in system */
 int	physmem;		/* physical memory used by NetBSD + some rsvd */
Index: sys/kern/kern_mutex.c
===================================================================
RCS file: /home/ncvs/src/sys/kern/kern_mutex.c,v
retrieving revision 1.83
diff -u -r1.83 kern_mutex.c
--- sys/kern/kern_mutex.c	27 Mar 2002 09:23:38 -0000	1.83
+++ sys/kern/kern_mutex.c	30 Mar 2002 15:06:26 -0000
@@ -37,17 +37,19 @@
 #include "opt_ddb.h"
 
 #include <sys/param.h>
+#include <sys/systm.h>
 #include <sys/bus.h>
+#include <sys/dump.h>
 #include <sys/kernel.h>
+#include <sys/ktr.h>
 #include <sys/lock.h>
 #include <sys/malloc.h>
 #include <sys/mutex.h>
 #include <sys/proc.h>
 #include <sys/resourcevar.h>
+#include <sys/sbuf.h>
 #include <sys/sysctl.h>
-#include <sys/systm.h>
 #include <sys/vmmeter.h>
-#include <sys/ktr.h>
 
 #include <machine/atomic.h>
 #include <machine/bus.h>
@@ -196,6 +198,104 @@
 	}
 }
 
+#ifdef TRACE_MUTEX_TIME
+#define TRACE_HASH_SIZE 1009
+SYSCTL_NODE(_kern, OID_AUTO, mtx, CTLFLAG_RD, NULL, "mutex manipulation");
+SYSCTL_NODE(_kern_mtx, OID_AUTO, trace, CTLFLAG_RD, NULL, "mutex tracing");
+static int kern_mtx_trace_enable = 0;
+SYSCTL_INT(_kern_mtx_trace, OID_AUTO, enable, CTLFLAG_RW,
+    &kern_mtx_trace_enable, 0, "Enable tracing of mutex holdtime");
+static int kern_mtx_trace_hashsize = TRACE_HASH_SIZE;
+SYSCTL_INT(_kern_mtx_trace, OID_AUTO, hashsize, CTLFLAG_RD,
+    &kern_mtx_trace_hashsize, 0, "Trace hash size");
+static int kern_mtx_trace_numtraced = 0;
+SYSCTL_INT(_kern_mtx_trace, OID_AUTO, numtraced, CTLFLAG_RD,
+    &kern_mtx_trace_numtraced, 0, "Number of traced mutices");
+static int kern_mtx_trace_collisions = 0;
+SYSCTL_INT(_kern_mtx_trace, OID_AUTO, collisions, CTLFLAG_RD,
+    &kern_mtx_trace_numtraced, 0, "Number of hash collisions");
+
+static struct mutex_trace {
+	char name[64];
+	u_int64_t count;
+	u_int64_t maxtsc;
+	u_int64_t totaltsc;
+	struct mutex_trace *next;
+} *mutex_traces[TRACE_HASH_SIZE];
+
+static struct mtx trace_mtx;
+
+/*
+ * tracebuf is the pool of trace records we have;
+ * we cannot (reliably) handle more than this number
+ * of places in the code where mutexes are aquired.
+ *
+ * We use a static allocation to avoid interacting
+ * with the rest of the system.
+ */
+#define NUM_TRACE_BUFFERS 1000
+static struct mutex_trace tracebuf[NUM_TRACE_BUFFERS];
+static int first_free_mutex_trace = 0;
+
+static const char *unknown = "(unknown)";
+
+/* Number of locks to show in the sysctl.  MUST BE AN EVEN NUMBER. */
+#define NUM_LOCKS_TO_DUMP 10
+#define mutex_trace_cmp(a, b) (tracebuf[a].maxtsc - tracebuf[b].maxtsc)
+
+/*
+ * Output statistics of mutex holders that keep the mutex the longest.
+ */
+static int
+dump_mtx_trace(SYSCTL_HANDLER_ARGS)
+{
+	struct sbuf *sb;
+	struct mutex_trace *mtp;
+	int traces[NUM_LOCKS_TO_DUMP];
+	int error, i, j, k;
+
+	if (kern_mtx_trace_numtraced == 0)
+		return SYSCTL_OUT(req, "No locking recorded",
+		    sizeof("No locking recorded"));
+
+	/*
+	 * Find the 10 largest
+	 */
+	mtx_lock_spin(&trace_mtx);
+	for (i = 0; i < NUM_LOCKS_TO_DUMP; ++i)
+		traces[i] = -1;
+	for (k = 0; k < first_free_mutex_trace; ++k) {
+		for (i = 0; i < NUM_LOCKS_TO_DUMP; ++i) {
+			if (traces[i] == -1) {
+				traces[i] = k;
+				break;
+			}
+			if (mutex_trace_cmp(k, traces[i]) < 0)
+				continue;
+			for (j = NUM_LOCKS_TO_DUMP - 1; j > i; --j)
+				traces[j] = traces[j - 1];
+			traces[i] = k;
+			break;
+		}
+	}
+
+	/* Now dump the garbage */
+	sb = sbuf_new(NULL, NULL, 256, SBUF_AUTOEXTEND);
+	for (i = 0; i < NUM_LOCKS_TO_DUMP && traces[i] != -1; ++i) {
+		mtp = &tracebuf[traces[i]];
+		sbuf_printf(sb, "%s: held %llu (%llu)\n",
+		    mtp->name, mtp->maxtsc, mtp->totaltsc);
+	}
+	sbuf_finish(sb);
+	mtx_unlock_spin(&trace_mtx);
+	error = SYSCTL_OUT(req, sbuf_data(sb), sbuf_len(sb));
+	sbuf_delete(sb);
+	return (error);
+}
+SYSCTL_PROC(_kern_mtx_trace, OID_AUTO, stats, CTLTYPE_STRING|CTLFLAG_RD,
+    NULL, 0, dump_mtx_trace, "A", "Statistics about how long mutexes are held");
+#endif		/* TRACE_MUTEX_TIME */
+
 /*
  * Function versions of the inlined __mtx_* macros.  These are used by
  * modules and can also be called from assembly language if needed.
@@ -209,6 +309,22 @@
 	LOCK_LOG_LOCK("LOCK", &m->mtx_object, opts, m->mtx_recurse, file,
 	    line);
 	WITNESS_LOCK(&m->mtx_object, opts | LOP_EXCLUSIVE, file, line);
+#ifdef TRACE_MUTEX_TIME
+	if (!(trace_mtx.mtx_object.lo_flags & LO_INITIALIZED))
+		mtx_init(&trace_mtx, "mutex trace lock", MTX_SPIN | MTX_QUIET);
+	mtx_lock_spin(&trace_mtx);
+	m->tsc = kern_mtx_trace_enable ? rdtsc() : 0;
+	if (m->name[0] == '\0') {
+		const char *p = file;
+
+		while (p && strncmp(p, "../", 3) == 0)
+		    p += 3;
+		if (p == NULL || *p == '\0')
+			p = unknown;
+		snprintf(m->name, sizeof m->name, "%s:%d", p, line);
+	}
+	mtx_unlock_spin(&trace_mtx);
+#endif
 }
 
 void
@@ -217,6 +333,54 @@
 
 	MPASS(curthread != NULL);
 	mtx_assert(m, MA_OWNED);
+#ifdef TRACE_MUTEX_TIME
+	if (m->tsc != 0 && m->name[0] != '\0') {
+		struct mutex_trace *trace;
+		u_int64_t tsc, mtsc;
+		u_int hash;
+		char *p;
+
+		tsc = rdtsc();
+		mtsc = m->tsc;
+		m->tsc = 0;
+		if (tsc <= mtsc)
+			goto out;
+		for (hash = 0, p = m->name; *p; p++)
+			hash += (unsigned char)*p;
+		hash %= TRACE_HASH_SIZE;
+		hash = line % TRACE_HASH_SIZE;
+		mtx_lock_spin(&trace_mtx);
+		for (trace = mutex_traces[hash]; trace; trace = trace->next)
+			if (strcmp(trace->name, m->name) == 0)
+				break;
+		if (trace == NULL) {
+			/* Just exit if we cannot get a trace buffer */
+			if (first_free_mutex_trace >= NUM_TRACE_BUFFERS)
+				goto unlock_out;
+			trace = &tracebuf[first_free_mutex_trace++];
+			/* Race protection */
+			if (first_free_mutex_trace > NUM_TRACE_BUFFERS)
+				goto unlock_out;
+			strcpy(trace->name, m->name);
+			if (mutex_traces[hash] != NULL)
+				++kern_mtx_trace_collisions;
+			trace->next = mutex_traces[hash];
+			mutex_traces[hash] = trace;
+			++kern_mtx_trace_numtraced;
+		}
+		/*
+		 * Record if the mutex has been held longer now than ever
+		 * before
+		 */
+		if ((tsc - mtsc) > trace->maxtsc)
+			trace->maxtsc = tsc - mtsc;
+		trace->totaltsc += tsc - mtsc;
+		trace->count += 1;
+ unlock_out:
+		mtx_unlock_spin(&trace_mtx);
+	}
+out:
+#endif
  	WITNESS_UNLOCK(&m->mtx_object, opts | LOP_EXCLUSIVE, file, line);
 	LOCK_LOG_LOCK("UNLOCK", &m->mtx_object, opts, m->mtx_recurse, file,
 	    line);
Index: sys/kern/kern_shutdown.c
===================================================================
RCS file: /home/ncvs/src/sys/kern/kern_shutdown.c,v
retrieving revision 1.120
diff -u -r1.120 kern_shutdown.c
--- sys/kern/kern_shutdown.c	7 Mar 2002 04:43:51 -0000	1.120
+++ sys/kern/kern_shutdown.c	13 Mar 2002 00:52:56 -0000
@@ -51,6 +51,7 @@
 #include <sys/conf.h>
 #include <sys/cons.h>
 #include <sys/disklabel.h>
+#include <sys/dump.h>
 #include <sys/eventhandler.h>
 #include <sys/kernel.h>
 #include <sys/kthread.h>
@@ -59,9 +60,11 @@
 #include <sys/proc.h>
 #include <sys/reboot.h>
 #include <sys/resourcevar.h>
+#include <sys/sbuf.h>
 #include <sys/smp.h>		/* smp_active */
 #include <sys/sysctl.h>
 #include <sys/sysproto.h>
+#include <sys/timetc.h>
 #include <sys/vnode.h>
 
 #include <machine/pcb.h>
@@ -116,7 +119,9 @@
  */
 const char *panicstr;
 
-int dumping;				 /* system is dumping */
+int dumping;			/* System is dumping */
+long dumplo;			/* Dump offset */
+char dumpinfo[DUMPINFO_SIZE];	/* Dump metadata */
 
 static void boot(int) __dead2;
 static void dumpsys(void);
@@ -207,7 +212,7 @@
 }
 
 /*
- *  Go through the rigmarole of shutting down..
+ * Go through the rigmarole of shutting down..
  * this used to be in machdep.c but I'll be dammned if I could see
  * anything machine dependant in it.
  */
@@ -444,9 +449,15 @@
 	if (psize == -1)
 		return (ENXIO);		/* XXX should be ENODEV ? */
 	/*
-	 * XXX should clean up checking in dumpsys() to be more like this.
+	 * Determine the dump offset.  Place it as high as possible on the
+	 * dump device, so it will survive a certain amount of swapping
+	 * before savecore(1) runs, and reserve enough space for all
+	 * physical memory, plus an extra page for metadata.
 	 */
-	newdumplo = psize - Maxmem * (PAGE_SIZE / DEV_BSIZE);
+	/*
+	 * XXX what happens if the device's sector size != DEV_BSIZE?
+	 */
+	newdumplo = psize - DUMP_SECS(DEV_BSIZE);
 	if (newdumplo <= LABELSECTOR)
 		return (ENOSPC);
 	dumpdev = dev;
@@ -490,6 +501,7 @@
 
 SYSCTL_PROC(_kern, KERN_DUMPDEV, dumpdev, CTLTYPE_OPAQUE|CTLFLAG_RW,
 	0, sizeof dumpdev, sysctl_kern_dumpdev, "T,dev_t", "");
+extern void *kernbase;
 
 /*
  * Doadump comes here after turning off memory management and
@@ -499,7 +511,22 @@
 static void
 dumpsys(void)
 {
-	int	error;
+	struct sbuf sb;
+	int error;
+
+	sbuf_new(&sb, dumpinfo, DUMPINFO_SIZE, SBUF_FIXEDLEN);
+	/* magic + length of dump metadata */
+	sbuf_printf(&sb, "DUMPINFO 0x%x\n", DUMPINFO_SIZE);
+	sbuf_printf(&sb, "dumpinfo_version=%d\n", DUMPINFO_VERSION);
+	sbuf_printf(&sb, "dumpinfo_size=0x%x\n", DUMPINFO_SIZE);
+	sbuf_printf(&sb, "page_size=0x%x\n", PAGE_SIZE);
+	sbuf_printf(&sb, "dev_bsize=0x%x\n", DEV_BSIZE);
+	sbuf_printf(&sb, "dumplo=0x%lx\n", dumplo);
+	sbuf_printf(&sb, "kernbase=0x%p\n", kernbase);
+	sbuf_printf(&sb, "dumptime=0x%lx\n", timecounter->tc_microtime.tv_sec);
+	sbuf_printf(&sb, "@0x0 0x%x\n", Maxmem);
+	sbuf_finish(&sb);
+	printf(dumpinfo);
 
 	savectx(&dumppcb);
 	if (!dodump)
Index: sys/kern/subr_disk.c
===================================================================
RCS file: /home/ncvs/src/sys/kern/subr_disk.c,v
retrieving revision 1.52
diff -u -r1.52 subr_disk.c
--- sys/kern/subr_disk.c	11 Mar 2002 08:08:02 -0000	1.52
+++ sys/kern/subr_disk.c	15 Mar 2002 20:35:43 -0000
@@ -15,6 +15,7 @@
 
 #include <sys/param.h>
 #include <sys/systm.h>
+#include <sys/dump.h>
 #include <sys/kernel.h>
 #include <sys/sysctl.h>
 #include <sys/bio.h>
@@ -213,7 +214,7 @@
 	dl = dsgetlabel(dev, dp->d_slice);
 	if (!dl)
 		return (ENXIO);
-	*count = Maxmem * (PAGE_SIZE / dl->d_secsize);
+	*count = DUMP_SECS(dl->d_secsize);
 	if (dumplo <= LABELSECTOR || 
 	    (dumplo + *count > dl->d_partitions[dkpart(dev)].p_size))
 		return (EINVAL);
Index: sys/kern/subr_witness.c
===================================================================
RCS file: /home/ncvs/src/sys/kern/subr_witness.c,v
retrieving revision 1.103
diff -u -r1.103 subr_witness.c
--- sys/kern/subr_witness.c	27 Mar 2002 09:23:38 -0000	1.103
+++ sys/kern/subr_witness.c	30 Mar 2002 15:06:27 -0000
@@ -214,6 +214,7 @@
 	{ "ithread table lock", &lock_class_mtx_spin },
 	{ "sched lock", &lock_class_mtx_spin },
 	{ "callout", &lock_class_mtx_spin },
+	{ "bio queue", &lock_class_mtx_spin },
 	/*
 	 * leaf locks
 	 */
Index: sys/pc98/i386/machdep.c
===================================================================
RCS file: /home/ncvs/src/sys/pc98/i386/machdep.c,v
retrieving revision 1.270
diff -u -r1.270 machdep.c
--- sys/pc98/i386/machdep.c	30 Mar 2002 11:14:52 -0000	1.270
+++ sys/pc98/i386/machdep.c	30 Mar 2002 15:07:00 -0000
@@ -209,7 +209,6 @@
 #ifdef PC98
 int Maxmem_under16M = 0;
 #endif
-long dumplo;
 
 vm_offset_t phys_avail[10];
 
Index: sys/sparc64/sparc64/machdep.c
===================================================================
RCS file: /home/ncvs/src/sys/sparc64/sparc64/machdep.c,v
retrieving revision 1.44
diff -u -r1.44 machdep.c
--- sys/sparc64/sparc64/machdep.c	30 Mar 2002 20:58:08 -0000	1.44
+++ sys/sparc64/sparc64/machdep.c	31 Mar 2002 00:37:10 -0000
@@ -112,7 +112,6 @@
 
 int physmem;
 int cold = 1;
-long dumplo;
 int Maxmem;
 
 struct mtx Giant;
Index: sys/sys/_mutex.h
===================================================================
RCS file: /home/ncvs/src/sys/sys/_mutex.h,v
retrieving revision 1.4
diff -u -r1.4 _mutex.h
--- sys/sys/_mutex.h	18 Dec 2001 00:27:18 -0000	1.4
+++ sys/sys/_mutex.h	23 Mar 2002 17:41:05 -0000
@@ -41,6 +41,10 @@
 	volatile u_int mtx_recurse;	/* number of recursive holds */
 	TAILQ_HEAD(, thread) mtx_blocked;	/* threads blocked on this lock */
 	LIST_ENTRY(mtx)	mtx_contested;	/* list of all contested locks */
+#ifdef	TRACE_MUTEX_TIME
+	u_int64_t tsc;
+	char name[64];
+#endif
 };
 
 #endif /* !_SYS_MUTEX_TYPES_H_ */
Index: sys/sys/systm.h
===================================================================
RCS file: /home/ncvs/src/sys/sys/systm.h,v
retrieving revision 1.167
diff -u -r1.167 systm.h
--- sys/sys/systm.h	30 Mar 2002 19:58:31 -0000	1.167
+++ sys/sys/systm.h	31 Mar 2002 00:37:12 -0000
@@ -62,9 +62,6 @@
 
 extern int physmem;		/* physical memory */
 
-extern dev_t dumpdev;		/* dump device */
-extern long dumplo;		/* offset into dumpdev */
-
 extern dev_t rootdev;		/* root device */
 extern dev_t rootdevs[2];	/* possible root devices */
 extern char *rootdevnames[2];	/* names of possible root devices */
help

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