#!/usr/local/bin/bash
#
# Get a CPU profile and save it into /ifs/profiles

usage()
{
    cat <<EOF
Usage: isi_get_profile [-C] [-m mode] [-r cmd] [-s stack] [name]
    -C			Capture continuously while command is running
    -m mode 		Capture using the given sampling mode
    -r cmd 		Run profile while executing cmd
    -s where,when,...	Capture the selected portion of the stack 

    Modes:
    cpu		Sample driven by hardclock interrupts [Default]
    pmc		Sample driven by NM pmc interrupts (instruction relative)
    mem		Sample driven by NM pmc interrupts (llc-miss relative)

    Stack:
    kernel	Capture the kernel stack		[Default]
    user	Capture the user space stack
    in-kernel	Capture when trap was in kernel mode	[Default]
    in-user	Capture when trap was in user mode
EOF
}

check_pmc()
{
    if kldstat -v | grep -q hwpmc; then
        return
    else
    	echo "isi_get_profile: Please load hwpmc.ko first"
    	exit 1
    fi
}

set_mode()
{
    case "$1" in
	cpu) PROFILE_CODE=2
	;;
	pmc) check_pmc; PROFILE_CODE=3
	;;
	mem) check_pmc; PROFILE_CODE=4
	;;
    esac
}

set_stack()
{
    STACK_CODE=0
    for a in ${1//,/ }; do
        case "$a" in
            kernel) STACK_CODE=$(( $STACK_CODE | 0x1 ))
            ;;
            user) STACK_CODE=$(( $STACK_CODE | 0x2 ))
            ;;
            in-kernel) STACK_CODE=$(( $STACK_CODE | 0x4 ))
            ;;
            in-user) STACK_CODE=$(( $STACK_CODE | 0x8 ))
            ;;
         esac
    done
}

# Begin

PROFILE_CODE=2
STACK_CODE=5
COMMAND="sleep 24"
sysctl debug.random_sampling_continuous=0 > /dev/null

while getopts 'Chm:r:s:' OPTION
do
  case $OPTION in
      C) sysctl debug.random_sampling_continuous=1 > /dev/null
      ;;
      h) usage; exit 1
      ;;
      s) set_stack "$OPTARG"
      ;;
      m) set_mode "$OPTARG"
      ;;
      r) COMMAND=$OPTARG
      ;;
  esac
done
shift $((OPTIND - 1))

echo -n "Starting profile..."
sysctl debug.random_sampling_stack_args=$STACK_CODE > /dev/null
sysctl debug.random_sampling=$PROFILE_CODE > /dev/null
$COMMAND
sysctl debug.random_sampling=0 > /dev/null

PROFNAME=$1
if [ "$PROFNAME" = "" ] ; then
    PROFNAME=unnamed
fi

FILENAME=${PROFNAME}_`hostname`_`date +"%b_%d_%H_%M_%S"`.ipr
CFILENAME=${FILENAME}.gz

if [ ! -d /ifs/profiles ]; then
    echo -n "making /ifs/profiles..."
    mkdir -p /ifs/profiles
fi

echo -n " saving..."
sysctl debug.dump_random_samples | gzip -c > /ifs/profiles/$CFILENAME

echo "done.  filename is /ifs/profiles/$CFILENAME"

sysctl debug.random_sampling_stack_args=5 > /dev/null
sysctl debug.random_sampling_continuous=0 > /dev/null

exit
