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.
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
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