#!/usr/local/bin/cbsd
#v11.1.17
MYARG=""
MYOPTARG=""
MYDESC="Show cpu topology"
CBSDMODULE="sys"

. ${subrdir}/nc.subr
. ${cbsdinit}

cpu_topology_in_ascii_art()
{
	local cores_per_sock=0

	cores_per_sock=$(( cores_max / sockets_num ))

	# CPU pinning still in WIP, so at the moment all vm/jails
	# use all cores: get all list
	local jail_list=$( jorder )
	local bhyve_list=$( border )

	[ -z "${jail_list}" -a -z "${bhyve_list}" ] && jail_list="no any environments"

	for i in $( ${SEQ_CMD} 1 ${sockets_num} ); do

		socket_id=$(( i - 1 ))

		eval _mythreads="\$threads_by_socket${socket_id}"
		eval _mycores="\$cores_by_socket${socket_id}"

		${ECHO} "${H3_COLOR}Socket ${socket_id}:${N0_COLOR}"
		${ECHO} "+-----------------------+"
		${ECHO} "|			|"
		for x in ${_mythreads}; do
			[ -n "${jail_list}" ] && ${ECHO} "|   ${N2_COLOR}core ${x} (THR)${N0_COLOR}	| - ${N2_COLOR}Jails:${jail_list}${N0_COLOR}"
			[ -n "${bhyve_list}" ] && ${ECHO} "|   ${H2_COLOR}core ${x} (THR)${N0_COLOR}	| - ${H2_COLOR}Bhyve:${bhyve_list}${N0_COLOR}"
		done
		for x in ${_mycores}; do
			[ -n "${jail_list}" ] && ${ECHO} "|   ${N2_COLOR}core ${x} (SMT)${N0_COLOR}	| - ${N2_COLOR}Jails:${jail_list}${N0_COLOR}"
			[ -n "${bhyve_list}" ] && ${ECHO} "|   ${H2_COLOR}core ${x} (SMT)${N0_COLOR}	| - ${H2_COLOR}Bhyve:${bhyve_list}${N0_COLOR}"
		done
		${ECHO} "|			|"
		${ECHO} "+-----------------------+"
	done
}

NDOMAINS=$( ${SYSCTL_CMD} -qn vm.ndomains 2>/dev/null )
[ -z "${NDOMAINS}" ] && NDOMAINS="0"				# x86 only?

${SYSCTL_CMD} -qn kern.sched.topology_spec > ${tmpdir}/top.$$
trap "${RM_CMD} -f ${tmpdir}/top.$$" HUP INT ABRT BUS TERM EXIT

sockets_num=
cores_num=
threads_num=
cores_max=

eval $( ${miscdir}/dump_cpu_topology ${tmpdir}/top.$$ 2>/dev/null )

#sockets_num="2"
#cores_num="8"
#threads_num="8"
#cores_max="16"
#cores_by_socket0="6 4 2 0 "
#threads_by_socket0="7 5 3 1 "
#cores_by_socket1="14 12 10 8 "
#threads_by_socket1="15 13 11 9 "

[ -z "${cores_max}" ] && err 1 "${N1_COLOR}${CBSD_APP} error: unknown cores_max${N0_COLOR}"
[ -z "${sockets_num}" ] && err 1 "${N1_COLOR}${CBSD_APP} error: unknown sockets_num${N0_COLOR}"
[ "${sockets_num}" = "0" ] && err 1 "${N1_COLOR}${CBSD_APP} error: sockets_num=0${N0_COLOR}"

if is_number ${sockets_num}; then
	err 1 "${N1_COLOR}${CBSD_APP} error: sockets_num is not number: ${N2_COLOR}[${sockets_num}]${N0_COLOR}"
fi
if is_number ${cores_max}; then
	err 1 "${N1_COLOR}${CBSD_APP} error: cores_max is not number: ${N2_COLOR}[${cores_max}]${N0_COLOR}"
fi

${ECHO} "${N1_COLOR}Model: ${N2_COLOR}${cpumodel}${N0_COLOR}"
${ECHO} "${N1_COLOR}Sockets num: ${N2_COLOR}${sockets_num}${N0_COLOR}"
${ECHO} "${N1_COLOR}Cores num: ${N2_COLOR}${cores_num}${N0_COLOR}"
${ECHO} "${N1_COLOR}Threads num: ${N2_COLOR}${threads_num}${N0_COLOR}"

if [ ${sockets_num} -gt 1 -a ${NDOMAINS} -lt 2 ]; then
	NUMA_INFO=" ${W1_COLOR}(but sockets > 1, NUMA not enabled in BIOS?)${N0_COLOR} "
fi
${ECHO} "${N1_COLOR}NUMA domains: ${N2_COLOR}${NDOMAINS}${NUMA_INFO}${N0_COLOR}"


${ECHO} "--"
${ECHO} "${N1_COLOR}Core max: ${N2_COLOR}${cores_max}${N0_COLOR}"

cpu_topology_in_ascii_art
