From 728b04bbb5667291f1e56058240fcd7e03cbfe74 Mon Sep 17 00:00:00 2001 From: Nathan Scott Date: Wed, 26 Aug 2020 10:15:00 +1000 Subject: [PATCH] Merge branch 'ci-hwloc-job' of https://github.com/bertwesarg/htop into bertwesarg-ci-hwloc-job --- Action.c | 5 +- AffinityPanel.c | 399 +++++++++++++++++++++++++++++++++++++++--- AffinityPanel.h | 23 ++- CRT.c | 68 ++++--- CRT.h | 28 ++- CheckItem.c | 7 +- DisplayOptionsPanel.c | 3 + Panel.c | 8 + Panel.h | 2 + ProcessList.c | 19 +- Settings.c | 13 ++ Settings.h | 3 + Vector.c | 12 ++ Vector.h | 2 + 14 files changed, 529 insertions(+), 63 deletions(-) diff --git a/Action.c b/Action.c index a7747f52..363c2b98 100644 --- a/Action.c +++ b/Action.c @@ -318,10 +318,11 @@ static Htop_Reaction actionSetAffinity(State* st) { if (!p) return HTOP_OK; Affinity* affinity1 = Affinity_get(p, st->pl); if (!affinity1) return HTOP_OK; - Panel* affinityPanel = AffinityPanel_new(st->pl, affinity1); + int width; + Panel* affinityPanel = AffinityPanel_new(st->pl, affinity1, &width); Affinity_delete(affinity1); - void* set = Action_pickFromVector(st, affinityPanel, 15, true); + void* set = Action_pickFromVector(st, affinityPanel, width, true); if (set) { Affinity* affinity2 = AffinityPanel_getAffinity(affinityPanel, st->pl); bool ok = MainPanel_foreachProcess((MainPanel*)panel, (MainPanel_ForeachProcessFn) Affinity_set, (Arg){ .v = affinity2 }, NULL); diff --git a/AffinityPanel.c b/AffinityPanel.c index d9f1612b..7accb2ab 100644 --- a/AffinityPanel.c +++ b/AffinityPanel.c @@ -8,69 +8,416 @@ in the source distribution for its full text. #include "AffinityPanel.h" #include "CRT.h" -#include "CheckItem.h" +#include "Vector.h" #include #include +#ifdef HAVE_LIBHWLOC +#include +#endif + /*{ #include "Panel.h" #include "Affinity.h" #include "ProcessList.h" -#include "ListItem.h" + }*/ -static HandlerResult AffinityPanel_eventHandler(Panel* this, int ch) { - CheckItem* selected = (CheckItem*) Panel_getSelected(this); +typedef struct MaskItem_ { + Object super; + const char* text; + const char* indent; + int value; /* tri-state: 0 - off, 1 - some set, 2 - all set */ + int sub_tree; /* tri-state: 0 - no sub-tree, 1 - open sub-tree, 2 - closed sub-tree */ + Vector *children; + #ifdef HAVE_LIBHWLOC + bool ownCpuset; + hwloc_bitmap_t cpuset; + #else + int cpu; + #endif +} MaskItem; + +static void MaskItem_delete(Object* cast) { + MaskItem* this = (MaskItem*) cast; + free((void*)this->text); + if (this->indent) + free((void*)this->indent); + Vector_delete(this->children); + #ifdef HAVE_LIBHWLOC + if (this->ownCpuset) + hwloc_bitmap_free(this->cpuset); + #endif + free(this); +} + +static void MaskItem_display(Object* cast, RichString* out) { + MaskItem* this = (MaskItem*)cast; + assert (this != NULL); + if (this->value == 2) + RichString_append(out, CRT_colors[CHECK_MARK], CRT_checkStr[CHECK_STR_FULL]); + else if (this->value == 1) + RichString_append(out, CRT_colors[CHECK_MARK], CRT_checkStr[CHECK_STR_PARTIAL]); + else + RichString_append(out, CRT_colors[CHECK_MARK], CRT_checkStr[CHECK_STR_NONE]); + RichString_append(out, CRT_colors[CHECK_TEXT], " "); + if (this->indent) + RichString_append(out, CRT_colors[PROCESS_TREE], this->indent); + if (this->sub_tree) { + RichString_append(out, CRT_colors[PROCESS_TREE], + this->sub_tree == 1 + ? CRT_collapStr[COLLAP_STR_OPEN] + : CRT_collapStr[COLLAP_STR_CLOSED]); + RichString_append(out, CRT_colors[CHECK_TEXT], " "); + } + RichString_append(out, CRT_colors[CHECK_TEXT], this->text); +} + +static ObjectClass MaskItem_class = { + .display = MaskItem_display, + .delete = MaskItem_delete +}; + +#ifdef HAVE_LIBHWLOC + +static MaskItem* MaskItem_newMask(const char* text, const char* indent, hwloc_bitmap_t cpuset, bool owner) { + MaskItem* this = AllocThis(MaskItem); + this->text = xStrdup(text); + this->indent = xStrdup(indent); + this->value = 0; + this->ownCpuset = owner; + this->cpuset = cpuset; + this->sub_tree = hwloc_bitmap_weight(cpuset) > 1 ? 1 : 0; + this->children = Vector_new(Class(MaskItem), true, DEFAULT_SIZE); + return this; +} + +#endif + +static MaskItem* MaskItem_newSingleton(const char* text, int cpu, bool isSet) { + MaskItem* this = AllocThis(MaskItem); + this->text = xStrdup(text); + this->indent = NULL; + this->sub_tree = 0; + this->children = Vector_new(Class(MaskItem), true, DEFAULT_SIZE); + + #ifdef HAVE_LIBHWLOC + this->ownCpuset = true; + this->cpuset = hwloc_bitmap_alloc(); + hwloc_bitmap_set(this->cpuset, cpu); + (void)isSet; + #else + this->cpu = cpu; + #endif + this->value = 2 * isSet; + + return this; +} + +typedef struct AffinityPanel_ { + Panel super; + ProcessList* pl; + bool topoView; + Vector *cpuids; + unsigned width; + + #ifdef HAVE_LIBHWLOC + MaskItem *topoRoot; + hwloc_const_cpuset_t allCpuset; + hwloc_bitmap_t workCpuset; + #endif +} AffinityPanel; + +static void AffinityPanel_delete(Object* cast) { + AffinityPanel* this = (AffinityPanel*) cast; + Panel* super = (Panel*) this; + Panel_done(super); + Vector_delete(this->cpuids); + #ifdef HAVE_LIBHWLOC + hwloc_bitmap_free(this->workCpuset); + MaskItem_delete((Object*) this->topoRoot); + #endif + free(this); +} + +#ifdef HAVE_LIBHWLOC + +static void AffinityPanel_updateItem(AffinityPanel* this, MaskItem* item) { + Panel* super = (Panel*) this; + + item->value = hwloc_bitmap_isincluded(item->cpuset, this->workCpuset) ? 2 : + hwloc_bitmap_intersects(item->cpuset, this->workCpuset) ? 1 : 0; + + Panel_add(super, (Object*) item); +} + +static void AffinityPanel_updateTopo(AffinityPanel* this, MaskItem* item) { + AffinityPanel_updateItem(this, item); + + if (item->sub_tree == 2) + return; + + for (int i = 0; i < Vector_size(item->children); i++) + AffinityPanel_updateTopo(this, (MaskItem*) Vector_get(item->children, i)); +} + +#endif + +static void AffinityPanel_update(AffinityPanel* this, bool keepSelected) { + Panel* super = (Panel*) this; + + FunctionBar_setLabel(super->currentBar, KEY_F(3), this->topoView ? "Collapse/Expand" : ""); + FunctionBar_draw(super->currentBar, NULL); + + int oldSelected = Panel_getSelectedIndex(super); + Panel_prune(super); + + #ifdef HAVE_LIBHWLOC + if (this->topoView) + AffinityPanel_updateTopo(this, this->topoRoot); + else { + for (int i = 0; i < Vector_size(this->cpuids); i++) + AffinityPanel_updateItem(this, (MaskItem*) Vector_get(this->cpuids, i)); + } + #else + Panel_splice(super, this->cpuids); + #endif + + if (keepSelected) + Panel_setSelected(super, oldSelected); + + super->needsRedraw = true; +} + +static HandlerResult AffinityPanel_eventHandler(Panel* super, int ch) { + AffinityPanel* this = (AffinityPanel*) super; + HandlerResult result = IGNORED; + MaskItem* selected = (MaskItem*) Panel_getSelected(super); + bool keepSelected = true; + switch(ch) { case KEY_MOUSE: case KEY_RECLICK: case ' ': - CheckItem_set(selected, ! (CheckItem_get(selected)) ); - return HANDLED; + #ifdef HAVE_LIBHWLOC + if (selected->value == 2) { + /* Item was selected, so remove this mask from the top cpuset. */ + hwloc_bitmap_andnot(this->workCpuset, this->workCpuset, selected->cpuset); + selected->value = 0; + } else { + /* Item was not or only partial selected, so set all bits from this object + in the top cpuset. */ + hwloc_bitmap_or(this->workCpuset, this->workCpuset, selected->cpuset); + selected->value = 2; + } + #else + selected->value = 2 * !selected->value; /* toggle between 0 and 2 */ + #endif + + result = HANDLED; + break; + + #ifdef HAVE_LIBHWLOC + + case KEY_F(1): + hwloc_bitmap_copy(this->workCpuset, this->allCpuset); + result = HANDLED; + break; + + case KEY_F(2): + this->topoView = !this->topoView; + keepSelected = false; + + result = HANDLED; + break; + + case KEY_F(3): + case '-': + case '+': + if (selected->sub_tree) + selected->sub_tree = 1 + !(selected->sub_tree - 1); /* toggle between 1 and 2 */ + + result = HANDLED; + break; + + #endif + case 0x0a: case 0x0d: case KEY_ENTER: - return BREAK_LOOP; + result = BREAK_LOOP; + break; } - return IGNORED; + + if (HANDLED == result) + AffinityPanel_update(this, keepSelected); + + return result; } +#ifdef HAVE_LIBHWLOC + +static MaskItem *AffinityPanel_addObject(AffinityPanel* this, hwloc_obj_t obj, unsigned indent, MaskItem *parent) { + const char* type_name = hwloc_obj_type_string(obj->type); + const char* index_prefix = " #"; + unsigned depth = obj->depth; + unsigned index = obj->logical_index; + size_t off = 0, left = 10 * depth; + char buf[64], indent_buf[left + 1]; + + if (obj->type == HWLOC_OBJ_PU) { + index = Settings_cpuId(this->pl->settings, obj->os_index); + type_name = "CPU"; + index_prefix = ""; + } + + indent_buf[0] = '\0'; + if (depth > 0) { + for (unsigned i = 1; i < depth; i++) { + xSnprintf(&indent_buf[off], left, "%s ", (indent & (1u << i)) ? CRT_treeStr[TREE_STR_VERT] : " "); + size_t len = strlen(&indent_buf[off]); + off += len, left -= len; + } + xSnprintf(&indent_buf[off], left, "%s%s ", + obj->next_sibling ? CRT_treeStr[TREE_STR_RTEE] : CRT_treeStr[TREE_STR_BEND], + CRT_treeStr[TREE_STR_HORZ]); + size_t len = strlen(&indent_buf[off]); + off += len, left -= len; + } + + xSnprintf(buf, 64, "%s%s%u", type_name, index_prefix, index); + + MaskItem *item = MaskItem_newMask(buf, indent_buf, obj->complete_cpuset, false); + if (parent) + Vector_add(parent->children, item); + + if (item->sub_tree && parent && parent->sub_tree == 1) { + /* if obj is fully included or fully excluded, collapse the item */ + hwloc_bitmap_t result = hwloc_bitmap_alloc(); + hwloc_bitmap_and(result, obj->complete_cpuset, this->workCpuset); + int weight = hwloc_bitmap_weight(result); + hwloc_bitmap_free(result); + if (weight == 0 || weight == (hwloc_bitmap_weight(this->workCpuset) + hwloc_bitmap_weight(obj->complete_cpuset))) + item->sub_tree = 2; + } + + /* "[x] " + "|- " * depth + ("[+] ")? + name */ + unsigned width = (CRT_utf8 ? 2 : 4) + 3 * depth + (item->sub_tree ? (CRT_utf8 ? 2 : 4) : 0) + strlen(buf); + if (width > this->width) + this->width = width; + + return item; +} + +static MaskItem *AffinityPanel_buildTopology(AffinityPanel* this, hwloc_obj_t obj, unsigned indent, MaskItem *parent) { + MaskItem *item = AffinityPanel_addObject(this, obj, indent, parent); + if (obj->next_sibling) { + indent |= (1u << obj->depth); + } else { + indent &= ~(1u << obj->depth); + } + for (unsigned i = 0; i < obj->arity; i++) + AffinityPanel_buildTopology(this, obj->children[i], indent, item); + + return parent == NULL ? item : NULL; +} + +#endif + PanelClass AffinityPanel_class = { .super = { .extends = Class(Panel), - .delete = Panel_delete + .delete = AffinityPanel_delete }, .eventHandler = AffinityPanel_eventHandler }; -Panel* AffinityPanel_new(ProcessList* pl, Affinity* affinity) { - Panel* this = Panel_new(1, 1, 1, 1, true, Class(CheckItem), FunctionBar_newEnterEsc("Set ", "Cancel ")); - Object_setClass(this, Class(AffinityPanel)); +static const char* const AffinityPanelFunctions[] = { + "Set ", + "Cancel ", + #ifdef HAVE_LIBHWLOC + "All", + "Topology", + " ", + #endif + NULL +}; +static const char* const AffinityPanelKeys[] = {"Enter", "Esc", "F1", "F2", "F3"}; +static const int AffinityPanelEvents[] = {13, 27, KEY_F(1), KEY_F(2), KEY_F(3)}; + +Panel* AffinityPanel_new(ProcessList* pl, Affinity* affinity, int* width) { + AffinityPanel* this = AllocThis(AffinityPanel); + Panel* super = (Panel*) this; + Panel_init(super, 1, 1, 1, 1, Class(MaskItem), false, FunctionBar_new(AffinityPanelFunctions, AffinityPanelKeys, AffinityPanelEvents)); + + this->pl = pl; + this->width = 15; + + this->cpuids = Vector_new(Class(MaskItem), true, DEFAULT_SIZE); + + #ifdef HAVE_LIBHWLOC + this->topoView = pl->settings->topologyAffinity; + #else + this->topoView = false; + #endif + + #ifdef HAVE_LIBHWLOC + this->allCpuset = hwloc_topology_get_complete_cpuset(pl->topology); + this->workCpuset = hwloc_bitmap_alloc(); + #endif + + Panel_setHeader(super, "Use CPUs:"); - Panel_setHeader(this, "Use CPUs:"); int curCpu = 0; for (int i = 0; i < pl->cpuCount; i++) { - char number[10]; - xSnprintf(number, 9, "%d", Settings_cpuId(pl->settings, i)); - bool mode; + char number[16]; + xSnprintf(number, 9, "CPU %d", Settings_cpuId(pl->settings, i)); + unsigned width = 4 + strlen(number); + if (width > this->width) + this->width = width; + + bool isSet = false; if (curCpu < affinity->used && affinity->cpus[curCpu] == i) { - mode = true; + #ifdef HAVE_LIBHWLOC + hwloc_bitmap_set(this->workCpuset, i); + #endif + isSet = true; curCpu++; - } else { - mode = false; } - Panel_add(this, (Object*) CheckItem_newByVal(xStrdup(number), mode)); + + MaskItem* cpuItem = MaskItem_newSingleton(number, i, isSet); + Vector_add(this->cpuids, (Object*) cpuItem); } - return this; + + #ifdef HAVE_LIBHWLOC + this->topoRoot = AffinityPanel_buildTopology(this, hwloc_get_root_obj(pl->topology), 0, NULL); + #endif + + if (width) + *width = this->width; + + AffinityPanel_update(this, false); + + return super; } -Affinity* AffinityPanel_getAffinity(Panel* this, ProcessList* pl) { +Affinity* AffinityPanel_getAffinity(Panel* super, ProcessList* pl) { + AffinityPanel* this = (AffinityPanel*) super; Affinity* affinity = Affinity_new(pl); - int size = Panel_size(this); - for (int i = 0; i < size; i++) { - if (CheckItem_get((CheckItem*)Panel_get(this, i))) - Affinity_add(affinity, i); + + #ifdef HAVE_LIBHWLOC + int i; + hwloc_bitmap_foreach_begin(i, this->workCpuset) + Affinity_add(affinity, i); + hwloc_bitmap_foreach_end(); + #else + for (int i = 0; i < this->pl->cpuCount; i++) { + MaskItem* item = (MaskItem*)Vector_get(this->cpuids, i); + if (item->value) + Affinity_add(affinity, item->cpu); } + #endif + return affinity; } diff --git a/AffinityPanel.h b/AffinityPanel.h index 3a9c7807..54d4f24c 100644 --- a/AffinityPanel.h +++ b/AffinityPanel.h @@ -9,15 +9,32 @@ Released under the GNU GPL, see the COPYING file in the source distribution for its full text. */ +#ifdef HAVE_LIBHWLOC +#endif + #include "Panel.h" #include "Affinity.h" #include "ProcessList.h" -#include "ListItem.h" + + + +#ifdef HAVE_LIBHWLOC + +#endif + + +#ifdef HAVE_LIBHWLOC + +#endif + +#ifdef HAVE_LIBHWLOC + +#endif extern PanelClass AffinityPanel_class; -extern Panel* AffinityPanel_new(ProcessList* pl, Affinity* affinity); +extern Panel* AffinityPanel_new(ProcessList* pl, Affinity* affinity, int* width); -extern Affinity* AffinityPanel_getAffinity(Panel* this, ProcessList* pl); +extern Affinity* AffinityPanel_getAffinity(Panel* super, ProcessList* pl); #endif diff --git a/CRT.c b/CRT.c index 35b285f7..869573e5 100644 --- a/CRT.c +++ b/CRT.c @@ -59,6 +59,19 @@ typedef enum TreeStr_ { TREE_STR_COUNT } TreeStr; +typedef enum CheckStr_ { + CHECK_STR_NONE, + CHECK_STR_PARTIAL, + CHECK_STR_FULL, + CHECK_STR_COUNT +} CheckStr; + +typedef enum CollapStr_ { + COLLAP_STR_OPEN, + COLLAP_STR_CLOSED, + COLLAP_STR_COUNT +} CollapStr; + typedef enum ColorSchemes_ { COLORSCHEME_DEFAULT = 0, COLORSCHEME_MONOCHROME = 1, @@ -113,7 +126,6 @@ typedef enum ColorElements_ { LOAD_AVERAGE_FIFTEEN, LOAD_AVERAGE_FIVE, LOAD_AVERAGE_ONE, - CHECK_BOX, CHECK_MARK, CHECK_TEXT, CLOCK, @@ -159,6 +171,17 @@ const char *CRT_treeStrAscii[TREE_STR_COUNT] = { "-", // TREE_STR_SHUT }; +const char *CRT_checkStrAscii[CHECK_STR_COUNT] = { + "[ ]", // CHECK_STR_NONE + "[o]", // CHECK_STR_PARTIAL + "[x]", // CHECK_STR_FULL +}; + +const char *CRT_collapStrAscii[COLLAP_STR_COUNT] = { + "[-]", // COLLAP_STR_OPEN + "[+]", // COLLAP_STR_CLOSED +}; + #ifdef HAVE_LIBNCURSESW const char *CRT_treeStrUtf8[TREE_STR_COUNT] = { @@ -171,12 +194,27 @@ const char *CRT_treeStrUtf8[TREE_STR_COUNT] = { "\xe2\x94\x80", // TREE_STR_SHUT ─ }; -bool CRT_utf8 = false; +const char *CRT_checkStrUtf8[CHECK_STR_COUNT] = { + "\xe2\x98\x90", // CHECK_STR_NONE ☐ + "\xe2\x98\x92", // CHECK_STR_PARTIAL ☒ + "\xe2\x98\x91", // CHECK_STR_FULL ☑ +}; + +const char *CRT_collapStrUtf8[COLLAP_STR_COUNT] = { + "\xe2\x8a\x9f", // COLLAP_STR_OPEN ⊟ + "\xe2\x8a\x9e", // COLLAP_STR_CLOSED ⊞ +}; #endif +bool CRT_utf8 = false; + const char **CRT_treeStr = CRT_treeStrAscii; +const char **CRT_checkStr = CRT_checkStrAscii; + +const char **CRT_collapStr = CRT_collapStrAscii; + static bool CRT_hasColors; int CRT_delay = 0; @@ -229,8 +267,7 @@ int CRT_colorSchemes[LAST_COLORSCHEME][LAST_COLORELEMENT] = { [LOAD] = A_BOLD, [HELP_BOLD] = A_BOLD | ColorPair(Cyan,Black), [CLOCK] = A_BOLD, - [CHECK_BOX] = ColorPair(Cyan,Black), - [CHECK_MARK] = A_BOLD, + [CHECK_MARK] = A_BOLD | ColorPair(Cyan,Black), [CHECK_TEXT] = A_NORMAL, [HOSTNAME] = A_BOLD, [CPU_NICE] = ColorPair(Blue,Black), @@ -298,8 +335,7 @@ int CRT_colorSchemes[LAST_COLORSCHEME][LAST_COLORELEMENT] = { [LOAD] = A_BOLD, [HELP_BOLD] = A_BOLD, [CLOCK] = A_BOLD, - [CHECK_BOX] = A_BOLD, - [CHECK_MARK] = A_NORMAL, + [CHECK_MARK] = A_BOLD, [CHECK_TEXT] = A_NORMAL, [HOSTNAME] = A_BOLD, [CPU_NICE] = A_NORMAL, @@ -367,7 +403,6 @@ int CRT_colorSchemes[LAST_COLORSCHEME][LAST_COLORELEMENT] = { [LOAD] = ColorPair(Black,White), [HELP_BOLD] = ColorPair(Blue,White), [CLOCK] = ColorPair(Black,White), - [CHECK_BOX] = ColorPair(Blue,White), [CHECK_MARK] = ColorPair(Black,White), [CHECK_TEXT] = ColorPair(Black,White), [HOSTNAME] = ColorPair(Black,White), @@ -436,7 +471,6 @@ int CRT_colorSchemes[LAST_COLORSCHEME][LAST_COLORELEMENT] = { [LOAD] = ColorPair(White,Black), [HELP_BOLD] = ColorPair(Blue,Black), [CLOCK] = ColorPair(White,Black), - [CHECK_BOX] = ColorPair(Blue,Black), [CHECK_MARK] = ColorPair(Black,Black), [CHECK_TEXT] = ColorPair(Black,Black), [HOSTNAME] = ColorPair(White,Black), @@ -505,8 +539,7 @@ int CRT_colorSchemes[LAST_COLORSCHEME][LAST_COLORELEMENT] = { [LOAD] = A_BOLD | ColorPair(White,Blue), [HELP_BOLD] = A_BOLD | ColorPair(Cyan,Blue), [CLOCK] = ColorPair(White,Blue), - [CHECK_BOX] = ColorPair(Cyan,Blue), - [CHECK_MARK] = A_BOLD | ColorPair(White,Blue), + [CHECK_MARK] = A_BOLD | ColorPair(Cyan,Blue), [CHECK_TEXT] = A_NORMAL | ColorPair(White,Blue), [HOSTNAME] = ColorPair(White,Blue), [CPU_NICE] = A_BOLD | ColorPair(Cyan,Blue), @@ -574,7 +607,6 @@ int CRT_colorSchemes[LAST_COLORSCHEME][LAST_COLORELEMENT] = { [LOAD] = A_BOLD, [HELP_BOLD] = A_BOLD | ColorPair(Cyan,Black), [CLOCK] = ColorPair(Green,Black), - [CHECK_BOX] = ColorPair(Green,Black), [CHECK_MARK] = A_BOLD | ColorPair(Green,Black), [CHECK_TEXT] = ColorPair(Cyan,Black), [HOSTNAME] = ColorPair(Green,Black), @@ -731,18 +763,14 @@ void CRT_init(int delay, int colorScheme) { setlocale(LC_CTYPE, ""); #ifdef HAVE_LIBNCURSESW - if(strcmp(nl_langinfo(CODESET), "UTF-8") == 0) + if(strcmp(nl_langinfo(CODESET), "UTF-8") == 0) { CRT_utf8 = true; - else - CRT_utf8 = false; + CRT_treeStr = CRT_treeStrUtf8; + CRT_checkStr = CRT_checkStrUtf8; + CRT_collapStr = CRT_collapStrUtf8; + } #endif - CRT_treeStr = -#ifdef HAVE_LIBNCURSESW - CRT_utf8 ? CRT_treeStrUtf8 : -#endif - CRT_treeStrAscii; - #if NCURSES_MOUSE_VERSION > 1 mousemask(BUTTON1_RELEASED | BUTTON4_PRESSED | BUTTON5_PRESSED, NULL); #else diff --git a/CRT.h b/CRT.h index 80022f70..5fb2f09c 100644 --- a/CRT.h +++ b/CRT.h @@ -47,6 +47,19 @@ typedef enum TreeStr_ { TREE_STR_COUNT } TreeStr; +typedef enum CheckStr_ { + CHECK_STR_NONE, + CHECK_STR_PARTIAL, + CHECK_STR_FULL, + CHECK_STR_COUNT +} CheckStr; + +typedef enum CollapStr_ { + COLLAP_STR_OPEN, + COLLAP_STR_CLOSED, + COLLAP_STR_COUNT +} CollapStr; + typedef enum ColorSchemes_ { COLORSCHEME_DEFAULT = 0, COLORSCHEME_MONOCHROME = 1, @@ -101,7 +114,6 @@ typedef enum ColorElements_ { LOAD_AVERAGE_FIFTEEN, LOAD_AVERAGE_FIVE, LOAD_AVERAGE_ONE, - CHECK_BOX, CHECK_MARK, CHECK_TEXT, CLOCK, @@ -138,16 +150,28 @@ extern void CRT_handleSIGSEGV(int sgn); extern const char *CRT_treeStrAscii[TREE_STR_COUNT]; +extern const char *CRT_checkStrAscii[CHECK_STR_COUNT]; + +extern const char *CRT_collapStrAscii[COLLAP_STR_COUNT]; + #ifdef HAVE_LIBNCURSESW extern const char *CRT_treeStrUtf8[TREE_STR_COUNT]; -extern bool CRT_utf8; +extern const char *CRT_checkStrUtf8[CHECK_STR_COUNT]; + +extern const char *CRT_collapStrUtf8[COLLAP_STR_COUNT]; #endif +extern bool CRT_utf8; + extern const char **CRT_treeStr; +extern const char **CRT_checkStr; + +extern const char **CRT_collapStr; + extern int CRT_delay; extern int* CRT_colors; diff --git a/CheckItem.c b/CheckItem.c index 910981e8..a045d2ff 100644 --- a/CheckItem.c +++ b/CheckItem.c @@ -35,12 +35,11 @@ static void CheckItem_delete(Object* cast) { static void CheckItem_display(Object* cast, RichString* out) { CheckItem* this = (CheckItem*)cast; assert (this != NULL); - RichString_write(out, CRT_colors[CHECK_BOX], "["); if (CheckItem_get(this)) - RichString_append(out, CRT_colors[CHECK_MARK], "x"); + RichString_append(out, CRT_colors[CHECK_MARK], CRT_checkStr[CHECK_STR_FULL]); else - RichString_append(out, CRT_colors[CHECK_MARK], " "); - RichString_append(out, CRT_colors[CHECK_BOX], "] "); + RichString_append(out, CRT_colors[CHECK_MARK], CRT_checkStr[CHECK_STR_NONE]); + RichString_append(out, CRT_colors[CHECK_TEXT], " "); RichString_append(out, CRT_colors[CHECK_TEXT], this->text); } diff --git a/DisplayOptionsPanel.c b/DisplayOptionsPanel.c index 0f44acc2..1222d823 100644 --- a/DisplayOptionsPanel.c +++ b/DisplayOptionsPanel.c @@ -100,5 +100,8 @@ DisplayOptionsPanel* DisplayOptionsPanel_new(Settings* settings, ScreenManager* Panel_add(super, (Object*) CheckItem_newByRef(xStrdup("Also show CPU percentage numerically"), &(settings->showCPUUsage))); Panel_add(super, (Object*) CheckItem_newByRef(xStrdup("Also show CPU frequency"), &(settings->showCPUFrequency))); Panel_add(super, (Object*) CheckItem_newByRef(xStrdup("Enable the mouse"), &(settings->enableMouse))); + #ifdef HAVE_LIBHWLOC + Panel_add(super, (Object*) CheckItem_newByRef(xStrdup("Show topology when selecting affinity by default"), &(settings->topologyAffinity))); + #endif return this; } diff --git a/Panel.c b/Panel.c index fc4fa3c2..348fd238 100644 --- a/Panel.c +++ b/Panel.c @@ -264,6 +264,14 @@ void Panel_setSelected(Panel* this, int selected) { } } +void Panel_splice(Panel *this, Vector* from) { + assert (this != NULL); + assert (from != NULL); + + Vector_splice(this->items, from); + this->needsRedraw = true; +} + void Panel_draw(Panel* this, bool focus) { assert (this != NULL); diff --git a/Panel.h b/Panel.h index b7480c6b..4b517f31 100644 --- a/Panel.h +++ b/Panel.h @@ -119,6 +119,8 @@ extern void Panel_setSelected(Panel* this, int selected); extern void Panel_draw(Panel* this, bool focus); +extern void Panel_splice(Panel *this, Vector* from); + extern bool Panel_onKey(Panel* this, int key); extern HandlerResult Panel_selectByTyping(Panel* this, int ch); diff --git a/ProcessList.c b/ProcessList.c index edbc114c..36b494e2 100644 --- a/ProcessList.c +++ b/ProcessList.c @@ -93,12 +93,19 @@ ProcessList* ProcessList_init(ProcessList* this, ObjectClass* klass, UsersTable* #ifdef HAVE_LIBHWLOC this->topologyOk = false; - int topoErr = hwloc_topology_init(&this->topology); - if (topoErr == 0) { - topoErr = hwloc_topology_load(this->topology); - } - if (topoErr == 0) { - this->topologyOk = true; + if (hwloc_topology_init(&this->topology) == 0) { + this->topologyOk = + #if HWLOC_API_VERSION < 0x00020000 + /* try to ignore the top-level machine object type */ + 0 == hwloc_topology_ignore_type_keep_structure(this->topology, HWLOC_OBJ_MACHINE) && + /* ignore caches, which don't add structure */ + 0 == hwloc_topology_ignore_type_keep_structure(this->topology, HWLOC_OBJ_CORE) && + 0 == hwloc_topology_ignore_type_keep_structure(this->topology, HWLOC_OBJ_CACHE) && + 0 == hwloc_topology_set_flags(this->topology, HWLOC_TOPOLOGY_FLAG_WHOLE_SYSTEM) && + #else + 0 == hwloc_topology_set_all_types_filter(this->topology, HWLOC_TYPE_FILTER_KEEP_STRUCTURE) && + #endif + 0 == hwloc_topology_load(this->topology); } #endif diff --git a/Settings.c b/Settings.c index 6197241f..81d547be 100644 --- a/Settings.c +++ b/Settings.c @@ -62,6 +62,9 @@ typedef struct Settings_ { bool headerMargin; bool enableMouse; bool vimMode; + #ifdef HAVE_LIBHWLOC + bool topologyAffinity; + #endif bool changed; } Settings; @@ -256,6 +259,10 @@ static bool Settings_read(Settings* this, const char* fileName) { didReadMeters = true; } else if (String_eq(option[0], "vim_mode")) { this->vimMode = atoi(option[1]); + #ifdef HAVE_LIBHWLOC + } else if (String_eq(option[0], "topology_affinity")) { + this->topologyAffinity = !!atoi(option[1]); + #endif } String_freeArray(option); } @@ -336,6 +343,9 @@ bool Settings_write(Settings* this) { fprintf(fd, "right_meters="); writeMeters(this, fd, 1); fprintf(fd, "right_meter_modes="); writeMeterModes(this, fd, 1); fprintf(fd, "vim_mode=%d\n", (int) this->vimMode); + #ifdef HAVE_LIBHWLOC + fprintf(fd, "topology_affinity=%d\n", (int) this->topologyAffinity); + #endif fclose(fd); return true; } @@ -362,6 +372,9 @@ Settings* Settings_new(int cpuCount) { this->cpuCount = cpuCount; this->showProgramPath = true; this->highlightThreads = true; + #ifdef HAVE_LIBHWLOC + this->topologyAffinity = false; + #endif this->fields = xCalloc(Platform_numberOfFields+1, sizeof(ProcessField)); // TODO: turn 'fields' into a Vector, diff --git a/Settings.h b/Settings.h index 89300951..f38b8ecd 100644 --- a/Settings.h +++ b/Settings.h @@ -53,6 +53,9 @@ typedef struct Settings_ { bool headerMargin; bool enableMouse; bool vimMode; + #ifdef HAVE_LIBHWLOC + bool topologyAffinity; + #endif bool changed; } Settings; diff --git a/Vector.c b/Vector.c index 819d9863..b5e77446 100644 --- a/Vector.c +++ b/Vector.c @@ -335,3 +335,15 @@ inline int Vector_indexOf(Vector* this, void* search_, Object_Compare compare) { } return -1; } + +void Vector_splice(Vector* this, Vector* from) { + assert(Vector_isConsistent(this)); + assert(Vector_isConsistent(from)); + assert(!(this->owner && from->owner)); + + int olditmes = this->items; + this->items += from->items; + Vector_checkArraySize(this); + for (int j = 0; j < from->items; j++) + this->array[olditmes + j] = from->array[j]; +} diff --git a/Vector.h b/Vector.h index b48c8363..0d9f1c2c 100644 --- a/Vector.h +++ b/Vector.h @@ -88,4 +88,6 @@ extern void Vector_add(Vector* this, void* data_); extern int Vector_indexOf(Vector* this, void* search_, Object_Compare compare); +void Vector_splice(Vector* this, Vector* from); + #endif