Changeset View
Changeset View
Standalone View
Standalone View
sys/kern/subr_epoch.c
Show First 20 Lines • Show All 163 Lines • ▼ Show 20 Lines | |||||
} | } | ||||
RB_HEAD(stacktree, stackentry) epoch_stacks = RB_INITIALIZER(&epoch_stacks); | RB_HEAD(stacktree, stackentry) epoch_stacks = RB_INITIALIZER(&epoch_stacks); | ||||
RB_GENERATE_STATIC(stacktree, stackentry, se_node, stackentry_compare); | RB_GENERATE_STATIC(stacktree, stackentry, se_node, stackentry_compare); | ||||
static struct mtx epoch_stacks_lock; | static struct mtx epoch_stacks_lock; | ||||
MTX_SYSINIT(epochstacks, &epoch_stacks_lock, "epoch_stacks", MTX_DEF); | MTX_SYSINIT(epochstacks, &epoch_stacks_lock, "epoch_stacks", MTX_DEF); | ||||
static bool epoch_trace_stack_print = true; | |||||
SYSCTL_BOOL(_kern_epoch, OID_AUTO, trace_stack_print, CTLFLAG_RWTUN, | |||||
&epoch_trace_stack_print, 0, "Print stack traces on epoch reports"); | |||||
static void epoch_trace_report(const char *fmt, ...) __printflike(1, 2); | static void epoch_trace_report(const char *fmt, ...) __printflike(1, 2); | ||||
static inline void | static inline void | ||||
epoch_trace_report(const char *fmt, ...) | epoch_trace_report(const char *fmt, ...) | ||||
{ | { | ||||
va_list ap; | va_list ap; | ||||
struct stackentry se, *new; | struct stackentry se, *new; | ||||
stack_zero(&se.se_stack); /* XXX: is it really needed? */ | stack_zero(&se.se_stack); /* XXX: is it really needed? */ | ||||
Show All 12 Lines | if (new != NULL) { | ||||
mtx_unlock(&epoch_stacks_lock); | mtx_unlock(&epoch_stacks_lock); | ||||
if (new != NULL) | if (new != NULL) | ||||
free(new, M_STACK); | free(new, M_STACK); | ||||
} | } | ||||
va_start(ap, fmt); | va_start(ap, fmt); | ||||
(void)vprintf(fmt, ap); | (void)vprintf(fmt, ap); | ||||
va_end(ap); | va_end(ap); | ||||
if (epoch_trace_stack_print) | |||||
stack_print_ddb(&se.se_stack); | stack_print_ddb(&se.se_stack); | ||||
} | } | ||||
static inline void | static inline void | ||||
epoch_trace_enter(struct thread *td, epoch_t epoch, epoch_tracker_t et, | epoch_trace_enter(struct thread *td, epoch_t epoch, epoch_tracker_t et, | ||||
const char *file, int line) | const char *file, int line) | ||||
{ | { | ||||
epoch_tracker_t iet; | epoch_tracker_t iet; | ||||
SLIST_FOREACH(iet, &td->td_epochs, et_tlink) | SLIST_FOREACH(iet, &td->td_epochs, et_tlink) | ||||
if (iet->et_epoch == epoch) | if (iet->et_epoch == epoch) | ||||
epoch_trace_report("Recursively entering epoch %s " | epoch_trace_report("Recursively entering epoch %s " | ||||
"previously entered at %s:%d\n", | "at %s:%d, previously entered at %s:%d\n", | ||||
epoch->e_name, iet->et_file, iet->et_line); | epoch->e_name, file, line, | ||||
iet->et_file, iet->et_line); | |||||
et->et_epoch = epoch; | et->et_epoch = epoch; | ||||
et->et_file = file; | et->et_file = file; | ||||
et->et_line = line; | et->et_line = line; | ||||
SLIST_INSERT_HEAD(&td->td_epochs, et, et_tlink); | SLIST_INSERT_HEAD(&td->td_epochs, et, et_tlink); | ||||
} | } | ||||
static inline void | static inline void | ||||
epoch_trace_exit(struct thread *td, epoch_t epoch, epoch_tracker_t et, | epoch_trace_exit(struct thread *td, epoch_t epoch, epoch_tracker_t et, | ||||
const char *file, int line) | const char *file, int line) | ||||
{ | { | ||||
if (SLIST_FIRST(&td->td_epochs) != et) { | if (SLIST_FIRST(&td->td_epochs) != et) { | ||||
epoch_trace_report("Exiting epoch %s in a not nested order. " | epoch_trace_report("Exiting epoch %s in a not nested order " | ||||
"Most recently entered %s at %s:%d\n", | "at %s:%d. Most recently entered %s at %s:%d\n", | ||||
epoch->e_name, | epoch->e_name, | ||||
file, line, | |||||
SLIST_FIRST(&td->td_epochs)->et_epoch->e_name, | SLIST_FIRST(&td->td_epochs)->et_epoch->e_name, | ||||
SLIST_FIRST(&td->td_epochs)->et_file, | SLIST_FIRST(&td->td_epochs)->et_file, | ||||
SLIST_FIRST(&td->td_epochs)->et_line); | SLIST_FIRST(&td->td_epochs)->et_line); | ||||
/* This will panic if et is not anywhere on td_epochs. */ | /* This will panic if et is not anywhere on td_epochs. */ | ||||
SLIST_REMOVE(&td->td_epochs, et, epoch_tracker, et_tlink); | SLIST_REMOVE(&td->td_epochs, et, epoch_tracker, et_tlink); | ||||
} else | } else | ||||
SLIST_REMOVE_HEAD(&td->td_epochs, et_tlink); | SLIST_REMOVE_HEAD(&td->td_epochs, et_tlink); | ||||
} | } | ||||
▲ Show 20 Lines • Show All 604 Lines • Show Last 20 Lines |