The branch main has been updated by glebius:

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

commit d96fccc50513b807c5ec5e880c2340c1efcb97c1
Author:     Gleb Smirnoff <[email protected]>
AuthorDate: 2021-12-02 18:59:43 +0000
Commit:     Gleb Smirnoff <[email protected]>
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

Reply via email to