ktrace and KTR_DROP

Peter Edwards peadar.edwards at gmail.com
Sun Jul 3 18:19:21 GMT 2005


> login: panic: ktrace: no trace vnode
> cpuid = 1
> KDB: stack backtrace:
> kdb_backtrace(100,c6c0b000,c65e08d4,c5d4ae80,c6c0b000) at 0xc053efa9 = kdb_backtrace+0x29
> panic(c06bec25,8,2,c717e180,ec519cd8) at 0xc0529174 = panic+0x114
> ktr_getrequest(1,0,c6c0b000,c65e08d4,ec519d30) at 0xc051aa7b = ktr_getrequest+0xf3
> ktrsyscall(bd,2,ec519d04) at 0xc051ad7f = ktrsyscall+0x3b
> syscall(2f,2f,2f,280ee000,0) at 0xc0680329 = syscall+0x155
> Xint0x80_syscall() at 0xc066fcff = Xint0x80_syscall+0x1f
> --- syscall (189, FreeBSD ELF32, fstat), eip = 0x280cea23, esp = 0xbfbfe9f0, ebp = 0xbfbfea8c ---
> boot() called on cpu#0
> Uptime: 17m39s
> Dumping 3967 MB
>  16 32 48 64 80 96 112 128 144 160 176 192 208 224 240 256 272 288 304 320 336 352 368 384 400 416 432 448 464 480 496 512 528 544 560 576 592 608 624 640 656 672 688 704 720 736 752 768 784 800 816 832 848 864 880 896 912 928 944 960 976 992 1008 1024 1040 1056 1072 1088 1104 1120 1136 1152 1168 1184 1200 1216 ...


This pointed out at least one fault in the patch: the conditions
tested by KTRCHECK() can be changed after dropping the lock in
cv_wait(). More testing to come, but this version is an improvement.
-------------- next part --------------
Index: kern/kern_ktrace.c
===================================================================
RCS file: /usr/cvs/FreeBSD-CVS/src/sys/kern/kern_ktrace.c,v
retrieving revision 1.101
diff -u -r1.101 kern_ktrace.c
--- kern/kern_ktrace.c	24 Jun 2005 12:05:24 -0000	1.101
+++ kern/kern_ktrace.c	3 Jul 2005 18:16:24 -0000
@@ -100,9 +100,15 @@
 SYSCTL_UINT(_kern_ktrace, OID_AUTO, genio_size, CTLFLAG_RW, &ktr_geniosize,
     0, "Maximum size of genio event payload");
 
+static int ktr_neverdrop = 0;
+SYSCTL_UINT(_kern_ktrace, OID_AUTO, neverdrop, CTLFLAG_RW, &ktr_neverdrop,
+    0, "Wait for free resources rather than dropping events ");
+
 static int print_message = 1;
 struct mtx ktrace_mtx;
-static struct cv ktrace_cv;
+static struct cv ktrace_todo_cv; /* service thread waiting for work */
+static struct cv ktrace_freeq_cv; /* threads waiting for free requests */
+static int ktrace_free_waiters = 0; /* No. of threads waiting on freeq_cv */
 
 static void ktrace_init(void *dummy);
 static int sysctl_kern_ktrace_request_pool(SYSCTL_HANDLER_ARGS);
@@ -123,7 +129,8 @@
 	int i;
 
 	mtx_init(&ktrace_mtx, "ktrace", NULL, MTX_DEF | MTX_QUIET);
-	cv_init(&ktrace_cv, "ktrace");
+	cv_init(&ktrace_todo_cv, "ktrace.todo");
+	cv_init(&ktrace_freeq_cv, "ktrace.freeq");
 	STAILQ_INIT(&ktr_todo);
 	STAILQ_INIT(&ktr_free);
 	for (i = 0; i < ktr_requestpool; i++) {
@@ -200,6 +207,8 @@
 			    M_WAITOK);
 			mtx_lock(&ktrace_mtx);
 			STAILQ_INSERT_HEAD(&ktr_free, req, ktr_list);
+			if (ktrace_free_waiters)
+				cv_signal(&ktrace_freeq_cv);
 			ktr_requestpool++;
 		}
 	return (ktr_requestpool);
@@ -215,12 +224,21 @@
 
 	td->td_pflags |= TDP_INKTRACE;
 	mtx_lock(&ktrace_mtx);
+	for (;;) {
+		req = STAILQ_FIRST(&ktr_free);
+		if (req != 0 || ktr_neverdrop == 0)
+			break;
+		ktrace_free_waiters++;
+		cv_wait(&ktrace_freeq_cv, &ktrace_mtx);
+		ktrace_free_waiters--;
+	}
+
 	if (!KTRCHECK(td, type)) {
 		mtx_unlock(&ktrace_mtx);
 		td->td_pflags &= ~TDP_INKTRACE;
 		return (NULL);
 	}
-	req = STAILQ_FIRST(&ktr_free);
+
 	if (req != NULL) {
 		STAILQ_REMOVE_HEAD(&ktr_free, ktr_list);
 		req->ktr_header.ktr_type = type;
@@ -257,7 +275,7 @@
 
 	mtx_lock(&ktrace_mtx);
 	STAILQ_INSERT_TAIL(&ktr_todo, req, ktr_list);
-	cv_signal(&ktrace_cv);
+	cv_signal(&ktrace_todo_cv);
 	mtx_unlock(&ktrace_mtx);
 	curthread->td_pflags &= ~TDP_INKTRACE;
 }
@@ -276,6 +294,8 @@
 		free(req->ktr_header.ktr_buffer, M_KTRACE);
 	mtx_lock(&ktrace_mtx);
 	STAILQ_INSERT_HEAD(&ktr_free, req, ktr_list);
+	if (ktrace_free_waiters)
+		cv_signal(&ktrace_freeq_cv);
 	mtx_unlock(&ktrace_mtx);
 }
 
@@ -292,7 +312,7 @@
 	for (;;) {
 		mtx_lock(&ktrace_mtx);
 		while (STAILQ_EMPTY(&ktr_todo))
-			cv_wait(&ktrace_cv, &ktrace_mtx);
+			cv_wait(&ktrace_todo_cv, &ktrace_mtx);
 		req = STAILQ_FIRST(&ktr_todo);
 		STAILQ_REMOVE_HEAD(&ktr_todo, ktr_list);
 		KASSERT(req != NULL, ("got a NULL request"));


More information about the freebsd-arch mailing list