mirror of
https://github.com/xzeldon/htop.git
synced 2025-07-15 13:34:35 +03:00
Compare commits
62 Commits
Author | SHA1 | Date | |
---|---|---|---|
ce6d60e7de | |||
5d92a9f20d | |||
b3500ac3b7 | |||
2ba8a81d47 | |||
f2f1c99ad9 | |||
1ffe5d79bd | |||
8502f4e64f | |||
a5db139a0a | |||
8a67d7f086 | |||
0b89c66f58 | |||
3bb731c645 | |||
fbaa0cd146 | |||
a076488809 | |||
6301d5c1da | |||
4979245aa5 | |||
0155980fd6 | |||
2af90b711f | |||
d55f394541 | |||
c7d93a8f30 | |||
2d2a2df6f2 | |||
de645ea16c | |||
6ae56f2578 | |||
bfcb8ca019 | |||
d800d7a3ce | |||
27db9297b7 | |||
330d4fe22f | |||
8e10cde800 | |||
ca2c01bd16 | |||
7043a93eba | |||
8fe04b7494 | |||
43d5c61884 | |||
e103ec0317 | |||
7ff654f2df | |||
7386c6fed0 | |||
ce9e7fd14f | |||
badeaf9e82 | |||
a3cced9fb6 | |||
24c5ca9ddf | |||
eb6f8d569d | |||
8c8149d146 | |||
a150a81669 | |||
90ea3ac3c9 | |||
293c16e22d | |||
f6aa5d29bb | |||
2c06566405 | |||
d609c04fe4 | |||
ca9d7cd708 | |||
debeac49cd | |||
a0b899f29d | |||
8b83a9f055 | |||
495f2292dc | |||
1cc3f8074f | |||
aa08279964 | |||
5359eae28b | |||
f1463fdd64 | |||
3edb6e1ea3 | |||
71ddc6a6a1 | |||
b9336af76f | |||
f46ddd3230 | |||
94d7f0b585 | |||
86d2931255 | |||
0672be7db1 |
9
.github/workflows/ci.yml
vendored
9
.github/workflows/ci.yml
vendored
@ -2,6 +2,11 @@ name: CI
|
||||
|
||||
on: [ push, pull_request ]
|
||||
|
||||
env:
|
||||
# Enable format attributes in ncurses headers
|
||||
# Enable fortified memory/string handling
|
||||
CPPFLAGS: -DGCC_PRINTF -DGCC_SCANF -D_FORTIFY_SOURCE=2
|
||||
|
||||
jobs:
|
||||
build-ubuntu-latest-minimal-gcc:
|
||||
runs-on: ubuntu-latest
|
||||
@ -47,6 +52,10 @@ jobs:
|
||||
|
||||
build-ubuntu-latest-full-featured-gcc:
|
||||
runs-on: ubuntu-latest
|
||||
# Enable LTO, might trigger additional warnings on advanced inlining
|
||||
env:
|
||||
CFLAGS: -O3 -g -flto
|
||||
LDFLAGS: -O3 -g -flto
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: Install Dependencies
|
||||
|
52
Action.c
52
Action.c
@ -104,7 +104,7 @@ static bool changePriority(MainPanel* panel, int delta) {
|
||||
return anyTagged;
|
||||
}
|
||||
|
||||
static void addUserToVector(hkey_t key, void* userCast, void* panelCast) {
|
||||
static void addUserToVector(ht_key_t key, void* userCast, void* panelCast) {
|
||||
const char* user = userCast;
|
||||
Panel* panel = panelCast;
|
||||
Panel_add(panel, (Object*) ListItem_new(user, key));
|
||||
@ -162,9 +162,11 @@ Htop_Reaction Action_setSortKey(Settings* settings, ProcessField sortKey) {
|
||||
return HTOP_REFRESH | HTOP_SAVE_SETTINGS | HTOP_UPDATE_PANELHDR | HTOP_KEEP_FOLLOWING;
|
||||
}
|
||||
|
||||
static Htop_Reaction sortBy(State* st) {
|
||||
// ----------------------------------------
|
||||
|
||||
static Htop_Reaction actionSetSortColumn(State* st) {
|
||||
Htop_Reaction reaction = HTOP_OK;
|
||||
Panel* sortPanel = Panel_new(0, 0, 0, 0, true, Class(ListItem), FunctionBar_newEnterEsc("Sort ", "Cancel "));
|
||||
Panel* sortPanel = Panel_new(0, 0, 0, 0, Class(ListItem), true, FunctionBar_newEnterEsc("Sort ", "Cancel "));
|
||||
Panel_setHeader(sortPanel, "Sort by");
|
||||
ProcessField* fields = st->settings->fields;
|
||||
for (int i = 0; fields[i]; i++) {
|
||||
@ -187,12 +189,8 @@ static Htop_Reaction sortBy(State* st) {
|
||||
return reaction | HTOP_REFRESH | HTOP_REDRAW_BAR | HTOP_UPDATE_PANELHDR;
|
||||
}
|
||||
|
||||
// ----------------------------------------
|
||||
|
||||
static Htop_Reaction actionResize(State* st) {
|
||||
clear();
|
||||
Panel_resize(st->panel, COLS, LINES - (st->panel->y) - 1);
|
||||
return HTOP_REDRAW_BAR;
|
||||
static Htop_Reaction actionSortByPID(State* st) {
|
||||
return Action_setSortKey(st->settings, PID);
|
||||
}
|
||||
|
||||
static Htop_Reaction actionSortByMemory(State* st) {
|
||||
@ -250,16 +248,6 @@ static Htop_Reaction actionIncSearch(State* st) {
|
||||
return HTOP_REFRESH | HTOP_KEEP_FOLLOWING;
|
||||
}
|
||||
|
||||
static Htop_Reaction actionIncNext(State* st) {
|
||||
IncSet_next(((MainPanel*)st->panel)->inc, INC_SEARCH, st->panel, (IncMode_GetPanelValue) MainPanel_getValue);
|
||||
return HTOP_REFRESH | HTOP_KEEP_FOLLOWING;
|
||||
}
|
||||
|
||||
static Htop_Reaction actionIncPrev(State* st) {
|
||||
IncSet_prev(((MainPanel*)st->panel)->inc, INC_SEARCH, st->panel, (IncMode_GetPanelValue) MainPanel_getValue);
|
||||
return HTOP_REFRESH | HTOP_KEEP_FOLLOWING;
|
||||
}
|
||||
|
||||
static Htop_Reaction actionHigherPriority(State* st) {
|
||||
bool changed = changePriority((MainPanel*)st->panel, -1);
|
||||
return changed ? HTOP_REFRESH : HTOP_OK;
|
||||
@ -277,10 +265,6 @@ static Htop_Reaction actionInvertSortOrder(State* st) {
|
||||
return HTOP_REFRESH | HTOP_SAVE_SETTINGS;
|
||||
}
|
||||
|
||||
static Htop_Reaction actionSetSortColumn(State* st) {
|
||||
return sortBy(st);
|
||||
}
|
||||
|
||||
static Htop_Reaction actionExpandOrCollapse(State* st) {
|
||||
bool changed = expandCollapse(st->panel);
|
||||
return changed ? HTOP_RECALCULATE : HTOP_OK;
|
||||
@ -341,7 +325,7 @@ static Htop_Reaction actionKill(State* st) {
|
||||
if (sgn) {
|
||||
if (sgn->key != 0) {
|
||||
Panel_setHeader(st->panel, "Sending...");
|
||||
Panel_draw(st->panel, false, true, true);
|
||||
Panel_draw(st->panel, false, true, true, State_hideFunctionBar(st));
|
||||
refresh();
|
||||
MainPanel_foreachProcess((MainPanel*)st->panel, Process_sendSignal, (Arg) { .i = sgn->key }, NULL);
|
||||
napms(500);
|
||||
@ -352,7 +336,7 @@ static Htop_Reaction actionKill(State* st) {
|
||||
}
|
||||
|
||||
static Htop_Reaction actionFilterByUser(State* st) {
|
||||
Panel* usersPanel = Panel_new(0, 0, 0, 0, true, Class(ListItem), FunctionBar_newEnterEsc("Show ", "Cancel "));
|
||||
Panel* usersPanel = Panel_new(0, 0, 0, 0, Class(ListItem), true, FunctionBar_newEnterEsc("Show ", "Cancel "));
|
||||
Panel_setHeader(usersPanel, "Show processes of:");
|
||||
UsersTable_foreach(st->ut, addUserToVector, usersPanel);
|
||||
Vector_insertionSort(usersPanel->items);
|
||||
@ -462,7 +446,7 @@ static const struct {
|
||||
{ .key = " K: ", .info = "hide/show kernel threads" },
|
||||
{ .key = " F: ", .info = "cursor follows process" },
|
||||
{ .key = " + -: ", .info = "expand/collapse tree" },
|
||||
{ .key = " P M T: ", .info = "sort by CPU%, MEM% or TIME" },
|
||||
{ .key = "N P M T: ", .info = "sort by PID, CPU%, MEM% or TIME" },
|
||||
{ .key = " I: ", .info = "invert sort order" },
|
||||
{ .key = " F6 > .: ", .info = "select sort column" },
|
||||
{ .key = NULL, .info = NULL }
|
||||
@ -563,24 +547,24 @@ static Htop_Reaction actionHelp(State* st) {
|
||||
int item;
|
||||
for (item = 0; helpLeft[item].key; item++) {
|
||||
attrset(CRT_colors[DEFAULT_COLOR]);
|
||||
mvaddstr(line + item, 9, helpLeft[item].info);
|
||||
mvaddstr(line + item, 10, helpLeft[item].info);
|
||||
attrset(CRT_colors[HELP_BOLD]);
|
||||
mvaddstr(line + item, 0, helpLeft[item].key);
|
||||
mvaddstr(line + item, 1, helpLeft[item].key);
|
||||
if (String_eq(helpLeft[item].key, " H: ")) {
|
||||
attrset(CRT_colors[PROCESS_THREAD]);
|
||||
mvaddstr(line + item, 32, "threads");
|
||||
mvaddstr(line + item, 33, "threads");
|
||||
} else if (String_eq(helpLeft[item].key, " K: ")) {
|
||||
attrset(CRT_colors[PROCESS_THREAD]);
|
||||
mvaddstr(line + item, 26, "threads");
|
||||
mvaddstr(line + item, 27, "threads");
|
||||
}
|
||||
}
|
||||
int leftHelpItems = item;
|
||||
|
||||
for (item = 0; helpRight[item].key; item++) {
|
||||
attrset(CRT_colors[HELP_BOLD]);
|
||||
mvaddstr(line + item, 40, helpRight[item].key);
|
||||
mvaddstr(line + item, 41, helpRight[item].key);
|
||||
attrset(CRT_colors[DEFAULT_COLOR]);
|
||||
mvaddstr(line + item, 49, helpRight[item].info);
|
||||
mvaddstr(line + item, 50, helpRight[item].info);
|
||||
}
|
||||
line += MAXIMUM(leftHelpItems, item);
|
||||
line++;
|
||||
@ -655,7 +639,7 @@ void Action_setBindings(Htop_Action* keys) {
|
||||
keys['I'] = actionInvertSortOrder;
|
||||
keys['K'] = actionToggleKernelThreads;
|
||||
keys['M'] = actionSortByMemory;
|
||||
keys['N'] = actionIncPrev;
|
||||
keys['N'] = actionSortByPID;
|
||||
keys['P'] = actionSortByCPU;
|
||||
keys['S'] = actionSetup;
|
||||
keys['T'] = actionSortByTime;
|
||||
@ -673,7 +657,6 @@ void Action_setBindings(Htop_Action* keys) {
|
||||
keys['k'] = actionKill;
|
||||
keys['l'] = actionLsof;
|
||||
keys['m'] = actionToggleMergedCommand;
|
||||
keys['n'] = actionIncNext;
|
||||
keys['p'] = actionToggleProgramPath;
|
||||
keys['q'] = actionQuit;
|
||||
keys['s'] = actionStrace;
|
||||
@ -693,5 +676,4 @@ void Action_setBindings(Htop_Action* keys) {
|
||||
keys[KEY_F(10)] = actionQuit;
|
||||
keys[KEY_F(18)] = actionExpandCollapseOrSortColumn;
|
||||
keys[KEY_RECLICK] = actionExpandOrCollapse;
|
||||
keys[KEY_RESIZE] = actionResize;
|
||||
}
|
||||
|
4
Action.h
4
Action.h
@ -41,6 +41,10 @@ typedef struct State_ {
|
||||
bool hideProcessSelection;
|
||||
} State;
|
||||
|
||||
static inline bool State_hideFunctionBar(const State* st) {
|
||||
return st->settings->hideFunctionBar == 2 || (st->settings->hideFunctionBar == 1 && st->hideProcessSelection);
|
||||
}
|
||||
|
||||
typedef Htop_Reaction (*Htop_Action)(State* st);
|
||||
|
||||
Object* Action_pickFromVector(State* st, Panel* list, int x, bool followProcess);
|
||||
|
82
CRT.c
82
CRT.c
@ -41,6 +41,9 @@ in the source distribution for its full text.
|
||||
#define ColorPairGrayBlack ColorPair(Magenta,Magenta)
|
||||
#define ColorIndexGrayBlack ColorIndex(Magenta,Magenta)
|
||||
|
||||
#define ColorPairWhiteDefault ColorPair(Red, Red)
|
||||
#define ColorIndexWhiteDefault ColorIndex(Red, Red)
|
||||
|
||||
static const char* const CRT_treeStrAscii[LAST_TREE_STR] = {
|
||||
[TREE_STR_VERT] = "|",
|
||||
[TREE_STR_RTEE] = "`",
|
||||
@ -48,6 +51,8 @@ static const char* const CRT_treeStrAscii[LAST_TREE_STR] = {
|
||||
[TREE_STR_TEND] = ",",
|
||||
[TREE_STR_OPEN] = "+",
|
||||
[TREE_STR_SHUT] = "-",
|
||||
[TREE_STR_ASC] = "+",
|
||||
[TREE_STR_DESC] = "-",
|
||||
};
|
||||
|
||||
#ifdef HAVE_LIBNCURSESW
|
||||
@ -61,6 +66,8 @@ static const char* const CRT_treeStrUtf8[LAST_TREE_STR] = {
|
||||
// WITH VERTICAL STROKE' (U+1FBAF, "\xf0\x9f\xae\xaf") when
|
||||
// Unicode 13 is common
|
||||
[TREE_STR_SHUT] = "\xe2\x94\x80", // ─
|
||||
[TREE_STR_ASC] = "\xe2\x96\xb3", // △
|
||||
[TREE_STR_DESC] = "\xe2\x96\xbd", // ▽
|
||||
};
|
||||
|
||||
bool CRT_utf8 = false;
|
||||
@ -114,6 +121,7 @@ static int CRT_colorSchemes[LAST_COLORSCHEME][LAST_COLORELEMENT] = {
|
||||
[METER_VALUE_IOWRITE] = ColorPair(Blue, Black),
|
||||
[METER_VALUE_NOTICE] = A_BOLD | ColorPair(White, Black),
|
||||
[METER_VALUE_OK] = ColorPair(Green, Black),
|
||||
[METER_VALUE_WARN] = A_BOLD | ColorPair(Yellow, Black),
|
||||
[LED_COLOR] = ColorPair(Green, Black),
|
||||
[TASKS_RUNNING] = A_BOLD | ColorPair(Green, Black),
|
||||
[PROCESS] = A_NORMAL,
|
||||
@ -198,6 +206,7 @@ static int CRT_colorSchemes[LAST_COLORSCHEME][LAST_COLORELEMENT] = {
|
||||
[METER_VALUE_IOWRITE] = A_NORMAL,
|
||||
[METER_VALUE_NOTICE] = A_BOLD,
|
||||
[METER_VALUE_OK] = A_NORMAL,
|
||||
[METER_VALUE_WARN] = A_BOLD,
|
||||
[LED_COLOR] = A_NORMAL,
|
||||
[TASKS_RUNNING] = A_BOLD,
|
||||
[PROCESS] = A_NORMAL,
|
||||
@ -282,6 +291,7 @@ static int CRT_colorSchemes[LAST_COLORSCHEME][LAST_COLORELEMENT] = {
|
||||
[METER_VALUE_IOWRITE] = ColorPair(Yellow, White),
|
||||
[METER_VALUE_NOTICE] = A_BOLD | ColorPair(Yellow, White),
|
||||
[METER_VALUE_OK] = ColorPair(Green, White),
|
||||
[METER_VALUE_WARN] = A_BOLD | ColorPair(Yellow, White),
|
||||
[LED_COLOR] = ColorPair(Green, White),
|
||||
[TASKS_RUNNING] = ColorPair(Green, White),
|
||||
[PROCESS] = ColorPair(Black, White),
|
||||
@ -344,10 +354,10 @@ static int CRT_colorSchemes[LAST_COLORSCHEME][LAST_COLORELEMENT] = {
|
||||
[ZRAM] = ColorPair(Yellow, White)
|
||||
},
|
||||
[COLORSCHEME_LIGHTTERMINAL] = {
|
||||
[RESET_COLOR] = ColorPair(Blue, Black),
|
||||
[DEFAULT_COLOR] = ColorPair(Blue, Black),
|
||||
[RESET_COLOR] = ColorPair(Black, Black),
|
||||
[DEFAULT_COLOR] = ColorPair(Black, Black),
|
||||
[FUNCTION_BAR] = ColorPair(Black, Cyan),
|
||||
[FUNCTION_KEY] = ColorPair(Blue, Black),
|
||||
[FUNCTION_KEY] = ColorPair(Black, Black),
|
||||
[PANEL_HEADER_FOCUS] = ColorPair(Black, Green),
|
||||
[PANEL_HEADER_UNFOCUS] = ColorPair(Black, Green),
|
||||
[PANEL_SELECTION_FOCUS] = ColorPair(Black, Cyan),
|
||||
@ -360,17 +370,18 @@ static int CRT_colorSchemes[LAST_COLORSCHEME][LAST_COLORELEMENT] = {
|
||||
[BATTERY] = ColorPair(Yellow, Black),
|
||||
[LARGE_NUMBER] = ColorPair(Red, Black),
|
||||
[METER_TEXT] = ColorPair(Blue, Black),
|
||||
[METER_VALUE] = ColorPair(Blue, Black),
|
||||
[METER_VALUE] = ColorPair(Black, Black),
|
||||
[METER_VALUE_ERROR] = A_BOLD | ColorPair(Red, Black),
|
||||
[METER_VALUE_IOREAD] = ColorPair(Green, Black),
|
||||
[METER_VALUE_IOWRITE] = ColorPair(Yellow, Black),
|
||||
[METER_VALUE_NOTICE] = A_BOLD | ColorPair(Yellow, Black),
|
||||
[METER_VALUE_NOTICE] = A_BOLD | ColorPairWhiteDefault,
|
||||
[METER_VALUE_OK] = ColorPair(Green, Black),
|
||||
[METER_VALUE_WARN] = A_BOLD | ColorPair(Yellow, Black),
|
||||
[LED_COLOR] = ColorPair(Green, Black),
|
||||
[TASKS_RUNNING] = ColorPair(Green, Black),
|
||||
[PROCESS] = ColorPair(Blue, Black),
|
||||
[PROCESS] = ColorPair(Black, Black),
|
||||
[PROCESS_SHADOW] = A_BOLD | ColorPairGrayBlack,
|
||||
[PROCESS_TAG] = ColorPair(Yellow, Blue),
|
||||
[PROCESS_TAG] = ColorPair(White, Blue),
|
||||
[PROCESS_MEGABYTES] = ColorPair(Blue, Black),
|
||||
[PROCESS_GIGABYTES] = ColorPair(Green, Black),
|
||||
[PROCESS_BASENAME] = ColorPair(Green, Black),
|
||||
@ -394,34 +405,34 @@ static int CRT_colorSchemes[LAST_COLORSCHEME][LAST_COLORELEMENT] = {
|
||||
[MEMORY_BUFFERS] = ColorPair(Cyan, Black),
|
||||
[MEMORY_BUFFERS_TEXT] = ColorPair(Cyan, Black),
|
||||
[MEMORY_CACHE] = ColorPair(Yellow, Black),
|
||||
[LOAD_AVERAGE_FIFTEEN] = ColorPair(Blue, Black),
|
||||
[LOAD_AVERAGE_FIVE] = ColorPair(Blue, Black),
|
||||
[LOAD_AVERAGE_ONE] = ColorPair(Yellow, Black),
|
||||
[LOAD] = ColorPair(Yellow, Black),
|
||||
[LOAD_AVERAGE_FIFTEEN] = ColorPair(Black, Black),
|
||||
[LOAD_AVERAGE_FIVE] = ColorPair(Black, Black),
|
||||
[LOAD_AVERAGE_ONE] = ColorPair(Black, Black),
|
||||
[LOAD] = ColorPairWhiteDefault,
|
||||
[HELP_BOLD] = ColorPair(Blue, Black),
|
||||
[CLOCK] = ColorPair(Yellow, Black),
|
||||
[DATE] = ColorPair(White, Black),
|
||||
[DATETIME] = ColorPair(White, Black),
|
||||
[CLOCK] = ColorPairWhiteDefault,
|
||||
[DATE] = ColorPairWhiteDefault,
|
||||
[DATETIME] = ColorPairWhiteDefault,
|
||||
[CHECK_BOX] = ColorPair(Blue, Black),
|
||||
[CHECK_MARK] = ColorPair(Blue, Black),
|
||||
[CHECK_TEXT] = ColorPair(Blue, Black),
|
||||
[HOSTNAME] = ColorPair(Yellow, Black),
|
||||
[CHECK_MARK] = ColorPair(Black, Black),
|
||||
[CHECK_TEXT] = ColorPair(Black, Black),
|
||||
[HOSTNAME] = ColorPairWhiteDefault,
|
||||
[CPU_NICE] = ColorPair(Cyan, Black),
|
||||
[CPU_NICE_TEXT] = ColorPair(Cyan, Black),
|
||||
[CPU_NORMAL] = ColorPair(Green, Black),
|
||||
[CPU_SYSTEM] = ColorPair(Red, Black),
|
||||
[CPU_IOWAIT] = A_BOLD | ColorPair(Blue, Black),
|
||||
[CPU_IOWAIT] = A_BOLD | ColorPair(Black, Black),
|
||||
[CPU_IRQ] = A_BOLD | ColorPair(Blue, Black),
|
||||
[CPU_SOFTIRQ] = ColorPair(Blue, Black),
|
||||
[CPU_STEAL] = ColorPair(Blue, Black),
|
||||
[CPU_GUEST] = ColorPair(Blue, Black),
|
||||
[PRESSURE_STALL_THREEHUNDRED] = ColorPair(Blue, Black),
|
||||
[PRESSURE_STALL_SIXTY] = ColorPair(Blue, Black),
|
||||
[PRESSURE_STALL_TEN] = ColorPair(Blue, Black),
|
||||
[CPU_STEAL] = ColorPair(Black, Black),
|
||||
[CPU_GUEST] = ColorPair(Black, Black),
|
||||
[PRESSURE_STALL_THREEHUNDRED] = ColorPair(Black, Black),
|
||||
[PRESSURE_STALL_SIXTY] = ColorPair(Black, Black),
|
||||
[PRESSURE_STALL_TEN] = ColorPair(Black, Black),
|
||||
[ZFS_MFU] = ColorPair(Cyan, Black),
|
||||
[ZFS_MRU] = ColorPair(Yellow, Black),
|
||||
[ZFS_ANON] = A_BOLD | ColorPair(Magenta, Black),
|
||||
[ZFS_HEADER] = ColorPair(Blue, Black),
|
||||
[ZFS_HEADER] = ColorPair(Black, Black),
|
||||
[ZFS_OTHER] = A_BOLD | ColorPair(Magenta, Black),
|
||||
[ZFS_COMPRESSED] = ColorPair(Cyan, Black),
|
||||
[ZFS_RATIO] = A_BOLD | ColorPair(Magenta, Black),
|
||||
@ -450,6 +461,7 @@ static int CRT_colorSchemes[LAST_COLORSCHEME][LAST_COLORELEMENT] = {
|
||||
[METER_VALUE_IOWRITE] = ColorPair(Black, Blue),
|
||||
[METER_VALUE_NOTICE] = A_BOLD | ColorPair(White, Blue),
|
||||
[METER_VALUE_OK] = ColorPair(Green, Blue),
|
||||
[METER_VALUE_WARN] = A_BOLD | ColorPair(Yellow, Black),
|
||||
[LED_COLOR] = ColorPair(Green, Blue),
|
||||
[TASKS_RUNNING] = A_BOLD | ColorPair(Green, Blue),
|
||||
[PROCESS] = ColorPair(White, Blue),
|
||||
@ -532,8 +544,9 @@ static int CRT_colorSchemes[LAST_COLORSCHEME][LAST_COLORELEMENT] = {
|
||||
[METER_VALUE_ERROR] = A_BOLD | ColorPair(Red, Black),
|
||||
[METER_VALUE_IOREAD] = ColorPair(Green, Black),
|
||||
[METER_VALUE_IOWRITE] = ColorPair(Blue, Black),
|
||||
[METER_VALUE_NOTICE] = A_BOLD | ColorPair(Yellow, Black),
|
||||
[METER_VALUE_NOTICE] = A_BOLD | ColorPair(White, Black),
|
||||
[METER_VALUE_OK] = ColorPair(Green, Black),
|
||||
[METER_VALUE_WARN] = A_BOLD | ColorPair(Yellow, Black),
|
||||
[LED_COLOR] = ColorPair(Green, Black),
|
||||
[TASKS_RUNNING] = A_BOLD | ColorPair(Green, Black),
|
||||
[PROCESS] = ColorPair(Cyan, Black),
|
||||
@ -689,6 +702,7 @@ void CRT_init(const int* delay, int colorScheme, bool allowUnicode) {
|
||||
define_key("\033[12~", KEY_F(2));
|
||||
define_key("\033[13~", KEY_F(3));
|
||||
define_key("\033[14~", KEY_F(4));
|
||||
define_key("\033[14;2~", KEY_F(15));
|
||||
define_key("\033[17;2~", KEY_F(18));
|
||||
char sequence[3] = "\033a";
|
||||
for (char c = 'a'; c <= 'z'; c++) {
|
||||
@ -778,7 +792,7 @@ void CRT_setColors(int colorScheme) {
|
||||
|
||||
for (short int i = 0; i < 8; i++) {
|
||||
for (short int j = 0; j < 8; j++) {
|
||||
if (ColorIndex(i, j) != ColorIndexGrayBlack) {
|
||||
if (ColorIndex(i, j) != ColorIndexGrayBlack && ColorIndex(i, j) != ColorIndexWhiteDefault) {
|
||||
short int bg = (colorScheme != COLORSCHEME_BLACKNIGHT)
|
||||
? (j == 0 ? -1 : j)
|
||||
: j;
|
||||
@ -791,6 +805,8 @@ void CRT_setColors(int colorScheme) {
|
||||
short int grayBlackBg = (colorScheme != COLORSCHEME_BLACKNIGHT) ? -1 : 0;
|
||||
init_pair(ColorIndexGrayBlack, grayBlackFg, grayBlackBg);
|
||||
|
||||
init_pair(ColorIndexWhiteDefault, White, -1);
|
||||
|
||||
CRT_colors = CRT_colorSchemes[colorScheme];
|
||||
}
|
||||
|
||||
@ -807,9 +823,13 @@ void CRT_handleSIGSEGV(int signal) {
|
||||
"- Your OS and kernel version (uname -a)\n"
|
||||
"- Your distribution and release (lsb_release -a)\n"
|
||||
"- Likely steps to reproduce (How did it happened?)\n"
|
||||
);
|
||||
|
||||
#ifdef HAVE_EXECINFO_H
|
||||
"- Backtrace of the issue (see below)\n"
|
||||
fprintf(stderr, "- Backtrace of the issue (see below)\n");
|
||||
#endif
|
||||
|
||||
fprintf(stderr,
|
||||
"\n"
|
||||
);
|
||||
|
||||
@ -844,11 +864,15 @@ void CRT_handleSIGSEGV(int signal) {
|
||||
"you should provide a disassembly of your binary.\n"
|
||||
"This can usually be done by running the following command:\n"
|
||||
"\n"
|
||||
);
|
||||
|
||||
#ifdef HTOP_DARWIN
|
||||
" otool -tvV `which htop` > ~/htop.otool\n"
|
||||
fprintf(stderr, " otool -tvV `which htop` > ~/htop.otool\n");
|
||||
#else
|
||||
" objdump -d -S -w `which htop` > ~/htop.objdump\n"
|
||||
fprintf(stderr, " objdump -d -S -w `which htop` > ~/htop.objdump\n");
|
||||
#endif
|
||||
|
||||
fprintf(stderr,
|
||||
"\n"
|
||||
"Please include the generated file in your report.\n"
|
||||
"\n"
|
||||
|
3
CRT.h
3
CRT.h
@ -22,6 +22,8 @@ typedef enum TreeStr_ {
|
||||
TREE_STR_TEND,
|
||||
TREE_STR_OPEN,
|
||||
TREE_STR_SHUT,
|
||||
TREE_STR_ASC,
|
||||
TREE_STR_DESC,
|
||||
LAST_TREE_STR
|
||||
} TreeStr;
|
||||
|
||||
@ -57,6 +59,7 @@ typedef enum ColorElements_ {
|
||||
METER_VALUE_IOWRITE,
|
||||
METER_VALUE_NOTICE,
|
||||
METER_VALUE_OK,
|
||||
METER_VALUE_WARN,
|
||||
LED_COLOR,
|
||||
UPTIME,
|
||||
BATTERY,
|
||||
|
33
ChangeLog
33
ChangeLog
@ -1,15 +1,40 @@
|
||||
What's new in version 3.0.5
|
||||
|
||||
* BUGFIX / SECURITY: InfoScreen: fix uncontrolled format string
|
||||
* BUGFIX: Improve white text in the Light Terminal colour scheme
|
||||
(both of the above thanks to V)
|
||||
* Enable the function bar on the main screen to be hidden (see Setup -> Display options)
|
||||
* BUGFIX: Reduce layout issues esp. around printing wide characters (not complete yet)
|
||||
* BUGFIX: Make the follow function exit cleanly after followed process died
|
||||
* Solaris: make Process callbacks static
|
||||
* Update help and man page for improved -t / -s options
|
||||
* Drop usage of formatted error messages from <err.h>
|
||||
* Show arrow indicating order of sorted process column
|
||||
* Lots of plumbing around the internal Hashtable, hardening and code cleanups
|
||||
* LibSensors: add support for Ryzen CPUs (vor 5 Tagen)
|
||||
(thanks to Matej Dian)
|
||||
* BUGFIX: Fix CPU percentage on M1 silicon Macs
|
||||
(thanks to Luke Groeninger)
|
||||
* LoadMeter: dynamically adjust color and total of bar
|
||||
* Find libsensors.so.4 for Fedora and friends
|
||||
* Add support to display CPU frequencies on Solarish platforms
|
||||
(thanks to Dominik Hassler)
|
||||
* Enable going back to previous search matches (Shift-F3)
|
||||
* Added keybind 'N' for sorting by PID (drops 'n'/'N' as not used before much)
|
||||
(thanks to Jake Mannens)
|
||||
|
||||
What's new in version 3.0.4
|
||||
|
||||
* Separate tree and list sort orders
|
||||
* Invert Process_compare so that superclass matches run first
|
||||
(thanks to Hisham Muhammad)
|
||||
(thanks to Hisham Muhammad)
|
||||
* Unhardcode Mac OS tick-to-milliseconds conversion
|
||||
(thanks to Alexander Momchilov)
|
||||
(thanks to Alexander Momchilov)
|
||||
* Check if clock_gettime needs linking of librt
|
||||
* Define O_PATH if not already defined
|
||||
(thanks to Chris Burr)
|
||||
(thanks to Chris Burr)
|
||||
* Add column on Mac for processes running under translation
|
||||
(thanks to Dániel Bakai)
|
||||
(thanks to Dániel Bakai)
|
||||
* Configure check for additional linker flags for keypad(3)
|
||||
* PSI Meter: constant width and only print ten-duration as bar
|
||||
* Sort in paused mode after inverting sort order
|
||||
|
@ -60,7 +60,7 @@ const InfoScreenClass CommandScreen_class = {
|
||||
|
||||
CommandScreen* CommandScreen_new(Process* process) {
|
||||
CommandScreen* this = AllocThis(CommandScreen);
|
||||
return (CommandScreen*) InfoScreen_init(&this->super, process, NULL, LINES - 3, " ");
|
||||
return (CommandScreen*) InfoScreen_init(&this->super, process, NULL, LINES - 2, " ");
|
||||
}
|
||||
|
||||
void CommandScreen_delete(Object* this) {
|
||||
|
@ -124,6 +124,7 @@ DisplayOptionsPanel* DisplayOptionsPanel_new(Settings* settings, ScreenManager*
|
||||
Panel_add(super, (Object*) NumberItem_newByRef("Update interval (in seconds)", &(settings->delay), -1, 1, 255));
|
||||
Panel_add(super, (Object*) CheckItem_newByRef("Highlight new and old processes", &(settings->highlightChanges)));
|
||||
Panel_add(super, (Object*) NumberItem_newByRef("- Highlight time (in seconds)", &(settings->highlightDelaySecs), 0, 1, 24*60*60));
|
||||
Panel_add(super, (Object*) NumberItem_newByRef("Hide main function bar (0 - off, 1 - on ESC until next input, 2 - permanently)", &(settings->hideFunctionBar), 0, 0, 2));
|
||||
#ifdef HAVE_LIBHWLOC
|
||||
Panel_add(super, (Object*) CheckItem_newByRef("Show topology when selecting affinity by default", &(settings->topologyAffinity)));
|
||||
#endif
|
||||
|
@ -17,7 +17,7 @@
|
||||
EnvScreen* EnvScreen_new(Process* process) {
|
||||
EnvScreen* this = xMalloc(sizeof(EnvScreen));
|
||||
Object_setClass(this, Class(EnvScreen));
|
||||
return (EnvScreen*) InfoScreen_init(&this->super, process, NULL, LINES - 3, " ");
|
||||
return (EnvScreen*) InfoScreen_init(&this->super, process, NULL, LINES - 2, " ");
|
||||
}
|
||||
|
||||
void EnvScreen_delete(Object* this) {
|
||||
|
90
Hashtable.c
90
Hashtable.c
@ -15,22 +15,37 @@ in the source distribution for its full text.
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "CRT.h"
|
||||
#include "Macros.h"
|
||||
#include "XUtils.h"
|
||||
|
||||
|
||||
typedef struct HashtableItem_ {
|
||||
ht_key_t key;
|
||||
size_t probe;
|
||||
void* value;
|
||||
} HashtableItem;
|
||||
|
||||
struct Hashtable_ {
|
||||
size_t size;
|
||||
HashtableItem* buckets;
|
||||
size_t items;
|
||||
bool owner;
|
||||
};
|
||||
|
||||
|
||||
#ifndef NDEBUG
|
||||
|
||||
static void Hashtable_dump(const Hashtable* this) {
|
||||
fprintf(stderr, "Hashtable %p: size=%u items=%u owner=%s\n",
|
||||
fprintf(stderr, "Hashtable %p: size=%zu items=%zu owner=%s\n",
|
||||
(const void*)this,
|
||||
this->size,
|
||||
this->items,
|
||||
this->owner ? "yes" : "no");
|
||||
|
||||
unsigned int items = 0;
|
||||
for (unsigned int i = 0; i < this->size; i++) {
|
||||
fprintf(stderr, " item %5u: key = %5u probe = %2u value = %p\n",
|
||||
size_t items = 0;
|
||||
for (size_t i = 0; i < this->size; i++) {
|
||||
fprintf(stderr, " item %5zu: key = %5u probe = %2zu value = %p\n",
|
||||
i,
|
||||
this->buckets[i].key,
|
||||
this->buckets[i].probe,
|
||||
@ -40,15 +55,15 @@ static void Hashtable_dump(const Hashtable* this) {
|
||||
items++;
|
||||
}
|
||||
|
||||
fprintf(stderr, "Hashtable %p: items=%u counted=%u\n",
|
||||
fprintf(stderr, "Hashtable %p: items=%zu counted=%zu\n",
|
||||
(const void*)this,
|
||||
this->items,
|
||||
items);
|
||||
}
|
||||
|
||||
static bool Hashtable_isConsistent(const Hashtable* this) {
|
||||
unsigned int items = 0;
|
||||
for (unsigned int i = 0; i < this->size; i++) {
|
||||
size_t items = 0;
|
||||
for (size_t i = 0; i < this->size; i++) {
|
||||
if (this->buckets[i].value)
|
||||
items++;
|
||||
}
|
||||
@ -58,9 +73,9 @@ static bool Hashtable_isConsistent(const Hashtable* this) {
|
||||
return res;
|
||||
}
|
||||
|
||||
unsigned int Hashtable_count(const Hashtable* this) {
|
||||
unsigned int items = 0;
|
||||
for (unsigned int i = 0; i < this->size; i++) {
|
||||
size_t Hashtable_count(const Hashtable* this) {
|
||||
size_t items = 0;
|
||||
for (size_t i = 0; i < this->size; i++) {
|
||||
if (this->buckets[i].value)
|
||||
items++;
|
||||
}
|
||||
@ -80,18 +95,17 @@ static const uint64_t OEISprimes[] = {
|
||||
34359738337, 68719476731, 137438953447
|
||||
};
|
||||
|
||||
static uint64_t nextPrime(unsigned int n) {
|
||||
assert(n <= OEISprimes[ARRAYSIZE(OEISprimes) - 1]);
|
||||
|
||||
for (unsigned int i = 0; i < ARRAYSIZE(OEISprimes); i++) {
|
||||
static uint64_t nextPrime(size_t n) {
|
||||
/* on 32-bit make sure we do not return primes not fitting in size_t */
|
||||
for (size_t i = 0; i < ARRAYSIZE(OEISprimes) && OEISprimes[i] < SIZE_MAX; i++) {
|
||||
if (n <= OEISprimes[i])
|
||||
return OEISprimes[i];
|
||||
}
|
||||
|
||||
return OEISprimes[ARRAYSIZE(OEISprimes) - 1];
|
||||
CRT_fatalError("Hashtable: no prime found");
|
||||
}
|
||||
|
||||
Hashtable* Hashtable_new(unsigned int size, bool owner) {
|
||||
Hashtable* Hashtable_new(size_t size, bool owner) {
|
||||
Hashtable* this;
|
||||
|
||||
this = xMalloc(sizeof(Hashtable));
|
||||
@ -115,7 +129,7 @@ void Hashtable_clear(Hashtable* this) {
|
||||
assert(Hashtable_isConsistent(this));
|
||||
|
||||
if (this->owner)
|
||||
for (unsigned int i = 0; i < this->size; i++)
|
||||
for (size_t i = 0; i < this->size; i++)
|
||||
free(this->buckets[i].value);
|
||||
|
||||
memset(this->buckets, 0, this->size * sizeof(HashtableItem));
|
||||
@ -124,11 +138,11 @@ void Hashtable_clear(Hashtable* this) {
|
||||
assert(Hashtable_isConsistent(this));
|
||||
}
|
||||
|
||||
static void insert(Hashtable* this, hkey_t key, void* value) {
|
||||
unsigned int index = key % this->size;
|
||||
unsigned int probe = 0;
|
||||
static void insert(Hashtable* this, ht_key_t key, void* value) {
|
||||
size_t index = key % this->size;
|
||||
size_t probe = 0;
|
||||
#ifndef NDEBUG
|
||||
unsigned int origIndex = index;
|
||||
size_t origIndex = index;
|
||||
#endif
|
||||
|
||||
for (;;) {
|
||||
@ -167,7 +181,7 @@ static void insert(Hashtable* this, hkey_t key, void* value) {
|
||||
}
|
||||
}
|
||||
|
||||
void Hashtable_setSize(Hashtable* this, unsigned int size) {
|
||||
void Hashtable_setSize(Hashtable* this, size_t size) {
|
||||
|
||||
assert(Hashtable_isConsistent(this));
|
||||
|
||||
@ -175,14 +189,14 @@ void Hashtable_setSize(Hashtable* this, unsigned int size) {
|
||||
return;
|
||||
|
||||
HashtableItem* oldBuckets = this->buckets;
|
||||
unsigned int oldSize = this->size;
|
||||
size_t oldSize = this->size;
|
||||
|
||||
this->size = nextPrime(size);
|
||||
this->buckets = (HashtableItem*) xCalloc(this->size, sizeof(HashtableItem));
|
||||
this->items = 0;
|
||||
|
||||
/* rehash */
|
||||
for (unsigned int i = 0; i < oldSize; i++) {
|
||||
for (size_t i = 0; i < oldSize; i++) {
|
||||
if (!oldBuckets[i].value)
|
||||
continue;
|
||||
|
||||
@ -194,15 +208,19 @@ void Hashtable_setSize(Hashtable* this, unsigned int size) {
|
||||
assert(Hashtable_isConsistent(this));
|
||||
}
|
||||
|
||||
void Hashtable_put(Hashtable* this, hkey_t key, void* value) {
|
||||
void Hashtable_put(Hashtable* this, ht_key_t key, void* value) {
|
||||
|
||||
assert(Hashtable_isConsistent(this));
|
||||
assert(this->size > 0);
|
||||
assert(value);
|
||||
|
||||
/* grow on load-factor > 0.7 */
|
||||
if (10 * this->items > 7 * this->size)
|
||||
if (10 * this->items > 7 * this->size) {
|
||||
if (SIZE_MAX / 2 < this->size)
|
||||
CRT_fatalError("Hashtable: size overflow");
|
||||
|
||||
Hashtable_setSize(this, 2 * this->size);
|
||||
}
|
||||
|
||||
insert(this, key, value);
|
||||
|
||||
@ -211,11 +229,11 @@ void Hashtable_put(Hashtable* this, hkey_t key, void* value) {
|
||||
assert(this->size > this->items);
|
||||
}
|
||||
|
||||
void* Hashtable_remove(Hashtable* this, hkey_t key) {
|
||||
unsigned int index = key % this->size;
|
||||
unsigned int probe = 0;
|
||||
void* Hashtable_remove(Hashtable* this, ht_key_t key) {
|
||||
size_t index = key % this->size;
|
||||
size_t probe = 0;
|
||||
#ifndef NDEBUG
|
||||
unsigned int origIndex = index;
|
||||
size_t origIndex = index;
|
||||
#endif
|
||||
|
||||
assert(Hashtable_isConsistent(this));
|
||||
@ -230,7 +248,7 @@ void* Hashtable_remove(Hashtable* this, hkey_t key) {
|
||||
res = this->buckets[index].value;
|
||||
}
|
||||
|
||||
unsigned int next = (index + 1) % this->size;
|
||||
size_t next = (index + 1) % this->size;
|
||||
|
||||
while (this->buckets[next].value && this->buckets[next].probe > 0) {
|
||||
this->buckets[index] = this->buckets[next];
|
||||
@ -266,12 +284,12 @@ void* Hashtable_remove(Hashtable* this, hkey_t key) {
|
||||
return res;
|
||||
}
|
||||
|
||||
void* Hashtable_get(Hashtable* this, hkey_t key) {
|
||||
unsigned int index = key % this->size;
|
||||
unsigned int probe = 0;
|
||||
void* Hashtable_get(Hashtable* this, ht_key_t key) {
|
||||
size_t index = key % this->size;
|
||||
size_t probe = 0;
|
||||
void* res = NULL;
|
||||
#ifndef NDEBUG
|
||||
unsigned int origIndex = index;
|
||||
size_t origIndex = index;
|
||||
#endif
|
||||
|
||||
assert(Hashtable_isConsistent(this));
|
||||
@ -296,7 +314,7 @@ void* Hashtable_get(Hashtable* this, hkey_t key) {
|
||||
|
||||
void Hashtable_foreach(Hashtable* this, Hashtable_PairFunction f, void* userData) {
|
||||
assert(Hashtable_isConsistent(this));
|
||||
for (unsigned int i = 0; i < this->size; i++) {
|
||||
for (size_t i = 0; i < this->size; i++) {
|
||||
HashtableItem* walk = &this->buckets[i];
|
||||
if (walk->value)
|
||||
f(walk->key, walk->value, userData);
|
||||
|
30
Hashtable.h
30
Hashtable.h
@ -8,44 +8,34 @@ in the source distribution for its full text.
|
||||
*/
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
|
||||
|
||||
typedef unsigned int hkey_t;
|
||||
typedef unsigned int ht_key_t;
|
||||
|
||||
typedef void(*Hashtable_PairFunction)(hkey_t key, void* value, void* userdata);
|
||||
typedef void(*Hashtable_PairFunction)(ht_key_t key, void* value, void* userdata);
|
||||
|
||||
typedef struct HashtableItem_ {
|
||||
hkey_t key;
|
||||
unsigned int probe;
|
||||
void* value;
|
||||
} HashtableItem;
|
||||
|
||||
typedef struct Hashtable_ {
|
||||
unsigned int size;
|
||||
HashtableItem* buckets;
|
||||
unsigned int items;
|
||||
bool owner;
|
||||
} Hashtable;
|
||||
typedef struct Hashtable_ Hashtable;
|
||||
|
||||
#ifndef NDEBUG
|
||||
|
||||
unsigned int Hashtable_count(const Hashtable* this);
|
||||
size_t Hashtable_count(const Hashtable* this);
|
||||
|
||||
#endif /* NDEBUG */
|
||||
|
||||
Hashtable* Hashtable_new(unsigned int size, bool owner);
|
||||
Hashtable* Hashtable_new(size_t size, bool owner);
|
||||
|
||||
void Hashtable_delete(Hashtable* this);
|
||||
|
||||
void Hashtable_clear(Hashtable* this);
|
||||
|
||||
void Hashtable_setSize(Hashtable* this, unsigned int size);
|
||||
void Hashtable_setSize(Hashtable* this, size_t size);
|
||||
|
||||
void Hashtable_put(Hashtable* this, hkey_t key, void* value);
|
||||
void Hashtable_put(Hashtable* this, ht_key_t key, void* value);
|
||||
|
||||
void* Hashtable_remove(Hashtable* this, hkey_t key);
|
||||
void* Hashtable_remove(Hashtable* this, ht_key_t key);
|
||||
|
||||
void* Hashtable_get(Hashtable* this, hkey_t key);
|
||||
void* Hashtable_get(Hashtable* this, ht_key_t key);
|
||||
|
||||
void Hashtable_foreach(Hashtable* this, Hashtable_PairFunction f, void* userData);
|
||||
|
||||
|
22
IncSet.c
22
IncSet.c
@ -29,9 +29,9 @@ void IncSet_reset(IncSet* this, IncType type) {
|
||||
IncMode_reset(&this->modes[type]);
|
||||
}
|
||||
|
||||
static const char* const searchFunctions[] = {"Next ", "Cancel ", " Search: ", NULL};
|
||||
static const char* const searchKeys[] = {"F3", "Esc", " "};
|
||||
static const int searchEvents[] = {KEY_F(3), 27, ERR};
|
||||
static const char* const searchFunctions[] = {"Next ", "Prev ", "Cancel ", " Search: ", NULL};
|
||||
static const char* const searchKeys[] = {"F3", "S-F3", "Esc", " "};
|
||||
static const int searchEvents[] = {KEY_F(3), KEY_F(15), 27, ERR};
|
||||
|
||||
static inline void IncMode_initSearch(IncMode* search) {
|
||||
memset(search, 0, sizeof(IncMode));
|
||||
@ -133,14 +133,6 @@ static bool IncMode_find(IncMode* mode, Panel* panel, IncMode_GetPanelValue getP
|
||||
}
|
||||
}
|
||||
|
||||
bool IncSet_next(IncSet* this, IncType type, Panel* panel, IncMode_GetPanelValue getPanelValue) {
|
||||
return IncMode_find(&this->modes[type], panel, getPanelValue, 1);
|
||||
}
|
||||
|
||||
bool IncSet_prev(IncSet* this, IncType type, Panel* panel, IncMode_GetPanelValue getPanelValue) {
|
||||
return IncMode_find(&this->modes[type], panel, getPanelValue, -1);
|
||||
}
|
||||
|
||||
bool IncSet_handleKey(IncSet* this, int ch, Panel* panel, IncMode_GetPanelValue getPanelValue, Vector* lines) {
|
||||
if (ch == ERR)
|
||||
return true;
|
||||
@ -149,11 +141,11 @@ bool IncSet_handleKey(IncSet* this, int ch, Panel* panel, IncMode_GetPanelValue
|
||||
int size = Panel_size(panel);
|
||||
bool filterChanged = false;
|
||||
bool doSearch = true;
|
||||
if (ch == KEY_F(3)) {
|
||||
if (ch == KEY_F(3) || ch == KEY_F(15)) {
|
||||
if (size == 0)
|
||||
return true;
|
||||
|
||||
IncMode_find(mode, panel, getPanelValue, 1);
|
||||
IncMode_find(mode, panel, getPanelValue, ch == KEY_F(3) ? 1 : -1);
|
||||
doSearch = false;
|
||||
} else if (0 < ch && ch < 255 && isprint((unsigned char)ch)) {
|
||||
if (mode->index < INCMODE_MAX) {
|
||||
@ -167,7 +159,7 @@ bool IncSet_handleKey(IncSet* this, int ch, Panel* panel, IncMode_GetPanelValue
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if ((ch == KEY_BACKSPACE || ch == 127)) {
|
||||
} else if (ch == KEY_BACKSPACE || ch == 127) {
|
||||
if (mode->index > 0) {
|
||||
mode->index--;
|
||||
mode->buffer[mode->index] = 0;
|
||||
@ -182,7 +174,7 @@ bool IncSet_handleKey(IncSet* this, int ch, Panel* panel, IncMode_GetPanelValue
|
||||
doSearch = false;
|
||||
}
|
||||
} else if (ch == KEY_RESIZE) {
|
||||
Panel_resize(panel, COLS, LINES - panel->y - 1);
|
||||
doSearch = (mode->index > 0);
|
||||
} else {
|
||||
if (mode->isFilter) {
|
||||
filterChanged = true;
|
||||
|
4
IncSet.h
4
IncSet.h
@ -48,10 +48,6 @@ IncSet* IncSet_new(FunctionBar* bar);
|
||||
|
||||
void IncSet_delete(IncSet* this);
|
||||
|
||||
bool IncSet_next(IncSet* this, IncType type, Panel* panel, IncMode_GetPanelValue getPanelValue);
|
||||
|
||||
bool IncSet_prev(IncSet* this, IncType type, Panel* panel, IncMode_GetPanelValue getPanelValue);
|
||||
|
||||
bool IncSet_handleKey(IncSet* this, int ch, Panel* panel, IncMode_GetPanelValue getPanelValue, Vector* lines);
|
||||
|
||||
const char* IncSet_getListItemValue(Panel* panel, int i);
|
||||
|
@ -26,7 +26,7 @@ InfoScreen* InfoScreen_init(InfoScreen* this, const Process* process, FunctionBa
|
||||
if (!bar) {
|
||||
bar = FunctionBar_new(InfoScreenFunctions, InfoScreenKeys, InfoScreenEvents);
|
||||
}
|
||||
this->display = Panel_new(0, 1, COLS, height, false, Class(ListItem), bar);
|
||||
this->display = Panel_new(0, 1, COLS, height, Class(ListItem), false, bar);
|
||||
this->inc = IncSet_new(bar);
|
||||
this->lines = Vector_new(this->display->items->type, true, DEFAULT_SIZE);
|
||||
Panel_setHeader(this->display, panelHeader);
|
||||
@ -54,9 +54,9 @@ void InfoScreen_drawTitled(InfoScreen* this, const char* fmt, ...) {
|
||||
|
||||
attrset(CRT_colors[METER_TEXT]);
|
||||
mvhline(0, 0, ' ', COLS);
|
||||
mvwprintw(stdscr, 0, 0, title);
|
||||
mvaddstr(0, 0, title);
|
||||
attrset(CRT_colors[DEFAULT_COLOR]);
|
||||
Panel_draw(this->display, true, true, true);
|
||||
Panel_draw(this->display, true, true, true, false);
|
||||
|
||||
IncSet_drawBar(this->inc);
|
||||
}
|
||||
@ -89,7 +89,7 @@ void InfoScreen_run(InfoScreen* this) {
|
||||
bool looping = true;
|
||||
while (looping) {
|
||||
|
||||
Panel_draw(panel, false, true, true);
|
||||
Panel_draw(panel, false, true, true, false);
|
||||
IncSet_drawBar(this->inc);
|
||||
|
||||
if (this->inc->active) {
|
||||
|
@ -57,7 +57,7 @@ void ListItem_append(ListItem* this, const char* text) {
|
||||
this->value[newLen] = '\0';
|
||||
}
|
||||
|
||||
static long ListItem_compare(const void* cast1, const void* cast2) {
|
||||
static int ListItem_compare(const void* cast1, const void* cast2) {
|
||||
const ListItem* obj1 = (const ListItem*) cast1;
|
||||
const ListItem* obj2 = (const ListItem*) cast2;
|
||||
return strcmp(obj1->value, obj2->value);
|
||||
|
@ -24,8 +24,36 @@ static const int LoadMeter_attributes[] = {
|
||||
LOAD
|
||||
};
|
||||
|
||||
static const int OK_attributes[] = {
|
||||
METER_VALUE_OK
|
||||
};
|
||||
|
||||
static const int Medium_attributes[] = {
|
||||
METER_VALUE_WARN
|
||||
};
|
||||
|
||||
static const int High_attributes[] = {
|
||||
METER_VALUE_ERROR
|
||||
};
|
||||
|
||||
static void LoadAverageMeter_updateValues(Meter* this, char* buffer, size_t size) {
|
||||
Platform_getLoadAverage(&this->values[0], &this->values[1], &this->values[2]);
|
||||
|
||||
// only show bar for 1min value
|
||||
this->curItems = 1;
|
||||
|
||||
// change bar color and total based on value
|
||||
if (this->values[0] < 1.0) {
|
||||
this->curAttributes = OK_attributes;
|
||||
this->total = 1.0;
|
||||
} else if (this->values[0] < this->pl->cpuCount) {
|
||||
this->curAttributes = Medium_attributes;
|
||||
this->total = this->pl->cpuCount;
|
||||
} else {
|
||||
this->curAttributes = High_attributes;
|
||||
this->total = 2 * this->pl->cpuCount;
|
||||
}
|
||||
|
||||
xSnprintf(buffer, size, "%.2f/%.2f/%.2f", this->values[0], this->values[1], this->values[2]);
|
||||
}
|
||||
|
||||
@ -43,9 +71,19 @@ static void LoadAverageMeter_display(const Object* cast, RichString* out) {
|
||||
static void LoadMeter_updateValues(Meter* this, char* buffer, size_t size) {
|
||||
double five, fifteen;
|
||||
Platform_getLoadAverage(&this->values[0], &five, &fifteen);
|
||||
if (this->values[0] > this->total) {
|
||||
this->total = this->values[0];
|
||||
|
||||
// change bar color and total based on value
|
||||
if (this->values[0] < 1.0) {
|
||||
this->curAttributes = OK_attributes;
|
||||
this->total = 1.0;
|
||||
} else if (this->values[0] < this->pl->cpuCount) {
|
||||
this->curAttributes = Medium_attributes;
|
||||
this->total = this->pl->cpuCount;
|
||||
} else {
|
||||
this->curAttributes = High_attributes;
|
||||
this->total = 2 * this->pl->cpuCount;
|
||||
}
|
||||
|
||||
xSnprintf(buffer, size, "%.2f", this->values[0]);
|
||||
}
|
||||
|
||||
|
36
MainPanel.c
36
MainPanel.c
@ -44,6 +44,11 @@ void MainPanel_pidSearch(MainPanel* this, int ch) {
|
||||
}
|
||||
}
|
||||
|
||||
static const char* MainPanel_getValue(Panel* this, int i) {
|
||||
const Process* p = (const Process*) Panel_get(this, i);
|
||||
return Process_getCommand(p);
|
||||
}
|
||||
|
||||
static HandlerResult MainPanel_eventHandler(Panel* super, int ch) {
|
||||
MainPanel* this = (MainPanel*) super;
|
||||
|
||||
@ -51,7 +56,12 @@ static HandlerResult MainPanel_eventHandler(Panel* super, int ch) {
|
||||
|
||||
Htop_Reaction reaction = HTOP_OK;
|
||||
|
||||
if (ch != ERR && ch != KEY_RESIZE)
|
||||
/* Let supervising ScreenManager handle resize */
|
||||
if (ch == KEY_RESIZE)
|
||||
return IGNORED;
|
||||
|
||||
/* reset on every normal key */
|
||||
if (ch != ERR)
|
||||
this->state->hideProcessSelection = false;
|
||||
|
||||
if (EVENT_IS_HEADER_CLICK(ch)) {
|
||||
@ -72,7 +82,7 @@ static HandlerResult MainPanel_eventHandler(Panel* super, int ch) {
|
||||
reaction |= HTOP_RECALCULATE | HTOP_REDRAW_BAR | HTOP_SAVE_SETTINGS;
|
||||
result = HANDLED;
|
||||
} else if (ch != ERR && this->inc->active) {
|
||||
bool filterChanged = IncSet_handleKey(this->inc, ch, super, (IncMode_GetPanelValue) MainPanel_getValue, NULL);
|
||||
bool filterChanged = IncSet_handleKey(this->inc, ch, super, MainPanel_getValue, NULL);
|
||||
if (filterChanged) {
|
||||
this->state->pl->incFilter = IncSet_filter(this->inc);
|
||||
reaction = HTOP_REFRESH | HTOP_REDRAW_BAR;
|
||||
@ -102,7 +112,7 @@ static HandlerResult MainPanel_eventHandler(Panel* super, int ch) {
|
||||
MainPanel_updateTreeFunctions(this, this->state->settings->treeView);
|
||||
}
|
||||
if (reaction & HTOP_UPDATE_PANELHDR) {
|
||||
ProcessList_printHeader(this->state->pl, Panel_getHeader(super));
|
||||
result |= REDRAW;
|
||||
}
|
||||
if (reaction & HTOP_REFRESH) {
|
||||
result |= REFRESH;
|
||||
@ -131,11 +141,6 @@ int MainPanel_selectedPid(MainPanel* this) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
const char* MainPanel_getValue(MainPanel* this, int i) {
|
||||
Process* p = (Process*) Panel_get((Panel*)this, i);
|
||||
return Process_getCommand(p);
|
||||
}
|
||||
|
||||
bool MainPanel_foreachProcess(MainPanel* this, MainPanel_ForeachProcessFn fn, Arg arg, bool* wasAnyTagged) {
|
||||
Panel* super = (Panel*) this;
|
||||
bool ok = true;
|
||||
@ -160,21 +165,32 @@ bool MainPanel_foreachProcess(MainPanel* this, MainPanel_ForeachProcessFn fn, Ar
|
||||
return ok;
|
||||
}
|
||||
|
||||
static void MainPanel_drawFunctionBar(Panel* super) {
|
||||
static void MainPanel_drawFunctionBar(Panel* super, bool hideFunctionBar) {
|
||||
MainPanel* this = (MainPanel*) super;
|
||||
|
||||
// Do not hide active search and filter bar.
|
||||
if (hideFunctionBar && !this->inc->active)
|
||||
return;
|
||||
|
||||
IncSet_drawBar(this->inc);
|
||||
if (this->state->pauseProcessUpdate) {
|
||||
FunctionBar_append("PAUSED", CRT_colors[PAUSED]);
|
||||
}
|
||||
}
|
||||
|
||||
static void MainPanel_printHeader(Panel* super) {
|
||||
MainPanel* this = (MainPanel*) super;
|
||||
ProcessList_printHeader(this->state->pl, &super->header);
|
||||
}
|
||||
|
||||
const PanelClass MainPanel_class = {
|
||||
.super = {
|
||||
.extends = Class(Panel),
|
||||
.delete = MainPanel_delete
|
||||
},
|
||||
.eventHandler = MainPanel_eventHandler,
|
||||
.drawFunctionBar = MainPanel_drawFunctionBar
|
||||
.drawFunctionBar = MainPanel_drawFunctionBar,
|
||||
.printHeader = MainPanel_printHeader
|
||||
};
|
||||
|
||||
MainPanel* MainPanel_new() {
|
||||
|
@ -38,8 +38,6 @@ void MainPanel_pidSearch(MainPanel* this, int ch);
|
||||
|
||||
int MainPanel_selectedPid(MainPanel* this);
|
||||
|
||||
const char* MainPanel_getValue(MainPanel* this, int i);
|
||||
|
||||
bool MainPanel_foreachProcess(MainPanel* this, MainPanel_ForeachProcessFn fn, Arg arg, bool* wasAnyTagged);
|
||||
|
||||
extern const PanelClass MainPanel_class;
|
||||
|
11
Meter.c
11
Meter.c
@ -39,6 +39,7 @@ Meter* Meter_new(const struct ProcessList_* pl, int param, const MeterClass* typ
|
||||
this->param = param;
|
||||
this->pl = pl;
|
||||
this->curItems = type->maxItems;
|
||||
this->curAttributes = NULL;
|
||||
this->values = type->maxItems ? xCalloc(type->maxItems, sizeof(double)) : NULL;
|
||||
this->total = type->total;
|
||||
this->caption = xStrdup(type->caption);
|
||||
@ -252,13 +253,14 @@ static void BarMeterMode_draw(Meter* this, int x, int y, int w) {
|
||||
// ...then print the buffer.
|
||||
offset = 0;
|
||||
for (uint8_t i = 0; i < this->curItems; i++) {
|
||||
RichString_setAttrn(&bar, CRT_colors[Meter_attributes(this)[i]], startPos + offset, startPos + offset + blockSizes[i] - 1);
|
||||
int attr = this->curAttributes ? this->curAttributes[i] : Meter_attributes(this)[i];
|
||||
RichString_setAttrn(&bar, CRT_colors[attr], startPos + offset, blockSizes[i]);
|
||||
RichString_printoffnVal(bar, y, x + offset, startPos + offset, MINIMUM(blockSizes[i], w - offset));
|
||||
offset += blockSizes[i];
|
||||
offset = CLAMP(offset, 0, w);
|
||||
}
|
||||
if (offset < w) {
|
||||
RichString_setAttrn(&bar, CRT_colors[BAR_SHADOW], startPos + offset, startPos + w - 1);
|
||||
RichString_setAttrn(&bar, CRT_colors[BAR_SHADOW], startPos + offset, w - offset);
|
||||
RichString_printoffnVal(bar, y, x + offset, startPos + offset, w - offset);
|
||||
}
|
||||
|
||||
@ -290,9 +292,6 @@ static const char* const GraphMeterMode_dotsAscii[] = {
|
||||
/*20*/":", /*21*/":", /*22*/":"
|
||||
};
|
||||
|
||||
static const char* const* GraphMeterMode_dots;
|
||||
static int GraphMeterMode_pixPerRow;
|
||||
|
||||
static void GraphMeterMode_draw(Meter* this, int x, int y, int w) {
|
||||
|
||||
if (!this->drawData) {
|
||||
@ -301,6 +300,8 @@ static void GraphMeterMode_draw(Meter* this, int x, int y, int w) {
|
||||
GraphData* data = this->drawData;
|
||||
const int nValues = METER_BUFFER_LEN;
|
||||
|
||||
const char* const* GraphMeterMode_dots;
|
||||
int GraphMeterMode_pixPerRow;
|
||||
#ifdef HAVE_LIBNCURSESW
|
||||
if (CRT_utf8) {
|
||||
GraphMeterMode_dots = GraphMeterMode_dotsUtf8;
|
||||
|
1
Meter.h
1
Meter.h
@ -100,6 +100,7 @@ struct Meter_ {
|
||||
int h;
|
||||
const ProcessList* pl;
|
||||
uint8_t curItems;
|
||||
const int* curAttributes;
|
||||
double* values;
|
||||
double total;
|
||||
void* meterData;
|
||||
|
2
Object.h
2
Object.h
@ -24,7 +24,7 @@ struct Object_;
|
||||
typedef struct Object_ Object;
|
||||
|
||||
typedef void(*Object_Display)(const Object*, RichString*);
|
||||
typedef long(*Object_Compare)(const void*, const void*);
|
||||
typedef int(*Object_Compare)(const void*, const void*);
|
||||
typedef void(*Object_Delete)(Object*);
|
||||
|
||||
#define Object_getClass(obj_) ((const Object*)(obj_))->klass
|
||||
|
@ -74,7 +74,7 @@ OpenFilesScreen* OpenFilesScreen_new(const Process* process) {
|
||||
} else {
|
||||
this->pid = process->pid;
|
||||
}
|
||||
return (OpenFilesScreen*) InfoScreen_init(&this->super, process, NULL, LINES - 3, " FD TYPE MODE DEVICE SIZE NODE NAME");
|
||||
return (OpenFilesScreen*) InfoScreen_init(&this->super, process, NULL, LINES - 2, " FD TYPE MODE DEVICE SIZE NODE NAME");
|
||||
}
|
||||
|
||||
void OpenFilesScreen_delete(Object* this) {
|
||||
|
70
Panel.c
70
Panel.c
@ -30,7 +30,7 @@ const PanelClass Panel_class = {
|
||||
.eventHandler = Panel_selectByTyping,
|
||||
};
|
||||
|
||||
Panel* Panel_new(int x, int y, int w, int h, bool owner, const ObjectClass* type, FunctionBar* fuBar) {
|
||||
Panel* Panel_new(int x, int y, int w, int h, const ObjectClass* type, bool owner, FunctionBar* fuBar) {
|
||||
Panel* this;
|
||||
this = xMalloc(sizeof(Panel));
|
||||
Object_setClass(this, Class(Panel));
|
||||
@ -76,13 +76,6 @@ void Panel_setSelectionColor(Panel* this, ColorElements colorId) {
|
||||
this->selectionColorId = colorId;
|
||||
}
|
||||
|
||||
RichString* Panel_getHeader(Panel* this) {
|
||||
assert (this != NULL);
|
||||
|
||||
this->needsRedraw = true;
|
||||
return &(this->header);
|
||||
}
|
||||
|
||||
inline void Panel_setHeader(Panel* this, const char* header) {
|
||||
RichString_writeWide(&(this->header), CRT_colors[PANEL_HEADER_FOCUS], header);
|
||||
this->needsRedraw = true;
|
||||
@ -99,10 +92,6 @@ void Panel_move(Panel* this, int x, int y) {
|
||||
void Panel_resize(Panel* this, int w, int h) {
|
||||
assert (this != NULL);
|
||||
|
||||
if (RichString_sizeVal(this->header) > 0) {
|
||||
h--;
|
||||
}
|
||||
|
||||
this->w = w;
|
||||
this->h = h;
|
||||
this->needsRedraw = true;
|
||||
@ -219,7 +208,7 @@ void Panel_splice(Panel* this, Vector* from) {
|
||||
this->needsRedraw = true;
|
||||
}
|
||||
|
||||
void Panel_draw(Panel* this, bool force_redraw, bool focus, bool highlightSelected) {
|
||||
void Panel_draw(Panel* this, bool force_redraw, bool focus, bool highlightSelected, bool hideFunctionBar) {
|
||||
assert (this != NULL);
|
||||
|
||||
int size = Vector_size(this->items);
|
||||
@ -228,20 +217,29 @@ void Panel_draw(Panel* this, bool force_redraw, bool focus, bool highlightSelect
|
||||
int x = this->x;
|
||||
int h = this->h;
|
||||
|
||||
if (hideFunctionBar)
|
||||
h++;
|
||||
|
||||
const int header_attr = focus
|
||||
? CRT_colors[PANEL_HEADER_FOCUS]
|
||||
: CRT_colors[PANEL_HEADER_UNFOCUS];
|
||||
if (force_redraw) {
|
||||
if (Panel_printHeaderFn(this))
|
||||
Panel_printHeader(this);
|
||||
else
|
||||
RichString_setAttr(&this->header, header_attr);
|
||||
}
|
||||
int headerLen = RichString_sizeVal(this->header);
|
||||
if (headerLen > 0) {
|
||||
int attr = focus
|
||||
? CRT_colors[PANEL_HEADER_FOCUS]
|
||||
: CRT_colors[PANEL_HEADER_UNFOCUS];
|
||||
attrset(attr);
|
||||
attrset(header_attr);
|
||||
mvhline(y, x, ' ', this->w);
|
||||
if (scrollH < headerLen) {
|
||||
RichString_setAttr(&this->header, attr);
|
||||
RichString_printoffnVal(this->header, y, x, scrollH,
|
||||
MINIMUM(headerLen - scrollH, this->w));
|
||||
}
|
||||
attrset(CRT_colors[RESET_COLOR]);
|
||||
y++;
|
||||
h--;
|
||||
}
|
||||
|
||||
// ensure scroll area is on screen
|
||||
@ -324,8 +322,8 @@ void Panel_draw(Panel* this, bool force_redraw, bool focus, bool highlightSelect
|
||||
|
||||
if (focus && (this->needsRedraw || force_redraw || !this->wasFocus)) {
|
||||
if (Panel_drawFunctionBarFn(this))
|
||||
Panel_drawFunctionBar(this);
|
||||
else
|
||||
Panel_drawFunctionBar(this, hideFunctionBar);
|
||||
else if (!hideFunctionBar)
|
||||
FunctionBar_draw(this->currentBar);
|
||||
}
|
||||
|
||||
@ -335,13 +333,21 @@ void Panel_draw(Panel* this, bool force_redraw, bool focus, bool highlightSelect
|
||||
move(0, 0);
|
||||
}
|
||||
|
||||
static int Panel_headerHeight(const Panel* this) {
|
||||
return RichString_sizeVal(this->header) > 0 ? 1 : 0;
|
||||
}
|
||||
|
||||
bool Panel_onKey(Panel* this, int key) {
|
||||
assert (this != NULL);
|
||||
|
||||
int size = Vector_size(this->items);
|
||||
const int size = Vector_size(this->items);
|
||||
|
||||
#define CLAMP_INDEX(var, delta, min, max) \
|
||||
CLAMP((var) + (delta), (min), MAXIMUM(0, (max)))
|
||||
#define PANEL_SCROLL(amount) \
|
||||
do { \
|
||||
this->selected += (amount); \
|
||||
this->scrollV = CLAMP(this->scrollV + (amount), 0, MAXIMUM(0, (size - this->h - Panel_headerHeight(this)))); \
|
||||
this->needsRedraw = true; \
|
||||
} while (0)
|
||||
|
||||
switch (key) {
|
||||
case KEY_DOWN:
|
||||
@ -375,27 +381,19 @@ bool Panel_onKey(Panel* this, int key) {
|
||||
break;
|
||||
|
||||
case KEY_PPAGE:
|
||||
this->selected -= (this->h - 1);
|
||||
this->scrollV = CLAMP_INDEX(this->scrollV, -(this->h - 1), 0, size - this->h);
|
||||
this->needsRedraw = true;
|
||||
PANEL_SCROLL(-(this->h - Panel_headerHeight(this)));
|
||||
break;
|
||||
|
||||
case KEY_NPAGE:
|
||||
this->selected += (this->h - 1);
|
||||
this->scrollV = CLAMP_INDEX(this->scrollV, +(this->h - 1), 0, size - this->h);
|
||||
this->needsRedraw = true;
|
||||
PANEL_SCROLL(+(this->h - Panel_headerHeight(this)));
|
||||
break;
|
||||
|
||||
case KEY_WHEELUP:
|
||||
this->selected -= CRT_scrollWheelVAmount;
|
||||
this->scrollV = CLAMP_INDEX(this->scrollV, -CRT_scrollWheelVAmount, 0, size - this->h);
|
||||
this->needsRedraw = true;
|
||||
PANEL_SCROLL(-CRT_scrollWheelVAmount);
|
||||
break;
|
||||
|
||||
case KEY_WHEELDOWN:
|
||||
this->selected += CRT_scrollWheelVAmount;
|
||||
this->scrollV = CLAMP_INDEX(this->scrollV, +CRT_scrollWheelVAmount, 0, size - this->h);
|
||||
this->needsRedraw = true;
|
||||
PANEL_SCROLL(+CRT_scrollWheelVAmount);
|
||||
break;
|
||||
|
||||
case KEY_HOME:
|
||||
@ -420,7 +418,7 @@ bool Panel_onKey(Panel* this, int key) {
|
||||
return false;
|
||||
}
|
||||
|
||||
#undef CLAMP_INDEX
|
||||
#undef PANEL_SCROLL
|
||||
|
||||
// ensure selection within bounds
|
||||
if (this->selected < 0 || size == 0) {
|
||||
|
22
Panel.h
22
Panel.h
@ -36,19 +36,23 @@ typedef enum HandlerResult_ {
|
||||
#define EVENT_HEADER_CLICK_GET_X(ev_) ((ev_) + 10000)
|
||||
|
||||
typedef HandlerResult (*Panel_EventHandler)(Panel*, int);
|
||||
typedef void (*Panel_DrawFunctionBar)(Panel*);
|
||||
typedef void (*Panel_DrawFunctionBar)(Panel*, bool);
|
||||
typedef void (*Panel_PrintHeader)(Panel*);
|
||||
|
||||
typedef struct PanelClass_ {
|
||||
const ObjectClass super;
|
||||
const Panel_EventHandler eventHandler;
|
||||
const Panel_DrawFunctionBar drawFunctionBar;
|
||||
const Panel_PrintHeader printHeader;
|
||||
} PanelClass;
|
||||
|
||||
#define As_Panel(this_) ((const PanelClass*)((this_)->super.klass))
|
||||
#define Panel_eventHandlerFn(this_) As_Panel(this_)->eventHandler
|
||||
#define Panel_eventHandler(this_, ev_) (assert(As_Panel(this_)->eventHandler), As_Panel(this_)->eventHandler((Panel*)(this_), ev_))
|
||||
#define Panel_drawFunctionBarFn(this_) As_Panel(this_)->drawFunctionBar
|
||||
#define Panel_drawFunctionBar(this_) (assert(As_Panel(this_)->drawFunctionBar), As_Panel(this_)->drawFunctionBar((Panel*)(this_)))
|
||||
#define As_Panel(this_) ((const PanelClass*)((this_)->super.klass))
|
||||
#define Panel_eventHandlerFn(this_) As_Panel(this_)->eventHandler
|
||||
#define Panel_eventHandler(this_, ev_) (assert(As_Panel(this_)->eventHandler), As_Panel(this_)->eventHandler((Panel*)(this_), ev_))
|
||||
#define Panel_drawFunctionBarFn(this_) As_Panel(this_)->drawFunctionBar
|
||||
#define Panel_drawFunctionBar(this_, hideFB_) (assert(As_Panel(this_)->drawFunctionBar), As_Panel(this_)->drawFunctionBar((Panel*)(this_), hideFB_))
|
||||
#define Panel_printHeaderFn(this_) As_Panel(this_)->printHeader
|
||||
#define Panel_printHeader(this_) (assert(As_Panel(this_)->printHeader), As_Panel(this_)->printHeader((Panel*)(this_)))
|
||||
|
||||
struct Panel_ {
|
||||
Object super;
|
||||
@ -74,7 +78,7 @@ struct Panel_ {
|
||||
|
||||
extern const PanelClass Panel_class;
|
||||
|
||||
Panel* Panel_new(int x, int y, int w, int h, bool owner, const ObjectClass* type, FunctionBar* fuBar);
|
||||
Panel* Panel_new(int x, int y, int w, int h, const ObjectClass* type, bool owner, FunctionBar* fuBar);
|
||||
|
||||
void Panel_delete(Object* cast);
|
||||
|
||||
@ -84,8 +88,6 @@ void Panel_done(Panel* this);
|
||||
|
||||
void Panel_setSelectionColor(Panel* this, ColorElements colorId);
|
||||
|
||||
RichString* Panel_getHeader(Panel* this);
|
||||
|
||||
void Panel_setHeader(Panel* this, const char* header);
|
||||
|
||||
void Panel_move(Panel* this, int x, int y);
|
||||
@ -116,7 +118,7 @@ int Panel_size(Panel* this);
|
||||
|
||||
void Panel_setSelected(Panel* this, int selected);
|
||||
|
||||
void Panel_draw(Panel* this, bool force_redraw, bool focus, bool highlightSelected);
|
||||
void Panel_draw(Panel* this, bool force_redraw, bool focus, bool highlightSelected, bool hideFunctionBar);
|
||||
|
||||
void Panel_splice(Panel* this, Vector* from);
|
||||
|
||||
|
41
Process.c
41
Process.c
@ -183,34 +183,34 @@ void Process_fillStarttimeBuffer(Process* this) {
|
||||
}
|
||||
|
||||
static inline void Process_writeCommand(const Process* this, int attr, int baseattr, RichString* str) {
|
||||
int start = RichString_size(str), finish = 0;
|
||||
int start = RichString_size(str);
|
||||
int len = 0;
|
||||
const char* comm = this->comm;
|
||||
|
||||
if (this->settings->highlightBaseName || !this->settings->showProgramPath) {
|
||||
int i, basename = 0;
|
||||
for (i = 0; i < this->basenameOffset; i++) {
|
||||
int basename = 0;
|
||||
for (int i = 0; i < this->basenameOffset; i++) {
|
||||
if (comm[i] == '/') {
|
||||
basename = i + 1;
|
||||
} else if (comm[i] == ':') {
|
||||
finish = i + 1;
|
||||
len = i + 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!finish) {
|
||||
if (len == 0) {
|
||||
if (this->settings->showProgramPath) {
|
||||
start += basename;
|
||||
} else {
|
||||
comm += basename;
|
||||
}
|
||||
finish = this->basenameOffset - basename;
|
||||
len = this->basenameOffset - basename;
|
||||
}
|
||||
finish += start - 1;
|
||||
}
|
||||
|
||||
RichString_appendWide(str, attr, comm);
|
||||
|
||||
if (this->settings->highlightBaseName) {
|
||||
RichString_setAttrn(str, baseattr, start, finish);
|
||||
RichString_setAttrn(str, baseattr, start, len);
|
||||
}
|
||||
}
|
||||
|
||||
@ -244,6 +244,11 @@ void Process_outputRate(RichString* str, char* buffer, size_t n, double rate, in
|
||||
}
|
||||
}
|
||||
|
||||
void Process_printLeftAlignedField(RichString* str, int attr, const char* content, unsigned int width) {
|
||||
int c = RichString_appendnWide(str, attr, content, MINIMUM(width, strlen(content)));
|
||||
RichString_appendChr(str, ' ', width + 1 - c);
|
||||
}
|
||||
|
||||
void Process_writeField(const Process* this, RichString* str, ProcessField field) {
|
||||
char buffer[256]; buffer[255] = '\0';
|
||||
int attr = CRT_colors[DEFAULT_COLOR];
|
||||
@ -363,15 +368,13 @@ void Process_writeField(const Process* this, RichString* str, ProcessField field
|
||||
case USER: {
|
||||
if (Process_getuid != this->st_uid)
|
||||
attr = CRT_colors[PROCESS_SHADOW];
|
||||
|
||||
if (this->user) {
|
||||
xSnprintf(buffer, n, "%-9s ", this->user);
|
||||
} else {
|
||||
xSnprintf(buffer, n, "%-9d ", this->st_uid);
|
||||
}
|
||||
if (buffer[9] != '\0') {
|
||||
buffer[9] = ' ';
|
||||
buffer[10] = '\0';
|
||||
Process_printLeftAlignedField(str, attr, this->user, 9);
|
||||
return;
|
||||
}
|
||||
|
||||
xSnprintf(buffer, n, "%-9d ", this->st_uid);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
@ -477,14 +480,14 @@ bool Process_sendSignal(Process* this, Arg sgn) {
|
||||
return ok;
|
||||
}
|
||||
|
||||
long Process_pidCompare(const void* v1, const void* v2) {
|
||||
int Process_pidCompare(const void* v1, const void* v2) {
|
||||
const Process* p1 = (const Process*)v1;
|
||||
const Process* p2 = (const Process*)v2;
|
||||
|
||||
return SPACESHIP_NUMBER(p1->pid, p2->pid);
|
||||
}
|
||||
|
||||
long Process_compare(const void* v1, const void* v2) {
|
||||
int Process_compare(const void* v1, const void* v2) {
|
||||
const Process *p1, *p2;
|
||||
const Settings *settings = ((const Process*)v1)->settings;
|
||||
|
||||
@ -498,7 +501,7 @@ long Process_compare(const void* v1, const void* v2) {
|
||||
|
||||
ProcessField key = Settings_getActiveSortKey(settings);
|
||||
|
||||
long result = Process_compareByKey(p1, p2, key);
|
||||
int result = Process_compareByKey(p1, p2, key);
|
||||
|
||||
// Implement tie-breaker (needed to make tree mode more stable)
|
||||
if (!result)
|
||||
@ -507,7 +510,7 @@ long Process_compare(const void* v1, const void* v2) {
|
||||
return result;
|
||||
}
|
||||
|
||||
long Process_compareByKey_Base(const Process* p1, const Process* p2, ProcessField key) {
|
||||
int Process_compareByKey_Base(const Process* p1, const Process* p2, ProcessField key) {
|
||||
int r;
|
||||
|
||||
switch (key) {
|
||||
|
10
Process.h
10
Process.h
@ -122,7 +122,7 @@ typedef struct ProcessFieldData_ {
|
||||
|
||||
// Implemented in platform-specific code:
|
||||
void Process_writeField(const Process* this, RichString* str, ProcessField field);
|
||||
long Process_compare(const void* v1, const void* v2);
|
||||
int Process_compare(const void* v1, const void* v2);
|
||||
void Process_delete(Object* cast);
|
||||
bool Process_isThread(const Process* this);
|
||||
extern const ProcessFieldData Process_fields[LAST_PROCESSFIELD];
|
||||
@ -131,7 +131,7 @@ extern int Process_pidDigits;
|
||||
|
||||
typedef Process*(*Process_New)(const struct Settings_*);
|
||||
typedef void (*Process_WriteField)(const Process*, RichString*, ProcessField);
|
||||
typedef long (*Process_CompareByKey)(const Process*, const Process*, ProcessField);
|
||||
typedef int (*Process_CompareByKey)(const Process*, const Process*, ProcessField);
|
||||
typedef const char* (*Process_GetCommandStr)(const Process*);
|
||||
|
||||
typedef struct ProcessClass_ {
|
||||
@ -179,6 +179,8 @@ void Process_fillStarttimeBuffer(Process* this);
|
||||
|
||||
void Process_outputRate(RichString* str, char* buffer, size_t n, double rate, int coloring);
|
||||
|
||||
void Process_printLeftAlignedField(RichString* str, int attr, const char* content, unsigned int width);
|
||||
|
||||
void Process_display(const Object* cast, RichString* out);
|
||||
|
||||
void Process_done(Process* this);
|
||||
@ -199,8 +201,8 @@ bool Process_changePriorityBy(Process* this, Arg delta);
|
||||
|
||||
bool Process_sendSignal(Process* this, Arg sgn);
|
||||
|
||||
long Process_pidCompare(const void* v1, const void* v2);
|
||||
int Process_pidCompare(const void* v1, const void* v2);
|
||||
|
||||
long Process_compareByKey_Base(const Process* p1, const Process* p2, ProcessField key);
|
||||
int Process_compareByKey_Base(const Process* p1, const Process* p2, ProcessField key);
|
||||
|
||||
#endif
|
||||
|
@ -112,6 +112,13 @@ void ProcessList_printHeader(ProcessList* this, RichString* header) {
|
||||
}
|
||||
|
||||
RichString_appendWide(header, color, alignedProcessFieldTitle(fields[i]));
|
||||
if (key == fields[i] && RichString_getCharVal(*header, RichString_size(header) - 1) == ' ') {
|
||||
header->chlen--; // rewind to override space
|
||||
RichString_appendnWide(header,
|
||||
CRT_colors[PANEL_SELECTION_FOCUS],
|
||||
CRT_treeStr[Settings_getActiveDirection(this->settings) == 1 ? TREE_STR_DESC : TREE_STR_ASC],
|
||||
1);
|
||||
}
|
||||
if (COMM == fields[i] && settings->showMergedCommand) {
|
||||
RichString_appendAscii(header, color, "(merged)");
|
||||
}
|
||||
@ -141,7 +148,7 @@ void ProcessList_remove(ProcessList* this, Process* p) {
|
||||
Process* pp = Hashtable_remove(this->processTable, p->pid);
|
||||
assert(pp == p); (void)pp;
|
||||
|
||||
unsigned int pid = p->pid;
|
||||
pid_t pid = p->pid;
|
||||
int idx = Vector_indexOf(this->processes, p, Process_pidCompare);
|
||||
assert(idx != -1);
|
||||
|
||||
@ -149,7 +156,12 @@ void ProcessList_remove(ProcessList* this, Process* p) {
|
||||
Vector_remove(this->processes, idx);
|
||||
}
|
||||
|
||||
assert(Hashtable_get(this->processTable, pid) == NULL); (void)pid;
|
||||
if (this->following != -1 && this->following == pid) {
|
||||
this->following = -1;
|
||||
Panel_setSelectionColor(this->panel, PANEL_SELECTION_FOCUS);
|
||||
}
|
||||
|
||||
assert(Hashtable_get(this->processTable, pid) == NULL);
|
||||
assert(Hashtable_count(this->processTable) == Vector_count(this->processes));
|
||||
}
|
||||
|
||||
@ -348,14 +360,14 @@ static void ProcessList_buildTreeBranch(ProcessList* this, pid_t pid, int level,
|
||||
Vector_delete(children);
|
||||
}
|
||||
|
||||
static long ProcessList_treeProcessCompare(const void* v1, const void* v2) {
|
||||
static int ProcessList_treeProcessCompare(const void* v1, const void* v2) {
|
||||
const Process *p1 = (const Process*)v1;
|
||||
const Process *p2 = (const Process*)v2;
|
||||
|
||||
return SPACESHIP_NUMBER(p1->tree_left, p2->tree_left);
|
||||
}
|
||||
|
||||
static long ProcessList_treeProcessCompareByPID(const void* v1, const void* v2) {
|
||||
static int ProcessList_treeProcessCompareByPID(const void* v1, const void* v2) {
|
||||
const Process *p1 = (const Process*)v1;
|
||||
const Process *p2 = (const Process*)v2;
|
||||
|
||||
@ -486,7 +498,6 @@ void ProcessList_rebuildPanel(ProcessList* this) {
|
||||
const char* incFilter = this->incFilter;
|
||||
|
||||
int currPos = Panel_getSelectedIndex(this->panel);
|
||||
pid_t currPid = this->following != -1 ? this->following : 0;
|
||||
int currScrollV = this->panel->scrollV;
|
||||
|
||||
Panel_prune(this->panel);
|
||||
@ -502,7 +513,7 @@ void ProcessList_rebuildPanel(ProcessList* this) {
|
||||
continue;
|
||||
|
||||
Panel_set(this->panel, idx, (Object*)p);
|
||||
if ((this->following == -1 && idx == currPos) || (this->following != -1 && p->pid == currPid)) {
|
||||
if ((this->following == -1 && idx == currPos) || (this->following != -1 && p->pid == this->following)) {
|
||||
Panel_setSelected(this->panel, idx);
|
||||
this->panel->scrollV = currScrollV;
|
||||
}
|
||||
|
@ -27,7 +27,7 @@ ProcessLocksScreen* ProcessLocksScreen_new(const Process* process) {
|
||||
this->pid = process->tgid;
|
||||
else
|
||||
this->pid = process->pid;
|
||||
return (ProcessLocksScreen*) InfoScreen_init(&this->super, process, NULL, LINES-3, " ID TYPE EXCLUSION READ/WRITE DEVICE:INODE START END FILENAME");
|
||||
return (ProcessLocksScreen*) InfoScreen_init(&this->super, process, NULL, LINES - 2, " ID TYPE EXCLUSION READ/WRITE DEVICE:INODE START END FILENAME");
|
||||
}
|
||||
|
||||
void ProcessLocksScreen_delete(Object* this) {
|
||||
|
66
RichString.c
66
RichString.c
@ -48,33 +48,35 @@ static void RichString_setLen(RichString* this, int len) {
|
||||
|
||||
#ifdef HAVE_LIBNCURSESW
|
||||
|
||||
static inline void RichString_writeFromWide(RichString* this, int attrs, const char* data_c, int from, int len) {
|
||||
static inline int RichString_writeFromWide(RichString* this, int attrs, const char* data_c, int from, int len) {
|
||||
wchar_t data[len + 1];
|
||||
len = mbstowcs(data, data_c, len);
|
||||
if (len < 0)
|
||||
return;
|
||||
if (len <= 0)
|
||||
return 0;
|
||||
|
||||
int newLen = from + len;
|
||||
RichString_setLen(this, newLen);
|
||||
for (int i = from, j = 0; i < newLen; i++, j++) {
|
||||
this->chptr[i] = (CharType) { .attr = attrs & 0xffffff, .chars = { (iswprint(data[j]) ? data[j] : '?') } };
|
||||
}
|
||||
|
||||
return wcswidth(data, len);
|
||||
}
|
||||
|
||||
static inline void RichString_writeFromAscii(RichString* this, int attrs, const char* data, int from, int len) {
|
||||
static inline int RichString_writeFromAscii(RichString* this, int attrs, const char* data, int from, int len) {
|
||||
int newLen = from + len;
|
||||
RichString_setLen(this, newLen);
|
||||
for (int i = from, j = 0; i < newLen; i++, j++) {
|
||||
this->chptr[i] = (CharType) { .attr = attrs & 0xffffff, .chars = { (isprint(data[j]) ? data[j] : '?') } };
|
||||
}
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
inline void RichString_setAttrn(RichString* this, int attrs, int start, int finish) {
|
||||
cchar_t* ch = this->chptr + start;
|
||||
finish = CLAMP(finish, 0, this->chlen - 1);
|
||||
for (int i = start; i <= finish; i++) {
|
||||
ch->attr = attrs;
|
||||
ch++;
|
||||
inline void RichString_setAttrn(RichString* this, int attrs, int start, int charcount) {
|
||||
int end = CLAMP(start + charcount, 0, this->chlen);
|
||||
for (int i = start; i < end; i++) {
|
||||
this->chptr[i].attr = attrs;
|
||||
}
|
||||
}
|
||||
|
||||
@ -91,25 +93,25 @@ int RichString_findChar(RichString* this, char c, int start) {
|
||||
|
||||
#else /* HAVE_LIBNCURSESW */
|
||||
|
||||
static inline void RichString_writeFromWide(RichString* this, int attrs, const char* data_c, int from, int len) {
|
||||
static inline int RichString_writeFromWide(RichString* this, int attrs, const char* data_c, int from, int len) {
|
||||
int newLen = from + len;
|
||||
RichString_setLen(this, newLen);
|
||||
for (int i = from, j = 0; i < newLen; i++, j++) {
|
||||
this->chptr[i] = (((unsigned char)data_c[j]) >= 32 ? ((unsigned char)data_c[j]) : '?') | attrs;
|
||||
}
|
||||
this->chptr[newLen] = 0;
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
static inline void RichString_writeFromAscii(RichString* this, int attrs, const char* data_c, int from, int len) {
|
||||
RichString_writeFromWide(this, attrs, data_c, from, len);
|
||||
static inline int RichString_writeFromAscii(RichString* this, int attrs, const char* data_c, int from, int len) {
|
||||
return RichString_writeFromWide(this, attrs, data_c, from, len);
|
||||
}
|
||||
|
||||
void RichString_setAttrn(RichString* this, int attrs, int start, int finish) {
|
||||
chtype* ch = this->chptr + start;
|
||||
finish = CLAMP(finish, 0, this->chlen - 1);
|
||||
for (int i = start; i <= finish; i++) {
|
||||
*ch = (*ch & 0xff) | attrs;
|
||||
ch++;
|
||||
void RichString_setAttrn(RichString* this, int attrs, int start, int charcount) {
|
||||
int end = CLAMP(start + charcount, 0, this->chlen);
|
||||
for (int i = start; i < end; i++) {
|
||||
this->chptr[i] = (this->chptr[i] & 0xff) | attrs;
|
||||
}
|
||||
}
|
||||
|
||||
@ -142,29 +144,29 @@ void RichString_appendChr(RichString* this, char c, int count) {
|
||||
}
|
||||
|
||||
void RichString_setAttr(RichString* this, int attrs) {
|
||||
RichString_setAttrn(this, attrs, 0, this->chlen - 1);
|
||||
RichString_setAttrn(this, attrs, 0, this->chlen);
|
||||
}
|
||||
|
||||
void RichString_appendWide(RichString* this, int attrs, const char* data) {
|
||||
RichString_writeFromWide(this, attrs, data, this->chlen, strlen(data));
|
||||
int RichString_appendWide(RichString* this, int attrs, const char* data) {
|
||||
return RichString_writeFromWide(this, attrs, data, this->chlen, strlen(data));
|
||||
}
|
||||
|
||||
void RichString_appendnWide(RichString* this, int attrs, const char* data, int len) {
|
||||
RichString_writeFromWide(this, attrs, data, this->chlen, len);
|
||||
int RichString_appendnWide(RichString* this, int attrs, const char* data, int len) {
|
||||
return RichString_writeFromWide(this, attrs, data, this->chlen, len);
|
||||
}
|
||||
|
||||
void RichString_writeWide(RichString* this, int attrs, const char* data) {
|
||||
RichString_writeFromWide(this, attrs, data, 0, strlen(data));
|
||||
int RichString_writeWide(RichString* this, int attrs, const char* data) {
|
||||
return RichString_writeFromWide(this, attrs, data, 0, strlen(data));
|
||||
}
|
||||
|
||||
void RichString_appendAscii(RichString* this, int attrs, const char* data) {
|
||||
RichString_writeFromAscii(this, attrs, data, this->chlen, strlen(data));
|
||||
int RichString_appendAscii(RichString* this, int attrs, const char* data) {
|
||||
return RichString_writeFromAscii(this, attrs, data, this->chlen, strlen(data));
|
||||
}
|
||||
|
||||
void RichString_appendnAscii(RichString* this, int attrs, const char* data, int len) {
|
||||
RichString_writeFromAscii(this, attrs, data, this->chlen, len);
|
||||
int RichString_appendnAscii(RichString* this, int attrs, const char* data, int len) {
|
||||
return RichString_writeFromAscii(this, attrs, data, this->chlen, len);
|
||||
}
|
||||
|
||||
void RichString_writeAscii(RichString* this, int attrs, const char* data) {
|
||||
RichString_writeFromAscii(this, attrs, data, 0, strlen(data));
|
||||
int RichString_writeAscii(RichString* this, int attrs, const char* data) {
|
||||
return RichString_writeFromAscii(this, attrs, data, 0, strlen(data));
|
||||
}
|
||||
|
14
RichString.h
14
RichString.h
@ -42,7 +42,7 @@ typedef struct RichString_ {
|
||||
int highlightAttr;
|
||||
} RichString;
|
||||
|
||||
void RichString_setAttrn(RichString* this, int attrs, int start, int finish);
|
||||
void RichString_setAttrn(RichString* this, int attrs, int start, int charcount);
|
||||
|
||||
int RichString_findChar(RichString* this, char c, int start);
|
||||
|
||||
@ -52,16 +52,16 @@ void RichString_setAttr(RichString* this, int attrs);
|
||||
|
||||
void RichString_appendChr(RichString* this, char c, int count);
|
||||
|
||||
void RichString_appendWide(RichString* this, int attrs, const char* data);
|
||||
int RichString_appendWide(RichString* this, int attrs, const char* data);
|
||||
|
||||
void RichString_appendnWide(RichString* this, int attrs, const char* data, int len);
|
||||
int RichString_appendnWide(RichString* this, int attrs, const char* data, int len);
|
||||
|
||||
void RichString_writeWide(RichString* this, int attrs, const char* data);
|
||||
int RichString_writeWide(RichString* this, int attrs, const char* data);
|
||||
|
||||
void RichString_appendAscii(RichString* this, int attrs, const char* data);
|
||||
int RichString_appendAscii(RichString* this, int attrs, const char* data);
|
||||
|
||||
void RichString_appendnAscii(RichString* this, int attrs, const char* data, int len);
|
||||
int RichString_appendnAscii(RichString* this, int attrs, const char* data, int len);
|
||||
|
||||
void RichString_writeAscii(RichString* this, int attrs, const char* data);
|
||||
int RichString_writeAscii(RichString* this, int attrs, const char* data);
|
||||
|
||||
#endif
|
||||
|
@ -123,8 +123,8 @@ static void ScreenManager_drawPanels(ScreenManager* this, int focus, bool force_
|
||||
const int nPanels = this->panelCount;
|
||||
for (int i = 0; i < nPanels; i++) {
|
||||
Panel* panel = (Panel*) Vector_get(this->panels, i);
|
||||
Panel_draw(panel, force_redraw, i == focus, !((panel == this->state->panel) && this->state->hideProcessSelection));
|
||||
mvvline(panel->y, panel->x + panel->w, ' ', panel->h + 1);
|
||||
Panel_draw(panel, force_redraw, i == focus, !((panel == this->state->panel) && this->state->hideProcessSelection), State_hideFunctionBar(this->state));
|
||||
mvvline(panel->y, panel->x + panel->w, ' ', panel->h + (State_hideFunctionBar(this->state) ? 1 : 0));
|
||||
}
|
||||
}
|
||||
|
||||
@ -141,7 +141,7 @@ void ScreenManager_run(ScreenManager* this, Panel** lastFocus, int* lastKey) {
|
||||
|
||||
bool timedOut = true;
|
||||
bool redraw = true;
|
||||
bool force_redraw = false;
|
||||
bool force_redraw = true;
|
||||
bool rescan = false;
|
||||
int sortTimeout = 0;
|
||||
int resetSortTimeout = 5;
|
||||
|
@ -221,6 +221,8 @@ static bool Settings_read(Settings* this, const char* fileName, int initialCpuCo
|
||||
} else if (String_eq(option[0], "right_meter_modes")) {
|
||||
Settings_readMeterModes(this, option[1], 1);
|
||||
didReadMeters = true;
|
||||
} else if (String_eq(option[0], "hide_function_bar")) {
|
||||
this->hideFunctionBar = atoi(option[1]);
|
||||
#ifdef HAVE_LIBHWLOC
|
||||
} else if (String_eq(option[0], "topology_affinity")) {
|
||||
this->topologyAffinity = !!atoi(option[1]);
|
||||
@ -315,6 +317,7 @@ bool Settings_write(Settings* this) {
|
||||
fprintf(fd, "left_meter_modes="); writeMeterModes(this, fd, 0);
|
||||
fprintf(fd, "right_meters="); writeMeters(this, fd, 1);
|
||||
fprintf(fd, "right_meter_modes="); writeMeterModes(this, fd, 1);
|
||||
fprintf(fd, "hide_function_bar=%d\n", (int) this->hideFunctionBar);
|
||||
#ifdef HAVE_LIBHWLOC
|
||||
fprintf(fd, "topology_affinity=%d\n", (int) this->topologyAffinity);
|
||||
#endif
|
||||
@ -352,6 +355,7 @@ Settings* Settings_new(int initialCpuCount) {
|
||||
this->findCommInCmdline = true;
|
||||
this->stripExeFromCmdline = true;
|
||||
this->showMergedCommand = false;
|
||||
this->hideFunctionBar = 0;
|
||||
#ifdef HAVE_LIBHWLOC
|
||||
this->topologyAffinity = false;
|
||||
#endif
|
||||
|
@ -64,6 +64,7 @@ typedef struct Settings_ {
|
||||
bool accountGuestInCPUMeter;
|
||||
bool headerMargin;
|
||||
bool enableMouse;
|
||||
int hideFunctionBar; // 0 - off, 1 - on ESC until next input, 2 - permanently
|
||||
#ifdef HAVE_LIBHWLOC
|
||||
bool topologyAffinity;
|
||||
#endif
|
||||
|
@ -19,7 +19,7 @@ in the source distribution for its full text.
|
||||
|
||||
|
||||
Panel* SignalsPanel_new() {
|
||||
Panel* this = Panel_new(1, 1, 1, 1, true, Class(ListItem), FunctionBar_newEnterEsc("Send ", "Cancel "));
|
||||
Panel* this = Panel_new(1, 1, 1, 1, Class(ListItem), true, FunctionBar_newEnterEsc("Send ", "Cancel "));
|
||||
const int defaultSignal = SIGTERM;
|
||||
int defaultPosition = 15;
|
||||
unsigned int i;
|
||||
|
2
Vector.h
2
Vector.h
@ -58,7 +58,7 @@ unsigned int Vector_count(const Vector* this);
|
||||
|
||||
#else /* NDEBUG */
|
||||
|
||||
static inline Object* Vector_get(Vector* this, int idx) {
|
||||
static inline Object* Vector_get(const Vector* this, int idx) {
|
||||
return this->array[idx];
|
||||
}
|
||||
|
||||
|
22
XUtils.c
22
XUtils.c
@ -13,6 +13,7 @@ in the source distribution for its full text.
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
@ -36,9 +37,21 @@ void* xMalloc(size_t size) {
|
||||
return data;
|
||||
}
|
||||
|
||||
void* xMallocArray(size_t nmemb, size_t size) {
|
||||
assert(nmemb > 0);
|
||||
assert(size > 0);
|
||||
if (SIZE_MAX / nmemb < size) {
|
||||
fail();
|
||||
}
|
||||
return xMalloc(nmemb * size);
|
||||
}
|
||||
|
||||
void* xCalloc(size_t nmemb, size_t size) {
|
||||
assert(nmemb > 0);
|
||||
assert(size > 0);
|
||||
if (SIZE_MAX / nmemb < size) {
|
||||
fail();
|
||||
}
|
||||
void* data = calloc(nmemb, size);
|
||||
if (!data) {
|
||||
fail();
|
||||
@ -56,6 +69,15 @@ void* xRealloc(void* ptr, size_t size) {
|
||||
return data;
|
||||
}
|
||||
|
||||
void* xReallocArray(void* ptr, size_t nmemb, size_t size) {
|
||||
assert(nmemb > 0);
|
||||
assert(size > 0);
|
||||
if (SIZE_MAX / nmemb < size) {
|
||||
fail();
|
||||
}
|
||||
return xRealloc(ptr, nmemb * size);
|
||||
}
|
||||
|
||||
char* String_cat(const char* s1, const char* s2) {
|
||||
const size_t l1 = strlen(s1);
|
||||
const size_t l2 = strlen(s2);
|
||||
|
4
XUtils.h
4
XUtils.h
@ -23,10 +23,14 @@ void fail(void) ATTR_NORETURN;
|
||||
|
||||
void* xMalloc(size_t size);
|
||||
|
||||
void* xMallocArray(size_t nmemb, size_t size);
|
||||
|
||||
void* xCalloc(size_t nmemb, size_t size);
|
||||
|
||||
void* xRealloc(void* ptr, size_t size);
|
||||
|
||||
void* xReallocArray(void* ptr, size_t nmemb, size_t size);
|
||||
|
||||
/*
|
||||
* String_startsWith gives better performance if strlen(match) can be computed
|
||||
* at compile time (e.g. when they are immutable string literals). :)
|
||||
|
@ -2,7 +2,7 @@
|
||||
# Process this file with autoconf to produce a configure script.
|
||||
|
||||
AC_PREREQ(2.65)
|
||||
AC_INIT([htop],[3.0.4],[htop@groups.io])
|
||||
AC_INIT([htop],[3.0.5],[htop@groups.io])
|
||||
|
||||
AC_CONFIG_SRCDIR([htop.c])
|
||||
AC_CONFIG_AUX_DIR([.])
|
||||
|
@ -82,7 +82,7 @@ static void DarwinProcess_writeField(const Process* this, RichString* str, Proce
|
||||
RichString_appendWide(str, attr, buffer);
|
||||
}
|
||||
|
||||
static long DarwinProcess_compareByKey(const Process* v1, const Process* v2, ProcessField key) {
|
||||
static int DarwinProcess_compareByKey(const Process* v1, const Process* v2, ProcessField key) {
|
||||
const DarwinProcess* p1 = (const DarwinProcess*)v1;
|
||||
const DarwinProcess* p2 = (const DarwinProcess*)v2;
|
||||
|
||||
|
@ -7,7 +7,6 @@ in the source distribution for its full text.
|
||||
|
||||
#include "DarwinProcessList.h"
|
||||
|
||||
#include <err.h>
|
||||
#include <errno.h>
|
||||
#include <libproc.h>
|
||||
#include <stdbool.h>
|
||||
@ -161,7 +160,7 @@ void ProcessList_delete(ProcessList* this) {
|
||||
|
||||
static double ticksToNanoseconds(const double ticks) {
|
||||
const double nanos_per_sec = 1e9;
|
||||
return ticks / (double) Platform_clockTicksPerSec * Platform_timebaseToNS * nanos_per_sec;
|
||||
return (ticks / Platform_timebaseToNS) * (nanos_per_sec / (double) Platform_clockTicksPerSec);
|
||||
}
|
||||
|
||||
void ProcessList_goThroughEntries(ProcessList* super, bool pauseProcessUpdate) {
|
||||
|
@ -71,14 +71,7 @@ static void DragonFlyBSDProcess_writeField(const Process* this, RichString* str,
|
||||
// add Platform-specific fields here
|
||||
case PID: xSnprintf(buffer, n, "%*d ", Process_pidDigits, (fp->kernel ? -1 : this->pid)); break;
|
||||
case JID: xSnprintf(buffer, n, "%*d ", Process_pidDigits, fp->jid); break;
|
||||
case JAIL: {
|
||||
xSnprintf(buffer, n, "%-11s ", fp->jname);
|
||||
if (buffer[11] != '\0') {
|
||||
buffer[11] = ' ';
|
||||
buffer[12] = '\0';
|
||||
}
|
||||
break;
|
||||
}
|
||||
case JAIL: Process_printLeftAlignedField(str, attr, fp->jname, 11); return;
|
||||
default:
|
||||
Process_writeField(this, str, field);
|
||||
return;
|
||||
@ -86,7 +79,7 @@ static void DragonFlyBSDProcess_writeField(const Process* this, RichString* str,
|
||||
RichString_appendWide(str, attr, buffer);
|
||||
}
|
||||
|
||||
static long DragonFlyBSDProcess_compareByKey(const Process* v1, const Process* v2, ProcessField key) {
|
||||
static int DragonFlyBSDProcess_compareByKey(const Process* v1, const Process* v2, ProcessField key) {
|
||||
const DragonFlyBSDProcess* p1 = (const DragonFlyBSDProcess*)v1;
|
||||
const DragonFlyBSDProcess* p2 = (const DragonFlyBSDProcess*)v2;
|
||||
|
||||
|
@ -15,7 +15,6 @@ in the source distribution for its full text.
|
||||
#include <sys/types.h>
|
||||
#include <sys/sysctl.h>
|
||||
#include <sys/user.h>
|
||||
#include <err.h>
|
||||
#include <fcntl.h>
|
||||
#include <limits.h>
|
||||
#include <string.h>
|
||||
@ -112,7 +111,7 @@ ProcessList* ProcessList_new(UsersTable* usersTable, Hashtable* pidMatchList, ui
|
||||
|
||||
dfpl->kd = kvm_openfiles(NULL, "/dev/null", NULL, 0, errbuf);
|
||||
if (dfpl->kd == NULL) {
|
||||
errx(1, "kvm_open: %s", errbuf);
|
||||
CRT_fatalError("kvm_openfiles() failed");
|
||||
}
|
||||
|
||||
return pl;
|
||||
@ -294,25 +293,20 @@ static inline void DragonFlyBSDProcessList_scanJails(DragonFlyBSDProcessList* df
|
||||
char* nextpos;
|
||||
|
||||
if (sysctlbyname("jail.list", NULL, &len, NULL, 0) == -1) {
|
||||
fprintf(stderr, "initial sysctlbyname / jail.list failed\n");
|
||||
exit(3);
|
||||
CRT_fatalError("initial sysctlbyname / jail.list failed");
|
||||
}
|
||||
retry:
|
||||
if (len == 0)
|
||||
return;
|
||||
|
||||
jls = xMalloc(len);
|
||||
if (jls == NULL) {
|
||||
fprintf(stderr, "xMalloc failed\n");
|
||||
exit(4);
|
||||
}
|
||||
|
||||
if (sysctlbyname("jail.list", jls, &len, NULL, 0) == -1) {
|
||||
if (errno == ENOMEM) {
|
||||
free(jls);
|
||||
goto retry;
|
||||
}
|
||||
fprintf(stderr, "sysctlbyname / jail.list failed\n");
|
||||
exit(5);
|
||||
CRT_fatalError("sysctlbyname / jail.list failed");
|
||||
}
|
||||
|
||||
if (dfpl->jails) {
|
||||
|
@ -71,14 +71,9 @@ static void FreeBSDProcess_writeField(const Process* this, RichString* str, Proc
|
||||
switch (field) {
|
||||
// add FreeBSD-specific fields here
|
||||
case JID: xSnprintf(buffer, n, "%*d ", Process_pidDigits, fp->jid); break;
|
||||
case JAIL: {
|
||||
xSnprintf(buffer, n, "%-11s ", fp->jname);
|
||||
if (buffer[11] != '\0') {
|
||||
buffer[11] = ' ';
|
||||
buffer[12] = '\0';
|
||||
}
|
||||
break;
|
||||
}
|
||||
case JAIL:
|
||||
Process_printLeftAlignedField(str, attr, fp->jname ? fp->jname : "N/A", 11);
|
||||
return;
|
||||
case TTY_NR:
|
||||
if (fp->ttyPath) {
|
||||
if (fp->ttyPath == nodevStr)
|
||||
@ -96,7 +91,7 @@ static void FreeBSDProcess_writeField(const Process* this, RichString* str, Proc
|
||||
RichString_appendWide(str, attr, buffer);
|
||||
}
|
||||
|
||||
static long FreeBSDProcess_compareByKey(const Process* v1, const Process* v2, ProcessField key) {
|
||||
static int FreeBSDProcess_compareByKey(const Process* v1, const Process* v2, ProcessField key) {
|
||||
const FreeBSDProcess* p1 = (const FreeBSDProcess*)v1;
|
||||
const FreeBSDProcess* p2 = (const FreeBSDProcess*)v2;
|
||||
|
||||
|
@ -9,7 +9,6 @@ in the source distribution for its full text.
|
||||
|
||||
#include <assert.h>
|
||||
#include <dirent.h>
|
||||
#include <err.h>
|
||||
#include <limits.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
@ -145,7 +144,7 @@ ProcessList* ProcessList_new(UsersTable* usersTable, Hashtable* pidMatchList, ui
|
||||
|
||||
fpl->kd = kvm_openfiles(NULL, "/dev/null", NULL, 0, errbuf);
|
||||
if (fpl->kd == NULL) {
|
||||
errx(1, "kvm_open: %s", errbuf);
|
||||
CRT_fatalError("kvm_openfiles() failed");
|
||||
}
|
||||
|
||||
fpl->ttys = Hashtable_new(20, true);
|
||||
@ -415,7 +414,7 @@ static char* FreeBSDProcessList_readJailName(const struct kinfo_proc* kproc) {
|
||||
char* jname = NULL;
|
||||
char jnamebuf[MAXHOSTNAMELEN];
|
||||
|
||||
if (kproc->ki_jid != 0 ) {
|
||||
if (kproc->ki_jid != 0) {
|
||||
struct iovec jiov[6];
|
||||
|
||||
memset(jnamebuf, 0, sizeof(jnamebuf));
|
||||
|
10
htop.1.in
10
htop.1.in
@ -42,7 +42,8 @@ Display a help message and exit
|
||||
Show only the given PIDs
|
||||
.TP
|
||||
\fB\-s \-\-sort\-key COLUMN\fR
|
||||
Sort by this column (use \-\-sort\-key help for a column list)
|
||||
Sort by this column (use \-\-sort\-key help for a column list).
|
||||
This will force a list view unless you specify -t at the same time.
|
||||
.TP
|
||||
\fB\-u \-\-user=USERNAME\fR
|
||||
Show only the processes of a given user
|
||||
@ -57,7 +58,8 @@ Disable support of mouse control
|
||||
Output version information and exit
|
||||
.TP
|
||||
\fB\-t \-\-tree
|
||||
Show processes in tree view
|
||||
Show processes in tree view. This can be used to force a tree view when
|
||||
requesting a sort order with -s.
|
||||
.TP
|
||||
\fB\-H \-\-highlight-changes=DELAY\fR
|
||||
Highlight new and old processes
|
||||
@ -135,6 +137,7 @@ select which columns are displayed, in which order.
|
||||
Incrementally search the command lines of all the displayed processes. The
|
||||
currently selected (highlighted) command will update as you type. While in
|
||||
search mode, pressing F3 will cycle through matching occurrences.
|
||||
Pressing Shift-F3 will cycle backwards.
|
||||
|
||||
Alternatively the search can be started by simply typing the command
|
||||
you are looking for, although for the first character normal key
|
||||
@ -184,6 +187,9 @@ Set CPU affinity: mark which CPUs a process is allowed to use.
|
||||
.B u
|
||||
Show only processes owned by a specified user.
|
||||
.TP
|
||||
.B N
|
||||
Sort by PID.
|
||||
.TP
|
||||
.B M
|
||||
Sort by memory usage (top compatibility key).
|
||||
.TP
|
||||
|
9
htop.c
9
htop.c
@ -49,8 +49,8 @@ static void printHelpFlag(void) {
|
||||
"-H --highlight-changes[=DELAY] Highlight new and old processes\n"
|
||||
"-M --no-mouse Disable the mouse\n"
|
||||
"-p --pid=PID[,PID,PID...] Show only the given PIDs\n"
|
||||
"-s --sort-key=COLUMN Sort by COLUMN (try --sort-key=help for a list)\n"
|
||||
"-t --tree Show the tree view by default\n"
|
||||
"-s --sort-key=COLUMN Sort by COLUMN in list view (try --sort-key=help for a list)\n"
|
||||
"-t --tree Show the tree view (can be combined with -s)\n"
|
||||
"-u --user[=USERNAME] Show only processes for a given user (or $USER)\n"
|
||||
"-U --no-unicode Do not use unicode but plain ASCII\n"
|
||||
"-V --version Print version info\n"
|
||||
@ -93,7 +93,7 @@ static CommandLineSettings parseArguments(int argc, char** argv) {
|
||||
.highlightDelaySecs = -1,
|
||||
};
|
||||
|
||||
static struct option long_opts[] =
|
||||
const struct option long_opts[] =
|
||||
{
|
||||
{"help", no_argument, 0, 'h'},
|
||||
{"version", no_argument, 0, 'V'},
|
||||
@ -204,6 +204,7 @@ static CommandLineSettings parseArguments(int argc, char** argv) {
|
||||
}
|
||||
case 'F': {
|
||||
assert(optarg);
|
||||
free(flags.commFilter);
|
||||
flags.commFilter = xStrdup(optarg);
|
||||
|
||||
break;
|
||||
@ -313,8 +314,6 @@ int main(int argc, char** argv) {
|
||||
|
||||
MainPanel_updateTreeFunctions(panel, settings->treeView);
|
||||
|
||||
ProcessList_printHeader(pl, Panel_getHeader((Panel*)panel));
|
||||
|
||||
State state = {
|
||||
.settings = settings,
|
||||
.ut = ut,
|
||||
|
@ -17,7 +17,7 @@ in the source distribution for its full text.
|
||||
|
||||
|
||||
Panel* IOPriorityPanel_new(IOPriority currPrio) {
|
||||
Panel* this = Panel_new(1, 1, 1, 1, true, Class(ListItem), FunctionBar_newEnterEsc("Set ", "Cancel "));
|
||||
Panel* this = Panel_new(1, 1, 1, 1, Class(ListItem), true, FunctionBar_newEnterEsc("Set ", "Cancel "));
|
||||
|
||||
Panel_setHeader(this, "IO Priority:");
|
||||
Panel_add(this, (Object*) ListItem_new("None (based on nice)", IOPriority_None));
|
||||
|
@ -23,13 +23,15 @@ static void* dlopenHandle = NULL;
|
||||
|
||||
int LibSensors_init(FILE* input) {
|
||||
if (!dlopenHandle) {
|
||||
/* Find the unversioned libsensors.so (symlink) and prefer that, but Debian has .so.5 and Fedora .so.4 without
|
||||
matching symlinks (unless people install the -dev packages) */
|
||||
dlopenHandle = dlopen("libsensors.so", RTLD_LAZY);
|
||||
if (!dlopenHandle) {
|
||||
/* Debian contains no unversioned .so in libsensors5, only in the -dev package, so work around that: */
|
||||
if (!dlopenHandle)
|
||||
dlopenHandle = dlopen("libsensors.so.5", RTLD_LAZY);
|
||||
if (!dlopenHandle)
|
||||
goto dlfailure;
|
||||
}
|
||||
if (!dlopenHandle)
|
||||
dlopenHandle = dlopen("libsensors.so.4", RTLD_LAZY);
|
||||
if (!dlopenHandle)
|
||||
goto dlfailure;
|
||||
|
||||
/* Clear any errors */
|
||||
dlerror();
|
||||
@ -84,7 +86,10 @@ void LibSensors_getCPUTemperatures(CPUData* cpus, unsigned int cpuCount) {
|
||||
for (const sensors_chip_name *chip = sym_sensors_get_detected_chips(NULL, &n); chip; chip = sym_sensors_get_detected_chips(NULL, &n)) {
|
||||
char buffer[32];
|
||||
sym_sensors_snprintf_chip_name(buffer, sizeof(buffer), chip);
|
||||
if (!String_startsWith(buffer, "coretemp") && !String_startsWith(buffer, "cpu_thermal"))
|
||||
if (!String_startsWith(buffer, "coretemp") &&
|
||||
!String_startsWith(buffer, "cpu_thermal") &&
|
||||
!String_startsWith(buffer, "k10temp") &&
|
||||
!String_startsWith(buffer, "zenpower"))
|
||||
continue;
|
||||
|
||||
int m = 0;
|
||||
@ -102,6 +107,8 @@ void LibSensors_getCPUTemperatures(CPUData* cpus, unsigned int cpuCount) {
|
||||
} else if (String_startsWith(label, "temp")) {
|
||||
/* Raspberry Pi has only temp1 */
|
||||
tempId = 0;
|
||||
} else if (String_startsWith(label, "Tdie")) {
|
||||
tempId = 0;
|
||||
} else if (String_startsWith(label, "Core ")) {
|
||||
tempId = 1 + atoi(label + strlen("Core "));
|
||||
} else {
|
||||
|
@ -88,9 +88,9 @@ const ProcessFieldData Process_fields[LAST_PROCESSFIELD] = {
|
||||
[OOM] = { .name = "OOM", .title = " OOM ", .description = "OOM (Out-of-Memory) killer score", .flags = PROCESS_FLAG_LINUX_OOM, },
|
||||
[IO_PRIORITY] = { .name = "IO_PRIORITY", .title = "IO ", .description = "I/O priority", .flags = PROCESS_FLAG_LINUX_IOPRIO, },
|
||||
#ifdef HAVE_DELAYACCT
|
||||
[PERCENT_CPU_DELAY] = { .name = "PERCENT_CPU_DELAY", .title = "CPUD% ", .description = "CPU delay %", .flags = 0, },
|
||||
[PERCENT_IO_DELAY] = { .name = "PERCENT_IO_DELAY", .title = "IOD% ", .description = "Block I/O delay %", .flags = 0, },
|
||||
[PERCENT_SWAP_DELAY] = { .name = "PERCENT_SWAP_DELAY", .title = "SWAPD% ", .description = "Swapin delay %", .flags = 0, },
|
||||
[PERCENT_CPU_DELAY] = { .name = "PERCENT_CPU_DELAY", .title = "CPUD% ", .description = "CPU delay %", .flags = PROCESS_FLAG_LINUX_DELAYACCT, },
|
||||
[PERCENT_IO_DELAY] = { .name = "PERCENT_IO_DELAY", .title = "IOD% ", .description = "Block I/O delay %", .flags = PROCESS_FLAG_LINUX_DELAYACCT, },
|
||||
[PERCENT_SWAP_DELAY] = { .name = "PERCENT_SWAP_DELAY", .title = "SWAPD% ", .description = "Swapin delay %", .flags = PROCESS_FLAG_LINUX_DELAYACCT, },
|
||||
#endif
|
||||
[M_PSS] = { .name = "M_PSS", .title = " PSS ", .description = "proportional set size, same as M_RESIDENT but each page is divided by the number of processes sharing it.", .flags = PROCESS_FLAG_LINUX_SMAPS, },
|
||||
[M_SWAP] = { .name = "M_SWAP", .title = " SWAP ", .description = "Size of the process's swapped pages", .flags = PROCESS_FLAG_LINUX_SMAPS, },
|
||||
@ -198,12 +198,11 @@ static bool findCommInCmdline(const char *comm, const char *cmdline, int cmdline
|
||||
/* Try to find procComm in tokenized cmdline - this might in rare cases
|
||||
* mis-identify a string or fail, if comm or cmdline had been unsuitably
|
||||
* modified by the process */
|
||||
const char *token;
|
||||
const char *tokenBase;
|
||||
size_t tokenLen;
|
||||
const size_t commLen = strlen(comm);
|
||||
|
||||
for (token = cmdline + cmdlineBasenameOffset; *token; ) {
|
||||
for (const char *token = cmdline + cmdlineBasenameOffset; *token; ) {
|
||||
for (tokenBase = token; *token && *token != '\n'; ++token) {
|
||||
if (*token == '/') {
|
||||
tokenBase = token + 1;
|
||||
@ -529,30 +528,30 @@ static void LinuxProcess_writeCommand(const Process* this, int attr, int baseAtt
|
||||
if (!lp->mergedCommand.separateComm && commStart == baseStart && highlightBaseName) {
|
||||
/* If it was matched with procExe's basename, make it bold if needed */
|
||||
if (commEnd > baseEnd) {
|
||||
RichString_setAttrn(str, A_BOLD | baseAttr, baseStart, baseEnd - 1);
|
||||
RichString_setAttrn(str, A_BOLD | commAttr, baseEnd, commEnd - 1);
|
||||
RichString_setAttrn(str, A_BOLD | baseAttr, baseStart, baseEnd - baseStart);
|
||||
RichString_setAttrn(str, A_BOLD | commAttr, baseEnd, commEnd - baseEnd);
|
||||
} else if (commEnd < baseEnd) {
|
||||
RichString_setAttrn(str, A_BOLD | commAttr, commStart, commEnd - 1);
|
||||
RichString_setAttrn(str, A_BOLD | baseAttr, commEnd, baseEnd - 1);
|
||||
RichString_setAttrn(str, A_BOLD | commAttr, commStart, commEnd - commStart);
|
||||
RichString_setAttrn(str, A_BOLD | baseAttr, commEnd, baseEnd - commEnd);
|
||||
} else {
|
||||
// Actually should be highlighted commAttr, but marked baseAttr to reduce visual noise
|
||||
RichString_setAttrn(str, A_BOLD | baseAttr, commStart, commEnd - 1);
|
||||
RichString_setAttrn(str, A_BOLD | baseAttr, commStart, commEnd - commStart);
|
||||
}
|
||||
|
||||
baseStart = baseEnd;
|
||||
} else {
|
||||
RichString_setAttrn(str, commAttr, commStart, commEnd - 1);
|
||||
RichString_setAttrn(str, commAttr, commStart, commEnd - commStart);
|
||||
}
|
||||
}
|
||||
|
||||
if (baseStart < baseEnd && highlightBaseName) {
|
||||
RichString_setAttrn(str, baseAttr, baseStart, baseEnd - 1);
|
||||
RichString_setAttrn(str, baseAttr, baseStart, baseEnd - baseStart);
|
||||
}
|
||||
|
||||
if (mc->sep1)
|
||||
RichString_setAttrn(str, CRT_colors[FAILED_READ], strStart + mc->sep1, strStart + mc->sep1);
|
||||
RichString_setAttrn(str, CRT_colors[FAILED_READ], strStart + mc->sep1, 1);
|
||||
if (mc->sep2)
|
||||
RichString_setAttrn(str, CRT_colors[FAILED_READ], strStart + mc->sep2, strStart + mc->sep2);
|
||||
RichString_setAttrn(str, CRT_colors[FAILED_READ], strStart + mc->sep2, 1);
|
||||
}
|
||||
|
||||
static void LinuxProcess_writeCommandField(const Process *this, RichString *str, char *buffer, int n, int attr) {
|
||||
@ -708,39 +707,46 @@ static void LinuxProcess_writeField(const Process* this, RichString* str, Proces
|
||||
return;
|
||||
}
|
||||
case PROC_COMM: {
|
||||
const char* procComm;
|
||||
if (lp->procComm) {
|
||||
attr = CRT_colors[Process_isUserlandThread(this) ? PROCESS_THREAD_COMM : PROCESS_COMM];
|
||||
/* 15 being (TASK_COMM_LEN - 1) */
|
||||
xSnprintf(buffer, n, "%-15.15s ", lp->procComm);
|
||||
procComm = lp->procComm;
|
||||
} else {
|
||||
attr = CRT_colors[PROCESS_SHADOW];
|
||||
xSnprintf(buffer, n, "%-15.15s ", Process_isKernelThread(lp) ? kthreadID : "N/A");
|
||||
procComm = Process_isKernelThread(lp) ? kthreadID : "N/A";
|
||||
}
|
||||
break;
|
||||
/* 15 being (TASK_COMM_LEN - 1) */
|
||||
Process_printLeftAlignedField(str, attr, procComm, 15);
|
||||
return;
|
||||
}
|
||||
case PROC_EXE: {
|
||||
const char* procExe;
|
||||
if (lp->procExe) {
|
||||
attr = CRT_colors[Process_isUserlandThread(this) ? PROCESS_THREAD_BASENAME : PROCESS_BASENAME];
|
||||
if (lp->procExeDeleted)
|
||||
attr = CRT_colors[FAILED_READ];
|
||||
xSnprintf(buffer, n, "%-15.15s ", lp->procExe + lp->procExeBasenameOffset);
|
||||
procExe = lp->procExe + lp->procExeBasenameOffset;
|
||||
} else {
|
||||
attr = CRT_colors[PROCESS_SHADOW];
|
||||
xSnprintf(buffer, n, "%-15.15s ", Process_isKernelThread(lp) ? kthreadID : "N/A");
|
||||
procExe = Process_isKernelThread(lp) ? kthreadID : "N/A";
|
||||
}
|
||||
break;
|
||||
Process_printLeftAlignedField(str, attr, procExe, 15);
|
||||
return;
|
||||
}
|
||||
case CWD:
|
||||
case CWD: {
|
||||
const char* cwd;
|
||||
if (!lp->cwd) {
|
||||
xSnprintf(buffer, n, "%-25s ", "N/A");
|
||||
attr = CRT_colors[PROCESS_SHADOW];
|
||||
cwd = "N/A";
|
||||
} else if (String_startsWith(lp->cwd, "/proc/") && strstr(lp->cwd, " (deleted)") != NULL) {
|
||||
xSnprintf(buffer, n, "%-25s ", "main thread terminated");
|
||||
attr = CRT_colors[PROCESS_SHADOW];
|
||||
cwd = "main thread terminated";
|
||||
} else {
|
||||
xSnprintf(buffer, n, "%-25.25s ", lp->cwd);
|
||||
cwd = lp->cwd;
|
||||
}
|
||||
break;
|
||||
Process_printLeftAlignedField(str, attr, cwd, 25);
|
||||
return;
|
||||
}
|
||||
default:
|
||||
Process_writeField(this, str, field);
|
||||
return;
|
||||
@ -748,7 +754,7 @@ static void LinuxProcess_writeField(const Process* this, RichString* str, Proces
|
||||
RichString_appendWide(str, attr, buffer);
|
||||
}
|
||||
|
||||
static long LinuxProcess_compareByKey(const Process* v1, const Process* v2, ProcessField key) {
|
||||
static int LinuxProcess_compareByKey(const Process* v1, const Process* v2, ProcessField key) {
|
||||
const LinuxProcess* p1 = (const LinuxProcess*)v1;
|
||||
const LinuxProcess* p2 = (const LinuxProcess*)v2;
|
||||
|
||||
|
@ -18,16 +18,17 @@ in the source distribution for its full text.
|
||||
#include "Settings.h"
|
||||
|
||||
|
||||
#define PROCESS_FLAG_LINUX_IOPRIO 0x00000100
|
||||
#define PROCESS_FLAG_LINUX_OPENVZ 0x00000200
|
||||
#define PROCESS_FLAG_LINUX_VSERVER 0x00000400
|
||||
#define PROCESS_FLAG_LINUX_CGROUP 0x00000800
|
||||
#define PROCESS_FLAG_LINUX_OOM 0x00001000
|
||||
#define PROCESS_FLAG_LINUX_SMAPS 0x00002000
|
||||
#define PROCESS_FLAG_LINUX_CTXT 0x00004000
|
||||
#define PROCESS_FLAG_LINUX_SECATTR 0x00008000
|
||||
#define PROCESS_FLAG_LINUX_LRS_FIX 0x00010000
|
||||
#define PROCESS_FLAG_LINUX_CWD 0x00020000
|
||||
#define PROCESS_FLAG_LINUX_IOPRIO 0x00000100
|
||||
#define PROCESS_FLAG_LINUX_OPENVZ 0x00000200
|
||||
#define PROCESS_FLAG_LINUX_VSERVER 0x00000400
|
||||
#define PROCESS_FLAG_LINUX_CGROUP 0x00000800
|
||||
#define PROCESS_FLAG_LINUX_OOM 0x00001000
|
||||
#define PROCESS_FLAG_LINUX_SMAPS 0x00002000
|
||||
#define PROCESS_FLAG_LINUX_CTXT 0x00004000
|
||||
#define PROCESS_FLAG_LINUX_SECATTR 0x00008000
|
||||
#define PROCESS_FLAG_LINUX_LRS_FIX 0x00010000
|
||||
#define PROCESS_FLAG_LINUX_CWD 0x00020000
|
||||
#define PROCESS_FLAG_LINUX_DELAYACCT 0x00040000
|
||||
|
||||
|
||||
/* LinuxProcessMergedCommand is populated by LinuxProcess_makeCommandStr: It
|
||||
|
@ -102,7 +102,7 @@ static void LinuxProcessList_initTtyDrivers(LinuxProcessList* this) {
|
||||
|
||||
int numDrivers = 0;
|
||||
int allocd = 10;
|
||||
ttyDrivers = xMalloc(sizeof(TtyDriver) * allocd);
|
||||
ttyDrivers = xMallocArray(allocd, sizeof(TtyDriver));
|
||||
char* at = buf;
|
||||
while (*at != '\0') {
|
||||
at = strchr(at, ' '); // skip first token
|
||||
@ -136,7 +136,7 @@ static void LinuxProcessList_initTtyDrivers(LinuxProcessList* this) {
|
||||
numDrivers++;
|
||||
if (numDrivers == allocd) {
|
||||
allocd += 10;
|
||||
ttyDrivers = xRealloc(ttyDrivers, sizeof(TtyDriver) * allocd);
|
||||
ttyDrivers = xReallocArray(ttyDrivers, allocd, sizeof(TtyDriver));
|
||||
}
|
||||
}
|
||||
numDrivers++;
|
||||
@ -208,10 +208,6 @@ ProcessList* ProcessList_new(UsersTable* usersTable, Hashtable* pidMatchList, ui
|
||||
ProcessList_init(pl, Class(LinuxProcess), usersTable, pidMatchList, userId);
|
||||
LinuxProcessList_initTtyDrivers(this);
|
||||
|
||||
#ifdef HAVE_DELAYACCT
|
||||
LinuxProcessList_initNetlinkSocket(this);
|
||||
#endif
|
||||
|
||||
// Initialize page size
|
||||
pageSize = sysconf(_SC_PAGESIZE);
|
||||
if (pageSize == -1)
|
||||
@ -488,7 +484,7 @@ static inline uint64_t fast_strtoull_hex(char **str, int maxlen) {
|
||||
return result;
|
||||
}
|
||||
|
||||
static void LinuxProcessList_calcLibSize_helper(ATTR_UNUSED hkey_t key, void* value, void* data) {
|
||||
static void LinuxProcessList_calcLibSize_helper(ATTR_UNUSED ht_key_t key, void* value, void* data) {
|
||||
if (!data)
|
||||
return;
|
||||
|
||||
@ -955,12 +951,19 @@ static int handleNetlinkMsg(struct nl_msg* nlmsg, void* linuxProcess) {
|
||||
static void LinuxProcessList_readDelayAcctData(LinuxProcessList* this, LinuxProcess* process) {
|
||||
struct nl_msg* msg;
|
||||
|
||||
if (!this->netlink_socket) {
|
||||
LinuxProcessList_initNetlinkSocket(this);
|
||||
if (!this->netlink_socket) {
|
||||
goto delayacct_failure;
|
||||
}
|
||||
}
|
||||
|
||||
if (nl_socket_modify_cb(this->netlink_socket, NL_CB_VALID, NL_CB_CUSTOM, handleNetlinkMsg, process) < 0) {
|
||||
return;
|
||||
goto delayacct_failure;
|
||||
}
|
||||
|
||||
if (! (msg = nlmsg_alloc())) {
|
||||
return;
|
||||
goto delayacct_failure;
|
||||
}
|
||||
|
||||
if (! genlmsg_put(msg, NL_AUTO_PID, NL_AUTO_SEQ, this->netlink_family, 0, NLM_F_REQUEST, TASKSTATS_CMD_GET, TASKSTATS_VERSION)) {
|
||||
@ -972,15 +975,19 @@ static void LinuxProcessList_readDelayAcctData(LinuxProcessList* this, LinuxProc
|
||||
}
|
||||
|
||||
if (nl_send_sync(this->netlink_socket, msg) < 0) {
|
||||
process->swapin_delay_percent = NAN;
|
||||
process->blkio_delay_percent = NAN;
|
||||
process->cpu_delay_percent = NAN;
|
||||
return;
|
||||
goto delayacct_failure;
|
||||
}
|
||||
|
||||
if (nl_recvmsgs_default(this->netlink_socket) < 0) {
|
||||
return;
|
||||
goto delayacct_failure;
|
||||
}
|
||||
|
||||
return;
|
||||
|
||||
delayacct_failure:
|
||||
process->swapin_delay_percent = NAN;
|
||||
process->blkio_delay_percent = NAN;
|
||||
process->cpu_delay_percent = NAN;
|
||||
}
|
||||
|
||||
#endif
|
||||
@ -1419,7 +1426,9 @@ static bool LinuxProcessList_recurseProcTree(LinuxProcessList* this, openat_arg_
|
||||
}
|
||||
|
||||
#ifdef HAVE_DELAYACCT
|
||||
LinuxProcessList_readDelayAcctData(this, lp);
|
||||
if (settings->flags & PROCESS_FLAG_LINUX_DELAYACCT) {
|
||||
LinuxProcessList_readDelayAcctData(this, lp);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (settings->flags & PROCESS_FLAG_LINUX_CGROUP) {
|
||||
@ -1793,7 +1802,9 @@ static void scanCPUFreqencyFromCPUinfo(LinuxProcessList* this) {
|
||||
continue;
|
||||
} else if (
|
||||
(sscanf(buffer, "cpu MHz : %lf", &frequency) == 1) ||
|
||||
(sscanf(buffer, "cpu MHz: %lf", &frequency) == 1)
|
||||
(sscanf(buffer, "cpu MHz: %lf", &frequency) == 1) ||
|
||||
(sscanf(buffer, "clock : %lfMHz", &frequency) == 1) ||
|
||||
(sscanf(buffer, "clock: %lfMHz", &frequency) == 1)
|
||||
) {
|
||||
if (cpuid < 0 || cpuid > (cpus - 1)) {
|
||||
continue;
|
||||
|
@ -202,7 +202,7 @@ static void OpenBSDProcess_writeField(const Process* this, RichString* str, Proc
|
||||
RichString_appendWide(str, attr, buffer);
|
||||
}
|
||||
|
||||
static long OpenBSDProcess_compareByKey(const Process* v1, const Process* v2, ProcessField key) {
|
||||
static int OpenBSDProcess_compareByKey(const Process* v1, const Process* v2, ProcessField key) {
|
||||
const OpenBSDProcess* p1 = (const OpenBSDProcess*)v1;
|
||||
const OpenBSDProcess* p2 = (const OpenBSDProcess*)v2;
|
||||
|
||||
|
@ -8,7 +8,6 @@ in the source distribution for its full text.
|
||||
|
||||
#include "OpenBSDProcessList.h"
|
||||
|
||||
#include <err.h>
|
||||
#include <kvm.h>
|
||||
#include <limits.h>
|
||||
#include <stdlib.h>
|
||||
@ -57,11 +56,11 @@ ProcessList* ProcessList_new(UsersTable* usersTable, Hashtable* pidMatchList, ui
|
||||
|
||||
size = sizeof(fscale);
|
||||
if (sysctl(fmib, 2, &fscale, &size, NULL, 0) < 0) {
|
||||
err(1, "fscale sysctl call failed");
|
||||
CRT_fatalError("fscale sysctl call failed");
|
||||
}
|
||||
|
||||
if ((pageSize = sysconf(_SC_PAGESIZE)) == -1)
|
||||
err(1, "pagesize sysconf call failed");
|
||||
CRT_fatalError("pagesize sysconf call failed");
|
||||
pageSizeKB = pageSize / ONE_K;
|
||||
|
||||
for (int i = 0; i <= pl->cpuCount; i++) {
|
||||
@ -72,7 +71,7 @@ ProcessList* ProcessList_new(UsersTable* usersTable, Hashtable* pidMatchList, ui
|
||||
|
||||
opl->kd = kvm_openfiles(NULL, NULL, NULL, KVM_NO_FILES, errbuf);
|
||||
if (opl->kd == NULL) {
|
||||
errx(1, "kvm_open: %s", errbuf);
|
||||
CRT_fatalError("kvm_openfiles() failed");
|
||||
}
|
||||
|
||||
return pl;
|
||||
@ -97,7 +96,7 @@ static void OpenBSDProcessList_scanMemoryInfo(ProcessList* pl) {
|
||||
size_t size_uvmexp = sizeof(uvmexp);
|
||||
|
||||
if (sysctl(uvmexp_mib, 2, &uvmexp, &size_uvmexp, NULL, 0) < 0) {
|
||||
err(1, "uvmexp sysctl call failed");
|
||||
CRT_fatalError("uvmexp sysctl call failed");
|
||||
}
|
||||
|
||||
pl->totalMem = uvmexp.npages * pageSizeKB;
|
||||
@ -109,7 +108,7 @@ static void OpenBSDProcessList_scanMemoryInfo(ProcessList* pl) {
|
||||
size_t size_bcstats = sizeof(bcstats);
|
||||
|
||||
if (sysctl(bcache_mib, 3, &bcstats, &size_bcstats, NULL, 0) < 0) {
|
||||
err(1, "cannot get vfs.bcachestat");
|
||||
CRT_fatalError("cannot get vfs.bcachestat");
|
||||
}
|
||||
|
||||
pl->cachedMem = bcstats.numbufpages * pageSizeKB;
|
||||
|
@ -205,7 +205,7 @@ double Platform_setCPUValues(Meter* this, int cpu) {
|
||||
|
||||
percent = isnan(percent) ? 0.0 : CLAMP(percent, 0.0, 100.0);
|
||||
|
||||
v[CPU_METER_FREQUENCY] = NAN;
|
||||
v[CPU_METER_FREQUENCY] = cpuData->frequency;
|
||||
v[CPU_METER_TEMPERATURE] = NAN;
|
||||
|
||||
return percent;
|
||||
|
@ -18,17 +18,6 @@ in the source distribution for its full text.
|
||||
#include <sys/syscall.h>
|
||||
|
||||
|
||||
const ProcessClass SolarisProcess_class = {
|
||||
.super = {
|
||||
.extends = Class(Process),
|
||||
.display = Process_display,
|
||||
.delete = Process_delete,
|
||||
.compare = Process_compare
|
||||
},
|
||||
.writeField = SolarisProcess_writeField,
|
||||
.compareByKey = SolarisProcess_compareByKey
|
||||
};
|
||||
|
||||
const ProcessFieldData Process_fields[LAST_PROCESSFIELD] = {
|
||||
[0] = { .name = "", .title = NULL, .description = NULL, .flags = 0, },
|
||||
[PID] = { .name = "PID", .title = "PID", .description = "Process/thread ID", .flags = 0, .pidColumn = true, },
|
||||
@ -78,7 +67,7 @@ void Process_delete(Object* cast) {
|
||||
free(sp);
|
||||
}
|
||||
|
||||
void SolarisProcess_writeField(const Process* this, RichString* str, ProcessField field) {
|
||||
static void SolarisProcess_writeField(const Process* this, RichString* str, ProcessField field) {
|
||||
const SolarisProcess* sp = (const SolarisProcess*) this;
|
||||
char buffer[256]; buffer[255] = '\0';
|
||||
int attr = CRT_colors[DEFAULT_COLOR];
|
||||
@ -90,7 +79,7 @@ void SolarisProcess_writeField(const Process* this, RichString* str, ProcessFiel
|
||||
case TASKID: xSnprintf(buffer, n, "%*d ", Process_pidDigits, sp->taskid); break;
|
||||
case POOLID: xSnprintf(buffer, n, "%*d ", Process_pidDigits, sp->poolid); break;
|
||||
case CONTID: xSnprintf(buffer, n, "%*d ", Process_pidDigits, sp->contid); break;
|
||||
case ZONE: xSnprintf(buffer, n, "%-*s ", ZONENAME_MAX/4, sp->zname); break;
|
||||
case ZONE: Process_printLeftAlignedField(str, attr, sp->zname ? sp->zname : "global", ZONENAME_MAX/4); return;
|
||||
case PID: xSnprintf(buffer, n, "%*d ", Process_pidDigits, sp->realpid); break;
|
||||
case PPID: xSnprintf(buffer, n, "%*d ", Process_pidDigits, sp->realppid); break;
|
||||
case LWPID: xSnprintf(buffer, n, "%*d ", Process_pidDigits, sp->lwpid); break;
|
||||
@ -101,7 +90,7 @@ void SolarisProcess_writeField(const Process* this, RichString* str, ProcessFiel
|
||||
RichString_appendWide(str, attr, buffer);
|
||||
}
|
||||
|
||||
long SolarisProcess_compareByKey(const void* v1, const void* v2, ProcessField key) {
|
||||
static int SolarisProcess_compareByKey(const Process* v1, const Process* v2, ProcessField key) {
|
||||
const SolarisProcess* p1 = (const SolarisProcess*)v1;
|
||||
const SolarisProcess* p2 = (const SolarisProcess*)v2;
|
||||
|
||||
@ -140,3 +129,14 @@ bool Process_isThread(const Process* this) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
const ProcessClass SolarisProcess_class = {
|
||||
.super = {
|
||||
.extends = Class(Process),
|
||||
.display = Process_display,
|
||||
.delete = Process_delete,
|
||||
.compare = Process_compare
|
||||
},
|
||||
.writeField = SolarisProcess_writeField,
|
||||
.compareByKey = SolarisProcess_compareByKey
|
||||
};
|
||||
|
@ -40,10 +40,6 @@ Process* SolarisProcess_new(const Settings* settings);
|
||||
|
||||
void Process_delete(Object* cast);
|
||||
|
||||
void SolarisProcess_writeField(const Process* this, RichString* str, ProcessField field);
|
||||
|
||||
long SolarisProcess_compareByKey(const Process* v1, const Process* v2, ProcessField field);
|
||||
|
||||
bool Process_isThread(const Process* this);
|
||||
|
||||
#endif
|
||||
|
@ -14,7 +14,6 @@ in the source distribution for its full text.
|
||||
#include <stdlib.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/user.h>
|
||||
#include <err.h>
|
||||
#include <limits.h>
|
||||
#include <string.h>
|
||||
#include <procfs.h>
|
||||
@ -72,11 +71,11 @@ static inline void SolarisProcessList_scanCPUTime(ProcessList* pl) {
|
||||
const SolarisProcessList* spl = (SolarisProcessList*) pl;
|
||||
int cpus = pl->cpuCount;
|
||||
kstat_t* cpuinfo = NULL;
|
||||
int kchain = 0;
|
||||
kstat_named_t* idletime = NULL;
|
||||
kstat_named_t* intrtime = NULL;
|
||||
kstat_named_t* krnltime = NULL;
|
||||
kstat_named_t* usertime = NULL;
|
||||
kstat_named_t* cpu_freq = NULL;
|
||||
double idlebuf = 0;
|
||||
double intrbuf = 0;
|
||||
double krnlbuf = 0;
|
||||
@ -94,21 +93,31 @@ static inline void SolarisProcessList_scanCPUTime(ProcessList* pl) {
|
||||
// Calculate per-CPU statistics first
|
||||
for (int i = 0; i < cpus; i++) {
|
||||
if (spl->kd != NULL) {
|
||||
cpuinfo = kstat_lookup(spl->kd, "cpu", i, "sys");
|
||||
}
|
||||
if (cpuinfo != NULL) {
|
||||
kchain = kstat_read(spl->kd, cpuinfo, NULL);
|
||||
}
|
||||
if (kchain != -1 ) {
|
||||
idletime = kstat_data_lookup(cpuinfo, "cpu_nsec_idle");
|
||||
intrtime = kstat_data_lookup(cpuinfo, "cpu_nsec_intr");
|
||||
krnltime = kstat_data_lookup(cpuinfo, "cpu_nsec_kernel");
|
||||
usertime = kstat_data_lookup(cpuinfo, "cpu_nsec_user");
|
||||
if ((cpuinfo = kstat_lookup(spl->kd, "cpu", i, "sys")) != NULL) {
|
||||
if (kstat_read(spl->kd, cpuinfo, NULL) != -1) {
|
||||
idletime = kstat_data_lookup(cpuinfo, "cpu_nsec_idle");
|
||||
intrtime = kstat_data_lookup(cpuinfo, "cpu_nsec_intr");
|
||||
krnltime = kstat_data_lookup(cpuinfo, "cpu_nsec_kernel");
|
||||
usertime = kstat_data_lookup(cpuinfo, "cpu_nsec_user");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
assert( (idletime != NULL) && (intrtime != NULL)
|
||||
&& (krnltime != NULL) && (usertime != NULL) );
|
||||
|
||||
if (pl->settings->showCPUFrequency) {
|
||||
if (spl->kd != NULL) {
|
||||
if ((cpuinfo = kstat_lookup(spl->kd, "cpu_info", i, NULL)) != NULL) {
|
||||
if (kstat_read(spl->kd, cpuinfo, NULL) != -1) {
|
||||
cpu_freq = kstat_data_lookup(cpuinfo, "current_clock_Hz");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
assert( cpu_freq != NULL );
|
||||
}
|
||||
|
||||
CPUData* cpuData = &(spl->cpus[i + arrskip]);
|
||||
|
||||
uint64_t totaltime = (idletime->value.ui64 - cpuData->lidle)
|
||||
@ -128,6 +137,8 @@ static inline void SolarisProcessList_scanCPUTime(ProcessList* pl) {
|
||||
cpuData->lkrnl = krnltime->value.ui64;
|
||||
cpuData->lintr = intrtime->value.ui64;
|
||||
cpuData->lidle = idletime->value.ui64;
|
||||
// Add frequency in MHz
|
||||
cpuData->frequency = pl->settings->showCPUFrequency ? (double)cpu_freq->value.ui64 / 1E6 : NAN;
|
||||
// Accumulate the current percentages into buffers for later average calculation
|
||||
if (cpus > 1) {
|
||||
userbuf += cpuData->userPercent;
|
||||
@ -165,8 +176,8 @@ static inline void SolarisProcessList_scanMemoryInfo(ProcessList* pl) {
|
||||
|
||||
// Part 1 - physical memory
|
||||
if (spl->kd != NULL && meminfo == NULL) {
|
||||
// Look up the kstat chain just one, it never changes
|
||||
meminfo = kstat_lookup(spl->kd, "unix", 0, "system_pages");
|
||||
// Look up the kstat chain just once, it never changes
|
||||
meminfo = kstat_lookup(spl->kd, "unix", 0, "system_pages");
|
||||
}
|
||||
if (meminfo != NULL) {
|
||||
ksrphyserr = kstat_read(spl->kd, meminfo, NULL);
|
||||
|
@ -33,6 +33,7 @@ typedef struct CPUData_ {
|
||||
double irqPercent;
|
||||
double idlePercent;
|
||||
double systemAllPercent;
|
||||
double frequency;
|
||||
uint64_t luser;
|
||||
uint64_t lkrnl;
|
||||
uint64_t lintr;
|
||||
|
Reference in New Issue
Block a user