mirror of https://github.com/xzeldon/htop.git
Performance improvement hackathon: improve process comparison routines,
disable useless code in release builds such as runtime type-checking on dynamic data structures and process fields that are not being computed, faster(?) method for verifying the process owner (still need to ensure correctness), don't destroy and create process objects for hidden kernel threads over and over. Phew. I shouldn't be doing all this today, but I could not resist.
This commit is contained in:
parent
4c41e78bbf
commit
5d48ab8c28
|
@ -1,8 +1,12 @@
|
||||||
|
|
||||||
What's new in version 0.6.3
|
What's new in version 0.6.3
|
||||||
|
|
||||||
|
* Performance improvements; uses much less CPU than the
|
||||||
|
previous release with the default setup.
|
||||||
* Use 64-bit values when storing processor times to
|
* Use 64-bit values when storing processor times to
|
||||||
avoid overflow.
|
avoid overflow.
|
||||||
|
* Memory consumption improvements, compensating storage
|
||||||
|
of 64-bit values.
|
||||||
* Internal change: rename TypedVector to Vector and
|
* Internal change: rename TypedVector to Vector and
|
||||||
ListBox (and related classes) to Panel.
|
ListBox (and related classes) to Panel.
|
||||||
|
|
||||||
|
|
|
@ -21,11 +21,15 @@ typedef struct CheckItem_ {
|
||||||
|
|
||||||
}*/
|
}*/
|
||||||
|
|
||||||
|
#ifdef DEBUG
|
||||||
char* CHECKITEM_CLASS = "CheckItem";
|
char* CHECKITEM_CLASS = "CheckItem";
|
||||||
|
#else
|
||||||
|
#define CHECKITEM_CLASS NULL
|
||||||
|
#endif
|
||||||
|
|
||||||
CheckItem* CheckItem_new(char* text, bool* value) {
|
CheckItem* CheckItem_new(char* text, bool* value) {
|
||||||
CheckItem* this = malloc(sizeof(CheckItem));
|
CheckItem* this = malloc(sizeof(CheckItem));
|
||||||
((Object*)this)->class = CHECKITEM_CLASS;
|
Object_setClass(this, CHECKITEM_CLASS);
|
||||||
((Object*)this)->display = CheckItem_display;
|
((Object*)this)->display = CheckItem_display;
|
||||||
((Object*)this)->delete = CheckItem_delete;
|
((Object*)this)->delete = CheckItem_delete;
|
||||||
this->text = text;
|
this->text = text;
|
||||||
|
|
|
@ -22,7 +22,11 @@ typedef struct CheckItem_ {
|
||||||
} CheckItem;
|
} CheckItem;
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef DEBUG
|
||||||
extern char* CHECKITEM_CLASS;
|
extern char* CHECKITEM_CLASS;
|
||||||
|
#else
|
||||||
|
#define CHECKITEM_CLASS NULL
|
||||||
|
#endif
|
||||||
|
|
||||||
CheckItem* CheckItem_new(char* text, bool* value);
|
CheckItem* CheckItem_new(char* text, bool* value);
|
||||||
|
|
||||||
|
|
|
@ -30,7 +30,11 @@ typedef struct FunctionBar_ {
|
||||||
|
|
||||||
}*/
|
}*/
|
||||||
|
|
||||||
|
#ifdef DEBUG
|
||||||
char* FUNCTIONBAR_CLASS = "FunctionBar";
|
char* FUNCTIONBAR_CLASS = "FunctionBar";
|
||||||
|
#else
|
||||||
|
#define FUNCTIONBAR_CLASS NULL
|
||||||
|
#endif
|
||||||
|
|
||||||
static char* FunctionBar_FKeys[10] = {"F1", "F2", "F3", "F4", "F5", "F6", "F7", "F8", "F9", "F10"};
|
static char* FunctionBar_FKeys[10] = {"F1", "F2", "F3", "F4", "F5", "F6", "F7", "F8", "F9", "F10"};
|
||||||
|
|
||||||
|
@ -40,7 +44,7 @@ static int FunctionBar_FEvents[10] = {KEY_F(1), KEY_F(2), KEY_F(3), KEY_F(4), KE
|
||||||
|
|
||||||
FunctionBar* FunctionBar_new(int size, char** functions, char** keys, int* events) {
|
FunctionBar* FunctionBar_new(int size, char** functions, char** keys, int* events) {
|
||||||
FunctionBar* this = malloc(sizeof(FunctionBar));
|
FunctionBar* this = malloc(sizeof(FunctionBar));
|
||||||
((Object*) this)->class = FUNCTIONBAR_CLASS;
|
Object_setClass(this, FUNCTIONBAR_CLASS);
|
||||||
((Object*) this)->delete = FunctionBar_delete;
|
((Object*) this)->delete = FunctionBar_delete;
|
||||||
this->functions = functions;
|
this->functions = functions;
|
||||||
this->size = size;
|
this->size = size;
|
||||||
|
|
|
@ -31,7 +31,11 @@ typedef struct FunctionBar_ {
|
||||||
} FunctionBar;
|
} FunctionBar;
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef DEBUG
|
||||||
extern char* FUNCTIONBAR_CLASS;
|
extern char* FUNCTIONBAR_CLASS;
|
||||||
|
#else
|
||||||
|
#define FUNCTIONBAR_CLASS NULL
|
||||||
|
#endif
|
||||||
|
|
||||||
FunctionBar* FunctionBar_new(int size, char** functions, char** keys, int* events);
|
FunctionBar* FunctionBar_new(int size, char** functions, char** keys, int* events);
|
||||||
|
|
||||||
|
|
|
@ -55,7 +55,7 @@ Hashtable* Hashtable_new(int size, bool owner) {
|
||||||
}
|
}
|
||||||
|
|
||||||
int Hashtable_hashAlgorithm(Hashtable* this, int key) {
|
int Hashtable_hashAlgorithm(Hashtable* this, int key) {
|
||||||
return (key % this->size);
|
return key % this->size;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Hashtable_delete(Hashtable* this) {
|
void Hashtable_delete(Hashtable* this) {
|
||||||
|
@ -116,17 +116,20 @@ void* Hashtable_remove(Hashtable* this, int key) {
|
||||||
} else
|
} else
|
||||||
bucketPtr = &((*bucketPtr)->next);
|
bucketPtr = &((*bucketPtr)->next);
|
||||||
}
|
}
|
||||||
|
//#include <stdio.h>
|
||||||
inline void* Hashtable_get(Hashtable* this, int key) {
|
inline void* Hashtable_get(Hashtable* this, int key) {
|
||||||
int index = this->hashAlgorithm(this, key);
|
int index = this->hashAlgorithm(this, key);
|
||||||
HashtableItem* bucketPtr = this->buckets[index];
|
HashtableItem* bucketPtr = this->buckets[index];
|
||||||
while (true)
|
// fprintf(stderr, "%d -> %d\n", key, index);
|
||||||
|
while (true) {
|
||||||
if (bucketPtr == NULL) {
|
if (bucketPtr == NULL) {
|
||||||
return NULL;
|
return NULL;
|
||||||
} else if (bucketPtr->key == key) {
|
} else if (bucketPtr->key == key) {
|
||||||
return bucketPtr->value;
|
return bucketPtr->value;
|
||||||
} else
|
} else
|
||||||
bucketPtr = bucketPtr->next;
|
bucketPtr = bucketPtr->next;
|
||||||
|
// fprintf(stderr, "*\n");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Hashtable_foreach(Hashtable* this, Hashtable_PairFunction f, void* userData) {
|
void Hashtable_foreach(Hashtable* this, Hashtable_PairFunction f, void* userData) {
|
||||||
|
|
|
@ -47,7 +47,7 @@ inline int Hashtable_size(Hashtable* this);
|
||||||
void Hashtable_put(Hashtable* this, int key, void* value);
|
void Hashtable_put(Hashtable* this, int key, void* value);
|
||||||
|
|
||||||
void* Hashtable_remove(Hashtable* this, int key);
|
void* Hashtable_remove(Hashtable* this, int key);
|
||||||
|
//#include <stdio.h>
|
||||||
inline void* Hashtable_get(Hashtable* this, int key);
|
inline void* Hashtable_get(Hashtable* this, int key);
|
||||||
|
|
||||||
void Hashtable_foreach(Hashtable* this, Hashtable_PairFunction f, void* userData);
|
void Hashtable_foreach(Hashtable* this, Hashtable_PairFunction f, void* userData);
|
||||||
|
|
4
Header.c
4
Header.c
|
@ -35,8 +35,8 @@ typedef struct Header_ {
|
||||||
|
|
||||||
Header* Header_new(ProcessList* pl) {
|
Header* Header_new(ProcessList* pl) {
|
||||||
Header* this = malloc(sizeof(Header));
|
Header* this = malloc(sizeof(Header));
|
||||||
this->leftMeters = Vector_new(METER_CLASS, true, DEFAULT_SIZE);
|
this->leftMeters = Vector_new(METER_CLASS, true, DEFAULT_SIZE, NULL);
|
||||||
this->rightMeters = Vector_new(METER_CLASS, true, DEFAULT_SIZE);
|
this->rightMeters = Vector_new(METER_CLASS, true, DEFAULT_SIZE, NULL);
|
||||||
this->margin = true;
|
this->margin = true;
|
||||||
this->pl = pl;
|
this->pl = pl;
|
||||||
return this;
|
return this;
|
||||||
|
|
|
@ -23,14 +23,17 @@ typedef struct ListItem_ {
|
||||||
|
|
||||||
}*/
|
}*/
|
||||||
|
|
||||||
|
#ifdef DEBUG
|
||||||
char* LISTITEM_CLASS = "ListItem";
|
char* LISTITEM_CLASS = "ListItem";
|
||||||
|
#else
|
||||||
|
#define LISTITEM_CLASS NULL
|
||||||
|
#endif
|
||||||
|
|
||||||
ListItem* ListItem_new(char* value, int key) {
|
ListItem* ListItem_new(char* value, int key) {
|
||||||
ListItem* this = malloc(sizeof(ListItem));
|
ListItem* this = malloc(sizeof(ListItem));
|
||||||
((Object*)this)->class = LISTITEM_CLASS;
|
Object_setClass(this, LISTITEM_CLASS);
|
||||||
((Object*)this)->display = ListItem_display;
|
((Object*)this)->display = ListItem_display;
|
||||||
((Object*)this)->delete = ListItem_delete;
|
((Object*)this)->delete = ListItem_delete;
|
||||||
((Object*)this)->compare = ListItem_compare;
|
|
||||||
this->value = String_copy(value);
|
this->value = String_copy(value);
|
||||||
this->key = key;
|
this->key = key;
|
||||||
return this;
|
return this;
|
||||||
|
@ -62,7 +65,7 @@ const char* ListItem_getRef(ListItem* this) {
|
||||||
return this->value;
|
return this->value;
|
||||||
}
|
}
|
||||||
|
|
||||||
int ListItem_compare(const Object* cast1, const Object* cast2) {
|
int ListItem_compare(const void* cast1, const void* cast2) {
|
||||||
ListItem* obj1 = (ListItem*) cast1;
|
ListItem* obj1 = (ListItem*) cast1;
|
||||||
ListItem* obj2 = (ListItem*) cast2;
|
ListItem* obj2 = (ListItem*) cast2;
|
||||||
return strcmp(obj1->value, obj2->value);
|
return strcmp(obj1->value, obj2->value);
|
||||||
|
|
|
@ -24,7 +24,11 @@ typedef struct ListItem_ {
|
||||||
} ListItem;
|
} ListItem;
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef DEBUG
|
||||||
extern char* LISTITEM_CLASS;
|
extern char* LISTITEM_CLASS;
|
||||||
|
#else
|
||||||
|
#define LISTITEM_CLASS NULL
|
||||||
|
#endif
|
||||||
|
|
||||||
ListItem* ListItem_new(char* value, int key);
|
ListItem* ListItem_new(char* value, int key);
|
||||||
|
|
||||||
|
@ -36,7 +40,7 @@ void ListItem_display(Object* cast, RichString* out);
|
||||||
|
|
||||||
const char* ListItem_getRef(ListItem* this);
|
const char* ListItem_getRef(ListItem* this);
|
||||||
|
|
||||||
int ListItem_compare(const Object* cast1, const Object* cast2);
|
int ListItem_compare(const void* cast1, const void* cast2);
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -27,6 +27,9 @@ ColorsPanel.c ColorsPanel.h TraceScreen.c TraceScreen.h \
|
||||||
AvailableColumnsPanel.c AvailableColumnsPanel.h ColumnsPanel.c \
|
AvailableColumnsPanel.c AvailableColumnsPanel.h ColumnsPanel.c \
|
||||||
ColumnsPanel.h
|
ColumnsPanel.h
|
||||||
|
|
||||||
|
profile:
|
||||||
|
$(MAKE) all CFLAGS="-pg -O2"
|
||||||
|
|
||||||
debug:
|
debug:
|
||||||
$(MAKE) all CFLAGS="-g -DDEBUG"
|
$(MAKE) all CFLAGS="-g -DDEBUG"
|
||||||
|
|
||||||
|
|
10
Meter.c
10
Meter.c
|
@ -104,7 +104,11 @@ typedef enum {
|
||||||
#define MAX(a,b) ((a)>(b)?(a):(b))
|
#define MAX(a,b) ((a)>(b)?(a):(b))
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef DEBUG
|
||||||
char* METER_CLASS = "Meter";
|
char* METER_CLASS = "Meter";
|
||||||
|
#else
|
||||||
|
#define METER_CLASS NULL
|
||||||
|
#endif
|
||||||
|
|
||||||
MeterType* Meter_types[] = {
|
MeterType* Meter_types[] = {
|
||||||
&CPUMeter,
|
&CPUMeter,
|
||||||
|
@ -162,6 +166,9 @@ static RichString Meter_stringBuffer;
|
||||||
|
|
||||||
Meter* Meter_new(ProcessList* pl, int param, MeterType* type) {
|
Meter* Meter_new(ProcessList* pl, int param, MeterType* type) {
|
||||||
Meter* this = calloc(sizeof(Meter), 1);
|
Meter* this = calloc(sizeof(Meter), 1);
|
||||||
|
Object_setClass(this, METER_CLASS);
|
||||||
|
((Object*)this)->delete = Meter_delete;
|
||||||
|
((Object*)this)->display = type->display;
|
||||||
this->h = 1;
|
this->h = 1;
|
||||||
this->type = type;
|
this->type = type;
|
||||||
this->param = param;
|
this->param = param;
|
||||||
|
@ -169,9 +176,6 @@ 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);
|
||||||
((Object*)this)->delete = Meter_delete;
|
|
||||||
((Object*)this)->class = METER_CLASS;
|
|
||||||
((Object*)this)->display = type->display;
|
|
||||||
Meter_setMode(this, type->mode);
|
Meter_setMode(this, type->mode);
|
||||||
if (this->type->init)
|
if (this->type->init)
|
||||||
this->type->init(this);
|
this->type->init(this);
|
||||||
|
|
5
Meter.h
5
Meter.h
|
@ -96,6 +96,7 @@ typedef enum {
|
||||||
#include "TasksMeter.h"
|
#include "TasksMeter.h"
|
||||||
#include "LoadAverageMeter.h"
|
#include "LoadAverageMeter.h"
|
||||||
#include "UptimeMeter.h"
|
#include "UptimeMeter.h"
|
||||||
|
#include "ClockMeter.h"
|
||||||
|
|
||||||
#ifndef MIN
|
#ifndef MIN
|
||||||
#define MIN(a,b) ((a)<(b)?(a):(b))
|
#define MIN(a,b) ((a)<(b)?(a):(b))
|
||||||
|
@ -104,7 +105,11 @@ typedef enum {
|
||||||
#define MAX(a,b) ((a)>(b)?(a):(b))
|
#define MAX(a,b) ((a)>(b)?(a):(b))
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef DEBUG
|
||||||
extern char* METER_CLASS;
|
extern char* METER_CLASS;
|
||||||
|
#else
|
||||||
|
#define METER_CLASS NULL
|
||||||
|
#endif
|
||||||
|
|
||||||
extern MeterType* Meter_types[];
|
extern MeterType* Meter_types[];
|
||||||
|
|
||||||
|
|
36
Object.c
36
Object.c
|
@ -15,37 +15,37 @@ in the source distribution for its full text.
|
||||||
#include "debug.h"
|
#include "debug.h"
|
||||||
|
|
||||||
/*{
|
/*{
|
||||||
|
|
||||||
|
#ifndef DEBUG
|
||||||
|
#define Object_setClass(obj, class)
|
||||||
|
#endif
|
||||||
|
|
||||||
typedef struct Object_ Object;
|
typedef struct Object_ Object;
|
||||||
|
|
||||||
typedef void(*Object_Display)(Object*, RichString*);
|
typedef void(*Object_Display)(Object*, RichString*);
|
||||||
typedef int(*Object_Compare)(const Object*, const Object*);
|
typedef int(*Object_Compare)(const void*, const void*);
|
||||||
typedef void(*Object_Delete)(Object*);
|
typedef void(*Object_Delete)(Object*);
|
||||||
|
|
||||||
struct Object_ {
|
struct Object_ {
|
||||||
|
#ifdef DEBUG
|
||||||
char* class;
|
char* class;
|
||||||
|
#endif
|
||||||
Object_Display display;
|
Object_Display display;
|
||||||
Object_Compare compare;
|
|
||||||
Object_Delete delete;
|
Object_Delete delete;
|
||||||
};
|
};
|
||||||
}*/
|
}*/
|
||||||
|
|
||||||
static char* OBJECT_CLASS = "Object";
|
#ifdef DEBUG
|
||||||
|
char* OBJECT_CLASS = "Object";
|
||||||
|
|
||||||
void Object_new() {
|
#else
|
||||||
Object* this;
|
#define OBJECT_CLASS NULL
|
||||||
this = malloc(sizeof(Object));
|
#endif
|
||||||
this->class = OBJECT_CLASS;
|
|
||||||
this->display = Object_display;
|
|
||||||
this->compare = Object_compare;
|
|
||||||
this->delete = Object_delete;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Object_instanceOf(Object* this, char* class) {
|
#ifdef DEBUG
|
||||||
return this->class == class;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Object_delete(Object* this) {
|
void Object_setClass(void* this, char* class) {
|
||||||
free(this);
|
((Object*)this)->class = class;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Object_display(Object* this, RichString* out) {
|
void Object_display(Object* this, RichString* out) {
|
||||||
|
@ -54,6 +54,4 @@ void Object_display(Object* this, RichString* out) {
|
||||||
RichString_write(out, CRT_colors[DEFAULT_COLOR], objAddress);
|
RichString_write(out, CRT_colors[DEFAULT_COLOR], objAddress);
|
||||||
}
|
}
|
||||||
|
|
||||||
int Object_compare(const Object* this, const Object* o) {
|
#endif
|
||||||
return (this - o);
|
|
||||||
}
|
|
||||||
|
|
23
Object.h
23
Object.h
|
@ -17,27 +17,38 @@ in the source distribution for its full text.
|
||||||
|
|
||||||
#include "debug.h"
|
#include "debug.h"
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef DEBUG
|
||||||
|
#define Object_setClass(obj, class)
|
||||||
|
#endif
|
||||||
|
|
||||||
typedef struct Object_ Object;
|
typedef struct Object_ Object;
|
||||||
|
|
||||||
typedef void(*Object_Display)(Object*, RichString*);
|
typedef void(*Object_Display)(Object*, RichString*);
|
||||||
typedef int(*Object_Compare)(const Object*, const Object*);
|
typedef int(*Object_Compare)(const void*, const void*);
|
||||||
typedef void(*Object_Delete)(Object*);
|
typedef void(*Object_Delete)(Object*);
|
||||||
|
|
||||||
struct Object_ {
|
struct Object_ {
|
||||||
|
#ifdef DEBUG
|
||||||
char* class;
|
char* class;
|
||||||
|
#endif
|
||||||
Object_Display display;
|
Object_Display display;
|
||||||
Object_Compare compare;
|
|
||||||
Object_Delete delete;
|
Object_Delete delete;
|
||||||
};
|
};
|
||||||
|
|
||||||
void Object_new();
|
#ifdef DEBUG
|
||||||
|
extern char* OBJECT_CLASS;
|
||||||
|
|
||||||
bool Object_instanceOf(Object* this, char* class);
|
#else
|
||||||
|
#define OBJECT_CLASS NULL
|
||||||
|
#endif
|
||||||
|
|
||||||
void Object_delete(Object* this);
|
#ifdef DEBUG
|
||||||
|
|
||||||
|
void Object_setClass(void* this, char* class);
|
||||||
|
|
||||||
void Object_display(Object* this, RichString* out);
|
void Object_display(Object* this, RichString* out);
|
||||||
|
|
||||||
int Object_compare(const Object* this, const Object* o);
|
#endif
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
13
Panel.c
13
Panel.c
|
@ -10,6 +10,7 @@ in the source distribution for its full text.
|
||||||
#include "Vector.h"
|
#include "Vector.h"
|
||||||
#include "CRT.h"
|
#include "CRT.h"
|
||||||
#include "RichString.h"
|
#include "RichString.h"
|
||||||
|
#include "ListItem.h"
|
||||||
|
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
|
@ -54,12 +55,18 @@ struct Panel_ {
|
||||||
#define MAX(a,b) ((a)>(b)?(a):(b))
|
#define MAX(a,b) ((a)>(b)?(a):(b))
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef DEBUG
|
||||||
char* PANEL_CLASS = "Panel";
|
char* PANEL_CLASS = "Panel";
|
||||||
|
#else
|
||||||
|
#define PANEL_CLASS NULL
|
||||||
|
#endif
|
||||||
|
|
||||||
Panel* Panel_new(int x, int y, int w, int h, char* type, bool owner) {
|
|
||||||
|
Panel* Panel_new(int x, int y, int w, int h, char* type, bool owner, Object_Compare compare) {
|
||||||
Panel* this;
|
Panel* this;
|
||||||
this = malloc(sizeof(Panel));
|
this = malloc(sizeof(Panel));
|
||||||
Panel_init(this, x, y, w, h, type, owner);
|
Panel_init(this, x, y, w, h, type, owner);
|
||||||
|
this->items->compare = compare;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -71,14 +78,14 @@ void Panel_delete(Object* cast) {
|
||||||
|
|
||||||
void Panel_init(Panel* this, int x, int y, int w, int h, char* type, bool owner) {
|
void Panel_init(Panel* this, int x, int y, int w, int h, char* type, bool owner) {
|
||||||
Object* super = (Object*) this;
|
Object* super = (Object*) this;
|
||||||
super->class = PANEL_CLASS;
|
Object_setClass(this, PANEL_CLASS);
|
||||||
super->delete = Panel_delete;
|
super->delete = Panel_delete;
|
||||||
this->x = x;
|
this->x = x;
|
||||||
this->y = y;
|
this->y = y;
|
||||||
this->w = w;
|
this->w = w;
|
||||||
this->h = h;
|
this->h = h;
|
||||||
this->eventHandler = NULL;
|
this->eventHandler = NULL;
|
||||||
this->items = Vector_new(type, owner, DEFAULT_SIZE);
|
this->items = Vector_new(type, owner, DEFAULT_SIZE, ListItem_compare);
|
||||||
this->scrollV = 0;
|
this->scrollV = 0;
|
||||||
this->scrollH = 0;
|
this->scrollH = 0;
|
||||||
this->selected = 0;
|
this->selected = 0;
|
||||||
|
|
7
Panel.h
7
Panel.h
|
@ -55,9 +55,14 @@ struct Panel_ {
|
||||||
#define MAX(a,b) ((a)>(b)?(a):(b))
|
#define MAX(a,b) ((a)>(b)?(a):(b))
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef DEBUG
|
||||||
extern char* PANEL_CLASS;
|
extern char* PANEL_CLASS;
|
||||||
|
#else
|
||||||
|
#define PANEL_CLASS NULL
|
||||||
|
#endif
|
||||||
|
|
||||||
Panel* Panel_new(int x, int y, int w, int h, char* type, bool owner);
|
|
||||||
|
Panel* Panel_new(int x, int y, int w, int h, char* type, bool owner, Object_Compare compare);
|
||||||
|
|
||||||
void Panel_delete(Object* cast);
|
void Panel_delete(Object* cast);
|
||||||
|
|
||||||
|
|
100
Process.c
100
Process.c
|
@ -62,16 +62,19 @@ typedef struct Process_ {
|
||||||
int tty_nr;
|
int tty_nr;
|
||||||
int tpgid;
|
int tpgid;
|
||||||
unsigned long int flags;
|
unsigned long int flags;
|
||||||
|
#ifdef DEBUG
|
||||||
unsigned long int minflt;
|
unsigned long int minflt;
|
||||||
unsigned long int cminflt;
|
unsigned long int cminflt;
|
||||||
unsigned long int majflt;
|
unsigned long int majflt;
|
||||||
unsigned long int cmajflt;
|
unsigned long int cmajflt;
|
||||||
|
#endif
|
||||||
unsigned long int utime;
|
unsigned long int utime;
|
||||||
unsigned long int stime;
|
unsigned long int stime;
|
||||||
long int cutime;
|
long int cutime;
|
||||||
long int cstime;
|
long int cstime;
|
||||||
long int priority;
|
long int priority;
|
||||||
long int nice;
|
long int nice;
|
||||||
|
#ifdef DEBUG
|
||||||
long int itrealvalue;
|
long int itrealvalue;
|
||||||
unsigned long int starttime;
|
unsigned long int starttime;
|
||||||
unsigned long int vsize;
|
unsigned long int vsize;
|
||||||
|
@ -89,6 +92,7 @@ typedef struct Process_ {
|
||||||
unsigned long int wchan;
|
unsigned long int wchan;
|
||||||
unsigned long int nswap;
|
unsigned long int nswap;
|
||||||
unsigned long int cnswap;
|
unsigned long int cnswap;
|
||||||
|
#endif
|
||||||
int exit_signal;
|
int exit_signal;
|
||||||
int processor;
|
int processor;
|
||||||
int m_size;
|
int m_size;
|
||||||
|
@ -106,7 +110,11 @@ typedef struct Process_ {
|
||||||
|
|
||||||
}*/
|
}*/
|
||||||
|
|
||||||
|
#ifdef DEBUG
|
||||||
char* PROCESS_CLASS = "Process";
|
char* PROCESS_CLASS = "Process";
|
||||||
|
#else
|
||||||
|
#define PROCESS_CLASS NULL
|
||||||
|
#endif
|
||||||
|
|
||||||
char *Process_fieldNames[] = {
|
char *Process_fieldNames[] = {
|
||||||
"", "PID", "Command", "STATE", "PPID", "PGRP", "SESSION", "TTY_NR", "TPGID", "FLAGS", "MINFLT", "CMINFLT", "MAJFLT", "CMAJFLT", "UTIME", "STIME", "CUTIME", "CSTIME", "PRIORITY", "NICE", "ITREALVALUE", "STARTTIME", "VSIZE", "RSS", "RLIM", "STARTCODE", "ENDCODE", "STARTSTACK", "KSTKESP", "KSTKEIP", "SIGNAL", "BLOCKED", "SIGIGNORE", "SIGCATCH", "WCHAN", "NSWAP", "CNSWAP", "EXIT_SIGNAL", "PROCESSOR", "M_SIZE", "M_RESIDENT", "M_SHARE", "M_TRS", "M_DRS", "M_LRS", "M_DT", "ST_UID", "PERCENT_CPU", "PERCENT_MEM", "USER", "TIME", "*** report bug! ***"
|
"", "PID", "Command", "STATE", "PPID", "PGRP", "SESSION", "TTY_NR", "TPGID", "FLAGS", "MINFLT", "CMINFLT", "MAJFLT", "CMAJFLT", "UTIME", "STIME", "CUTIME", "CSTIME", "PRIORITY", "NICE", "ITREALVALUE", "STARTTIME", "VSIZE", "RSS", "RLIM", "STARTCODE", "ENDCODE", "STARTSTACK", "KSTKESP", "KSTKEIP", "SIGNAL", "BLOCKED", "SIGIGNORE", "SIGCATCH", "WCHAN", "NSWAP", "CNSWAP", "EXIT_SIGNAL", "PROCESSOR", "M_SIZE", "M_RESIDENT", "M_SHARE", "M_TRS", "M_DRS", "M_LRS", "M_DT", "ST_UID", "PERCENT_CPU", "PERCENT_MEM", "USER", "TIME", "*** report bug! ***"
|
||||||
|
@ -114,9 +122,8 @@ char *Process_fieldNames[] = {
|
||||||
|
|
||||||
Process* Process_new(struct ProcessList_ *pl) {
|
Process* Process_new(struct ProcessList_ *pl) {
|
||||||
Process* this = malloc(sizeof(Process));
|
Process* this = malloc(sizeof(Process));
|
||||||
((Object*)this)->class = PROCESS_CLASS;
|
Object_setClass(this, PROCESS_CLASS);
|
||||||
((Object*)this)->display = Process_display;
|
((Object*)this)->display = Process_display;
|
||||||
((Object*)this)->compare = Process_compare;
|
|
||||||
((Object*)this)->delete = Process_delete;
|
((Object*)this)->delete = Process_delete;
|
||||||
this->pl = pl;
|
this->pl = pl;
|
||||||
this->tag = false;
|
this->tag = false;
|
||||||
|
@ -265,21 +272,21 @@ void Process_writeField(Process* this, RichString* str, ProcessField field) {
|
||||||
for (int i = 0; i < 32; i++)
|
for (int i = 0; i < 32; i++)
|
||||||
if (this->indent & (1 << i))
|
if (this->indent & (1 << i))
|
||||||
maxIndent = i+1;
|
maxIndent = i+1;
|
||||||
for (int i = 0; i < maxIndent - 1; i++) {
|
for (int i = 0; i < maxIndent - 1; i++) {
|
||||||
if (this->indent & (1 << i))
|
if (this->indent & (1 << i))
|
||||||
snprintf(buf, n, " | ");
|
snprintf(buf, n, " | ");
|
||||||
else
|
else
|
||||||
snprintf(buf, n, " ");
|
snprintf(buf, n, " ");
|
||||||
buf += 4;
|
buf += 4;
|
||||||
n -= 4;
|
n -= 4;
|
||||||
}
|
}
|
||||||
if (this->pl->direction == 1)
|
if (this->pl->direction == 1)
|
||||||
snprintf(buf, n, " `- ");
|
snprintf(buf, n, " `- ");
|
||||||
else
|
else
|
||||||
snprintf(buf, n, " ,- ");
|
snprintf(buf, n, " ,- ");
|
||||||
RichString_append(str, CRT_colors[PROCESS_TREE], buffer);
|
RichString_append(str, CRT_colors[PROCESS_TREE], buffer);
|
||||||
Process_writeCommand(this, attr, str);
|
Process_writeCommand(this, attr, str);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
case STATE: {
|
case STATE: {
|
||||||
|
@ -345,44 +352,57 @@ void Process_writeField(Process* this, RichString* str, ProcessField field) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
int Process_compare(const Object* v1, const Object* v2) {
|
int Process_pidCompare(const void* v1, const void* v2) {
|
||||||
Process* p1 = (Process*)v1;
|
Process* p1 = (Process*)v1;
|
||||||
Process* p2 = (Process*)v2;
|
Process* p2 = (Process*)v2;
|
||||||
int direction = p1->pl->direction;
|
return (p1->pid - p2->pid);
|
||||||
switch (p1->pl->sortKey) {
|
}
|
||||||
case PID:
|
|
||||||
return (p2->pid - p1->pid) * direction;
|
int Process_compare(const void* v1, const void* v2) {
|
||||||
case PPID:
|
Process *p1, *p2;
|
||||||
return (p2->ppid - p1->ppid) * direction;
|
ProcessList *pl = ((Process*)v1)->pl;
|
||||||
case USER:
|
if (pl->direction == 1) {
|
||||||
return strcmp(p2->user, p1->user) * direction;
|
p1 = (Process*)v1;
|
||||||
case PRIORITY:
|
p2 = (Process*)v2;
|
||||||
return (p2->priority - p1->priority) * direction;
|
} else {
|
||||||
case STATE:
|
p2 = (Process*)v1;
|
||||||
return (p2->state - p1->state) * direction;
|
p1 = (Process*)v2;
|
||||||
case NICE:
|
|
||||||
return (p2->nice - p1->nice) * direction;
|
|
||||||
case M_SIZE:
|
|
||||||
return (p1->m_size - p2->m_size) * direction;
|
|
||||||
case M_RESIDENT:
|
|
||||||
return (p1->m_resident - p2->m_resident) * direction;
|
|
||||||
case M_SHARE:
|
|
||||||
return (p1->m_share - p2->m_share) * direction;
|
|
||||||
case PERCENT_CPU:
|
|
||||||
return (p1->percent_cpu < p2->percent_cpu ? -1 : 1) * direction;
|
|
||||||
case PERCENT_MEM:
|
|
||||||
return (p1->percent_mem < p2->percent_mem ? -1 : 1) * direction;
|
|
||||||
case UTIME:
|
|
||||||
return (p1->utime - p2->utime) * direction;
|
|
||||||
case STIME:
|
|
||||||
return (p1->stime - p2->stime) * direction;
|
|
||||||
case TIME:
|
|
||||||
return ((p1->utime+p1->stime) - (p2->utime+p2->stime)) * direction;
|
|
||||||
case COMM:
|
|
||||||
return strcmp(p2->comm, p1->comm) * direction;
|
|
||||||
default:
|
|
||||||
return (p2->pid - p1->pid) * direction;
|
|
||||||
}
|
}
|
||||||
|
switch (pl->sortKey) {
|
||||||
|
case PID:
|
||||||
|
return (p1->pid - p2->pid);
|
||||||
|
case PPID:
|
||||||
|
return (p1->ppid - p2->ppid);
|
||||||
|
case USER:
|
||||||
|
return strcmp(p1->user, p2->user);
|
||||||
|
case PRIORITY:
|
||||||
|
return (p1->priority - p2->priority);
|
||||||
|
case STATE:
|
||||||
|
return (p1->state - p2->state);
|
||||||
|
case NICE:
|
||||||
|
return (p1->nice - p2->nice);
|
||||||
|
case M_SIZE:
|
||||||
|
return (p2->m_size - p1->m_size);
|
||||||
|
case M_RESIDENT:
|
||||||
|
return (p2->m_resident - p1->m_resident);
|
||||||
|
case M_SHARE:
|
||||||
|
return (p2->m_share - p1->m_share);
|
||||||
|
case PERCENT_CPU:
|
||||||
|
return (p2->percent_cpu > p1->percent_cpu ? 1 : -1);
|
||||||
|
case PERCENT_MEM:
|
||||||
|
return (p2->m_resident - p1->m_resident);
|
||||||
|
case UTIME:
|
||||||
|
return (p2->utime - p1->utime);
|
||||||
|
case STIME:
|
||||||
|
return (p2->stime - p1->stime);
|
||||||
|
case TIME:
|
||||||
|
return ((p2->utime+p2->stime) - (p1->utime+p1->stime));
|
||||||
|
case COMM:
|
||||||
|
return strcmp(p1->comm, p2->comm);
|
||||||
|
default:
|
||||||
|
return (p1->pid - p2->pid);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
char* Process_printField(ProcessField field) {
|
char* Process_printField(ProcessField field) {
|
||||||
|
|
12
Process.h
12
Process.h
|
@ -64,16 +64,19 @@ typedef struct Process_ {
|
||||||
int tty_nr;
|
int tty_nr;
|
||||||
int tpgid;
|
int tpgid;
|
||||||
unsigned long int flags;
|
unsigned long int flags;
|
||||||
|
#ifdef DEBUG
|
||||||
unsigned long int minflt;
|
unsigned long int minflt;
|
||||||
unsigned long int cminflt;
|
unsigned long int cminflt;
|
||||||
unsigned long int majflt;
|
unsigned long int majflt;
|
||||||
unsigned long int cmajflt;
|
unsigned long int cmajflt;
|
||||||
|
#endif
|
||||||
unsigned long int utime;
|
unsigned long int utime;
|
||||||
unsigned long int stime;
|
unsigned long int stime;
|
||||||
long int cutime;
|
long int cutime;
|
||||||
long int cstime;
|
long int cstime;
|
||||||
long int priority;
|
long int priority;
|
||||||
long int nice;
|
long int nice;
|
||||||
|
#ifdef DEBUG
|
||||||
long int itrealvalue;
|
long int itrealvalue;
|
||||||
unsigned long int starttime;
|
unsigned long int starttime;
|
||||||
unsigned long int vsize;
|
unsigned long int vsize;
|
||||||
|
@ -91,6 +94,7 @@ typedef struct Process_ {
|
||||||
unsigned long int wchan;
|
unsigned long int wchan;
|
||||||
unsigned long int nswap;
|
unsigned long int nswap;
|
||||||
unsigned long int cnswap;
|
unsigned long int cnswap;
|
||||||
|
#endif
|
||||||
int exit_signal;
|
int exit_signal;
|
||||||
int processor;
|
int processor;
|
||||||
int m_size;
|
int m_size;
|
||||||
|
@ -107,7 +111,11 @@ typedef struct Process_ {
|
||||||
} Process;
|
} Process;
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef DEBUG
|
||||||
extern char* PROCESS_CLASS;
|
extern char* PROCESS_CLASS;
|
||||||
|
#else
|
||||||
|
#define PROCESS_CLASS NULL
|
||||||
|
#endif
|
||||||
|
|
||||||
extern char *Process_fieldNames[];
|
extern char *Process_fieldNames[];
|
||||||
|
|
||||||
|
@ -131,7 +139,9 @@ void Process_sendSignal(Process* this, int signal);
|
||||||
|
|
||||||
void Process_writeField(Process* this, RichString* str, ProcessField field);
|
void Process_writeField(Process* this, RichString* str, ProcessField field);
|
||||||
|
|
||||||
int Process_compare(const Object* v1, const Object* v2);
|
int Process_pidCompare(const void* v1, const void* v2);
|
||||||
|
|
||||||
|
int Process_compare(const void* v1, const void* v2);
|
||||||
|
|
||||||
char* Process_printField(ProcessField field);
|
char* Process_printField(ProcessField field);
|
||||||
|
|
||||||
|
|
140
ProcessList.c
140
ProcessList.c
|
@ -15,6 +15,7 @@ in the source distribution for its full text.
|
||||||
#include "Vector.h"
|
#include "Vector.h"
|
||||||
#include "UsersTable.h"
|
#include "UsersTable.h"
|
||||||
#include "Hashtable.h"
|
#include "Hashtable.h"
|
||||||
|
#include "String.h"
|
||||||
|
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
|
@ -48,13 +49,17 @@ in the source distribution for its full text.
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef MAX_READ
|
#ifndef MAX_READ
|
||||||
#define MAX_READ 8192
|
#define MAX_READ 2048
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
}*/
|
}*/
|
||||||
|
|
||||||
/*{
|
/*{
|
||||||
|
|
||||||
|
#ifdef DEBUG
|
||||||
|
typedef int(*vxscanf)(void*, const char*, va_list);
|
||||||
|
#endif
|
||||||
|
|
||||||
typedef struct ProcessList_ {
|
typedef struct ProcessList_ {
|
||||||
Vector* processes;
|
Vector* processes;
|
||||||
Vector* processes2;
|
Vector* processes2;
|
||||||
|
@ -108,8 +113,6 @@ static ProcessField defaultHeaders[] = { PID, USER, PRIORITY, NICE, M_SIZE, M_RE
|
||||||
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
|
|
||||||
typedef int(*vxscanf)(void*, const char*, va_list);
|
|
||||||
|
|
||||||
#define ProcessList_read(this, buffer, format, ...) ProcessList_xread(this, (vxscanf) vsscanf, buffer, format, ## __VA_ARGS__ )
|
#define ProcessList_read(this, buffer, format, ...) ProcessList_xread(this, (vxscanf) vsscanf, buffer, format, ## __VA_ARGS__ )
|
||||||
#define ProcessList_fread(this, file, format, ...) ProcessList_xread(this, (vxscanf) vfscanf, file, format, ## __VA_ARGS__ )
|
#define ProcessList_fread(this, file, format, ...) ProcessList_xread(this, (vxscanf) vfscanf, file, format, ## __VA_ARGS__ )
|
||||||
|
|
||||||
|
@ -173,13 +176,13 @@ static inline int ProcessList_xread(ProcessList* this, vxscanf fn, void* buffer,
|
||||||
ProcessList* ProcessList_new(UsersTable* usersTable) {
|
ProcessList* ProcessList_new(UsersTable* usersTable) {
|
||||||
ProcessList* this;
|
ProcessList* this;
|
||||||
this = malloc(sizeof(ProcessList));
|
this = malloc(sizeof(ProcessList));
|
||||||
this->processes = Vector_new(PROCESS_CLASS, true, DEFAULT_SIZE);
|
this->processes = Vector_new(PROCESS_CLASS, true, DEFAULT_SIZE, Process_compare);
|
||||||
this->processTable = Hashtable_new(20, false);
|
this->processTable = Hashtable_new(20, false);
|
||||||
this->prototype = Process_new(this);
|
this->prototype = Process_new(this);
|
||||||
this->usersTable = usersTable;
|
this->usersTable = usersTable;
|
||||||
|
|
||||||
/* tree-view auxiliary buffers */
|
/* tree-view auxiliary buffers */
|
||||||
this->processes2 = Vector_new(PROCESS_CLASS, true, DEFAULT_SIZE);
|
this->processes2 = Vector_new(PROCESS_CLASS, true, DEFAULT_SIZE, Process_compare);
|
||||||
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
this->traceFile = fopen("/tmp/htop-proc-trace", "w");
|
this->traceFile = fopen("/tmp/htop-proc-trace", "w");
|
||||||
|
@ -286,11 +289,8 @@ void ProcessList_add(ProcessList* this, Process* p) {
|
||||||
|
|
||||||
void ProcessList_remove(ProcessList* this, Process* p) {
|
void ProcessList_remove(ProcessList* this, Process* p) {
|
||||||
Hashtable_remove(this->processTable, p->pid);
|
Hashtable_remove(this->processTable, p->pid);
|
||||||
ProcessField pf = this->sortKey;
|
int index = Vector_indexOf(this->processes, p, Process_pidCompare);
|
||||||
this->sortKey = PID;
|
|
||||||
int index = Vector_indexOf(this->processes, p);
|
|
||||||
Vector_remove(this->processes, index);
|
Vector_remove(this->processes, index);
|
||||||
this->sortKey = pf;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Process* ProcessList_get(ProcessList* this, int index) {
|
Process* ProcessList_get(ProcessList* this, int index) {
|
||||||
|
@ -302,7 +302,7 @@ int ProcessList_size(ProcessList* this) {
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ProcessList_buildTree(ProcessList* this, int pid, int level, int indent, int direction) {
|
static void ProcessList_buildTree(ProcessList* this, int pid, int level, int indent, int direction) {
|
||||||
Vector* children = Vector_new(PROCESS_CLASS, false, DEFAULT_SIZE);
|
Vector* children = Vector_new(PROCESS_CLASS, false, DEFAULT_SIZE, Process_compare);
|
||||||
|
|
||||||
for (int i = 0; i < Vector_size(this->processes); i++) {
|
for (int i = 0; i < Vector_size(this->processes); i++) {
|
||||||
Process* process = (Process*) (Vector_get(this->processes, i));
|
Process* process = (Process*) (Vector_get(this->processes, i));
|
||||||
|
@ -352,7 +352,7 @@ void ProcessList_sort(ProcessList* this) {
|
||||||
|
|
||||||
static int ProcessList_readStatFile(ProcessList* this, Process *proc, FILE *f, char *command) {
|
static int ProcessList_readStatFile(ProcessList* this, Process *proc, FILE *f, char *command) {
|
||||||
static char buf[MAX_READ];
|
static char buf[MAX_READ];
|
||||||
long int zero;
|
unsigned long int zero;
|
||||||
|
|
||||||
int size = fread(buf, 1, MAX_READ, f);
|
int size = fread(buf, 1, MAX_READ, f);
|
||||||
if(!size) return 0;
|
if(!size) return 0;
|
||||||
|
@ -370,6 +370,7 @@ static int ProcessList_readStatFile(ProcessList* this, Process *proc, FILE *f, c
|
||||||
command[commsize] = '\0';
|
command[commsize] = '\0';
|
||||||
location = end + 2;
|
location = end + 2;
|
||||||
|
|
||||||
|
#ifdef DEBUG
|
||||||
int num = ProcessList_read(this, location,
|
int num = ProcessList_read(this, location,
|
||||||
"%c %d %d %d %d %d %lu %lu %lu %lu "
|
"%c %d %d %d %d %d %lu %lu %lu %lu "
|
||||||
"%lu %lu %lu %ld %ld %ld %ld %ld %ld "
|
"%lu %lu %lu %ld %ld %ld %ld %ld %ld "
|
||||||
|
@ -377,14 +378,34 @@ static int ProcessList_readStatFile(ProcessList* this, Process *proc, FILE *f, c
|
||||||
"%lu %lu %lu %lu %lu %lu %lu %lu "
|
"%lu %lu %lu %lu %lu %lu %lu %lu "
|
||||||
"%d %d",
|
"%d %d",
|
||||||
&proc->state, &proc->ppid, &proc->pgrp, &proc->session, &proc->tty_nr,
|
&proc->state, &proc->ppid, &proc->pgrp, &proc->session, &proc->tty_nr,
|
||||||
&proc->tpgid, &proc->flags, &proc->minflt, &proc->cminflt, &proc->majflt,
|
&proc->tpgid, &proc->flags,
|
||||||
&proc->cmajflt, &proc->utime, &proc->stime, &proc->cutime, &proc->cstime,
|
&proc->minflt, &proc->cminflt, &proc->majflt, &proc->cmajflt,
|
||||||
|
&proc->utime, &proc->stime, &proc->cutime, &proc->cstime,
|
||||||
&proc->priority, &proc->nice, &zero, &proc->itrealvalue,
|
&proc->priority, &proc->nice, &zero, &proc->itrealvalue,
|
||||||
&proc->starttime, &proc->vsize, &proc->rss, &proc->rlim,
|
&proc->starttime, &proc->vsize, &proc->rss, &proc->rlim,
|
||||||
&proc->startcode, &proc->endcode, &proc->startstack, &proc->kstkesp,
|
&proc->startcode, &proc->endcode, &proc->startstack, &proc->kstkesp,
|
||||||
&proc->kstkeip, &proc->signal, &proc->blocked, &proc->sigignore,
|
&proc->kstkeip, &proc->signal, &proc->blocked, &proc->sigignore,
|
||||||
&proc->sigcatch, &proc->wchan, &proc->nswap, &proc->cnswap,
|
&proc->sigcatch, &proc->wchan, &proc->nswap, &proc->cnswap,
|
||||||
&proc->exit_signal, &proc->processor);
|
&proc->exit_signal, &proc->processor);
|
||||||
|
#else
|
||||||
|
long int uzero;
|
||||||
|
int num = ProcessList_read(this, location,
|
||||||
|
"%c %d %d %d %d %d %lu %lu %lu %lu "
|
||||||
|
"%lu %lu %lu %ld %ld %ld %ld %ld %ld "
|
||||||
|
"%lu %lu %ld %lu %lu %lu %lu %lu "
|
||||||
|
"%lu %lu %lu %lu %lu %lu %lu %lu "
|
||||||
|
"%d %d",
|
||||||
|
&proc->state, &proc->ppid, &proc->pgrp, &proc->session, &proc->tty_nr,
|
||||||
|
&proc->tpgid, &proc->flags,
|
||||||
|
&zero, &zero, &zero, &zero,
|
||||||
|
&proc->utime, &proc->stime, &proc->cutime, &proc->cstime,
|
||||||
|
&proc->priority, &proc->nice, &uzero, &uzero,
|
||||||
|
&zero, &zero, &uzero, &zero,
|
||||||
|
&zero, &zero, &zero, &zero,
|
||||||
|
&zero, &zero, &zero, &zero,
|
||||||
|
&zero, &zero, &zero, &zero,
|
||||||
|
&proc->exit_signal, &proc->processor);
|
||||||
|
#endif
|
||||||
|
|
||||||
// This assert is always valid on 2.4, but reportedly not always valid on 2.6.
|
// This assert is always valid on 2.4, but reportedly not always valid on 2.6.
|
||||||
// TODO: Check if the semantics of this field has changed.
|
// TODO: Check if the semantics of this field has changed.
|
||||||
|
@ -397,14 +418,15 @@ static int ProcessList_readStatFile(ProcessList* this, Process *proc, FILE *f, c
|
||||||
bool ProcessList_readStatusFile(ProcessList* this, Process* proc, char* dirname, char* name) {
|
bool ProcessList_readStatusFile(ProcessList* this, Process* proc, char* dirname, char* name) {
|
||||||
char statusfilename[MAX_NAME+1];
|
char statusfilename[MAX_NAME+1];
|
||||||
statusfilename[MAX_NAME] = '\0';
|
statusfilename[MAX_NAME] = '\0';
|
||||||
|
/*
|
||||||
|
bool success = false;
|
||||||
|
char buffer[256];
|
||||||
|
buffer[255] = '\0';
|
||||||
snprintf(statusfilename, MAX_NAME, "%s/%s/status", dirname, name);
|
snprintf(statusfilename, MAX_NAME, "%s/%s/status", dirname, name);
|
||||||
FILE* status = ProcessList_fopen(this, statusfilename, "r");
|
FILE* status = ProcessList_fopen(this, statusfilename, "r");
|
||||||
bool success = false;
|
|
||||||
if (status) {
|
if (status) {
|
||||||
char buffer[1024];
|
|
||||||
buffer[1023] = '\0';
|
|
||||||
while (!feof(status)) {
|
while (!feof(status)) {
|
||||||
char* ok = fgets(buffer, 1023, status);
|
char* ok = fgets(buffer, 255, status);
|
||||||
if (!ok)
|
if (!ok)
|
||||||
break;
|
break;
|
||||||
if (String_startsWith(buffer, "Uid:")) {
|
if (String_startsWith(buffer, "Uid:")) {
|
||||||
|
@ -421,14 +443,18 @@ bool ProcessList_readStatusFile(ProcessList* this, Process* proc, char* dirname,
|
||||||
fclose(status);
|
fclose(status);
|
||||||
}
|
}
|
||||||
if (!success) {
|
if (!success) {
|
||||||
snprintf(statusfilename, MAX_NAME, "%s/%s/stat", dirname, name);
|
*/
|
||||||
|
snprintf(statusfilename, MAX_NAME, "%s/%s", dirname, name);
|
||||||
struct stat sstat;
|
struct stat sstat;
|
||||||
int statok = stat(statusfilename, &sstat);
|
int statok = stat(statusfilename, &sstat);
|
||||||
if (statok == -1)
|
if (statok == -1)
|
||||||
return false;
|
return false;
|
||||||
proc->st_uid = sstat.st_uid;
|
proc->st_uid = sstat.st_uid;
|
||||||
}
|
return true;
|
||||||
return success;
|
/*
|
||||||
|
} else
|
||||||
|
return true;
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
|
|
||||||
void ProcessList_processEntries(ProcessList* this, char* dirname, int parent, float period) {
|
void ProcessList_processEntries(ProcessList* this, char* dirname, int parent, float period) {
|
||||||
|
@ -469,25 +495,25 @@ void ProcessList_processEntries(ProcessList* this, char* dirname, int parent, fl
|
||||||
char command[PROCESS_COMM_LEN + 1];
|
char command[PROCESS_COMM_LEN + 1];
|
||||||
|
|
||||||
Process* process;
|
Process* process;
|
||||||
|
|
||||||
Process* existingProcess = (Process*) Hashtable_get(this->processTable, pid);
|
Process* existingProcess = (Process*) Hashtable_get(this->processTable, pid);
|
||||||
if (!existingProcess) {
|
if (existingProcess) {
|
||||||
process = Process_clone(prototype);
|
process = existingProcess;
|
||||||
|
} else {
|
||||||
|
process = prototype;
|
||||||
|
process->comm = NULL;
|
||||||
process->pid = pid;
|
process->pid = pid;
|
||||||
ProcessList_add(this, process);
|
|
||||||
if (! ProcessList_readStatusFile(this, process, dirname, name))
|
if (! ProcessList_readStatusFile(this, process, dirname, name))
|
||||||
goto errorReadingProcess;
|
goto errorReadingProcess;
|
||||||
} else {
|
char* username = UsersTable_getRef(this->usersTable, process->st_uid);
|
||||||
process = existingProcess;
|
if (username) {
|
||||||
|
strncpy(process->user, username, PROCESS_USER_LEN);
|
||||||
|
} else {
|
||||||
|
snprintf(process->user, PROCESS_USER_LEN, "%d", process->st_uid);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
process->updated = true;
|
process->updated = true;
|
||||||
|
|
||||||
char* username = UsersTable_getRef(this->usersTable, process->st_uid);
|
|
||||||
if (username) {
|
|
||||||
strncpy(process->user, username, PROCESS_USER_LEN);
|
|
||||||
} else {
|
|
||||||
snprintf(process->user, PROCESS_USER_LEN, "%d", process->st_uid);
|
|
||||||
}
|
|
||||||
|
|
||||||
int lasttimes = (process->utime + process->stime);
|
int lasttimes = (process->utime + process->stime);
|
||||||
|
|
||||||
snprintf(statusfilename, MAX_NAME, "%s/%s/stat", dirname, name);
|
snprintf(statusfilename, MAX_NAME, "%s/%s/stat", dirname, name);
|
||||||
|
@ -498,13 +524,30 @@ void ProcessList_processEntries(ProcessList* this, char* dirname, int parent, fl
|
||||||
|
|
||||||
int success = ProcessList_readStatFile(this, process, status, command);
|
int success = ProcessList_readStatFile(this, process, status, command);
|
||||||
fclose(status);
|
fclose(status);
|
||||||
if(!success) {
|
if(!success)
|
||||||
goto errorReadingProcess;
|
goto errorReadingProcess;
|
||||||
}
|
|
||||||
|
|
||||||
process->percent_cpu = (process->utime + process->stime - lasttimes) /
|
process->percent_cpu = (process->utime + process->stime - lasttimes) /
|
||||||
period * 100.0;
|
period * 100.0;
|
||||||
|
|
||||||
|
snprintf(statusfilename, MAX_NAME, "%s/%s/statm", dirname, name);
|
||||||
|
status = ProcessList_fopen(this, statusfilename, "r");
|
||||||
|
|
||||||
|
if(!status) {
|
||||||
|
goto errorReadingProcess;
|
||||||
|
}
|
||||||
|
int num = ProcessList_fread(this, status, "%d %d %d %d %d %d %d",
|
||||||
|
&process->m_size, &process->m_resident, &process->m_share,
|
||||||
|
&process->m_trs, &process->m_drs, &process->m_lrs,
|
||||||
|
&process->m_dt);
|
||||||
|
|
||||||
|
fclose(status);
|
||||||
|
if(num != 7)
|
||||||
|
goto errorReadingProcess;
|
||||||
|
|
||||||
|
if (this->hideKernelThreads && process->m_size == 0)
|
||||||
|
goto errorReadingProcess;
|
||||||
|
|
||||||
if(!existingProcess) {
|
if(!existingProcess) {
|
||||||
snprintf(statusfilename, MAX_NAME, "%s/%s/cmdline", dirname, name);
|
snprintf(statusfilename, MAX_NAME, "%s/%s/cmdline", dirname, name);
|
||||||
status = ProcessList_fopen(this, statusfilename, "r");
|
status = ProcessList_fopen(this, statusfilename, "r");
|
||||||
|
@ -524,21 +567,6 @@ void ProcessList_processEntries(ProcessList* this, char* dirname, int parent, fl
|
||||||
fclose(status);
|
fclose(status);
|
||||||
}
|
}
|
||||||
|
|
||||||
snprintf(statusfilename, MAX_NAME, "%s/%s/statm", dirname, name);
|
|
||||||
status = ProcessList_fopen(this, statusfilename, "r");
|
|
||||||
|
|
||||||
if(!status) {
|
|
||||||
goto errorReadingProcess;
|
|
||||||
}
|
|
||||||
int num = ProcessList_fread(this, status, "%d %d %d %d %d %d %d",
|
|
||||||
&process->m_size, &process->m_resident, &process->m_share,
|
|
||||||
&process->m_trs, &process->m_drs, &process->m_lrs,
|
|
||||||
&process->m_dt);
|
|
||||||
|
|
||||||
fclose(status);
|
|
||||||
if(num != 7)
|
|
||||||
goto errorReadingProcess;
|
|
||||||
|
|
||||||
process->percent_mem = process->m_resident /
|
process->percent_mem = process->m_resident /
|
||||||
(float)(this->usedMem - this->cachedMem - this->buffersMem) *
|
(float)(this->usedMem - this->cachedMem - this->buffersMem) *
|
||||||
100.0;
|
100.0;
|
||||||
|
@ -548,17 +576,25 @@ void ProcessList_processEntries(ProcessList* this, char* dirname, int parent, fl
|
||||||
this->runningTasks++;
|
this->runningTasks++;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this->hideKernelThreads && process->m_size == 0)
|
if (!existingProcess) {
|
||||||
ProcessList_remove(this, process);
|
process = Process_clone(process);
|
||||||
|
ProcessList_add(this, process);
|
||||||
|
}
|
||||||
|
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
// Exception handler.
|
// Exception handler.
|
||||||
errorReadingProcess: {
|
errorReadingProcess: {
|
||||||
ProcessList_remove(this, process);
|
if (existingProcess)
|
||||||
|
ProcessList_remove(this, process);
|
||||||
|
else {
|
||||||
|
if (process->comm)
|
||||||
|
free(process->comm);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
prototype->comm = NULL;
|
||||||
closedir(dir);
|
closedir(dir);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -18,6 +18,7 @@ in the source distribution for its full text.
|
||||||
#include "Vector.h"
|
#include "Vector.h"
|
||||||
#include "UsersTable.h"
|
#include "UsersTable.h"
|
||||||
#include "Hashtable.h"
|
#include "Hashtable.h"
|
||||||
|
#include "String.h"
|
||||||
|
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
|
@ -50,11 +51,15 @@ in the source distribution for its full text.
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef MAX_READ
|
#ifndef MAX_READ
|
||||||
#define MAX_READ 8192
|
#define MAX_READ 2048
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef DEBUG
|
||||||
|
typedef int(*vxscanf)(void*, const char*, va_list);
|
||||||
|
#endif
|
||||||
|
|
||||||
typedef struct ProcessList_ {
|
typedef struct ProcessList_ {
|
||||||
Vector* processes;
|
Vector* processes;
|
||||||
Vector* processes2;
|
Vector* processes2;
|
||||||
|
|
|
@ -47,8 +47,8 @@ ScreenManager* ScreenManager_new(int x1, int y1, int x2, int y2, Orientation ori
|
||||||
this->y2 = y2;
|
this->y2 = y2;
|
||||||
this->fuBar = NULL;
|
this->fuBar = NULL;
|
||||||
this->orientation = orientation;
|
this->orientation = orientation;
|
||||||
this->items = Vector_new(PANEL_CLASS, owner, DEFAULT_SIZE);
|
this->items = Vector_new(PANEL_CLASS, owner, DEFAULT_SIZE, NULL);
|
||||||
this->fuBars = Vector_new(FUNCTIONBAR_CLASS, true, DEFAULT_SIZE);
|
this->fuBars = Vector_new(FUNCTIONBAR_CLASS, true, DEFAULT_SIZE, NULL);
|
||||||
this->itemCount = 0;
|
this->itemCount = 0;
|
||||||
this->owner = owner;
|
this->owner = owner;
|
||||||
return this;
|
return this;
|
||||||
|
@ -130,7 +130,7 @@ void ScreenManager_run(ScreenManager* this, Panel** lastFocus, int* lastKey) {
|
||||||
if (this->fuBar)
|
if (this->fuBar)
|
||||||
FunctionBar_draw(this->fuBar, NULL);
|
FunctionBar_draw(this->fuBar, NULL);
|
||||||
|
|
||||||
int ch;
|
int ch = 0;
|
||||||
while (!quit) {
|
while (!quit) {
|
||||||
int items = this->itemCount;
|
int items = this->itemCount;
|
||||||
for (int i = 0; i < items; i++) {
|
for (int i = 0; i < items; i++) {
|
||||||
|
|
|
@ -25,11 +25,15 @@ typedef struct Signal_ {
|
||||||
|
|
||||||
}*/
|
}*/
|
||||||
|
|
||||||
|
#ifdef DEBUG
|
||||||
char* SIGNAL_CLASS = "Signal";
|
char* SIGNAL_CLASS = "Signal";
|
||||||
|
#else
|
||||||
|
#define SIGNAL_CLASS NULL
|
||||||
|
#endif
|
||||||
|
|
||||||
Signal* Signal_new(char* name, int number) {
|
Signal* Signal_new(char* name, int number) {
|
||||||
Signal* this = malloc(sizeof(Signal));
|
Signal* this = malloc(sizeof(Signal));
|
||||||
((Object*)this)->class = SIGNAL_CLASS;
|
Object_setClass(this, SIGNAL_CLASS);
|
||||||
((Object*)this)->display = Signal_display;
|
((Object*)this)->display = Signal_display;
|
||||||
((Object*)this)->delete = Signal_delete;
|
((Object*)this)->delete = Signal_delete;
|
||||||
this->name = name;
|
this->name = name;
|
||||||
|
|
|
@ -26,7 +26,11 @@ typedef struct Signal_ {
|
||||||
} Signal;
|
} Signal;
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef DEBUG
|
||||||
extern char* SIGNAL_CLASS;
|
extern char* SIGNAL_CLASS;
|
||||||
|
#else
|
||||||
|
#define SIGNAL_CLASS NULL
|
||||||
|
#endif
|
||||||
|
|
||||||
Signal* Signal_new(char* name, int number);
|
Signal* Signal_new(char* name, int number);
|
||||||
|
|
||||||
|
|
8
String.c
8
String.c
|
@ -14,6 +14,10 @@ in the source distribution for its full text.
|
||||||
|
|
||||||
#include "debug.h"
|
#include "debug.h"
|
||||||
|
|
||||||
|
/*{
|
||||||
|
#define String_startsWith(s, match) (strstr((s), (match)) == (s))
|
||||||
|
}*/
|
||||||
|
|
||||||
inline void String_delete(char* s) {
|
inline void String_delete(char* s) {
|
||||||
free(s);
|
free(s);
|
||||||
}
|
}
|
||||||
|
@ -102,10 +106,6 @@ inline int String_eq(char* s1, char* s2) {
|
||||||
return (strcmp(s1, s2) == 0);
|
return (strcmp(s1, s2) == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline int String_startsWith(char* s, char* match) {
|
|
||||||
return (strstr(s, match) == s);
|
|
||||||
}
|
|
||||||
|
|
||||||
char** String_split(char* s, char sep) {
|
char** String_split(char* s, char sep) {
|
||||||
const int rate = 10;
|
const int rate = 10;
|
||||||
char** out = (char**) malloc(sizeof(char*) * rate);
|
char** out = (char**) malloc(sizeof(char*) * rate);
|
||||||
|
|
4
String.h
4
String.h
|
@ -17,6 +17,8 @@ in the source distribution for its full text.
|
||||||
|
|
||||||
#include "debug.h"
|
#include "debug.h"
|
||||||
|
|
||||||
|
#define String_startsWith(s, match) (strstr((s), (match)) == (s))
|
||||||
|
|
||||||
inline void String_delete(char* s);
|
inline void String_delete(char* s);
|
||||||
|
|
||||||
inline char* String_copy(char* orig);
|
inline char* String_copy(char* orig);
|
||||||
|
@ -39,8 +41,6 @@ void String_printPointer(void* p);
|
||||||
|
|
||||||
inline int String_eq(char* s1, char* s2);
|
inline int String_eq(char* s1, char* s2);
|
||||||
|
|
||||||
inline int String_startsWith(char* s, char* match);
|
|
||||||
|
|
||||||
char** String_split(char* s, char sep);
|
char** String_split(char* s, char sep);
|
||||||
|
|
||||||
void String_freeArray(char** s);
|
void String_freeArray(char** s);
|
||||||
|
|
|
@ -41,7 +41,7 @@ static int tbEvents[3] = {KEY_F(4), KEY_F(5), 27};
|
||||||
TraceScreen* TraceScreen_new(Process* process) {
|
TraceScreen* TraceScreen_new(Process* process) {
|
||||||
TraceScreen* this = (TraceScreen*) malloc(sizeof(TraceScreen));
|
TraceScreen* this = (TraceScreen*) malloc(sizeof(TraceScreen));
|
||||||
this->process = process;
|
this->process = process;
|
||||||
this->display = Panel_new(0, 1, COLS, LINES-2, LISTITEM_CLASS, true);
|
this->display = Panel_new(0, 1, COLS, LINES-2, LISTITEM_CLASS, true, ListItem_compare);
|
||||||
this->bar = FunctionBar_new(3, tbFunctions, tbKeys, tbEvents);
|
this->bar = FunctionBar_new(3, tbFunctions, tbKeys, tbEvents);
|
||||||
this->tracing = true;
|
this->tracing = true;
|
||||||
return this;
|
return this;
|
||||||
|
|
39
Vector.c
39
Vector.c
|
@ -24,6 +24,7 @@ typedef void(*Vector_procedure)(void*);
|
||||||
|
|
||||||
typedef struct Vector_ {
|
typedef struct Vector_ {
|
||||||
Object **array;
|
Object **array;
|
||||||
|
Object_Compare compare;
|
||||||
int arraySize;
|
int arraySize;
|
||||||
int growthRate;
|
int growthRate;
|
||||||
int items;
|
int items;
|
||||||
|
@ -33,7 +34,7 @@ typedef struct Vector_ {
|
||||||
|
|
||||||
}*/
|
}*/
|
||||||
|
|
||||||
Vector* Vector_new(char* vectorType_, bool owner, int size) {
|
Vector* Vector_new(char* vectorType_, bool owner, int size, Object_Compare compare) {
|
||||||
Vector* this;
|
Vector* this;
|
||||||
|
|
||||||
if (size == DEFAULT_SIZE)
|
if (size == DEFAULT_SIZE)
|
||||||
|
@ -45,6 +46,7 @@ Vector* Vector_new(char* vectorType_, bool owner, int size) {
|
||||||
this->items = 0;
|
this->items = 0;
|
||||||
this->vectorType = vectorType_;
|
this->vectorType = vectorType_;
|
||||||
this->owner = owner;
|
this->owner = owner;
|
||||||
|
this->compare = compare;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -58,6 +60,8 @@ void Vector_delete(Vector* this) {
|
||||||
free(this);
|
free(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef DEBUG
|
||||||
|
|
||||||
static inline bool Vector_isConsistent(Vector* this) {
|
static inline bool Vector_isConsistent(Vector* this) {
|
||||||
if (this->owner) {
|
if (this->owner) {
|
||||||
for (int i = 0; i < this->items; i++)
|
for (int i = 0; i < this->items; i++)
|
||||||
|
@ -69,6 +73,8 @@ static inline bool Vector_isConsistent(Vector* this) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
void Vector_prune(Vector* this) {
|
void Vector_prune(Vector* this) {
|
||||||
assert(Vector_isConsistent(this));
|
assert(Vector_isConsistent(this));
|
||||||
int i;
|
int i;
|
||||||
|
@ -83,27 +89,18 @@ void Vector_prune(Vector* this) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void Vector_sort(Vector* this) {
|
void Vector_sort(Vector* this) {
|
||||||
|
assert(this->compare);
|
||||||
assert(Vector_isConsistent(this));
|
assert(Vector_isConsistent(this));
|
||||||
int i, j;
|
Object_Compare compare = this->compare;
|
||||||
for (i = 1; i < this->items; i++) {
|
/* Insertion sort works best on mostly-sorted arrays. */
|
||||||
|
for (int i = 1; i < this->items; i++) {
|
||||||
|
int j;
|
||||||
void* t = this->array[i];
|
void* t = this->array[i];
|
||||||
for (j = i-1; j >= 0 && this->array[j]->compare(this->array[j], t) < 0; j--)
|
for (j = i-1; j >= 0 && compare(this->array[j], t) > 0; j--)
|
||||||
this->array[j+1] = this->array[j];
|
this->array[j+1] = this->array[j];
|
||||||
this->array[j+1] = t;
|
this->array[j+1] = t;
|
||||||
}
|
}
|
||||||
assert(Vector_isConsistent(this));
|
assert(Vector_isConsistent(this));
|
||||||
|
|
||||||
/*
|
|
||||||
for (int i = 0; i < this->items; i++) {
|
|
||||||
for (int j = i+1; j < this->items; j++) {
|
|
||||||
if (this->array[j]->compare(this->array[j], t) < 0) {
|
|
||||||
void* tmp = this->array[i];
|
|
||||||
this->array[i] = this->array[j];
|
|
||||||
this->array[j] = tmp;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void Vector_checkArraySize(Vector* this) {
|
static void Vector_checkArraySize(Vector* this) {
|
||||||
|
@ -230,16 +227,14 @@ void Vector_add(Vector* this, void* data_) {
|
||||||
assert(Vector_isConsistent(this));
|
assert(Vector_isConsistent(this));
|
||||||
}
|
}
|
||||||
|
|
||||||
inline int Vector_indexOf(Vector* this, void* search_) {
|
inline int Vector_indexOf(Vector* this, void* search_, Object_Compare compare) {
|
||||||
assert(((Object*)search_)->class == this->vectorType);
|
assert(((Object*)search_)->class == this->vectorType);
|
||||||
|
assert(this->compare);
|
||||||
Object* search = search_;
|
Object* search = search_;
|
||||||
assert(Vector_isConsistent(this));
|
assert(Vector_isConsistent(this));
|
||||||
|
for (int i = 0; i < this->items; i++) {
|
||||||
int i;
|
|
||||||
|
|
||||||
for (i = 0; i < this->items; i++) {
|
|
||||||
Object* o = (Object*)this->array[i];
|
Object* o = (Object*)this->array[i];
|
||||||
if (o && o->compare(o, search) == 0)
|
if (o && compare(search, o) == 0)
|
||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
return -1;
|
return -1;
|
||||||
|
|
9
Vector.h
9
Vector.h
|
@ -26,6 +26,7 @@ typedef void(*Vector_procedure)(void*);
|
||||||
|
|
||||||
typedef struct Vector_ {
|
typedef struct Vector_ {
|
||||||
Object **array;
|
Object **array;
|
||||||
|
Object_Compare compare;
|
||||||
int arraySize;
|
int arraySize;
|
||||||
int growthRate;
|
int growthRate;
|
||||||
int items;
|
int items;
|
||||||
|
@ -34,10 +35,14 @@ typedef struct Vector_ {
|
||||||
} Vector;
|
} Vector;
|
||||||
|
|
||||||
|
|
||||||
Vector* Vector_new(char* vectorType_, bool owner, int size);
|
Vector* Vector_new(char* vectorType_, bool owner, int size, Object_Compare compare);
|
||||||
|
|
||||||
void Vector_delete(Vector* this);
|
void Vector_delete(Vector* this);
|
||||||
|
|
||||||
|
#ifdef DEBUG
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
void Vector_prune(Vector* this);
|
void Vector_prune(Vector* this);
|
||||||
|
|
||||||
void Vector_sort(Vector* this);
|
void Vector_sort(Vector* this);
|
||||||
|
@ -62,7 +67,7 @@ void Vector_merge(Vector* this, Vector* v2);
|
||||||
|
|
||||||
void Vector_add(Vector* this, void* data_);
|
void Vector_add(Vector* this, void* data_);
|
||||||
|
|
||||||
inline int Vector_indexOf(Vector* this, void* search_);
|
inline int Vector_indexOf(Vector* this, void* search_, Object_Compare compare);
|
||||||
|
|
||||||
void Vector_foreach(Vector* this, Vector_procedure f);
|
void Vector_foreach(Vector* this, Vector_procedure f);
|
||||||
|
|
||||||
|
|
6
htop.c
6
htop.c
|
@ -245,7 +245,7 @@ int main(int argc, char** argv) {
|
||||||
|
|
||||||
CRT_init(settings->delay, settings->colorScheme);
|
CRT_init(settings->delay, settings->colorScheme);
|
||||||
|
|
||||||
panel = Panel_new(0, headerHeight, COLS, LINES - headerHeight - 2, PROCESS_CLASS, false);
|
panel = Panel_new(0, headerHeight, COLS, LINES - headerHeight - 2, PROCESS_CLASS, false, NULL);
|
||||||
Panel_setRichHeader(panel, ProcessList_printHeader(pl));
|
Panel_setRichHeader(panel, ProcessList_printHeader(pl));
|
||||||
|
|
||||||
char* searchFunctions[3] = {"Next ", "Exit ", " Search: "};
|
char* searchFunctions[3] = {"Next ", "Exit ", " Search: "};
|
||||||
|
@ -506,7 +506,7 @@ int main(int argc, char** argv) {
|
||||||
}
|
}
|
||||||
case 'u':
|
case 'u':
|
||||||
{
|
{
|
||||||
Panel* usersPanel = Panel_new(0, 0, 0, 0, LISTITEM_CLASS, true);
|
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, addUserToList, usersPanel);
|
UsersTable_foreach(ut, addUserToList, usersPanel);
|
||||||
Vector_sort(usersPanel->items);
|
Vector_sort(usersPanel->items);
|
||||||
|
@ -569,7 +569,7 @@ int main(int argc, char** argv) {
|
||||||
case '.':
|
case '.':
|
||||||
case KEY_F(6):
|
case KEY_F(6):
|
||||||
{
|
{
|
||||||
Panel* sortPanel = Panel_new(0,0,0,0,LISTITEM_CLASS,true);
|
Panel* sortPanel = Panel_new(0, 0, 0, 0, LISTITEM_CLASS, true, ListItem_compare);
|
||||||
Panel_setHeader(sortPanel, "Sort by");
|
Panel_setHeader(sortPanel, "Sort by");
|
||||||
char* fuFunctions[2] = {"Sort ", "Cancel "};
|
char* fuFunctions[2] = {"Sort ", "Cancel "};
|
||||||
ProcessField* fields = pl->fields;
|
ProcessField* fields = pl->fields;
|
||||||
|
|
Loading…
Reference in New Issue