mirror of https://github.com/xzeldon/htop.git
Mega-commit with features and tweaks for 1.0:
* Performance improvements * Support for splitting CPU meters into two or four columns (thanks to Wim Heirman) * Switch from PLPA, which is now deprecated, to HWLOC. * Bring back support for native Linux sched_setaffinity, so we don't have to use HWLOC where we don't need to. * Support for typing in user names and column fields in selection panels.
This commit is contained in:
parent
3885648881
commit
7ca1081712
|
@ -46,6 +46,11 @@ static HandlerResult AvailableColumnsPanel_eventHandler(Panel* super, int ch) {
|
||||||
result = HANDLED;
|
result = HANDLED;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
default:
|
||||||
|
{
|
||||||
|
result = Panel_selectByTyping(super, ch);
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
152
CPUMeter.c
152
CPUMeter.c
|
@ -122,38 +122,91 @@ static void CPUMeter_display(Object* cast, RichString* out) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void AllCPUsMeter_getRange(Meter* this, int* start, int* count) {
|
||||||
|
int cpus = this->pl->cpuCount;
|
||||||
|
switch(this->type->name[0]) {
|
||||||
|
default:
|
||||||
|
case 'A': // All
|
||||||
|
*start = 0;
|
||||||
|
*count = cpus;
|
||||||
|
break;
|
||||||
|
case 'L': // First Half
|
||||||
|
*start = 0;
|
||||||
|
*count = (cpus+1) / 2;
|
||||||
|
break;
|
||||||
|
case 'R': // Second Half
|
||||||
|
*start = (cpus+1) / 2;
|
||||||
|
*count = cpus / 2;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void AllCPUsMeter_init(Meter* this) {
|
static void AllCPUsMeter_init(Meter* this) {
|
||||||
int cpus = this->pl->cpuCount;
|
int cpus = this->pl->cpuCount;
|
||||||
if (!this->drawData)
|
if (!this->drawData)
|
||||||
this->drawData = calloc(sizeof(Meter*), cpus);
|
this->drawData = calloc(sizeof(Meter*), cpus);
|
||||||
Meter** meters = (Meter**) this->drawData;
|
Meter** meters = (Meter**) this->drawData;
|
||||||
for (int i = 0; i < cpus; i++) {
|
int start, count;
|
||||||
|
AllCPUsMeter_getRange(this, &start, &count);
|
||||||
|
for (int i = 0; i < count; i++) {
|
||||||
if (!meters[i])
|
if (!meters[i])
|
||||||
meters[i] = Meter_new(this->pl, i+1, &CPUMeter);
|
meters[i] = Meter_new(this->pl, start+i+1, &CPUMeter);
|
||||||
meters[i]->type->init(meters[i]);
|
meters[i]->type->init(meters[i]);
|
||||||
}
|
}
|
||||||
this->h = Meter_modes[this->mode]->h * cpus;
|
if (this->mode == 0)
|
||||||
|
this->mode = BAR_METERMODE;
|
||||||
|
int h = Meter_modes[this->mode]->h;
|
||||||
|
if (strchr(this->type->name, '2'))
|
||||||
|
this->h = h * ((count+1) / 2);
|
||||||
|
else
|
||||||
|
this->h = h * count;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void AllCPUsMeter_done(Meter* this) {
|
static void AllCPUsMeter_done(Meter* this) {
|
||||||
int cpus = this->pl->cpuCount;
|
|
||||||
Meter** meters = (Meter**) this->drawData;
|
Meter** meters = (Meter**) this->drawData;
|
||||||
for (int i = 0; i < cpus; i++)
|
int start, count;
|
||||||
|
AllCPUsMeter_getRange(this, &start, &count);
|
||||||
|
for (int i = 0; i < count; i++)
|
||||||
Meter_delete((Object*)meters[i]);
|
Meter_delete((Object*)meters[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void AllCPUsMeter_setMode(Meter* this, int mode) {
|
static void AllCPUsMeter_setMode(Meter* this, int mode) {
|
||||||
|
Meter** meters = (Meter**) this->drawData;
|
||||||
this->mode = mode;
|
this->mode = mode;
|
||||||
int cpus = this->pl->cpuCount;
|
int h = Meter_modes[mode]->h;
|
||||||
int h = Meter_modes[this->mode]->h;
|
int start, count;
|
||||||
this->h = h * cpus;
|
AllCPUsMeter_getRange(this, &start, &count);
|
||||||
|
for (int i = 0; i < count; i++) {
|
||||||
|
Meter_setMode(meters[i], mode);
|
||||||
|
}
|
||||||
|
if (strchr(this->type->name, '2'))
|
||||||
|
this->h = h * ((count+1) / 2);
|
||||||
|
else
|
||||||
|
this->h = h * count;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void AllCPUsMeter_draw(Meter* this, int x, int y, int w) {
|
static void DualColCPUsMeter_draw(Meter* this, int x, int y, int w) {
|
||||||
int cpus = this->pl->cpuCount;
|
|
||||||
Meter** meters = (Meter**) this->drawData;
|
Meter** meters = (Meter**) this->drawData;
|
||||||
for (int i = 0; i < cpus; i++) {
|
int start, count;
|
||||||
Meter_setMode(meters[i], this->mode);
|
AllCPUsMeter_getRange(this, &start, &count);
|
||||||
|
int height = (count+1)/2;
|
||||||
|
int startY = y;
|
||||||
|
for (int i = 0; i < height; i++) {
|
||||||
|
meters[i]->draw(meters[i], x, y, (w-2)/2);
|
||||||
|
y += meters[i]->h;
|
||||||
|
}
|
||||||
|
y = startY;
|
||||||
|
for (int i = height; i < count; i++) {
|
||||||
|
meters[i]->draw(meters[i], x+(w-1)/2+2, y, (w-2)/2);
|
||||||
|
y += meters[i]->h;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void SingleColCPUsMeter_draw(Meter* this, int x, int y, int w) {
|
||||||
|
Meter** meters = (Meter**) this->drawData;
|
||||||
|
int start, count;
|
||||||
|
AllCPUsMeter_getRange(this, &start, &count);
|
||||||
|
for (int i = 0; i < count; i++) {
|
||||||
meters[i]->draw(meters[i], x, y, w);
|
meters[i]->draw(meters[i], x, y, w);
|
||||||
y += meters[i]->h;
|
y += meters[i]->h;
|
||||||
}
|
}
|
||||||
|
@ -178,10 +231,81 @@ MeterType AllCPUsMeter = {
|
||||||
.total = 100.0,
|
.total = 100.0,
|
||||||
.attributes = CPUMeter_attributes,
|
.attributes = CPUMeter_attributes,
|
||||||
.name = "AllCPUs",
|
.name = "AllCPUs",
|
||||||
.uiName = "All CPUs",
|
.uiName = "CPUs (1/1)",
|
||||||
.caption = "CPU",
|
.caption = "CPU",
|
||||||
.draw = AllCPUsMeter_draw,
|
.draw = SingleColCPUsMeter_draw,
|
||||||
.init = AllCPUsMeter_init,
|
.init = AllCPUsMeter_init,
|
||||||
.setMode = AllCPUsMeter_setMode,
|
.setMode = AllCPUsMeter_setMode,
|
||||||
.done = AllCPUsMeter_done
|
.done = AllCPUsMeter_done
|
||||||
};
|
};
|
||||||
|
|
||||||
|
MeterType AllCPUs2Meter = {
|
||||||
|
.mode = 0,
|
||||||
|
.items = 1,
|
||||||
|
.total = 100.0,
|
||||||
|
.attributes = CPUMeter_attributes,
|
||||||
|
.name = "AllCPUs2",
|
||||||
|
.uiName = "CPUs (1&2/2)",
|
||||||
|
.caption = "CPU",
|
||||||
|
.draw = DualColCPUsMeter_draw,
|
||||||
|
.init = AllCPUsMeter_init,
|
||||||
|
.setMode = AllCPUsMeter_setMode,
|
||||||
|
.done = AllCPUsMeter_done
|
||||||
|
};
|
||||||
|
|
||||||
|
MeterType LeftCPUsMeter = {
|
||||||
|
.mode = 0,
|
||||||
|
.items = 1,
|
||||||
|
.total = 100.0,
|
||||||
|
.attributes = CPUMeter_attributes,
|
||||||
|
.name = "LeftCPUs",
|
||||||
|
.uiName = "CPUs (1/2)",
|
||||||
|
.caption = "CPU",
|
||||||
|
.draw = SingleColCPUsMeter_draw,
|
||||||
|
.init = AllCPUsMeter_init,
|
||||||
|
.setMode = AllCPUsMeter_setMode,
|
||||||
|
.done = AllCPUsMeter_done
|
||||||
|
};
|
||||||
|
|
||||||
|
MeterType RightCPUsMeter = {
|
||||||
|
.mode = 0,
|
||||||
|
.items = 1,
|
||||||
|
.total = 100.0,
|
||||||
|
.attributes = CPUMeter_attributes,
|
||||||
|
.name = "RightCPUs",
|
||||||
|
.uiName = "CPUs (2/2)",
|
||||||
|
.caption = "CPU",
|
||||||
|
.draw = SingleColCPUsMeter_draw,
|
||||||
|
.init = AllCPUsMeter_init,
|
||||||
|
.setMode = AllCPUsMeter_setMode,
|
||||||
|
.done = AllCPUsMeter_done
|
||||||
|
};
|
||||||
|
|
||||||
|
MeterType LeftCPUs2Meter = {
|
||||||
|
.mode = 0,
|
||||||
|
.items = 1,
|
||||||
|
.total = 100.0,
|
||||||
|
.attributes = CPUMeter_attributes,
|
||||||
|
.name = "LeftCPUs2",
|
||||||
|
.uiName = "CPUs (1&2/4)",
|
||||||
|
.caption = "CPU",
|
||||||
|
.draw = DualColCPUsMeter_draw,
|
||||||
|
.init = AllCPUsMeter_init,
|
||||||
|
.setMode = AllCPUsMeter_setMode,
|
||||||
|
.done = AllCPUsMeter_done
|
||||||
|
};
|
||||||
|
|
||||||
|
MeterType RightCPUs2Meter = {
|
||||||
|
.mode = 0,
|
||||||
|
.items = 1,
|
||||||
|
.total = 100.0,
|
||||||
|
.attributes = CPUMeter_attributes,
|
||||||
|
.name = "RightCPUs2",
|
||||||
|
.uiName = "CPUs (3&4/4)",
|
||||||
|
.caption = "CPU",
|
||||||
|
.draw = DualColCPUsMeter_draw,
|
||||||
|
.init = AllCPUsMeter_init,
|
||||||
|
.setMode = AllCPUsMeter_setMode,
|
||||||
|
.done = AllCPUsMeter_done
|
||||||
|
};
|
||||||
|
|
||||||
|
|
11
CPUMeter.h
11
CPUMeter.h
|
@ -34,4 +34,15 @@ extern MeterType CPUMeter;
|
||||||
|
|
||||||
extern MeterType AllCPUsMeter;
|
extern MeterType AllCPUsMeter;
|
||||||
|
|
||||||
|
extern MeterType AllCPUs2Meter;
|
||||||
|
|
||||||
|
extern MeterType LeftCPUsMeter;
|
||||||
|
|
||||||
|
extern MeterType RightCPUsMeter;
|
||||||
|
|
||||||
|
extern MeterType LeftCPUs2Meter;
|
||||||
|
|
||||||
|
extern MeterType RightCPUs2Meter;
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -1,7 +1,12 @@
|
||||||
|
|
||||||
What's new in version 0.9.1
|
What's new in version 1.0
|
||||||
|
|
||||||
|
* Performance improvements
|
||||||
|
* Support for splitting CPU meters into two or four columns
|
||||||
|
(thanks to Wim Heirman)
|
||||||
* Switch from PLPA, which is now deprecated, to HWLOC.
|
* Switch from PLPA, which is now deprecated, to HWLOC.
|
||||||
|
* Bring back support for native Linux sched_setaffinity,
|
||||||
|
so we don't have to use HWLOC where we don't need to.
|
||||||
* Support for typing in user names and column fields in selection panels.
|
* Support for typing in user names and column fields in selection panels.
|
||||||
* Support for UTF-8 tree drawing
|
* Support for UTF-8 tree drawing
|
||||||
(thanks to Bin Guo)
|
(thanks to Bin Guo)
|
||||||
|
|
|
@ -60,6 +60,13 @@ static HandlerResult ColumnsPanel_eventHandler(Panel* super, int ch) {
|
||||||
result = HANDLED;
|
result = HANDLED;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
default:
|
||||||
|
{
|
||||||
|
result = Panel_selectByTyping(super, ch);
|
||||||
|
if (result == BREAK_LOOP)
|
||||||
|
result = IGNORED;
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (result == HANDLED)
|
if (result == HANDLED)
|
||||||
ColumnsPanel_update(super);
|
ColumnsPanel_update(super);
|
||||||
|
|
12
Header.c
12
Header.c
|
@ -124,8 +124,16 @@ MeterModeId Header_readMeterMode(Header* this, int i, HeaderSide side) {
|
||||||
return meter->mode;
|
return meter->mode;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Header_defaultMeters(Header* this) {
|
void Header_defaultMeters(Header* this, int cpuCount) {
|
||||||
Vector_add(this->leftMeters, Meter_new(this->pl, 0, &AllCPUsMeter));
|
if (cpuCount > 8) {
|
||||||
|
Vector_add(this->leftMeters, Meter_new(this->pl, 0, &LeftCPUs2Meter));
|
||||||
|
Vector_add(this->rightMeters, Meter_new(this->pl, 0, &RightCPUs2Meter));
|
||||||
|
} else if (cpuCount > 4) {
|
||||||
|
Vector_add(this->leftMeters, Meter_new(this->pl, 0, &LeftCPUsMeter));
|
||||||
|
Vector_add(this->rightMeters, Meter_new(this->pl, 0, &RightCPUsMeter));
|
||||||
|
} else {
|
||||||
|
Vector_add(this->leftMeters, Meter_new(this->pl, 0, &AllCPUsMeter));
|
||||||
|
}
|
||||||
Vector_add(this->leftMeters, Meter_new(this->pl, 0, &MemoryMeter));
|
Vector_add(this->leftMeters, Meter_new(this->pl, 0, &MemoryMeter));
|
||||||
Vector_add(this->leftMeters, Meter_new(this->pl, 0, &SwapMeter));
|
Vector_add(this->leftMeters, Meter_new(this->pl, 0, &SwapMeter));
|
||||||
Vector_add(this->rightMeters, Meter_new(this->pl, 0, &TasksMeter));
|
Vector_add(this->rightMeters, Meter_new(this->pl, 0, &TasksMeter));
|
||||||
|
|
2
Header.h
2
Header.h
|
@ -51,7 +51,7 @@ char* Header_readMeterName(Header* this, int i, HeaderSide side);
|
||||||
|
|
||||||
MeterModeId Header_readMeterMode(Header* this, int i, HeaderSide side);
|
MeterModeId Header_readMeterMode(Header* this, int i, HeaderSide side);
|
||||||
|
|
||||||
void Header_defaultMeters(Header* this);
|
void Header_defaultMeters(Header* this, int cpuCount);
|
||||||
|
|
||||||
void Header_reinit(Header* this);
|
void Header_reinit(Header* this);
|
||||||
|
|
||||||
|
|
9
Meter.c
9
Meter.c
|
@ -130,8 +130,13 @@ MeterType* Meter_types[] = {
|
||||||
&TasksMeter,
|
&TasksMeter,
|
||||||
&UptimeMeter,
|
&UptimeMeter,
|
||||||
&BatteryMeter,
|
&BatteryMeter,
|
||||||
&AllCPUsMeter,
|
|
||||||
&HostnameMeter,
|
&HostnameMeter,
|
||||||
|
&AllCPUsMeter,
|
||||||
|
&AllCPUs2Meter,
|
||||||
|
&LeftCPUsMeter,
|
||||||
|
&RightCPUsMeter,
|
||||||
|
&LeftCPUs2Meter,
|
||||||
|
&RightCPUs2Meter,
|
||||||
NULL
|
NULL
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -147,9 +152,9 @@ Meter* Meter_new(ProcessList* pl, int param, MeterType* type) {
|
||||||
this->values = calloc(sizeof(double), type->items);
|
this->values = calloc(sizeof(double), type->items);
|
||||||
this->total = type->total;
|
this->total = type->total;
|
||||||
this->caption = strdup(type->caption);
|
this->caption = strdup(type->caption);
|
||||||
Meter_setMode(this, type->mode);
|
|
||||||
if (this->type->init)
|
if (this->type->init)
|
||||||
this->type->init(this);
|
this->type->init(this);
|
||||||
|
Meter_setMode(this, type->mode);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -151,7 +151,7 @@ static void OpenFilesScreen_scan(OpenFilesScreen* this) {
|
||||||
free(process->data[i]);
|
free(process->data[i]);
|
||||||
}
|
}
|
||||||
free(process);
|
free(process);
|
||||||
Vector_sort(panel->items);
|
Vector_insertionSort(panel->items);
|
||||||
Panel_setSelected(panel, idx);
|
Panel_setSelected(panel, idx);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
37
Panel.c
37
Panel.c
|
@ -93,6 +93,7 @@ void Panel_init(Panel* this, int x, int y, int w, int h, char* type, bool owner)
|
||||||
this->w = w;
|
this->w = w;
|
||||||
this->h = h;
|
this->h = h;
|
||||||
this->eventHandler = NULL;
|
this->eventHandler = NULL;
|
||||||
|
this->eventHandlerBuffer = NULL;
|
||||||
this->items = Vector_new(type, owner, DEFAULT_SIZE, ListItem_compare);
|
this->items = Vector_new(type, owner, DEFAULT_SIZE, ListItem_compare);
|
||||||
this->scrollV = 0;
|
this->scrollV = 0;
|
||||||
this->scrollH = 0;
|
this->scrollH = 0;
|
||||||
|
@ -108,6 +109,7 @@ void Panel_init(Panel* this, int x, int y, int w, int h, char* type, bool owner)
|
||||||
|
|
||||||
void Panel_done(Panel* this) {
|
void Panel_done(Panel* this) {
|
||||||
assert (this != NULL);
|
assert (this != NULL);
|
||||||
|
free(this->eventHandlerBuffer);
|
||||||
Vector_delete(this->items);
|
Vector_delete(this->items);
|
||||||
RichString_end(this->header);
|
RichString_end(this->header);
|
||||||
}
|
}
|
||||||
|
@ -405,3 +407,38 @@ bool Panel_onKey(Panel* this, int key) {
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
HandlerResult Panel_selectByTyping(Panel* this, int ch) {
|
||||||
|
int size = Panel_size(this);
|
||||||
|
if (!this->eventHandlerBuffer)
|
||||||
|
this->eventHandlerBuffer = calloc(100, 1);
|
||||||
|
|
||||||
|
if (isalnum(ch)) {
|
||||||
|
int len = strlen(this->eventHandlerBuffer);
|
||||||
|
if (len < 99) {
|
||||||
|
this->eventHandlerBuffer[len] = ch;
|
||||||
|
this->eventHandlerBuffer[len+1] = '\0';
|
||||||
|
}
|
||||||
|
for (int try = 0; try < 2; try++) {
|
||||||
|
len = strlen(this->eventHandlerBuffer);
|
||||||
|
for (int i = 0; i < size; i++) {
|
||||||
|
char* cur = ((ListItem*) Panel_get(this, i))->value;
|
||||||
|
while (*cur == ' ') cur++;
|
||||||
|
if (strncasecmp(cur, this->eventHandlerBuffer, len) == 0) {
|
||||||
|
Panel_setSelected(this, i);
|
||||||
|
return HANDLED;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this->eventHandlerBuffer[0] = ch;
|
||||||
|
this->eventHandlerBuffer[1] = '\0';
|
||||||
|
}
|
||||||
|
return HANDLED;
|
||||||
|
} else if (ch != ERR) {
|
||||||
|
this->eventHandlerBuffer[0] = '\0';
|
||||||
|
}
|
||||||
|
if (ch == 13) {
|
||||||
|
return BREAK_LOOP;
|
||||||
|
}
|
||||||
|
return IGNORED;
|
||||||
|
}
|
||||||
|
|
3
Panel.h
3
Panel.h
|
@ -117,4 +117,7 @@ void Panel_draw(Panel* this, bool focus);
|
||||||
|
|
||||||
bool Panel_onKey(Panel* this, int key);
|
bool Panel_onKey(Panel* this, int key);
|
||||||
|
|
||||||
|
|
||||||
|
HandlerResult Panel_selectByTyping(Panel* this, int ch);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
26
Process.c
26
Process.c
|
@ -567,6 +567,7 @@ bool Process_setPriority(Process* this, int priority) {
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef HAVE_HWLOC
|
#ifdef HAVE_HWLOC
|
||||||
|
|
||||||
Affinity* Process_getAffinity(Process* this) {
|
Affinity* Process_getAffinity(Process* this) {
|
||||||
hwloc_cpuset_t cpuset = hwloc_bitmap_alloc();
|
hwloc_cpuset_t cpuset = hwloc_bitmap_alloc();
|
||||||
bool ok = (hwloc_linux_get_tid_cpubind(this->pl->topology, this->pid, cpuset) == 0);
|
bool ok = (hwloc_linux_get_tid_cpubind(this->pl->topology, this->pid, cpuset) == 0);
|
||||||
|
@ -597,6 +598,31 @@ bool Process_setAffinity(Process* this, Affinity* affinity) {
|
||||||
hwloc_bitmap_free(cpuset);
|
hwloc_bitmap_free(cpuset);
|
||||||
return ok;
|
return ok;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#elif HAVE_NATIVE_AFFINITY
|
||||||
|
|
||||||
|
Affinity* Process_getAffinity(Process* this) {
|
||||||
|
cpu_set_t cpuset;
|
||||||
|
bool ok = (sched_getaffinity(this->pid, sizeof(cpu_set_t), &cpuset) == 0);
|
||||||
|
if (!ok) return NULL;
|
||||||
|
Affinity* affinity = Affinity_new();
|
||||||
|
for (int i = 0; i < this->pl->cpuCount; i++) {
|
||||||
|
if (CPU_ISSET(i, &cpuset))
|
||||||
|
Affinity_add(affinity, i);
|
||||||
|
}
|
||||||
|
return affinity;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Process_setAffinity(Process* this, Affinity* affinity) {
|
||||||
|
cpu_set_t cpuset;
|
||||||
|
CPU_ZERO(&cpuset);
|
||||||
|
for (int i = 0; i < affinity->used; i++) {
|
||||||
|
CPU_SET(affinity->cpus[i], &cpuset);
|
||||||
|
}
|
||||||
|
bool ok = (sched_setaffinity(this->pid, sizeof(unsigned long), &cpuset) == 0);
|
||||||
|
return ok;
|
||||||
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
void Process_sendSignal(Process* this, int sgn) {
|
void Process_sendSignal(Process* this, int sgn) {
|
||||||
|
|
|
@ -197,9 +197,17 @@ void Process_toggleTag(Process* this);
|
||||||
bool Process_setPriority(Process* this, int priority);
|
bool Process_setPriority(Process* this, int priority);
|
||||||
|
|
||||||
#ifdef HAVE_HWLOC
|
#ifdef HAVE_HWLOC
|
||||||
|
|
||||||
Affinity* Process_getAffinity(Process* this);
|
Affinity* Process_getAffinity(Process* this);
|
||||||
|
|
||||||
bool Process_setAffinity(Process* this, Affinity* affinity);
|
bool Process_setAffinity(Process* this, Affinity* affinity);
|
||||||
|
|
||||||
|
#elif HAVE_NATIVE_AFFINITY
|
||||||
|
|
||||||
|
Affinity* Process_getAffinity(Process* this);
|
||||||
|
|
||||||
|
bool Process_setAffinity(Process* this, Affinity* affinity);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
void Process_sendSignal(Process* this, int sgn);
|
void Process_sendSignal(Process* this, int sgn);
|
||||||
|
|
|
@ -178,8 +178,7 @@ ProcessList* ProcessList_new(UsersTable* usersTable) {
|
||||||
ProcessList* this;
|
ProcessList* this;
|
||||||
this = calloc(sizeof(ProcessList), 1);
|
this = calloc(sizeof(ProcessList), 1);
|
||||||
this->processes = Vector_new(PROCESS_CLASS, true, DEFAULT_SIZE, Process_compare);
|
this->processes = Vector_new(PROCESS_CLASS, true, DEFAULT_SIZE, Process_compare);
|
||||||
this->processTable = Hashtable_new(70, false);
|
this->processTable = Hashtable_new(140, false);
|
||||||
assert(Hashtable_count(this->processTable) == Vector_count(this->processes));
|
|
||||||
this->usersTable = usersTable;
|
this->usersTable = usersTable;
|
||||||
|
|
||||||
/* tree-view auxiliary buffers */
|
/* tree-view auxiliary buffers */
|
||||||
|
@ -329,7 +328,7 @@ static void ProcessList_buildTree(ProcessList* this, pid_t pid, int level, int i
|
||||||
|
|
||||||
void ProcessList_sort(ProcessList* this) {
|
void ProcessList_sort(ProcessList* this) {
|
||||||
if (!this->treeView) {
|
if (!this->treeView) {
|
||||||
Vector_sort(this->processes);
|
Vector_insertionSort(this->processes);
|
||||||
} else {
|
} else {
|
||||||
// Save settings
|
// Save settings
|
||||||
int direction = this->direction;
|
int direction = this->direction;
|
||||||
|
@ -337,7 +336,7 @@ void ProcessList_sort(ProcessList* this) {
|
||||||
// Sort by PID
|
// Sort by PID
|
||||||
this->sortKey = PID;
|
this->sortKey = PID;
|
||||||
this->direction = 1;
|
this->direction = 1;
|
||||||
Vector_sort(this->processes);
|
Vector_quickSort(this->processes);
|
||||||
// Restore settings
|
// Restore settings
|
||||||
this->sortKey = sortKey;
|
this->sortKey = sortKey;
|
||||||
this->direction = direction;
|
this->direction = direction;
|
||||||
|
@ -448,23 +447,34 @@ static void ProcessList_readIoFile(Process* process, const char* dirname, char*
|
||||||
unsigned long long last_read = process->io_read_bytes;
|
unsigned long long last_read = process->io_read_bytes;
|
||||||
unsigned long long last_write = process->io_write_bytes;
|
unsigned long long last_write = process->io_write_bytes;
|
||||||
while (fgets(buffer, 255, file)) {
|
while (fgets(buffer, 255, file)) {
|
||||||
if (sscanf(buffer, "rchar: %llu", &process->io_rchar)) continue;
|
switch (buffer[0]) {
|
||||||
if (sscanf(buffer, "wchar: %llu", &process->io_wchar)) continue;
|
case 'r':
|
||||||
if (sscanf(buffer, "syscr: %llu", &process->io_syscr)) continue;
|
if (buffer[1] == 'c')
|
||||||
if (sscanf(buffer, "syscw: %llu", &process->io_syscw)) continue;
|
sscanf(buffer, "rchar: %llu", &process->io_rchar);
|
||||||
if (sscanf(buffer, "read_bytes: %llu", &process->io_read_bytes)) {
|
else if (sscanf(buffer, "read_bytes: %llu", &process->io_read_bytes)) {
|
||||||
process->io_rate_read_bps =
|
process->io_rate_read_bps =
|
||||||
((double)(process->io_read_bytes - last_read))/(((double)(now - process->io_rate_read_time))/1000);
|
((double)(process->io_read_bytes - last_read))/(((double)(now - process->io_rate_read_time))/1000);
|
||||||
process->io_rate_read_time = now;
|
process->io_rate_read_time = now;
|
||||||
continue;
|
}
|
||||||
|
break;
|
||||||
|
case 'w':
|
||||||
|
if (buffer[1] == 'c')
|
||||||
|
sscanf(buffer, "wchar: %llu", &process->io_wchar);
|
||||||
|
else if (sscanf(buffer, "write_bytes: %llu", &process->io_write_bytes)) {
|
||||||
|
process->io_rate_write_bps =
|
||||||
|
((double)(process->io_write_bytes - last_write))/(((double)(now - process->io_rate_write_time))/1000);
|
||||||
|
process->io_rate_write_time = now;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 's':
|
||||||
|
if (buffer[5] == 'r')
|
||||||
|
sscanf(buffer, "syscr: %llu", &process->io_syscr);
|
||||||
|
else
|
||||||
|
sscanf(buffer, "syscw: %llu", &process->io_syscw);
|
||||||
|
break;
|
||||||
|
case 'c':
|
||||||
|
sscanf(buffer, "cancelled_write_bytes: %llu", &process->io_cancelled_write_bytes);
|
||||||
}
|
}
|
||||||
if (sscanf(buffer, "write_bytes: %llu", &process->io_write_bytes)) {
|
|
||||||
process->io_rate_write_bps =
|
|
||||||
((double)(process->io_write_bytes - last_write))/(((double)(now - process->io_rate_write_time))/1000);
|
|
||||||
process->io_rate_write_time = now;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
sscanf(buffer, "cancelled_write_bytes: %llu", &process->io_cancelled_write_bytes);
|
|
||||||
}
|
}
|
||||||
fclose(file);
|
fclose(file);
|
||||||
}
|
}
|
||||||
|
|
12
Settings.c
12
Settings.c
|
@ -55,7 +55,7 @@ static void Settings_readMeterModes(Settings* this, char* line, HeaderSide side)
|
||||||
String_freeArray(ids);
|
String_freeArray(ids);
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool Settings_read(Settings* this, char* fileName) {
|
static bool Settings_read(Settings* this, char* fileName, int cpuCount) {
|
||||||
// TODO: implement File object and make
|
// TODO: implement File object and make
|
||||||
// file I/O object-oriented.
|
// file I/O object-oriented.
|
||||||
FILE* fd;
|
FILE* fd;
|
||||||
|
@ -144,7 +144,7 @@ static bool Settings_read(Settings* this, char* fileName) {
|
||||||
}
|
}
|
||||||
fclose(fd);
|
fclose(fd);
|
||||||
if (!readMeters) {
|
if (!readMeters) {
|
||||||
Header_defaultMeters(this->header);
|
Header_defaultMeters(this->header, cpuCount);
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -208,7 +208,7 @@ bool Settings_write(Settings* this) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
Settings* Settings_new(ProcessList* pl, Header* header) {
|
Settings* Settings_new(ProcessList* pl, Header* header, int cpuCount) {
|
||||||
Settings* this = malloc(sizeof(Settings));
|
Settings* this = malloc(sizeof(Settings));
|
||||||
this->pl = pl;
|
this->pl = pl;
|
||||||
this->header = header;
|
this->header = header;
|
||||||
|
@ -225,15 +225,15 @@ Settings* Settings_new(ProcessList* pl, Header* header) {
|
||||||
this->colorScheme = 0;
|
this->colorScheme = 0;
|
||||||
this->changed = false;
|
this->changed = false;
|
||||||
this->delay = DEFAULT_DELAY;
|
this->delay = DEFAULT_DELAY;
|
||||||
bool ok = Settings_read(this, this->userSettings);
|
bool ok = Settings_read(this, this->userSettings, cpuCount);
|
||||||
if (!ok) {
|
if (!ok) {
|
||||||
this->changed = true;
|
this->changed = true;
|
||||||
// TODO: how to get SYSCONFDIR correctly through Autoconf?
|
// TODO: how to get SYSCONFDIR correctly through Autoconf?
|
||||||
char* systemSettings = String_cat(SYSCONFDIR, "/htoprc");
|
char* systemSettings = String_cat(SYSCONFDIR, "/htoprc");
|
||||||
ok = Settings_read(this, systemSettings);
|
ok = Settings_read(this, systemSettings, cpuCount);
|
||||||
free(systemSettings);
|
free(systemSettings);
|
||||||
if (!ok) {
|
if (!ok) {
|
||||||
Header_defaultMeters(this->header);
|
Header_defaultMeters(this->header, cpuCount);
|
||||||
pl->hideKernelThreads = true;
|
pl->hideKernelThreads = true;
|
||||||
pl->highlightMegabytes = true;
|
pl->highlightMegabytes = true;
|
||||||
pl->highlightThreads = false;
|
pl->highlightThreads = false;
|
||||||
|
|
|
@ -32,6 +32,6 @@ void Settings_delete(Settings* this);
|
||||||
|
|
||||||
bool Settings_write(Settings* this);
|
bool Settings_write(Settings* this);
|
||||||
|
|
||||||
Settings* Settings_new(ProcessList* pl, Header* header);
|
Settings* Settings_new(ProcessList* pl, Header* header, int cpuCount);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
93
Vector.c
93
Vector.c
|
@ -16,6 +16,8 @@ in the source distribution for its full text.
|
||||||
|
|
||||||
/*{
|
/*{
|
||||||
|
|
||||||
|
#define swap(a_,x_,y_) do{ void* tmp_ = a_[x_]; a_[x_] = a_[y_]; a_[y_] = tmp_; }while(0)
|
||||||
|
|
||||||
#ifndef DEFAULT_SIZE
|
#ifndef DEFAULT_SIZE
|
||||||
#define DEFAULT_SIZE -1
|
#define DEFAULT_SIZE -1
|
||||||
#endif
|
#endif
|
||||||
|
@ -97,18 +99,83 @@ void Vector_prune(Vector* this) {
|
||||||
this->items = 0;
|
this->items = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Vector_sort(Vector* this) {
|
static int comparisons = 0;
|
||||||
|
|
||||||
|
static int partition(Object** array, int left, int right, int pivotIndex, Object_Compare compare) {
|
||||||
|
void* pivotValue = array[pivotIndex];
|
||||||
|
swap(array, pivotIndex, right);
|
||||||
|
int storeIndex = left;
|
||||||
|
for (int i = left; i < right; i++) {
|
||||||
|
comparisons++;
|
||||||
|
if (compare(array[i], pivotValue) <= 0) {
|
||||||
|
swap(array, i, storeIndex);
|
||||||
|
storeIndex++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
swap(array, storeIndex, right);
|
||||||
|
return storeIndex;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void quickSort(Object** array, int left, int right, Object_Compare compare) {
|
||||||
|
if (left >= right)
|
||||||
|
return;
|
||||||
|
int pivotIndex = (left+right) / 2;
|
||||||
|
int pivotNewIndex = partition(array, left, right, pivotIndex, compare);
|
||||||
|
quickSort(array, left, pivotNewIndex - 1, compare);
|
||||||
|
quickSort(array, pivotNewIndex + 1, right, compare);
|
||||||
|
}
|
||||||
|
|
||||||
|
// If I were to use only one sorting algorithm for both cases, it would probably be this one:
|
||||||
|
/*
|
||||||
|
|
||||||
|
static void combSort(Object** array, int left, int right, Object_Compare compare) {
|
||||||
|
int gap = right - left;
|
||||||
|
bool swapped = true;
|
||||||
|
while ((gap > 1) || swapped) {
|
||||||
|
if (gap > 1) {
|
||||||
|
gap = (int)((double)gap / 1.247330950103979);
|
||||||
|
}
|
||||||
|
swapped = false;
|
||||||
|
for (int i = left; gap + i <= right; i++) {
|
||||||
|
comparisons++;
|
||||||
|
if (compare(array[i], array[i+gap]) > 0) {
|
||||||
|
swap(array, i, i+gap);
|
||||||
|
swapped = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
static void insertionSort(Object** array, int left, int right, Object_Compare compare) {
|
||||||
|
for (int i = left+1; i <= right; i++) {
|
||||||
|
void* t = array[i];
|
||||||
|
int j = i - 1;
|
||||||
|
while (j >= left) {
|
||||||
|
comparisons++;
|
||||||
|
if (compare(array[j], t) <= 0)
|
||||||
|
break;
|
||||||
|
array[j+1] = array[j];
|
||||||
|
j--;
|
||||||
|
}
|
||||||
|
array[j+1] = t;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Vector_quickSort(Vector* this) {
|
||||||
assert(this->compare);
|
assert(this->compare);
|
||||||
assert(Vector_isConsistent(this));
|
assert(Vector_isConsistent(this));
|
||||||
Object_Compare compare = this->compare;
|
Object_Compare compare = this->compare;
|
||||||
/* Insertion sort works best on mostly-sorted arrays. */
|
quickSort(this->array, 0, this->items - 1, compare);
|
||||||
for (int i = 1; i < this->items; i++) {
|
assert(Vector_isConsistent(this));
|
||||||
int j;
|
}
|
||||||
void* t = this->array[i];
|
|
||||||
for (j = i-1; j >= 0 && compare(this->array[j], t) > 0; j--)
|
void Vector_insertionSort(Vector* this) {
|
||||||
this->array[j+1] = this->array[j];
|
assert(this->compare);
|
||||||
this->array[j+1] = t;
|
assert(Vector_isConsistent(this));
|
||||||
}
|
Object_Compare compare = this->compare;
|
||||||
|
insertionSort(this->array, 0, this->items - 1, compare);
|
||||||
assert(Vector_isConsistent(this));
|
assert(Vector_isConsistent(this));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -205,12 +272,20 @@ void Vector_set(Vector* this, int idx, void* data_) {
|
||||||
assert(Vector_isConsistent(this));
|
assert(Vector_isConsistent(this));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef DEBUG
|
||||||
|
|
||||||
inline Object* Vector_get(Vector* this, int idx) {
|
inline Object* Vector_get(Vector* this, int idx) {
|
||||||
assert(idx < this->items);
|
assert(idx < this->items);
|
||||||
assert(Vector_isConsistent(this));
|
assert(Vector_isConsistent(this));
|
||||||
return this->array[idx];
|
return this->array[idx];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
#define Vector_get(v_, idx_) ((v_)->array[idx_])
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
inline int Vector_size(Vector* this) {
|
inline int Vector_size(Vector* this) {
|
||||||
assert(Vector_isConsistent(this));
|
assert(Vector_isConsistent(this));
|
||||||
return this->items;
|
return this->items;
|
||||||
|
|
19
Vector.h
19
Vector.h
|
@ -18,6 +18,8 @@ in the source distribution for its full text.
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
|
|
||||||
|
|
||||||
|
#define swap(a_,x_,y_) do{ void* tmp_ = a_[x_]; a_[x_] = a_[y_]; a_[y_] = tmp_; }while(0)
|
||||||
|
|
||||||
#ifndef DEFAULT_SIZE
|
#ifndef DEFAULT_SIZE
|
||||||
#define DEFAULT_SIZE -1
|
#define DEFAULT_SIZE -1
|
||||||
#endif
|
#endif
|
||||||
|
@ -45,7 +47,14 @@ int Vector_count(Vector* this);
|
||||||
|
|
||||||
void Vector_prune(Vector* this);
|
void Vector_prune(Vector* this);
|
||||||
|
|
||||||
void Vector_sort(Vector* this);
|
// If I were to use only one sorting algorithm for both cases, it would probably be this one:
|
||||||
|
/*
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
void Vector_quickSort(Vector* this);
|
||||||
|
|
||||||
|
void Vector_insertionSort(Vector* this);
|
||||||
|
|
||||||
void Vector_insert(Vector* this, int idx, void* data_);
|
void Vector_insert(Vector* this, int idx, void* data_);
|
||||||
|
|
||||||
|
@ -59,8 +68,16 @@ void Vector_moveDown(Vector* this, int idx);
|
||||||
|
|
||||||
void Vector_set(Vector* this, int idx, void* data_);
|
void Vector_set(Vector* this, int idx, void* data_);
|
||||||
|
|
||||||
|
#ifdef DEBUG
|
||||||
|
|
||||||
extern Object* Vector_get(Vector* this, int idx);
|
extern Object* Vector_get(Vector* this, int idx);
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
#define Vector_get(v_, idx_) ((v_)->array[idx_])
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
extern int Vector_size(Vector* this);
|
extern int Vector_size(Vector* this);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
29
configure.ac
29
configure.ac
|
@ -2,7 +2,7 @@
|
||||||
# Process this file with autoconf to produce a configure script.
|
# Process this file with autoconf to produce a configure script.
|
||||||
|
|
||||||
AC_PREREQ(2.65)
|
AC_PREREQ(2.65)
|
||||||
AC_INIT([htop],[0.9.1],[loderunner@users.sourceforge.net])
|
AC_INIT([htop],[1.0],[loderunner@users.sourceforge.net])
|
||||||
|
|
||||||
# The following two lines are required by hwloc scripts
|
# The following two lines are required by hwloc scripts
|
||||||
AC_USE_SYSTEM_EXTENSIONS
|
AC_USE_SYSTEM_EXTENSIONS
|
||||||
|
@ -87,9 +87,12 @@ if test "x$enable_taskstats" = xyes; then
|
||||||
AC_DEFINE(HAVE_TASKSTATS, 1, [Define if taskstats support enabled.])
|
AC_DEFINE(HAVE_TASKSTATS, 1, [Define if taskstats support enabled.])
|
||||||
fi
|
fi
|
||||||
|
|
||||||
AC_ARG_ENABLE(unicode, [AC_HELP_STRING([--enable-unicode], [enable Unicode support])], ,enable_unicode="no")
|
AC_ARG_ENABLE(unicode, [AC_HELP_STRING([--enable-unicode], [enable Unicode support])], ,enable_unicode="yes")
|
||||||
if test "x$enable_unicode" = xyes; then
|
if test "x$enable_unicode" = xyes; then
|
||||||
AC_CHECK_LIB([ncursesw], [refresh], [], [missing_libraries="$missing_libraries libncursesw"])
|
AC_CHECK_LIB([ncursesw], [refresh], [], [
|
||||||
|
missing_libraries="$missing_libraries libncursesw"
|
||||||
|
AC_MSG_ERROR([You may want to use --disable-unicode or install libncursesw.])
|
||||||
|
])
|
||||||
AC_CHECK_HEADERS([ncursesw/curses.h],[:],
|
AC_CHECK_HEADERS([ncursesw/curses.h],[:],
|
||||||
[AC_CHECK_HEADERS([ncurses/ncurses.h],[:],
|
[AC_CHECK_HEADERS([ncurses/ncurses.h],[:],
|
||||||
[AC_CHECK_HEADERS([ncurses.h],[:],[missing_headers="$missing_headers $ac_header"])])])
|
[AC_CHECK_HEADERS([ncurses.h],[:],[missing_headers="$missing_headers $ac_header"])])])
|
||||||
|
@ -110,10 +113,28 @@ AC_CHECK_FILE($PROCDIR/stat,,AC_MSG_ERROR(Cannot find /proc/stat. Make sure you
|
||||||
AC_CHECK_FILE($PROCDIR/meminfo,,AC_MSG_ERROR(Cannot find /proc/meminfo. Make sure you have a Linux-compatible /proc filesystem mounted. See the file README for help.))
|
AC_CHECK_FILE($PROCDIR/meminfo,,AC_MSG_ERROR(Cannot find /proc/meminfo. Make sure you have a Linux-compatible /proc filesystem mounted. See the file README for help.))
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
AC_ARG_ENABLE(native_affinity, [AC_HELP_STRING([--enable-native-affinity], [enable native sched_setaffinity and sched_getaffinity for affinity support, disables hwloc])], ,enable_native_affinity="yes")
|
||||||
|
if test "x$enable_native_affinity" = xyes; then
|
||||||
|
AC_MSG_CHECKING([for usable sched_setaffinity])
|
||||||
|
AC_RUN_IFELSE([
|
||||||
|
AC_LANG_PROGRAM([[
|
||||||
|
#include <sched.h>
|
||||||
|
#include <errno.h>
|
||||||
|
static cpu_set_t cpuset;
|
||||||
|
]], [[
|
||||||
|
CPU_ZERO(&cpuset);
|
||||||
|
sched_setaffinity(0, sizeof(cpu_set_t), &cpuset);
|
||||||
|
if (errno == ENOSYS) return 1;
|
||||||
|
]])],
|
||||||
|
[AC_DEFINE(HAVE_NATIVE_AFFINITY, 1, [Define if native sched_setaffinity and sched_getaffinity are to be used.])
|
||||||
|
AC_MSG_RESULT([yes])],
|
||||||
|
[AC_MSG_RESULT([no])])
|
||||||
|
fi
|
||||||
|
|
||||||
##### hwloc
|
##### hwloc
|
||||||
AC_ARG_ENABLE(system-hwloc, [AC_HELP_STRING([--enable-system-hwloc], [use the copy of hwloc from your system and not the one bundled with the htop sources. (hwloc required)])], ,enable_system_hwloc="no")
|
AC_ARG_ENABLE(system-hwloc, [AC_HELP_STRING([--enable-system-hwloc], [use the copy of hwloc from your system and not the one bundled with the htop sources. (hwloc required)])], ,enable_system_hwloc="no")
|
||||||
enable_xml=no
|
enable_xml=no
|
||||||
AC_ARG_ENABLE(hwloc, [AC_HELP_STRING([--enable-hwloc], [enable hwloc support for CPU affinity])],, enable_hwloc="yes")
|
AC_ARG_ENABLE(hwloc, [AC_HELP_STRING([--enable-hwloc], [enable hwloc support for CPU affinity])],, test "x$enable_native_affinity" = xno && enable_hwloc="yes")
|
||||||
if test "x$enable_hwloc" = xyes
|
if test "x$enable_hwloc" = xyes
|
||||||
then
|
then
|
||||||
if test "x$enable_system_hwloc" = xyes
|
if test "x$enable_system_hwloc" = xyes
|
||||||
|
|
2
debug.h
2
debug.h
|
@ -8,7 +8,7 @@
|
||||||
#define realloc(x,s) DebugMemory_realloc(x, s, __FILE__, __LINE__, #x)
|
#define realloc(x,s) DebugMemory_realloc(x, s, __FILE__, __LINE__, #x)
|
||||||
#define strdup(x) DebugMemory_strdup(x, __FILE__, __LINE__)
|
#define strdup(x) DebugMemory_strdup(x, __FILE__, __LINE__)
|
||||||
#define free(x) DebugMemory_free(x, __FILE__, __LINE__)
|
#define free(x) DebugMemory_free(x, __FILE__, __LINE__)
|
||||||
#define debug_done() DebugMemory_report(); _nc_free_and_exit()
|
#define debug_done() DebugMemory_report(); _nc_freeall()
|
||||||
|
|
||||||
#elif defined(DEBUGLITE)
|
#elif defined(DEBUGLITE)
|
||||||
|
|
||||||
|
|
43
htop.c
43
htop.c
|
@ -193,44 +193,11 @@ static bool changePriority(Panel* panel, int delta) {
|
||||||
return anyTagged;
|
return anyTagged;
|
||||||
}
|
}
|
||||||
|
|
||||||
static HandlerResult pickWithEnter(Panel* panel, int ch) {
|
|
||||||
int size = Panel_size(panel);
|
|
||||||
|
|
||||||
if (isalnum(ch)) {
|
|
||||||
int len = strlen(panel->eventHandlerBuffer);
|
|
||||||
if (len < 99) {
|
|
||||||
panel->eventHandlerBuffer[len] = ch;
|
|
||||||
panel->eventHandlerBuffer[len+1] = '\0';
|
|
||||||
}
|
|
||||||
for (int try = 0; try < 2; try++) {
|
|
||||||
len = strlen(panel->eventHandlerBuffer);
|
|
||||||
for (int i = 0; i < size; i++) {
|
|
||||||
char* cur = ((ListItem*) Panel_get(panel, i))->value;
|
|
||||||
while (*cur == ' ') cur++;
|
|
||||||
if (strncasecmp(cur, panel->eventHandlerBuffer, len) == 0) {
|
|
||||||
Panel_setSelected(panel, i);
|
|
||||||
return HANDLED;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
panel->eventHandlerBuffer[0] = ch;
|
|
||||||
panel->eventHandlerBuffer[1] = '\0';
|
|
||||||
}
|
|
||||||
return HANDLED;
|
|
||||||
} else if (ch != ERR) {
|
|
||||||
panel->eventHandlerBuffer[0] = '\0';
|
|
||||||
}
|
|
||||||
if (ch == 13) {
|
|
||||||
return BREAK_LOOP;
|
|
||||||
}
|
|
||||||
return IGNORED;
|
|
||||||
}
|
|
||||||
|
|
||||||
static Object* pickFromVector(Panel* panel, Panel* list, int x, int y, const char** keyLabels, FunctionBar* prevBar, Header* header) {
|
static Object* pickFromVector(Panel* panel, Panel* list, int x, int y, const char** keyLabels, FunctionBar* prevBar, Header* header) {
|
||||||
const char* fuKeys[] = {"Enter", "Esc", NULL};
|
const char* fuKeys[] = {"Enter", "Esc", NULL};
|
||||||
int fuEvents[] = {13, 27};
|
int fuEvents[] = {13, 27};
|
||||||
list->eventHandlerBuffer = calloc(100, 1);
|
|
||||||
if (!list->eventHandler)
|
if (!list->eventHandler)
|
||||||
Panel_setEventHandler(list, pickWithEnter);
|
Panel_setEventHandler(list, Panel_selectByTyping);
|
||||||
ScreenManager* scr = ScreenManager_new(0, y, 0, -1, HORIZONTAL, header, false);
|
ScreenManager* scr = ScreenManager_new(0, y, 0, -1, HORIZONTAL, header, false);
|
||||||
ScreenManager_add(scr, list, FunctionBar_new(keyLabels, fuKeys, fuEvents), x - 1);
|
ScreenManager_add(scr, list, FunctionBar_new(keyLabels, fuKeys, fuEvents), x - 1);
|
||||||
ScreenManager_add(scr, panel, NULL, -1);
|
ScreenManager_add(scr, panel, NULL, -1);
|
||||||
|
@ -238,8 +205,6 @@ static Object* pickFromVector(Panel* panel, Panel* list, int x, int y, const cha
|
||||||
int ch;
|
int ch;
|
||||||
ScreenManager_run(scr, &panelFocus, &ch);
|
ScreenManager_run(scr, &panelFocus, &ch);
|
||||||
ScreenManager_delete(scr);
|
ScreenManager_delete(scr);
|
||||||
free(list->eventHandlerBuffer);
|
|
||||||
list->eventHandlerBuffer = NULL;
|
|
||||||
Panel_move(panel, 0, y);
|
Panel_move(panel, 0, y);
|
||||||
Panel_resize(panel, COLS, LINES-y-1);
|
Panel_resize(panel, COLS, LINES-y-1);
|
||||||
FunctionBar_draw(prevBar, NULL);
|
FunctionBar_draw(prevBar, NULL);
|
||||||
|
@ -383,7 +348,7 @@ int main(int argc, char** argv) {
|
||||||
Process_getMaxPid();
|
Process_getMaxPid();
|
||||||
|
|
||||||
Header* header = Header_new(pl);
|
Header* header = Header_new(pl);
|
||||||
settings = Settings_new(pl, header);
|
settings = Settings_new(pl, header, pl->cpuCount);
|
||||||
int headerHeight = Header_calculateHeight(header);
|
int headerHeight = Header_calculateHeight(header);
|
||||||
|
|
||||||
// FIXME: move delay code to settings
|
// FIXME: move delay code to settings
|
||||||
|
@ -750,7 +715,7 @@ int main(int argc, char** argv) {
|
||||||
Panel* usersPanel = Panel_new(0, 0, 0, 0, LISTITEM_CLASS, true, ListItem_compare);
|
Panel* usersPanel = Panel_new(0, 0, 0, 0, LISTITEM_CLASS, true, ListItem_compare);
|
||||||
Panel_setHeader(usersPanel, "Show processes of:");
|
Panel_setHeader(usersPanel, "Show processes of:");
|
||||||
UsersTable_foreach(ut, addUserToVector, usersPanel);
|
UsersTable_foreach(ut, addUserToVector, usersPanel);
|
||||||
Vector_sort(usersPanel->items);
|
Vector_insertionSort(usersPanel->items);
|
||||||
ListItem* allUsers = ListItem_new("All users", -1);
|
ListItem* allUsers = ListItem_new("All users", -1);
|
||||||
Panel_insert(usersPanel, 0, (Object*) allUsers);
|
Panel_insert(usersPanel, 0, (Object*) allUsers);
|
||||||
const char* fuFunctions[] = {"Show ", "Cancel ", NULL};
|
const char* fuFunctions[] = {"Show ", "Cancel ", NULL};
|
||||||
|
@ -808,7 +773,7 @@ int main(int argc, char** argv) {
|
||||||
refreshTimeout = 0;
|
refreshTimeout = 0;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
#ifdef HAVE_HWLOC
|
#if (HAVE_HWLOC || HAVE_NATIVE_AFFINITY)
|
||||||
case 'a':
|
case 'a':
|
||||||
{
|
{
|
||||||
if (pl->cpuCount == 1)
|
if (pl->cpuCount == 1)
|
||||||
|
|
Loading…
Reference in New Issue