Skip to content

Preliminary support for NVIDIA Jetson boards #1692

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 29 additions & 0 deletions Action.c
Original file line number Diff line number Diff line change
Expand Up @@ -646,6 +646,29 @@ static Htop_Reaction actionTogglePauseUpdate(State* st) {
return HTOP_REFRESH | HTOP_REDRAW_BAR | HTOP_KEEP_FOLLOWING;
}

#ifdef NVIDIA_JETSON
#include "NvidiaJetson.h"
#include "ProcessTable.h"

static Htop_Reaction actionToggleGpuFilter(State* st) {
static Hashtable *stash = NULL;

Hashtable *GpuPidMatchList = NvidiaJetson_GetPidMatchList();
if (GpuPidMatchList) {
st->showGpuProcesses = !st->showGpuProcesses;

ProcessTable *pt = (ProcessTable *)st->host->activeTable;
if (st->showGpuProcesses) {
stash = pt->pidMatchList;
pt->pidMatchList = GpuPidMatchList;
} else {
pt->pidMatchList = stash;
}
}
return HTOP_REFRESH | HTOP_REDRAW_BAR | HTOP_KEEP_FOLLOWING;
}
#endif

static const struct {
const char* key;
bool roInactive;
Expand All @@ -658,6 +681,9 @@ static const struct {
{ .key = " F3 /: ", .roInactive = false, .info = "incremental name search" },
{ .key = " F4 \\: ", .roInactive = false, .info = "incremental name filtering" },
{ .key = " F5 t: ", .roInactive = false, .info = "tree view" },
#ifdef NVIDIA_JETSON
{ .key = " g: ", .roInactive = false, .info = "show GPU processes (root only)" },
#endif
{ .key = " p: ", .roInactive = false, .info = "toggle program path" },
{ .key = " m: ", .roInactive = false, .info = "toggle merged command" },
{ .key = " Z: ", .roInactive = false, .info = "pause/resume process updates" },
Expand Down Expand Up @@ -933,6 +959,9 @@ void Action_setBindings(Htop_Action* keys) {
keys['a'] = actionSetAffinity;
keys['c'] = actionTagAllChildren;
keys['e'] = actionShowEnvScreen;
#ifdef NVIDIA_JETSON
keys['g'] = actionToggleGpuFilter;
#endif
keys['h'] = actionHelp;
keys['k'] = actionKill;
keys['l'] = actionLsof;
Expand Down
3 changes: 3 additions & 0 deletions Action.h
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,9 @@ typedef struct State_ {
bool pauseUpdate;
bool hideSelection;
bool hideMeters;
#ifdef NVIDIA_JETSON
bool showGpuProcesses;
#endif
} State;

static inline bool State_hideFunctionBar(const State* st) {
Expand Down
15 changes: 14 additions & 1 deletion CPUMeter.c
Original file line number Diff line number Diff line change
Expand Up @@ -98,17 +98,30 @@ static void CPUMeter_updateValues(Meter* this) {
}
}

#ifdef NVIDIA_JETSON
if (settings->showCPUTemperature) {
char c = 'C';
double cpuTemperature = this->values[CPU_METER_TEMPERATURE];
if (settings->degreeFahrenheit) {
c = 'F';
cpuTemperature = ConvCelsiusToFahrenheit(cpuTemperature);
}
/* snprintf correctly represents double NAN numbers as 'nan' */
xSnprintf(cpuTemperatureBuffer, sizeof(cpuTemperatureBuffer), "%.1f%s%c", cpuTemperature, CRT_degreeSign, c);
}
#else
#ifdef BUILD_WITH_CPU_TEMP
if (settings->showCPUTemperature) {
double cpuTemperature = this->values[CPU_METER_TEMPERATURE];
if (isNaN(cpuTemperature))
xSnprintf(cpuTemperatureBuffer, sizeof(cpuTemperatureBuffer), "N/A");
else if (settings->degreeFahrenheit)
xSnprintf(cpuTemperatureBuffer, sizeof(cpuTemperatureBuffer), "%3d%sF", (int)(cpuTemperature * 9 / 5 + 32), CRT_degreeSign);
xSnprintf(cpuTemperatureBuffer, sizeof(cpuTemperatureBuffer), "%3d%sF", (int)(ConvCelsiusToFahrenheit(cpuTemperature)), CRT_degreeSign);
else
xSnprintf(cpuTemperatureBuffer, sizeof(cpuTemperatureBuffer), "%d%sC", (int)cpuTemperature, CRT_degreeSign);
}
#endif
#endif

xSnprintf(this->txtBuffer, sizeof(this->txtBuffer), "%s%s%s%s%s",
cpuUsageBuffer,
Expand Down
3 changes: 3 additions & 0 deletions CRT.c
Original file line number Diff line number Diff line change
Expand Up @@ -231,6 +231,9 @@ static int CRT_colorSchemes[LAST_COLORSCHEME][LAST_COLORELEMENT] = {
[DYNAMIC_MAGENTA] = ColorPair(Magenta, Black),
[DYNAMIC_YELLOW] = ColorPair(Yellow, Black),
[DYNAMIC_WHITE] = ColorPair(White, Black),
#ifdef NVIDIA_JETSON
[GPU_FILTER] = A_BOLD | ColorPair(Red, Cyan),
#endif
},
[COLORSCHEME_MONOCHROME] = {
[RESET_COLOR] = A_NORMAL,
Expand Down
3 changes: 3 additions & 0 deletions CRT.h
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,9 @@ typedef enum ColorElements_ {
DYNAMIC_MAGENTA,
DYNAMIC_YELLOW,
DYNAMIC_WHITE,
#ifdef NVIDIA_JETSON
GPU_FILTER,
#endif
LAST_COLORELEMENT
} ColorElements;

Expand Down
6 changes: 3 additions & 3 deletions DisplayOptionsPanel.c
Original file line number Diff line number Diff line change
Expand Up @@ -173,10 +173,10 @@ DisplayOptionsPanel* DisplayOptionsPanel_new(Settings* settings, ScreenManager*
Panel_add(super, (Object*) CheckItem_newByRef("Also show CPU frequency", &(settings->showCPUFrequency)));
#ifdef BUILD_WITH_CPU_TEMP
Panel_add(super, (Object*) CheckItem_newByRef(
#if defined(HTOP_LINUX)
"Also show CPU temperature (requires libsensors)",
#elif defined(HTOP_FREEBSD)
#if defined(HTOP_FREEBSD) || defined(NVIDIA_JETSON)
"Also show CPU temperature",
#elif defined(HTOP_LINUX)
"Also show CPU temperature (requires libsensors)",
#else
#error Unknown temperature implementation!
#endif
Expand Down
5 changes: 5 additions & 0 deletions Machine.c
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ Released under the GNU GPLv2+, see the COPYING file
in the source distribution for its full text.
*/

#include "NvidiaJetson.h"
#include "config.h" // IWYU pragma: keep

#include "Machine.h"
Expand Down Expand Up @@ -128,4 +129,8 @@ void Machine_scanTables(Machine* this) {
}

Row_setUidColumnWidth(this->maxUserId);

#ifdef NVIDIA_JETSON
NvidiaJetson_LoadGpuProcessTable(this->activeTable->table);
#endif
}
5 changes: 5 additions & 0 deletions MainPanel.c
Original file line number Diff line number Diff line change
Expand Up @@ -195,6 +195,11 @@ static void MainPanel_drawFunctionBar(Panel* super, bool hideFunctionBar) {
if (this->state->pauseUpdate) {
FunctionBar_append("PAUSED", CRT_colors[PAUSED]);
}
#ifdef NVIDIA_JETSON
if (this->state->showGpuProcesses) {
FunctionBar_append("GPU", CRT_colors[GPU_FILTER]);
}
#endif
}

static void MainPanel_printHeader(Panel* super) {
Expand Down
5 changes: 5 additions & 0 deletions Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -215,6 +215,11 @@ linux_platform_sources = \
zfs/ZfsArcMeter.c \
zfs/ZfsCompressedArcMeter.c

if NVIDIA_JETSON
linux_platform_headers += linux/NvidiaJetson.h
linux_platform_sources += linux/NvidiaJetson.c
endif

if HAVE_DELAYACCT
linux_platform_headers += linux/LibNl.h
linux_platform_sources += linux/LibNl.c
Expand Down
12 changes: 12 additions & 0 deletions XUtils.h
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,13 @@ char* xStrndup(const char* str, size_t len);

ATTR_NONNULL ATTR_ACCESS3_W(2, 3)
ssize_t xReadfile(const char* pathname, void* buffer, size_t count);
#ifdef NVIDIA_JETSON /* uncomment if you need this functionality somewhere else */
ATTR_NONNULL ATTR_ACCESS3_W(2, 3)
static inline double xReadNumberFromFile(const char *pathname, char *buf, const size_t len) {
ssize_t nread = xReadfile(pathname, buf, len);
return nread > 0 ? strtod(buf, NULL) : NAN;
}
#endif
ATTR_NONNULL ATTR_ACCESS3_W(3, 4)
ssize_t xReadfileat(openat_arg_t dirfd, const char* pathname, void* buffer, size_t count);

Expand Down Expand Up @@ -178,4 +185,9 @@ static inline int xDirfd(DIR* dirp) {
return r;
}


static inline double ConvCelsiusToFahrenheit(const double celsius) {
return celsius * 9 / 5 + 32;
}

#endif
43 changes: 42 additions & 1 deletion configure.ac
Original file line number Diff line number Diff line change
Expand Up @@ -1140,7 +1140,47 @@ case "$enable_sensors" in
AC_MSG_ERROR([bad value '$enable_sensors' for --enable-sensors])
;;
esac
if test "$enable_sensors" = yes || test "$my_htop_platform" = freebsd; then

AC_ARG_ENABLE([nvidia-jetson],
[AS_HELP_STRING([--enable-nvidia-jetson],
[enable nvidia jetson support @<:@default=check@:>@])],
[],
[enable_nvidia_jetson=check])
case "$enable_nvidia_jetson" in
no)
;;
check)
if test -f "/etc/nv_tegra_release"; then
if grep -q "BOARD" "/etc/nv_tegra_release"; then
enable_nvidia_jetson=yes
fi
fi
;;
yes)
if test -f "/etc/nv_tegra_release"; then
if grep -q "BOARD" "/etc/nv_tegra_release"; then
enable_nvidia_jetson=yes
else
enable_nvidia_jetson=no
fi
else
enable_nvidia_jetson=no
fi
;;
*)
AC_MSG_ERROR([bad value '$enable_nvidia_jetson' for --enable-nvidia-jetson])
;;
esac

if test "$enable_nvidia_jetson" = yes; then
AC_DEFINE([NVIDIA_JETSON], [1], [Detected correct NVIDIA Jetson board])
else
AC_MSG_NOTICE([This is not a NVIDIA Jetson board])
fi

AM_CONDITIONAL([NVIDIA_JETSON], [test "$enable_nvidia_jetson" = yes])

if test "$enable_sensors" = yes || test "$my_htop_platform" = freebsd || test "$enable_nvidia_jetson" = yes; then
AC_DEFINE([BUILD_WITH_CPU_TEMP], [1], [Define if CPU temperature option should be enabled.])
fi

Expand Down Expand Up @@ -1278,6 +1318,7 @@ AC_MSG_RESULT([
(Linux) delay accounting: $enable_delayacct
(Linux) sensors: $enable_sensors
(Linux) capabilities: $enable_capabilities
(Linux) nvidia-jeston $enable_nvidia_jetson
unicode: $enable_unicode
affinity: $enable_affinity
unwind: $enable_unwind
Expand Down
12 changes: 11 additions & 1 deletion linux/LinuxMachine.c
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ in the source distribution for its full text.
#include "UsersTable.h"
#include "XUtils.h"

#include "linux/NvidiaJetson.h"
#include "linux/Platform.h" // needed for GNU/hurd to get PATH_MAX // IWYU pragma: keep

#ifdef HAVE_SENSORS_SENSORS_H
Expand Down Expand Up @@ -741,15 +742,20 @@ void Machine_scan(Machine* super) {
const Settings* settings = super->settings;
if (settings->showCPUFrequency
#ifdef HAVE_SENSORS_SENSORS_H
|| settings->showCPUTemperature
|| settings->showCPUTemperature /* TODO: looks like this line in the condition might be removed */
#endif
)
LinuxMachine_scanCPUFrequency(this);

#ifdef NVIDIA_JETSON
if (settings->showCPUTemperature)
NvidiaJetson_getCPUTemperatures(this->cpuData, super->existingCPUs);
#else
#ifdef HAVE_SENSORS_SENSORS_H
if (settings->showCPUTemperature)
LibSensors_getCPUTemperatures(this->cpuData, super->existingCPUs, super->activeCPUs);
#endif
#endif
}

Machine* Machine_new(UsersTable* usersTable, uid_t userId) {
Expand Down Expand Up @@ -792,6 +798,10 @@ Machine* Machine_new(UsersTable* usersTable, uid_t userId) {
// Initialize CPU count
LinuxMachine_updateCPUcount(this);

#ifdef NVIDIA_JETSON
NvidiaJetson_FindSensors();
#endif

#ifdef HAVE_SENSORS_SENSORS_H
// Fetch CPU topology
LinuxMachine_fetchCPUTopologyFromCPUinfo(this);
Expand Down
5 changes: 3 additions & 2 deletions linux/LinuxMachine.h
Original file line number Diff line number Diff line change
Expand Up @@ -46,9 +46,10 @@ typedef struct CPUData_ {

double frequency;

#ifdef HAVE_SENSORS_SENSORS_H
#ifdef BUILD_WITH_CPU_TEMP
double temperature;

#endif
#ifdef HAVE_SENSORS_SENSORS_H
int physicalID; /* different for each CPU socket */
int coreID; /* same for hyperthreading */
int ccdID; /* same for each AMD chiplet */
Expand Down
11 changes: 11 additions & 0 deletions linux/LinuxProcess.c
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ Released under the GNU GPLv2+, see the COPYING file
in the source distribution for its full text.
*/

#include "NvidiaJetson.h"
#include "config.h" // IWYU pragma: keep

#include "linux/LinuxProcess.h"
Expand Down Expand Up @@ -112,6 +113,9 @@ const ProcessFieldData Process_fields[LAST_PROCESSFIELD] = {
#endif
[GPU_TIME] = { .name = "GPU_TIME", .title = "GPU_TIME ", .description = "Total GPU time", .flags = PROCESS_FLAG_LINUX_GPU, .defaultSortDesc = true, },
[GPU_PERCENT] = { .name = "GPU_PERCENT", .title = " GPU% ", .description = "Percentage of the GPU time the process used in the last sampling", .flags = PROCESS_FLAG_LINUX_GPU, .defaultSortDesc = true, },
#ifdef NVIDIA_JETSON
[GPU_MEM]= { .name = "GPU_MEM", .title = "GPU_M ", .description = "GPU memory allocated for the process", .flags = 0, .defaultSortDesc = true, },
#endif
};

Process* LinuxProcess_new(const Machine* host) {
Expand Down Expand Up @@ -362,6 +366,9 @@ static void LinuxProcess_rowWriteField(const Row* super, RichString* str, Proces
xSnprintf(buffer, n, "N/A ");
}
break;
#ifdef NVIDIA_JETSON
case GPU_MEM: Row_printKBytes(str, lp->gpu_mem, coloring); return;
#endif
default:
Process_writeField(this, str, field);
return;
Expand Down Expand Up @@ -466,6 +473,10 @@ static int LinuxProcess_compareByKey(const Process* v1, const Process* v2, Proce
return SPACESHIP_NUMBER(p1->gpu_time, p2->gpu_time);
case ISCONTAINER:
return SPACESHIP_NUMBER(v1->isRunningInContainer, v2->isRunningInContainer);
#ifdef NVIDIA_JETSON
case GPU_MEM:
return SPACESHIP_NUMBER(p1->gpu_mem, p2->gpu_mem);
#endif
default:
return Process_compareByKey_Base(v1, v2, key);
}
Expand Down
4 changes: 4 additions & 0 deletions linux/LinuxProcess.h
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,10 @@ typedef struct LinuxProcess_ {
/* Activity of GPU: 0 if active, otherwise time of last scan in milliseconds */
uint64_t gpu_activityMs;

#ifdef NVIDIA_JETSON
uint64_t gpu_mem;
#endif

/* Autogroup scheduling (CFS) information */
long int autogroup_id;
int autogroup_nice;
Expand Down
Loading