Changeset View
Standalone View
sys/kern/kern_tslog.c
Show All 24 Lines | |||||
*/ | */ | ||||
#include <sys/cdefs.h> | #include <sys/cdefs.h> | ||||
__FBSDID("$FreeBSD$"); | __FBSDID("$FreeBSD$"); | ||||
#include <sys/param.h> | #include <sys/param.h> | ||||
#include <sys/kernel.h> | #include <sys/kernel.h> | ||||
#include <sys/linker.h> | #include <sys/linker.h> | ||||
#include <sys/malloc.h> | |||||
#include <sys/proc.h> | |||||
#include <sys/sbuf.h> | #include <sys/sbuf.h> | ||||
#include <sys/sysctl.h> | #include <sys/sysctl.h> | ||||
#include <sys/systm.h> | #include <sys/systm.h> | ||||
#include <sys/tslog.h> | #include <sys/tslog.h> | ||||
#include <machine/atomic.h> | #include <machine/atomic.h> | ||||
#include <machine/cpu.h> | #include <machine/cpu.h> | ||||
▲ Show 20 Lines • Show All 85 Lines • ▼ Show 20 Lines | sysctl_debug_tslog(SYSCTL_HANDLER_ARGS) | ||||
} | } | ||||
error = sbuf_finish(sb); | error = sbuf_finish(sb); | ||||
sbuf_delete(sb); | sbuf_delete(sb); | ||||
return (error); | return (error); | ||||
} | } | ||||
SYSCTL_PROC(_debug, OID_AUTO, tslog, CTLTYPE_STRING|CTLFLAG_RD|CTLFLAG_MPSAFE, | SYSCTL_PROC(_debug, OID_AUTO, tslog, CTLTYPE_STRING|CTLFLAG_RD|CTLFLAG_MPSAFE, | ||||
0, 0, sysctl_debug_tslog, "", "Dump recorded event timestamps"); | 0, 0, sysctl_debug_tslog, "", "Dump recorded event timestamps"); | ||||
MALLOC_DEFINE(M_TSLOGUSER, "tsloguser", "Strings used by userland tslog"); | |||||
static struct procdata { | |||||
pid_t ppid; | |||||
uint64_t tsc_forked; | |||||
uint64_t tsc_exited; | |||||
char * execname; | |||||
char * namei; | |||||
int reused; | |||||
} procs[PID_MAX + 1]; | |||||
void | |||||
tslog_user(pid_t pid, pid_t ppid, const char * execname, const char * namei) | |||||
{ | |||||
uint64_t tsc = get_cyclecount(); | |||||
/* If we wrapped, do nothing. */ | |||||
if (procs[pid].reused) | |||||
return; | |||||
/* If we have a ppid, we're recording a fork. */ | |||||
if (ppid != (pid_t)(-1)) { | |||||
/* If we have a ppid already, we wrapped. */ | |||||
if (procs[pid].ppid) { | |||||
procs[pid].reused = 1; | |||||
return; | |||||
} | |||||
/* Fill in some fields. */ | |||||
procs[pid].ppid = ppid; | |||||
procs[pid].tsc_forked = tsc; | |||||
return; | |||||
} | |||||
/* If we have an execname, record it. */ | |||||
if (execname != NULL) { | |||||
mhorne: style(9) prefers explicit `execname != NULL`. | |||||
Done Inline ActionsThanks, will fix. cperciva: Thanks, will fix. | |||||
if (procs[pid].execname == NULL) | |||||
procs[pid].execname = strdup(execname, M_TSLOGUSER); | |||||
return; | |||||
} | |||||
/* Record the first namei for the process. */ | |||||
if (namei != NULL) { | |||||
if (procs[pid].namei == NULL) | |||||
procs[pid].namei = strdup(namei, M_TSLOGUSER); | |||||
return; | |||||
} | |||||
/* Otherwise we're recording an exit. */ | |||||
procs[pid].tsc_exited = tsc; | |||||
Not Done Inline ActionsIt is somewhat strange to have a function that performs four independent actions depending on the arguments provided, but I think its fine given the simplicity. mhorne: It is somewhat strange to have a function that performs four independent actions depending on… | |||||
Done Inline ActionsYeah I considered making it separate functions, but having a single interface had the advantage of simplifying the macro logic in sys/tslog.h which makes everything vanish when the kernel doesn't have options TSLOG. cperciva: Yeah I considered making it separate functions, but having a single interface had the advantage… | |||||
} | |||||
static int | |||||
sysctl_debug_tslog_user(SYSCTL_HANDLER_ARGS) | |||||
{ | |||||
int error; | |||||
struct sbuf *sb; | |||||
pid_t pid; | |||||
sb = sbuf_new_for_sysctl(NULL, NULL, 1024, req); | |||||
/* Export the data we logged. */ | |||||
Not Done Inline ActionsThis check should be against pid_max, given that it is tunable with kern.pid_max. mhorne: This check should be against `pid_max`, given that it is tunable with `kern.pid_max`. | |||||
Done Inline ActionsHmm, we have a static buffer, though -- static struct procdata { ... } procs[PID_MAX + 1]. I guess that could be allocated at runtime -- but since we probably only care about the first thousand-ish pids, it seems like unnecessary complication. cperciva: Hmm, we have a static buffer, though -- `static struct procdata { ... } procs[PID_MAX + 1]`. I… | |||||
Not Done Inline ActionsI don't think the buffer needs to be allocated dynamically, since it is behind options TSLOG. I also doubt anyone would run tslog AND set the tunable, but in this odd case checking pid_max would avoid dumping the entries which are guaranteed to be empty. I'll leave it up to you. mhorne: I don't think the buffer needs to be allocated dynamically, since it is behind `options TSLOG`. | |||||
for (pid = 0; pid <= PID_MAX; pid++) { | |||||
sbuf_printf(sb, "%zu", (size_t)pid); | |||||
sbuf_printf(sb, " %zu", (size_t)procs[pid].ppid); | |||||
sbuf_printf(sb, " %llu", | |||||
Not Done Inline ActionsNit: %ju and uintmax_t are typically preferred for this type of thing. mhorne: Nit: `%ju` and `uintmax_t` are typically preferred for this type of thing. | |||||
Done Inline ActionsI'm using %lld for other 64-bit cycle counts in this file, so since this should work on all platforms I'd prefer to stay consistent. cperciva: I'm using `%lld` for other 64-bit cycle counts in this file, so since this should work on all… | |||||
Not Done Inline ActionsSounds good. mhorne: Sounds good. | |||||
(unsigned long long)procs[pid].tsc_forked); | |||||
sbuf_printf(sb, " %llu", | |||||
(unsigned long long)procs[pid].tsc_exited); | |||||
sbuf_printf(sb, " \"%s\"", procs[pid].execname ? | |||||
procs[pid].execname : ""); | |||||
sbuf_printf(sb, " \"%s\"", procs[pid].namei ? | |||||
procs[pid].namei : ""); | |||||
sbuf_printf(sb, "\n"); | |||||
} | |||||
error = sbuf_finish(sb); | |||||
sbuf_delete(sb); | |||||
return (error); | |||||
} | |||||
SYSCTL_PROC(_debug, OID_AUTO, tslog_user, | |||||
CTLTYPE_STRING|CTLFLAG_RD|CTLFLAG_MPSAFE, 0, 0, sysctl_debug_tslog_user, | |||||
"", "Dump recorded userland event timestamps"); |
style(9) prefers explicit execname != NULL.