diff --git a/ChangeLog b/ChangeLog index 2fe7fb80..e5670533 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,8 +1,12 @@ 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 avoid overflow. +* Memory consumption improvements, compensating storage + of 64-bit values. * Internal change: rename TypedVector to Vector and ListBox (and related classes) to Panel. diff --git a/CheckItem.c b/CheckItem.c index 73148f32..83261237 100644 --- a/CheckItem.c +++ b/CheckItem.c @@ -21,11 +21,15 @@ typedef struct CheckItem_ { }*/ +#ifdef DEBUG char* CHECKITEM_CLASS = "CheckItem"; +#else +#define CHECKITEM_CLASS NULL +#endif CheckItem* CheckItem_new(char* text, bool* value) { CheckItem* this = malloc(sizeof(CheckItem)); - ((Object*)this)->class = CHECKITEM_CLASS; + Object_setClass(this, CHECKITEM_CLASS); ((Object*)this)->display = CheckItem_display; ((Object*)this)->delete = CheckItem_delete; this->text = text; diff --git a/CheckItem.h b/CheckItem.h index eaf43ba6..e1ad4c9b 100644 --- a/CheckItem.h +++ b/CheckItem.h @@ -22,7 +22,11 @@ typedef struct CheckItem_ { } CheckItem; +#ifdef DEBUG extern char* CHECKITEM_CLASS; +#else +#define CHECKITEM_CLASS NULL +#endif CheckItem* CheckItem_new(char* text, bool* value); diff --git a/FunctionBar.c b/FunctionBar.c index 7764136c..1140267b 100644 --- a/FunctionBar.c +++ b/FunctionBar.c @@ -30,7 +30,11 @@ typedef struct FunctionBar_ { }*/ +#ifdef DEBUG 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"}; @@ -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* this = malloc(sizeof(FunctionBar)); - ((Object*) this)->class = FUNCTIONBAR_CLASS; + Object_setClass(this, FUNCTIONBAR_CLASS); ((Object*) this)->delete = FunctionBar_delete; this->functions = functions; this->size = size; diff --git a/FunctionBar.h b/FunctionBar.h index 2998cf7a..dfdef606 100644 --- a/FunctionBar.h +++ b/FunctionBar.h @@ -31,7 +31,11 @@ typedef struct FunctionBar_ { } FunctionBar; +#ifdef DEBUG extern char* FUNCTIONBAR_CLASS; +#else +#define FUNCTIONBAR_CLASS NULL +#endif FunctionBar* FunctionBar_new(int size, char** functions, char** keys, int* events); diff --git a/Hashtable.c b/Hashtable.c index 759cbef7..f971c8c2 100644 --- a/Hashtable.c +++ b/Hashtable.c @@ -55,7 +55,7 @@ Hashtable* Hashtable_new(int size, bool owner) { } int Hashtable_hashAlgorithm(Hashtable* this, int key) { - return (key % this->size); + return key % this->size; } void Hashtable_delete(Hashtable* this) { @@ -116,17 +116,20 @@ void* Hashtable_remove(Hashtable* this, int key) { } else bucketPtr = &((*bucketPtr)->next); } - +//#include inline void* Hashtable_get(Hashtable* this, int key) { int index = this->hashAlgorithm(this, key); HashtableItem* bucketPtr = this->buckets[index]; - while (true) + // fprintf(stderr, "%d -> %d\n", key, index); + while (true) { if (bucketPtr == NULL) { return NULL; } else if (bucketPtr->key == key) { return bucketPtr->value; } else bucketPtr = bucketPtr->next; + // fprintf(stderr, "*\n"); + } } void Hashtable_foreach(Hashtable* this, Hashtable_PairFunction f, void* userData) { diff --git a/Hashtable.h b/Hashtable.h index 99e06d1b..a5f2434d 100644 --- a/Hashtable.h +++ b/Hashtable.h @@ -47,7 +47,7 @@ inline int Hashtable_size(Hashtable* this); void Hashtable_put(Hashtable* this, int key, void* value); void* Hashtable_remove(Hashtable* this, int key); - +//#include inline void* Hashtable_get(Hashtable* this, int key); void Hashtable_foreach(Hashtable* this, Hashtable_PairFunction f, void* userData); diff --git a/Header.c b/Header.c index ddd35e81..b55b557b 100644 --- a/Header.c +++ b/Header.c @@ -35,8 +35,8 @@ typedef struct Header_ { Header* Header_new(ProcessList* pl) { Header* this = malloc(sizeof(Header)); - this->leftMeters = Vector_new(METER_CLASS, true, DEFAULT_SIZE); - this->rightMeters = 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, NULL); this->margin = true; this->pl = pl; return this; diff --git a/ListItem.c b/ListItem.c index 13d94d00..90107e4b 100644 --- a/ListItem.c +++ b/ListItem.c @@ -23,14 +23,17 @@ typedef struct ListItem_ { }*/ +#ifdef DEBUG char* LISTITEM_CLASS = "ListItem"; +#else +#define LISTITEM_CLASS NULL +#endif ListItem* ListItem_new(char* value, int key) { ListItem* this = malloc(sizeof(ListItem)); - ((Object*)this)->class = LISTITEM_CLASS; + Object_setClass(this, LISTITEM_CLASS); ((Object*)this)->display = ListItem_display; ((Object*)this)->delete = ListItem_delete; - ((Object*)this)->compare = ListItem_compare; this->value = String_copy(value); this->key = key; return this; @@ -62,7 +65,7 @@ const char* ListItem_getRef(ListItem* this) { 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* obj2 = (ListItem*) cast2; return strcmp(obj1->value, obj2->value); diff --git a/ListItem.h b/ListItem.h index 84d01027..a58db3a3 100644 --- a/ListItem.h +++ b/ListItem.h @@ -24,7 +24,11 @@ typedef struct ListItem_ { } ListItem; +#ifdef DEBUG extern char* LISTITEM_CLASS; +#else +#define LISTITEM_CLASS NULL +#endif ListItem* ListItem_new(char* value, int key); @@ -36,7 +40,7 @@ void ListItem_display(Object* cast, RichString* out); 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 diff --git a/Makefile.am b/Makefile.am index ccaa95fc..3cc4d916 100644 --- a/Makefile.am +++ b/Makefile.am @@ -27,6 +27,9 @@ ColorsPanel.c ColorsPanel.h TraceScreen.c TraceScreen.h \ AvailableColumnsPanel.c AvailableColumnsPanel.h ColumnsPanel.c \ ColumnsPanel.h +profile: + $(MAKE) all CFLAGS="-pg -O2" + debug: $(MAKE) all CFLAGS="-g -DDEBUG" diff --git a/Meter.c b/Meter.c index 437dd681..1d447f87 100644 --- a/Meter.c +++ b/Meter.c @@ -104,7 +104,11 @@ typedef enum { #define MAX(a,b) ((a)>(b)?(a):(b)) #endif +#ifdef DEBUG char* METER_CLASS = "Meter"; +#else +#define METER_CLASS NULL +#endif MeterType* Meter_types[] = { &CPUMeter, @@ -162,6 +166,9 @@ static RichString Meter_stringBuffer; Meter* Meter_new(ProcessList* pl, int param, MeterType* type) { 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->type = type; this->param = param; @@ -169,9 +176,6 @@ Meter* Meter_new(ProcessList* pl, int param, MeterType* type) { this->values = calloc(sizeof(double), type->items); this->total = type->total; 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); if (this->type->init) this->type->init(this); diff --git a/Meter.h b/Meter.h index c8cb703d..e564d3c3 100644 --- a/Meter.h +++ b/Meter.h @@ -96,6 +96,7 @@ typedef enum { #include "TasksMeter.h" #include "LoadAverageMeter.h" #include "UptimeMeter.h" +#include "ClockMeter.h" #ifndef MIN #define MIN(a,b) ((a)<(b)?(a):(b)) @@ -104,7 +105,11 @@ typedef enum { #define MAX(a,b) ((a)>(b)?(a):(b)) #endif +#ifdef DEBUG extern char* METER_CLASS; +#else +#define METER_CLASS NULL +#endif extern MeterType* Meter_types[]; diff --git a/Object.c b/Object.c index 62a1c3a3..15b9a6ec 100644 --- a/Object.c +++ b/Object.c @@ -15,37 +15,37 @@ in the source distribution for its full text. #include "debug.h" /*{ + +#ifndef DEBUG +#define Object_setClass(obj, class) +#endif + typedef struct Object_ Object; 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*); struct Object_ { + #ifdef DEBUG char* class; + #endif Object_Display display; - Object_Compare compare; Object_Delete delete; }; }*/ -static char* OBJECT_CLASS = "Object"; +#ifdef DEBUG +char* OBJECT_CLASS = "Object"; -void Object_new() { - Object* this; - this = malloc(sizeof(Object)); - this->class = OBJECT_CLASS; - this->display = Object_display; - this->compare = Object_compare; - this->delete = Object_delete; -} +#else +#define OBJECT_CLASS NULL +#endif -bool Object_instanceOf(Object* this, char* class) { - return this->class == class; -} +#ifdef DEBUG -void Object_delete(Object* this) { - free(this); +void Object_setClass(void* this, char* class) { + ((Object*)this)->class = class; } 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); } -int Object_compare(const Object* this, const Object* o) { - return (this - o); -} +#endif diff --git a/Object.h b/Object.h index b4c3dffb..f8a8c6d2 100644 --- a/Object.h +++ b/Object.h @@ -17,27 +17,38 @@ in the source distribution for its full text. #include "debug.h" + +#ifndef DEBUG +#define Object_setClass(obj, class) +#endif + typedef struct Object_ Object; 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*); struct Object_ { + #ifdef DEBUG char* class; + #endif Object_Display display; - Object_Compare compare; 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); -int Object_compare(const Object* this, const Object* o); +#endif #endif diff --git a/Panel.c b/Panel.c index 081306cf..fef7018b 100644 --- a/Panel.c +++ b/Panel.c @@ -10,6 +10,7 @@ in the source distribution for its full text. #include "Vector.h" #include "CRT.h" #include "RichString.h" +#include "ListItem.h" #include #include @@ -54,12 +55,18 @@ struct Panel_ { #define MAX(a,b) ((a)>(b)?(a):(b)) #endif +#ifdef DEBUG 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; this = malloc(sizeof(Panel)); Panel_init(this, x, y, w, h, type, owner); + this->items->compare = compare; 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) { Object* super = (Object*) this; - super->class = PANEL_CLASS; + Object_setClass(this, PANEL_CLASS); super->delete = Panel_delete; this->x = x; this->y = y; this->w = w; this->h = h; 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->scrollH = 0; this->selected = 0; diff --git a/Panel.h b/Panel.h index 4b96fe48..eda9c85d 100644 --- a/Panel.h +++ b/Panel.h @@ -55,9 +55,14 @@ struct Panel_ { #define MAX(a,b) ((a)>(b)?(a):(b)) #endif +#ifdef DEBUG 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); diff --git a/Process.c b/Process.c index a97d5d13..7707a1a1 100644 --- a/Process.c +++ b/Process.c @@ -62,16 +62,19 @@ typedef struct Process_ { int tty_nr; int tpgid; unsigned long int flags; + #ifdef DEBUG unsigned long int minflt; unsigned long int cminflt; unsigned long int majflt; unsigned long int cmajflt; + #endif unsigned long int utime; unsigned long int stime; long int cutime; long int cstime; long int priority; long int nice; + #ifdef DEBUG long int itrealvalue; unsigned long int starttime; unsigned long int vsize; @@ -89,6 +92,7 @@ typedef struct Process_ { unsigned long int wchan; unsigned long int nswap; unsigned long int cnswap; + #endif int exit_signal; int processor; int m_size; @@ -106,7 +110,11 @@ typedef struct Process_ { }*/ +#ifdef DEBUG char* PROCESS_CLASS = "Process"; +#else +#define PROCESS_CLASS NULL +#endif 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! ***" @@ -114,9 +122,8 @@ char *Process_fieldNames[] = { Process* Process_new(struct ProcessList_ *pl) { Process* this = malloc(sizeof(Process)); - ((Object*)this)->class = PROCESS_CLASS; + Object_setClass(this, PROCESS_CLASS); ((Object*)this)->display = Process_display; - ((Object*)this)->compare = Process_compare; ((Object*)this)->delete = Process_delete; this->pl = pl; this->tag = false; @@ -265,21 +272,21 @@ void Process_writeField(Process* this, RichString* str, ProcessField field) { for (int i = 0; i < 32; i++) if (this->indent & (1 << i)) maxIndent = i+1; - for (int i = 0; i < maxIndent - 1; i++) { + for (int i = 0; i < maxIndent - 1; i++) { if (this->indent & (1 << i)) snprintf(buf, n, " | "); else snprintf(buf, n, " "); buf += 4; n -= 4; - } + } if (this->pl->direction == 1) snprintf(buf, n, " `- "); else snprintf(buf, n, " ,- "); RichString_append(str, CRT_colors[PROCESS_TREE], buffer); Process_writeCommand(this, attr, str); - return; + return; } } case STATE: { @@ -345,44 +352,57 @@ void Process_writeField(Process* this, RichString* str, ProcessField field) { return; } -int Process_compare(const Object* v1, const Object* v2) { +int Process_pidCompare(const void* v1, const void* v2) { Process* p1 = (Process*)v1; Process* p2 = (Process*)v2; - int direction = p1->pl->direction; - switch (p1->pl->sortKey) { - case PID: - return (p2->pid - p1->pid) * direction; - case PPID: - return (p2->ppid - p1->ppid) * direction; - case USER: - return strcmp(p2->user, p1->user) * direction; - case PRIORITY: - return (p2->priority - p1->priority) * direction; - case STATE: - return (p2->state - p1->state) * direction; - 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; + return (p1->pid - p2->pid); +} + +int Process_compare(const void* v1, const void* v2) { + Process *p1, *p2; + ProcessList *pl = ((Process*)v1)->pl; + if (pl->direction == 1) { + p1 = (Process*)v1; + p2 = (Process*)v2; + } else { + p2 = (Process*)v1; + p1 = (Process*)v2; } + 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) { diff --git a/Process.h b/Process.h index 51b11d9a..680b0d4a 100644 --- a/Process.h +++ b/Process.h @@ -64,16 +64,19 @@ typedef struct Process_ { int tty_nr; int tpgid; unsigned long int flags; + #ifdef DEBUG unsigned long int minflt; unsigned long int cminflt; unsigned long int majflt; unsigned long int cmajflt; + #endif unsigned long int utime; unsigned long int stime; long int cutime; long int cstime; long int priority; long int nice; + #ifdef DEBUG long int itrealvalue; unsigned long int starttime; unsigned long int vsize; @@ -91,6 +94,7 @@ typedef struct Process_ { unsigned long int wchan; unsigned long int nswap; unsigned long int cnswap; + #endif int exit_signal; int processor; int m_size; @@ -107,7 +111,11 @@ typedef struct Process_ { } Process; +#ifdef DEBUG extern char* PROCESS_CLASS; +#else +#define PROCESS_CLASS NULL +#endif extern char *Process_fieldNames[]; @@ -131,7 +139,9 @@ void Process_sendSignal(Process* this, int signal); 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); diff --git a/ProcessList.c b/ProcessList.c index fb7f8e9d..d6984568 100644 --- a/ProcessList.c +++ b/ProcessList.c @@ -15,6 +15,7 @@ in the source distribution for its full text. #include "Vector.h" #include "UsersTable.h" #include "Hashtable.h" +#include "String.h" #include #include @@ -48,13 +49,17 @@ in the source distribution for its full text. #endif #ifndef MAX_READ -#define MAX_READ 8192 +#define MAX_READ 2048 #endif }*/ /*{ +#ifdef DEBUG +typedef int(*vxscanf)(void*, const char*, va_list); +#endif + typedef struct ProcessList_ { Vector* processes; Vector* processes2; @@ -108,8 +113,6 @@ static ProcessField defaultHeaders[] = { PID, USER, PRIORITY, NICE, M_SIZE, M_RE #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_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* this; 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->prototype = Process_new(this); this->usersTable = usersTable; /* 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 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) { Hashtable_remove(this->processTable, p->pid); - ProcessField pf = this->sortKey; - this->sortKey = PID; - int index = Vector_indexOf(this->processes, p); + int index = Vector_indexOf(this->processes, p, Process_pidCompare); Vector_remove(this->processes, index); - this->sortKey = pf; } 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) { - 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++) { 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 char buf[MAX_READ]; - long int zero; + unsigned long int zero; int size = fread(buf, 1, MAX_READ, f); if(!size) return 0; @@ -370,6 +370,7 @@ static int ProcessList_readStatFile(ProcessList* this, Process *proc, FILE *f, c command[commsize] = '\0'; location = end + 2; + #ifdef DEBUG 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 " @@ -377,14 +378,34 @@ static int ProcessList_readStatFile(ProcessList* this, Process *proc, FILE *f, c "%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, &proc->minflt, &proc->cminflt, &proc->majflt, - &proc->cmajflt, &proc->utime, &proc->stime, &proc->cutime, &proc->cstime, + &proc->tpgid, &proc->flags, + &proc->minflt, &proc->cminflt, &proc->majflt, &proc->cmajflt, + &proc->utime, &proc->stime, &proc->cutime, &proc->cstime, &proc->priority, &proc->nice, &zero, &proc->itrealvalue, &proc->starttime, &proc->vsize, &proc->rss, &proc->rlim, &proc->startcode, &proc->endcode, &proc->startstack, &proc->kstkesp, &proc->kstkeip, &proc->signal, &proc->blocked, &proc->sigignore, &proc->sigcatch, &proc->wchan, &proc->nswap, &proc->cnswap, &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. // 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) { char statusfilename[MAX_NAME+1]; statusfilename[MAX_NAME] = '\0'; + /* + bool success = false; + char buffer[256]; + buffer[255] = '\0'; snprintf(statusfilename, MAX_NAME, "%s/%s/status", dirname, name); FILE* status = ProcessList_fopen(this, statusfilename, "r"); - bool success = false; if (status) { - char buffer[1024]; - buffer[1023] = '\0'; while (!feof(status)) { - char* ok = fgets(buffer, 1023, status); + char* ok = fgets(buffer, 255, status); if (!ok) break; if (String_startsWith(buffer, "Uid:")) { @@ -421,14 +443,18 @@ bool ProcessList_readStatusFile(ProcessList* this, Process* proc, char* dirname, fclose(status); } if (!success) { - snprintf(statusfilename, MAX_NAME, "%s/%s/stat", dirname, name); + */ + snprintf(statusfilename, MAX_NAME, "%s/%s", dirname, name); struct stat sstat; int statok = stat(statusfilename, &sstat); if (statok == -1) return false; proc->st_uid = sstat.st_uid; - } - return success; + return true; + /* + } else + return true; + */ } 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]; Process* process; + Process* existingProcess = (Process*) Hashtable_get(this->processTable, pid); - if (!existingProcess) { - process = Process_clone(prototype); + if (existingProcess) { + process = existingProcess; + } else { + process = prototype; + process->comm = NULL; process->pid = pid; - ProcessList_add(this, process); if (! ProcessList_readStatusFile(this, process, dirname, name)) goto errorReadingProcess; - } else { - process = existingProcess; + 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); + } } 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); 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); fclose(status); - if(!success) { + if(!success) goto errorReadingProcess; - } process->percent_cpu = (process->utime + process->stime - lasttimes) / 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) { snprintf(statusfilename, MAX_NAME, "%s/%s/cmdline", dirname, name); status = ProcessList_fopen(this, statusfilename, "r"); @@ -524,21 +567,6 @@ void ProcessList_processEntries(ProcessList* this, char* dirname, int parent, fl 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 / (float)(this->usedMem - this->cachedMem - this->buffersMem) * 100.0; @@ -548,17 +576,25 @@ void ProcessList_processEntries(ProcessList* this, char* dirname, int parent, fl this->runningTasks++; } - if (this->hideKernelThreads && process->m_size == 0) - ProcessList_remove(this, process); + if (!existingProcess) { + process = Process_clone(process); + ProcessList_add(this, process); + } continue; // Exception handler. errorReadingProcess: { - ProcessList_remove(this, process); + if (existingProcess) + ProcessList_remove(this, process); + else { + if (process->comm) + free(process->comm); + } } } } + prototype->comm = NULL; closedir(dir); } diff --git a/ProcessList.h b/ProcessList.h index 15fc2824..b38cefcd 100644 --- a/ProcessList.h +++ b/ProcessList.h @@ -18,6 +18,7 @@ in the source distribution for its full text. #include "Vector.h" #include "UsersTable.h" #include "Hashtable.h" +#include "String.h" #include #include @@ -50,11 +51,15 @@ in the source distribution for its full text. #endif #ifndef MAX_READ -#define MAX_READ 8192 +#define MAX_READ 2048 #endif +#ifdef DEBUG +typedef int(*vxscanf)(void*, const char*, va_list); +#endif + typedef struct ProcessList_ { Vector* processes; Vector* processes2; diff --git a/ScreenManager.c b/ScreenManager.c index 7ec30ab2..8e88e28d 100644 --- a/ScreenManager.c +++ b/ScreenManager.c @@ -47,8 +47,8 @@ ScreenManager* ScreenManager_new(int x1, int y1, int x2, int y2, Orientation ori this->y2 = y2; this->fuBar = NULL; this->orientation = orientation; - this->items = Vector_new(PANEL_CLASS, owner, DEFAULT_SIZE); - this->fuBars = Vector_new(FUNCTIONBAR_CLASS, true, DEFAULT_SIZE); + this->items = Vector_new(PANEL_CLASS, owner, DEFAULT_SIZE, NULL); + this->fuBars = Vector_new(FUNCTIONBAR_CLASS, true, DEFAULT_SIZE, NULL); this->itemCount = 0; this->owner = owner; return this; @@ -130,7 +130,7 @@ void ScreenManager_run(ScreenManager* this, Panel** lastFocus, int* lastKey) { if (this->fuBar) FunctionBar_draw(this->fuBar, NULL); - int ch; + int ch = 0; while (!quit) { int items = this->itemCount; for (int i = 0; i < items; i++) { diff --git a/SignalItem.c b/SignalItem.c index ae84fa86..81f564d2 100644 --- a/SignalItem.c +++ b/SignalItem.c @@ -25,11 +25,15 @@ typedef struct Signal_ { }*/ +#ifdef DEBUG char* SIGNAL_CLASS = "Signal"; +#else +#define SIGNAL_CLASS NULL +#endif Signal* Signal_new(char* name, int number) { Signal* this = malloc(sizeof(Signal)); - ((Object*)this)->class = SIGNAL_CLASS; + Object_setClass(this, SIGNAL_CLASS); ((Object*)this)->display = Signal_display; ((Object*)this)->delete = Signal_delete; this->name = name; diff --git a/SignalItem.h b/SignalItem.h index 04828c0a..c60dfa40 100644 --- a/SignalItem.h +++ b/SignalItem.h @@ -26,7 +26,11 @@ typedef struct Signal_ { } Signal; +#ifdef DEBUG extern char* SIGNAL_CLASS; +#else +#define SIGNAL_CLASS NULL +#endif Signal* Signal_new(char* name, int number); diff --git a/String.c b/String.c index 00cd4f2c..e862bff5 100644 --- a/String.c +++ b/String.c @@ -14,6 +14,10 @@ in the source distribution for its full text. #include "debug.h" +/*{ +#define String_startsWith(s, match) (strstr((s), (match)) == (s)) +}*/ + inline void String_delete(char* s) { free(s); } @@ -102,10 +106,6 @@ inline int String_eq(char* s1, char* s2) { 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) { const int rate = 10; char** out = (char**) malloc(sizeof(char*) * rate); diff --git a/String.h b/String.h index 8539f613..3a348c2a 100644 --- a/String.h +++ b/String.h @@ -17,6 +17,8 @@ in the source distribution for its full text. #include "debug.h" +#define String_startsWith(s, match) (strstr((s), (match)) == (s)) + inline void String_delete(char* s); 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_startsWith(char* s, char* match); - char** String_split(char* s, char sep); void String_freeArray(char** s); diff --git a/TraceScreen.c b/TraceScreen.c index 001ef571..ff470c4f 100644 --- a/TraceScreen.c +++ b/TraceScreen.c @@ -41,7 +41,7 @@ static int tbEvents[3] = {KEY_F(4), KEY_F(5), 27}; TraceScreen* TraceScreen_new(Process* process) { TraceScreen* this = (TraceScreen*) malloc(sizeof(TraceScreen)); 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->tracing = true; return this; diff --git a/Vector.c b/Vector.c index 349dd127..4ad697cb 100644 --- a/Vector.c +++ b/Vector.c @@ -24,6 +24,7 @@ typedef void(*Vector_procedure)(void*); typedef struct Vector_ { Object **array; + Object_Compare compare; int arraySize; int growthRate; 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; if (size == DEFAULT_SIZE) @@ -45,6 +46,7 @@ Vector* Vector_new(char* vectorType_, bool owner, int size) { this->items = 0; this->vectorType = vectorType_; this->owner = owner; + this->compare = compare; return this; } @@ -58,6 +60,8 @@ void Vector_delete(Vector* this) { free(this); } +#ifdef DEBUG + static inline bool Vector_isConsistent(Vector* this) { if (this->owner) { 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) { assert(Vector_isConsistent(this)); int i; @@ -83,27 +89,18 @@ void Vector_prune(Vector* this) { } void Vector_sort(Vector* this) { + assert(this->compare); assert(Vector_isConsistent(this)); - int i, j; - for (i = 1; i < this->items; i++) { + Object_Compare compare = this->compare; + /* Insertion sort works best on mostly-sorted arrays. */ + for (int i = 1; i < this->items; i++) { + int j; 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] = t; } 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) { @@ -230,16 +227,14 @@ void Vector_add(Vector* this, void* data_) { 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(this->compare); Object* search = search_; assert(Vector_isConsistent(this)); - - int i; - - for (i = 0; i < this->items; i++) { + for (int i = 0; i < this->items; i++) { Object* o = (Object*)this->array[i]; - if (o && o->compare(o, search) == 0) + if (o && compare(search, o) == 0) return i; } return -1; diff --git a/Vector.h b/Vector.h index a01c8fa7..b332ae80 100644 --- a/Vector.h +++ b/Vector.h @@ -26,6 +26,7 @@ typedef void(*Vector_procedure)(void*); typedef struct Vector_ { Object **array; + Object_Compare compare; int arraySize; int growthRate; int items; @@ -34,10 +35,14 @@ typedef struct 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); +#ifdef DEBUG + +#endif + void Vector_prune(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_); -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); diff --git a/htop.c b/htop.c index de3f14eb..7ffccaa2 100644 --- a/htop.c +++ b/htop.c @@ -245,7 +245,7 @@ int main(int argc, char** argv) { 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)); char* searchFunctions[3] = {"Next ", "Exit ", " Search: "}; @@ -506,7 +506,7 @@ int main(int argc, char** argv) { } 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:"); UsersTable_foreach(ut, addUserToList, usersPanel); Vector_sort(usersPanel->items); @@ -569,7 +569,7 @@ int main(int argc, char** argv) { case '.': 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"); char* fuFunctions[2] = {"Sort ", "Cancel "}; ProcessField* fields = pl->fields;