git: d96fccc50513 - main - epoch: with EPOCH_TRACE add epoch_where_report() which will report where the epoch was entered and also mark the tracker, so that exit will also be reported.

From: Gleb Smirnoff <glebius_at_FreeBSD.org>
Date: Thu, 02 Dec 2021 19:07:13 UTC
The branch main has been updated by glebius:

URL: https://cgit.FreeBSD.org/src/commit/?id=d96fccc50513b807c5ec5e880c2340c1efcb97c1

commit d96fccc50513b807c5ec5e880c2340c1efcb97c1
Author:     Gleb Smirnoff <glebius@FreeBSD.org>
AuthorDate: 2021-12-02 18:59:43 +0000
Commit:     Gleb Smirnoff <glebius@FreeBSD.org>
CommitDate: 2021-12-02 19:02:51 +0000

    epoch: with EPOCH_TRACE add epoch_where_report()
    which will report where the epoch was entered and also
    mark the tracker, so that exit will also be reported.
    
    Helps to understand epoch entrance/exit scenarios in
    complex cases, like network stack.  As everything else
    under EPOCH_TRACE it is a developer only tool.
---
 sys/kern/subr_epoch.c | 40 +++++++++++++++++++++++++++++++++-------
 sys/sys/epoch.h       |  3 +++
 2 files changed, 36 insertions(+), 7 deletions(-)

diff --git a/sys/kern/subr_epoch.c b/sys/kern/subr_epoch.c
index 651fd8b419f0..74524fb3f97e 100644
--- a/sys/kern/subr_epoch.c
+++ b/sys/kern/subr_epoch.c
@@ -147,6 +147,13 @@ static struct sx epoch_sx;
 #define	EPOCH_LOCK() sx_xlock(&epoch_sx)
 #define	EPOCH_UNLOCK() sx_xunlock(&epoch_sx)
 
+static epoch_record_t
+epoch_currecord(epoch_t epoch)
+{
+
+	return (zpcpu_get(epoch->e_pcpu_record));
+}
+
 #ifdef EPOCH_TRACE
 struct stackentry {
 	RB_ENTRY(stackentry) se_node;
@@ -230,6 +237,7 @@ epoch_trace_enter(struct thread *td, epoch_t epoch, epoch_tracker_t et,
 	et->et_epoch = epoch;
 	et->et_file = file;
 	et->et_line = line;
+	et->et_flags = 0;
 	SLIST_INSERT_HEAD(&td->td_epochs, et, et_tlink);
 }
 
@@ -250,6 +258,9 @@ epoch_trace_exit(struct thread *td, epoch_t epoch, epoch_tracker_t et,
 		SLIST_REMOVE(&td->td_epochs, et, epoch_tracker, et_tlink);
 	} else
 		SLIST_REMOVE_HEAD(&td->td_epochs, et_tlink);
+	if (et->et_flags & ET_REPORT_EXIT)
+		printf("Td %p exiting epoch %s at %s:%d\n", td, epoch->e_name,
+		    file, line);
 }
 
 /* Used by assertions that check thread state before going to sleep. */
@@ -262,6 +273,28 @@ epoch_trace_list(struct thread *td)
 		printf("Epoch %s entered at %s:%d\n", iet->et_epoch->e_name,
 		    iet->et_file, iet->et_line);
 }
+
+void
+epoch_where_report(epoch_t epoch)
+{
+	epoch_record_t er;
+	struct epoch_tracker *tdwait;
+
+	MPASS(epoch != NULL);
+	MPASS((epoch->e_flags & EPOCH_PREEMPT) != 0);
+	MPASS(!THREAD_CAN_SLEEP());
+	critical_enter();
+	er = epoch_currecord(epoch);
+	TAILQ_FOREACH(tdwait, &er->er_tdlist, et_link)
+		if (tdwait->et_td == curthread)
+			break;
+	critical_exit();
+	if (tdwait != NULL) {
+		tdwait->et_flags |= ET_REPORT_EXIT;
+		printf("Td %p entered epoch %s at %s:%d\n", curthread,
+		    epoch->e_name, tdwait->et_file, tdwait->et_line);
+	}
+}
 #endif /* EPOCH_TRACE */
 
 static void
@@ -422,13 +455,6 @@ epoch_free(epoch_t epoch)
 	EPOCH_UNLOCK();
 }
 
-static epoch_record_t
-epoch_currecord(epoch_t epoch)
-{
-
-	return (zpcpu_get(epoch->e_pcpu_record));
-}
-
 #define INIT_CHECK(epoch)					\
 	do {							\
 		if (__predict_false((epoch) == NULL))		\
diff --git a/sys/sys/epoch.h b/sys/sys/epoch.h
index 85c791d3df6c..6ce0fcd01c60 100644
--- a/sys/sys/epoch.h
+++ b/sys/sys/epoch.h
@@ -61,6 +61,8 @@ struct epoch_tracker {
 	SLIST_ENTRY(epoch_tracker) et_tlink;
 	const char *et_file;
 	int et_line;
+	int et_flags;
+#define	ET_REPORT_EXIT	0x1
 #endif
 }  __aligned(sizeof(void *));
 typedef struct epoch_tracker *epoch_tracker_t;
@@ -86,6 +88,7 @@ void _epoch_enter_preempt(epoch_t epoch, epoch_tracker_t et EPOCH_FILE_LINE);
 void _epoch_exit_preempt(epoch_t epoch, epoch_tracker_t et EPOCH_FILE_LINE);
 #ifdef EPOCH_TRACE
 void epoch_trace_list(struct thread *);
+void epoch_where_report(epoch_t);
 #define	epoch_enter_preempt(epoch, et)	_epoch_enter_preempt(epoch, et, __FILE__, __LINE__)
 #define	epoch_exit_preempt(epoch, et)	_epoch_exit_preempt(epoch, et, __FILE__, __LINE__)
 #else