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.
This commit is contained in:
parent
9e93d2b335
commit
d96fccc505
@ -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)) \
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user