# -*- tab-width: 4 -*- ;; Emacs # vi: set filetype=sh tabstop=8 shiftwidth=8 noexpandtab :: Vi/ViM ############################################################ IDENT(1) # # $Title: dwatch(8) module for malloc(9) type activity $ # $Copyright: 2026 Devin Teske. All rights reserved. $ # ############################################################ DESCRIPTION # # Print kernel malloc(9) and free(9) activity by malloc type, via the # dtmalloc provider (one malloc and one free probe per type; see # vmstat -m for the types). The default profile prints allocations and # frees meeting a size threshold (default 65536 bytes; tunable via # DWATCH_MALLOC_MIN in the environment, 0 to show everything), # answering "who is allocating huge kernel buffers?" Use # dtmalloc-NAME to watch a single type (e.g., dtmalloc-devbuf). # The dtmalloc-top profile maintains a running catalog, updated every # 3 seconds, of net bytes and outstanding allocation balance by type: # a type whose net bytes climb without bound while the system is in # steady state is a leak suspect. NB: the catalog reflects activity # since the watch began, not preexisting allocations, and caches # legitimately hold what they allocate. # ############################################################ PRAGMAS case "$PROFILE" in dtmalloc-top) DTRACE_PRAGMA=" option quiet option aggsortrev " # END-QUOTE ;; esac ############################################################ PROBE case "$PROFILE" in dtmalloc) : ${PROBE:=dtmalloc:::malloc, dtmalloc:::free} ;; dtmalloc-top) : ${PROBE:=profile:::tick-3s} ;; *) : ${PROBE:=$( echo \ dtmalloc::${PROFILE#dtmalloc-}:malloc, \ dtmalloc::${PROFILE#dtmalloc-}:free )} ;; esac ############################################################ EVENT ACTION : ${DWATCH_MALLOC_MIN:=65536} case "$DWATCH_MALLOC_MIN" in ""|*[!0-9]*) die "DWATCH_MALLOC_MIN must be a number" ;; # NOTREACHED esac [ "$CUSTOM_TEST" ] || case "$PROFILE" in dtmalloc-top) ;; *) EVENT_TEST="(uint64_t)arg3 >= $DWATCH_MALLOC_MIN" esac ############################################################ ACTIONS if [ "$PROFILE" = "dtmalloc-top" ]; then exec 9<dtmalloc_delta = (int64_t)arg3; } dtmalloc:::free /* probe ID $(( $ID + 2 )) */ { this->dtmalloc_delta = -(int64_t)arg3; } dtmalloc:::malloc, dtmalloc:::free /* probe ID $(( $ID + 3 )) */ { @dtmalloc_bytes[probefunc] = sum(this->dtmalloc_delta); @dtmalloc_allocs[probefunc] = sum(this->dtmalloc_delta > 0 ? 1 : -1); } EOF ACTIONS=$( cat <&9 ) ID=$(( $ID + 4 )) fi ############################################################ EVENT TAG # For the running catalog, override the default `UID.GID CMD[PID]: ' tag # with ANSI cursor-homing and screen-clearing codes plus column headers. if [ "$PROFILE" = "dtmalloc-top" ]; then size=$( stty size 2> /dev/null ) rows="${size%% *}" cols="${size#* }" exec 9<