mirror of https://github.com/xzeldon/htop.git
Add IO priority support ('i' key)
This commit is contained in:
parent
e6c6d7fbf7
commit
47e881f460
2
CRT.c
2
CRT.c
|
@ -129,7 +129,7 @@ static void CRT_handleSIGSEGV(int sgn) {
|
||||||
fprintf(stderr, "\n\nhtop " VERSION " aborting. Please report bug at http://htop.sf.net\n");
|
fprintf(stderr, "\n\nhtop " VERSION " aborting. Please report bug at http://htop.sf.net\n");
|
||||||
#ifdef HAVE_EXECINFO_H
|
#ifdef HAVE_EXECINFO_H
|
||||||
size_t size = backtrace(backtraceArray, sizeof(backtraceArray) / sizeof(void *));
|
size_t size = backtrace(backtraceArray, sizeof(backtraceArray) / sizeof(void *));
|
||||||
fprintf(stderr, "Backtrace: \n");
|
fprintf(stderr, "\n Please include in your report the following backtrace: \n");
|
||||||
backtrace_symbols_fd(backtraceArray, size, 2);
|
backtrace_symbols_fd(backtraceArray, size, 2);
|
||||||
fprintf(stderr, "\nAdditionally, in order to make the above backtrace useful,");
|
fprintf(stderr, "\nAdditionally, in order to make the above backtrace useful,");
|
||||||
fprintf(stderr, "\nplease also run the following command to generate a disassembly of your binary:");
|
fprintf(stderr, "\nplease also run the following command to generate a disassembly of your binary:");
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
|
|
||||||
What's new in version 1.0.2
|
What's new in version 1.0.2
|
||||||
|
|
||||||
|
* Add IO priority support ('i' key)
|
||||||
* Avoid deleting .htoprc if it is a symlink
|
* Avoid deleting .htoprc if it is a symlink
|
||||||
* BUGFIX: Fix crashes when process list is empty
|
* BUGFIX: Fix crashes when process list is empty
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,41 @@
|
||||||
|
/*
|
||||||
|
htop - IOPriority.c
|
||||||
|
(C) 2004-2012 Hisham H. Muhammad
|
||||||
|
Released under the GNU GPL, see the COPYING file
|
||||||
|
in the source distribution for its full text.
|
||||||
|
|
||||||
|
Based on ionice,
|
||||||
|
Copyright (C) 2005 Jens Axboe <jens@axboe.dk>
|
||||||
|
Released under the terms of the GNU General Public License version 2
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "IOPriority.h"
|
||||||
|
|
||||||
|
/*{
|
||||||
|
|
||||||
|
enum {
|
||||||
|
IOPRIO_CLASS_NONE,
|
||||||
|
IOPRIO_CLASS_RT,
|
||||||
|
IOPRIO_CLASS_BE,
|
||||||
|
IOPRIO_CLASS_IDLE,
|
||||||
|
};
|
||||||
|
|
||||||
|
#define IOPRIO_WHO_PROCESS 1
|
||||||
|
|
||||||
|
#define IOPRIO_CLASS_SHIFT (13)
|
||||||
|
#define IOPRIO_PRIO_MASK ((1UL << IOPRIO_CLASS_SHIFT) - 1)
|
||||||
|
|
||||||
|
#define IOPriority_class(ioprio_) ((int) ((ioprio_) >> IOPRIO_CLASS_SHIFT) )
|
||||||
|
#define IOPriority_data(ioprio_) ((int) ((ioprio_) & IOPRIO_PRIO_MASK) )
|
||||||
|
|
||||||
|
typedef int IOPriority;
|
||||||
|
|
||||||
|
#define IOPriority_tuple(class_, data_) (((class_) << IOPRIO_CLASS_SHIFT) | data_)
|
||||||
|
|
||||||
|
#define IOPriority_error 0xffffffff
|
||||||
|
|
||||||
|
#define IOPriority_None IOPriority_tuple(IOPRIO_CLASS_NONE, 0)
|
||||||
|
#define IOPriority_Idle IOPriority_tuple(IOPRIO_CLASS_IDLE, 0)
|
||||||
|
|
||||||
|
}*/
|
||||||
|
|
|
@ -0,0 +1,43 @@
|
||||||
|
/* Do not edit this file. It was automatically generated. */
|
||||||
|
|
||||||
|
#ifndef HEADER_IOPriority
|
||||||
|
#define HEADER_IOPriority
|
||||||
|
/*
|
||||||
|
htop - IOPriority.h
|
||||||
|
(C) 2004-2012 Hisham H. Muhammad
|
||||||
|
Released under the GNU GPL, see the COPYING file
|
||||||
|
in the source distribution for its full text.
|
||||||
|
|
||||||
|
Based on ionice,
|
||||||
|
Copyright (C) 2005 Jens Axboe <jens@axboe.dk>
|
||||||
|
Released under the terms of the GNU General Public License version 2
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
enum {
|
||||||
|
IOPRIO_CLASS_NONE,
|
||||||
|
IOPRIO_CLASS_RT,
|
||||||
|
IOPRIO_CLASS_BE,
|
||||||
|
IOPRIO_CLASS_IDLE,
|
||||||
|
};
|
||||||
|
|
||||||
|
#define IOPRIO_WHO_PROCESS 1
|
||||||
|
|
||||||
|
#define IOPRIO_CLASS_SHIFT (13)
|
||||||
|
#define IOPRIO_PRIO_MASK ((1UL << IOPRIO_CLASS_SHIFT) - 1)
|
||||||
|
|
||||||
|
#define IOPriority_class(ioprio_) ((int) ((ioprio_) >> IOPRIO_CLASS_SHIFT) )
|
||||||
|
#define IOPriority_data(ioprio_) ((int) ((ioprio_) & IOPRIO_PRIO_MASK) )
|
||||||
|
|
||||||
|
typedef int IOPriority;
|
||||||
|
|
||||||
|
#define IOPriority_tuple(class_, data_) (((class_) << IOPRIO_CLASS_SHIFT) | data_)
|
||||||
|
|
||||||
|
#define IOPriority_error 0xffffffff
|
||||||
|
|
||||||
|
#define IOPriority_None IOPriority_tuple(IOPRIO_CLASS_NONE, 0)
|
||||||
|
#define IOPriority_Idle IOPriority_tuple(IOPRIO_CLASS_IDLE, 0)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,43 @@
|
||||||
|
/*
|
||||||
|
htop - IOPriorityPanel.c
|
||||||
|
(C) 2004-2012 Hisham H. Muhammad
|
||||||
|
Released under the GNU GPL, see the COPYING file
|
||||||
|
in the source distribution for its full text.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "IOPriorityPanel.h"
|
||||||
|
|
||||||
|
/*{
|
||||||
|
#include "Panel.h"
|
||||||
|
#include "IOPriority.h"
|
||||||
|
#include "ListItem.h"
|
||||||
|
}*/
|
||||||
|
|
||||||
|
Panel* IOPriorityPanel_new(IOPriority currPrio) {
|
||||||
|
Panel* this = Panel_new(1, 1, 1, 1, LISTITEM_CLASS, true, ListItem_compare);
|
||||||
|
|
||||||
|
Panel_setHeader(this, "IO Priority:");
|
||||||
|
Panel_add(this, (Object*) ListItem_new("None (based on nice)", IOPriority_None));
|
||||||
|
if (currPrio == IOPriority_None) Panel_setSelected(this, 0);
|
||||||
|
struct { int klass; const char* name; } classes[] = {
|
||||||
|
{ .klass = IOPRIO_CLASS_RT, .name = "Realtime" },
|
||||||
|
{ .klass = IOPRIO_CLASS_BE, .name = "Best-effort" },
|
||||||
|
{ .klass = 0, .name = NULL }
|
||||||
|
};
|
||||||
|
for (int c = 0; classes[c].name; c++) {
|
||||||
|
for (int i = 0; i < 8; i++) {
|
||||||
|
char name[50];
|
||||||
|
snprintf(name, sizeof(name)-1, "%s %d %s", classes[c].name, i, i == 0 ? "(High)" : (i == 7 ? "(Low)" : ""));
|
||||||
|
IOPriority ioprio = IOPriority_tuple(classes[c].klass, i);
|
||||||
|
Panel_add(this, (Object*) ListItem_new(name, ioprio));
|
||||||
|
if (currPrio == ioprio) Panel_setSelected(this, Panel_size(this) - 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Panel_add(this, (Object*) ListItem_new("Idle", IOPriority_Idle));
|
||||||
|
if (currPrio == IOPriority_Idle) Panel_setSelected(this, Panel_size(this) - 1);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
IOPriority IOPriorityPanel_getIOPriority(Panel* this) {
|
||||||
|
return (IOPriority) ( ((ListItem*) Panel_getSelected(this))->key );
|
||||||
|
}
|
|
@ -0,0 +1,20 @@
|
||||||
|
/* Do not edit this file. It was automatically generated. */
|
||||||
|
|
||||||
|
#ifndef HEADER_IOPriorityPanel
|
||||||
|
#define HEADER_IOPriorityPanel
|
||||||
|
/*
|
||||||
|
htop - IOPriorityPanel.h
|
||||||
|
(C) 2004-2012 Hisham H. Muhammad
|
||||||
|
Released under the GNU GPL, see the COPYING file
|
||||||
|
in the source distribution for its full text.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "Panel.h"
|
||||||
|
#include "IOPriority.h"
|
||||||
|
#include "ListItem.h"
|
||||||
|
|
||||||
|
Panel* IOPriorityPanel_new(IOPriority currPrio);
|
||||||
|
|
||||||
|
IOPriority IOPriorityPanel_getIOPriority(Panel* this);
|
||||||
|
|
||||||
|
#endif
|
|
@ -18,18 +18,18 @@ ClockMeter.c ColorsPanel.c ColumnsPanel.c CPUMeter.c CRT.c \
|
||||||
DisplayOptionsPanel.c FunctionBar.c Hashtable.c Header.c htop.c ListItem.c \
|
DisplayOptionsPanel.c FunctionBar.c Hashtable.c Header.c htop.c ListItem.c \
|
||||||
LoadAverageMeter.c MemoryMeter.c Meter.c MetersPanel.c Object.c Panel.c \
|
LoadAverageMeter.c MemoryMeter.c Meter.c MetersPanel.c Object.c Panel.c \
|
||||||
BatteryMeter.c Process.c ProcessList.c RichString.c ScreenManager.c Settings.c \
|
BatteryMeter.c Process.c ProcessList.c RichString.c ScreenManager.c Settings.c \
|
||||||
SignalsPanel.c String.c SwapMeter.c TasksMeter.c TraceScreen.c \
|
IOPriorityPanel.c SignalsPanel.c String.c SwapMeter.c TasksMeter.c TraceScreen.c \
|
||||||
UptimeMeter.c UsersTable.c Vector.c AvailableColumnsPanel.c AffinityPanel.c \
|
UptimeMeter.c UsersTable.c Vector.c AvailableColumnsPanel.c AffinityPanel.c \
|
||||||
HostnameMeter.c OpenFilesScreen.c Affinity.c
|
HostnameMeter.c OpenFilesScreen.c Affinity.c IOPriority.c
|
||||||
|
|
||||||
myhtopheaders = AvailableColumnsPanel.h AvailableMetersPanel.h \
|
myhtopheaders = AvailableColumnsPanel.h AvailableMetersPanel.h \
|
||||||
CategoriesPanel.h CheckItem.h ClockMeter.h ColorsPanel.h ColumnsPanel.h \
|
CategoriesPanel.h CheckItem.h ClockMeter.h ColorsPanel.h ColumnsPanel.h \
|
||||||
CPUMeter.h CRT.h DisplayOptionsPanel.h FunctionBar.h \
|
IOPriorityPanel.h CPUMeter.h CRT.h DisplayOptionsPanel.h FunctionBar.h \
|
||||||
Hashtable.h Header.h htop.h ListItem.h LoadAverageMeter.h MemoryMeter.h \
|
Hashtable.h Header.h htop.h ListItem.h LoadAverageMeter.h MemoryMeter.h \
|
||||||
BatteryMeter.h Meter.h MetersPanel.h Object.h Panel.h ProcessList.h RichString.h \
|
BatteryMeter.h Meter.h MetersPanel.h Object.h Panel.h ProcessList.h RichString.h \
|
||||||
ScreenManager.h Settings.h SignalsPanel.h String.h \
|
ScreenManager.h Settings.h SignalsPanel.h String.h \
|
||||||
SwapMeter.h TasksMeter.h TraceScreen.h UptimeMeter.h UsersTable.h Vector.h \
|
SwapMeter.h TasksMeter.h TraceScreen.h UptimeMeter.h UsersTable.h Vector.h \
|
||||||
Process.h AffinityPanel.h HostnameMeter.h OpenFilesScreen.h Affinity.h
|
Process.h AffinityPanel.h HostnameMeter.h OpenFilesScreen.h Affinity.h IOPriority.h
|
||||||
|
|
||||||
SUFFIXES = .h
|
SUFFIXES = .h
|
||||||
|
|
||||||
|
|
57
Process.c
57
Process.c
|
@ -26,6 +26,7 @@ in the source distribution for its full text.
|
||||||
#include <sched.h>
|
#include <sched.h>
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
|
#include <sys/syscall.h>
|
||||||
|
|
||||||
#ifdef HAVE_LIBHWLOC
|
#ifdef HAVE_LIBHWLOC
|
||||||
#include <hwloc/linux.h>
|
#include <hwloc/linux.h>
|
||||||
|
@ -41,6 +42,7 @@ in the source distribution for its full text.
|
||||||
/*{
|
/*{
|
||||||
#include "Object.h"
|
#include "Object.h"
|
||||||
#include "Affinity.h"
|
#include "Affinity.h"
|
||||||
|
#include "IOPriority.h"
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
|
|
||||||
#ifndef Process_isKernelThread
|
#ifndef Process_isKernelThread
|
||||||
|
@ -73,6 +75,7 @@ typedef enum ProcessField_ {
|
||||||
#ifdef HAVE_CGROUP
|
#ifdef HAVE_CGROUP
|
||||||
CGROUP,
|
CGROUP,
|
||||||
#endif
|
#endif
|
||||||
|
IO_PRIORITY,
|
||||||
LAST_PROCESSFIELD
|
LAST_PROCESSFIELD
|
||||||
} ProcessField;
|
} ProcessField;
|
||||||
|
|
||||||
|
@ -111,6 +114,7 @@ typedef struct Process_ {
|
||||||
long int priority;
|
long int priority;
|
||||||
long int nice;
|
long int nice;
|
||||||
long int nlwp;
|
long int nlwp;
|
||||||
|
IOPriority ioPriority;
|
||||||
char starttime_show[8];
|
char starttime_show[8];
|
||||||
time_t starttime_ctime;
|
time_t starttime_ctime;
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
|
@ -199,6 +203,7 @@ const char *Process_fieldNames[] = {
|
||||||
#ifdef HAVE_CGROUP
|
#ifdef HAVE_CGROUP
|
||||||
"CGROUP",
|
"CGROUP",
|
||||||
#endif
|
#endif
|
||||||
|
"IO_PRIORITY",
|
||||||
"*** report bug! ***"
|
"*** report bug! ***"
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -224,6 +229,7 @@ const char *Process_fieldTitles[] = {
|
||||||
#ifdef HAVE_CGROUP
|
#ifdef HAVE_CGROUP
|
||||||
" CGROUP ",
|
" CGROUP ",
|
||||||
#endif
|
#endif
|
||||||
|
"IO ",
|
||||||
"*** report bug! ***"
|
"*** report bug! ***"
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -507,7 +513,24 @@ static void Process_writeField(Process* this, RichString* str, ProcessField fiel
|
||||||
#ifdef HAVE_CGROUP
|
#ifdef HAVE_CGROUP
|
||||||
case CGROUP: snprintf(buffer, n, "%-10s ", this->cgroup); break;
|
case CGROUP: snprintf(buffer, n, "%-10s ", this->cgroup); break;
|
||||||
#endif
|
#endif
|
||||||
|
case IO_PRIORITY: {
|
||||||
|
int klass = IOPriority_class(this->ioPriority);
|
||||||
|
if (klass == IOPRIO_CLASS_NONE) {
|
||||||
|
// see note [1] above
|
||||||
|
snprintf(buffer, n, "B%1d ", (int) (this->nice + 20) / 5);
|
||||||
|
} else if (klass == IOPRIO_CLASS_BE) {
|
||||||
|
snprintf(buffer, n, "B%1d ", IOPriority_data(this->ioPriority));
|
||||||
|
} else if (klass == IOPRIO_CLASS_RT) {
|
||||||
|
attr = CRT_colors[PROCESS_HIGH_PRIORITY];
|
||||||
|
snprintf(buffer, n, "R%1d ", IOPriority_data(this->ioPriority));
|
||||||
|
} else if (this->ioPriority == IOPriority_Idle) {
|
||||||
|
attr = CRT_colors[PROCESS_LOW_PRIORITY];
|
||||||
|
snprintf(buffer, n, "id ");
|
||||||
|
} else {
|
||||||
|
snprintf(buffer, n, "?? ");
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
snprintf(buffer, n, "- ");
|
snprintf(buffer, n, "- ");
|
||||||
}
|
}
|
||||||
|
@ -572,6 +595,31 @@ bool Process_setPriority(Process* this, int priority) {
|
||||||
return (err == 0);
|
return (err == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Process_changePriorityBy(Process* this, size_t delta) {
|
||||||
|
return Process_setPriority(this, this->nice + delta);
|
||||||
|
}
|
||||||
|
|
||||||
|
IOPriority Process_updateIOPriority(Process* this) {
|
||||||
|
IOPriority ioprio = syscall(SYS_ioprio_get, IOPRIO_WHO_PROCESS, this->pid);
|
||||||
|
this->ioPriority = ioprio;
|
||||||
|
return ioprio;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Process_setIOPriority(Process* this, IOPriority ioprio) {
|
||||||
|
syscall(SYS_ioprio_set, IOPRIO_WHO_PROCESS, this->pid, ioprio);
|
||||||
|
return (Process_updateIOPriority(this) == ioprio);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
[1] Note that before kernel 2.6.26 a process that has not asked for
|
||||||
|
an io priority formally uses "none" as scheduling class, but the
|
||||||
|
io scheduler will treat such processes as if it were in the best
|
||||||
|
effort class. The priority within the best effort class will be
|
||||||
|
dynamically derived from the cpu nice level of the process:
|
||||||
|
io_priority = (cpu_nice + 20) / 5. -- From ionice(1) man page
|
||||||
|
*/
|
||||||
|
#define Process_effectiveIOPriority(p_) (IOPriority_class(p_->ioPriority) == IOPRIO_CLASS_NONE ? IOPriority_tuple(IOPRIO_CLASS_BE, (p_->nice + 20) / 5) : p_->ioPriority)
|
||||||
|
|
||||||
#ifdef HAVE_LIBHWLOC
|
#ifdef HAVE_LIBHWLOC
|
||||||
|
|
||||||
Affinity* Process_getAffinity(Process* this) {
|
Affinity* Process_getAffinity(Process* this) {
|
||||||
|
@ -631,8 +679,8 @@ bool Process_setAffinity(Process* this, Affinity* affinity) {
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
void Process_sendSignal(Process* this, int sgn) {
|
void Process_sendSignal(Process* this, size_t sgn) {
|
||||||
kill(this->pid, sgn);
|
kill(this->pid, (int) sgn);
|
||||||
}
|
}
|
||||||
|
|
||||||
int Process_pidCompare(const void* v1, const void* v2) {
|
int Process_pidCompare(const void* v1, const void* v2) {
|
||||||
|
@ -729,7 +777,8 @@ int Process_compare(const void* v1, const void* v2) {
|
||||||
case CGROUP:
|
case CGROUP:
|
||||||
return strcmp(p1->cgroup ? p1->cgroup : "", p2->cgroup ? p2->cgroup : "");
|
return strcmp(p1->cgroup ? p1->cgroup : "", p2->cgroup ? p2->cgroup : "");
|
||||||
#endif
|
#endif
|
||||||
|
case IO_PRIORITY:
|
||||||
|
return Process_effectiveIOPriority(p1) - Process_effectiveIOPriority(p2);
|
||||||
default:
|
default:
|
||||||
return (p1->pid - p2->pid);
|
return (p1->pid - p2->pid);
|
||||||
}
|
}
|
||||||
|
|
21
Process.h
21
Process.h
|
@ -21,6 +21,7 @@ in the source distribution for its full text.
|
||||||
|
|
||||||
#include "Object.h"
|
#include "Object.h"
|
||||||
#include "Affinity.h"
|
#include "Affinity.h"
|
||||||
|
#include "IOPriority.h"
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
|
|
||||||
#ifndef Process_isKernelThread
|
#ifndef Process_isKernelThread
|
||||||
|
@ -53,6 +54,7 @@ typedef enum ProcessField_ {
|
||||||
#ifdef HAVE_CGROUP
|
#ifdef HAVE_CGROUP
|
||||||
CGROUP,
|
CGROUP,
|
||||||
#endif
|
#endif
|
||||||
|
IO_PRIORITY,
|
||||||
LAST_PROCESSFIELD
|
LAST_PROCESSFIELD
|
||||||
} ProcessField;
|
} ProcessField;
|
||||||
|
|
||||||
|
@ -91,6 +93,7 @@ typedef struct Process_ {
|
||||||
long int priority;
|
long int priority;
|
||||||
long int nice;
|
long int nice;
|
||||||
long int nlwp;
|
long int nlwp;
|
||||||
|
IOPriority ioPriority;
|
||||||
char starttime_show[8];
|
char starttime_show[8];
|
||||||
time_t starttime_ctime;
|
time_t starttime_ctime;
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
|
@ -175,6 +178,22 @@ void Process_toggleTag(Process* this);
|
||||||
|
|
||||||
bool Process_setPriority(Process* this, int priority);
|
bool Process_setPriority(Process* this, int priority);
|
||||||
|
|
||||||
|
bool Process_changePriorityBy(Process* this, size_t delta);
|
||||||
|
|
||||||
|
IOPriority Process_updateIOPriority(Process* this);
|
||||||
|
|
||||||
|
bool Process_setIOPriority(Process* this, IOPriority ioprio);
|
||||||
|
|
||||||
|
/*
|
||||||
|
[1] Note that before kernel 2.6.26 a process that has not asked for
|
||||||
|
an io priority formally uses "none" as scheduling class, but the
|
||||||
|
io scheduler will treat such processes as if it were in the best
|
||||||
|
effort class. The priority within the best effort class will be
|
||||||
|
dynamically derived from the cpu nice level of the process:
|
||||||
|
extern io_priority;
|
||||||
|
*/
|
||||||
|
#define Process_effectiveIOPriority(p_) (IOPriority_class(p_->ioPriority) == IOPRIO_CLASS_NONE ? IOPriority_tuple(IOPRIO_CLASS_BE, (p_->nice + 20) / 5) : p_->ioPriority)
|
||||||
|
|
||||||
#ifdef HAVE_LIBHWLOC
|
#ifdef HAVE_LIBHWLOC
|
||||||
|
|
||||||
Affinity* Process_getAffinity(Process* this);
|
Affinity* Process_getAffinity(Process* this);
|
||||||
|
@ -189,7 +208,7 @@ bool Process_setAffinity(Process* this, Affinity* affinity);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
void Process_sendSignal(Process* this, int sgn);
|
void Process_sendSignal(Process* this, size_t sgn);
|
||||||
|
|
||||||
int Process_pidCompare(const void* v1, const void* v2);
|
int Process_pidCompare(const void* v1, const void* v2);
|
||||||
|
|
||||||
|
|
|
@ -268,7 +268,7 @@ void ProcessList_printHeader(ProcessList* this, RichString* header) {
|
||||||
ProcessField* fields = this->fields;
|
ProcessField* fields = this->fields;
|
||||||
for (int i = 0; fields[i]; i++) {
|
for (int i = 0; fields[i]; i++) {
|
||||||
const char* field = Process_fieldTitles[fields[i]];
|
const char* field = Process_fieldTitles[fields[i]];
|
||||||
if (this->sortKey == fields[i])
|
if (!this->treeView && this->sortKey == fields[i])
|
||||||
RichString_append(header, CRT_colors[PANEL_HIGHLIGHT_FOCUS], field);
|
RichString_append(header, CRT_colors[PANEL_HIGHLIGHT_FOCUS], field);
|
||||||
else
|
else
|
||||||
RichString_append(header, CRT_colors[PANEL_HEADER_FOCUS], field);
|
RichString_append(header, CRT_colors[PANEL_HEADER_FOCUS], field);
|
||||||
|
@ -681,6 +681,7 @@ static bool ProcessList_processEntries(ProcessList* this, const char* dirname, P
|
||||||
unsigned long long int lasttimes = (process->utime + process->stime);
|
unsigned long long int lasttimes = (process->utime + process->stime);
|
||||||
if (! ProcessList_readStatFile(process, dirname, name, command))
|
if (! ProcessList_readStatFile(process, dirname, name, command))
|
||||||
goto errorReadingProcess;
|
goto errorReadingProcess;
|
||||||
|
Process_updateIOPriority(process);
|
||||||
float percent_cpu = (process->utime + process->stime - lasttimes) / period * 100.0;
|
float percent_cpu = (process->utime + process->stime - lasttimes) / period * 100.0;
|
||||||
process->percent_cpu = MAX(MIN(percent_cpu, cpus*100.0), 0.0);
|
process->percent_cpu = MAX(MIN(percent_cpu, cpus*100.0), 0.0);
|
||||||
if (isnan(process->percent_cpu)) process->percent_cpu = 0.0;
|
if (isnan(process->percent_cpu)) process->percent_cpu = 0.0;
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
# Process this file with autoconf to produce a configure script.
|
# Process this file with autoconf to produce a configure script.
|
||||||
|
|
||||||
AC_PREREQ(2.65)
|
AC_PREREQ(2.65)
|
||||||
AC_INIT([htop],[1.0.1],[loderunner@users.sourceforge.net])
|
AC_INIT([htop],[1.0.2],[loderunner@users.sourceforge.net])
|
||||||
|
|
||||||
# The following two lines are required by hwloc scripts
|
# The following two lines are required by hwloc scripts
|
||||||
AC_USE_SYSTEM_EXTENSIONS
|
AC_USE_SYSTEM_EXTENSIONS
|
||||||
|
|
112
htop.c
112
htop.c
|
@ -22,6 +22,7 @@ in the source distribution for its full text.
|
||||||
#include "TraceScreen.h"
|
#include "TraceScreen.h"
|
||||||
#include "OpenFilesScreen.h"
|
#include "OpenFilesScreen.h"
|
||||||
#include "AffinityPanel.h"
|
#include "AffinityPanel.h"
|
||||||
|
#include "IOPriorityPanel.h"
|
||||||
|
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
|
@ -124,18 +125,18 @@ static void showHelp(ProcessList* pl) {
|
||||||
mvaddstr(12, 0, " F4 \\: incremental name filtering K: hide/show kernel threads");
|
mvaddstr(12, 0, " F4 \\: incremental name filtering K: hide/show kernel threads");
|
||||||
mvaddstr(13, 0, " Space: tag processes F: cursor follows process");
|
mvaddstr(13, 0, " Space: tag processes F: cursor follows process");
|
||||||
mvaddstr(14, 0, " U: untag all processes + -: expand/collapse tree");
|
mvaddstr(14, 0, " U: untag all processes + -: expand/collapse tree");
|
||||||
mvaddstr(15, 0, " F9 k: kill process/tagged processes P: sort by CPU%");
|
mvaddstr(15, 0, " F9 k: kill process/tagged processes P M T: sort by CPU%, MEM% or TIME");
|
||||||
mvaddstr(16, 0, " ] F7: higher priority (root only) M: sort by MEM%");
|
mvaddstr(16, 0, " ] F7: higher priority (root only) i: set IO priority");
|
||||||
mvaddstr(17, 0, " [ F8: lower priority (+ nice) T: sort by TIME");
|
mvaddstr(17, 0, " [ F8: lower priority (+ nice) I: invert sort order");
|
||||||
#if (HAVE_LIBHWLOC || HAVE_NATIVE_AFFINITY)
|
#if (HAVE_LIBHWLOC || HAVE_NATIVE_AFFINITY)
|
||||||
if (pl->cpuCount > 1)
|
if (pl->cpuCount > 1)
|
||||||
mvaddstr(18, 0, " a: set CPU affinity I: invert sort order");
|
mvaddstr(18, 0, " a: set CPU affinity F6 >: select sort column");
|
||||||
else
|
else
|
||||||
#endif
|
#endif
|
||||||
mvaddstr(18, 0, " I: invert sort order");
|
mvaddstr(18, 0, " F6 >: select sort column");
|
||||||
mvaddstr(19, 0, " F2 S: setup F6 >: select sort column");
|
mvaddstr(19, 0, " F2 S: setup l: list open files with lsof");
|
||||||
mvaddstr(20, 0, " F1 h: show this help screen l: list open files with lsof");
|
mvaddstr(20, 0, " F1 h: show this help screen s: trace syscalls with strace");
|
||||||
mvaddstr(21, 0, " F10 q: quit s: trace syscalls with strace");
|
mvaddstr(21, 0, " F10 q: quit");
|
||||||
|
|
||||||
attrset(CRT_colors[HELP_BOLD]);
|
attrset(CRT_colors[HELP_BOLD]);
|
||||||
mvaddstr( 9, 0, " Arrows"); mvaddstr( 9,40, " F5 t");
|
mvaddstr( 9, 0, " Arrows"); mvaddstr( 9,40, " F5 t");
|
||||||
|
@ -144,17 +145,17 @@ static void showHelp(ProcessList* pl) {
|
||||||
mvaddstr(12, 0, " F4 \\"); mvaddstr(12,40, " K");
|
mvaddstr(12, 0, " F4 \\"); mvaddstr(12,40, " K");
|
||||||
mvaddstr(13, 0, " Space"); mvaddstr(13,40, " F");
|
mvaddstr(13, 0, " Space"); mvaddstr(13,40, " F");
|
||||||
mvaddstr(14, 0, " U"); mvaddstr(14,40, " + -");
|
mvaddstr(14, 0, " U"); mvaddstr(14,40, " + -");
|
||||||
mvaddstr(15, 0, " F9 k"); mvaddstr(15,40, " P");
|
mvaddstr(15, 0, " F9 k"); mvaddstr(15,40, "P M T");
|
||||||
mvaddstr(16, 0, " ] F7"); mvaddstr(16,40, " M");
|
mvaddstr(16, 0, " ] F7"); mvaddstr(16,40, " i");
|
||||||
mvaddstr(17, 0, " [ F8"); mvaddstr(17,40, " T");
|
mvaddstr(17, 0, " [ F8"); mvaddstr(17,40, " I");
|
||||||
mvaddstr(18,40, " I");
|
mvaddstr(18,40, " F6 >");
|
||||||
#if (HAVE_LIBHWLOC || HAVE_NATIVE_AFFINITY)
|
#if (HAVE_LIBHWLOC || HAVE_NATIVE_AFFINITY)
|
||||||
if (pl->cpuCount > 1)
|
if (pl->cpuCount > 1)
|
||||||
mvaddstr(18, 0, " a:");
|
mvaddstr(18, 0, " a:");
|
||||||
#endif
|
#endif
|
||||||
mvaddstr(19, 0, " F2 S"); mvaddstr(19,40, " F6 >");
|
mvaddstr(19, 0, " F2 S"); mvaddstr(19,40, " l");
|
||||||
mvaddstr(20, 0, " ? F1 h"); mvaddstr(20,40, " l");
|
mvaddstr(20, 0, " ? F1 h"); mvaddstr(20,40, " s");
|
||||||
mvaddstr(21, 0, " F10 q"); mvaddstr(21,40, " s");
|
mvaddstr(21, 0, " F10 q");
|
||||||
attrset(CRT_colors[DEFAULT_COLOR]);
|
attrset(CRT_colors[DEFAULT_COLOR]);
|
||||||
|
|
||||||
attrset(CRT_colors[HELP_BOLD]);
|
attrset(CRT_colors[HELP_BOLD]);
|
||||||
|
@ -178,20 +179,30 @@ static void Setup_run(Settings* settings, const Header* header) {
|
||||||
ScreenManager_delete(scr);
|
ScreenManager_delete(scr);
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool changePriority(Panel* panel, int delta) {
|
typedef bool(*ForeachProcessFn)(Process*, size_t);
|
||||||
|
|
||||||
|
static bool foreachProcess(Panel* panel, ForeachProcessFn fn, int arg, bool* wasAnyTagged) {
|
||||||
bool ok = true;
|
bool ok = true;
|
||||||
bool anyTagged = false;
|
bool anyTagged = false;
|
||||||
for (int i = 0; i < Panel_size(panel); i++) {
|
for (int i = 0; i < Panel_size(panel); i++) {
|
||||||
Process* p = (Process*) Panel_get(panel, i);
|
Process* p = (Process*) Panel_get(panel, i);
|
||||||
if (p->tag) {
|
if (p->tag) {
|
||||||
ok = Process_setPriority(p, p->nice + delta) && ok;
|
ok = fn(p, arg) && ok;
|
||||||
anyTagged = true;
|
anyTagged = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!anyTagged) {
|
if (!anyTagged) {
|
||||||
Process* p = (Process*) Panel_getSelected(panel);
|
Process* p = (Process*) Panel_getSelected(panel);
|
||||||
if (p) ok = Process_setPriority(p, p->nice + delta) && ok;
|
if (p) ok = fn(p, arg) && ok;
|
||||||
}
|
}
|
||||||
|
if (wasAnyTagged)
|
||||||
|
*wasAnyTagged = anyTagged;
|
||||||
|
return ok;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool changePriority(Panel* panel, int delta) {
|
||||||
|
bool anyTagged;
|
||||||
|
bool ok = foreachProcess(panel, (ForeachProcessFn) Process_changePriorityBy, delta, &anyTagged);
|
||||||
if (!ok)
|
if (!ok)
|
||||||
beep();
|
beep();
|
||||||
return anyTagged;
|
return anyTagged;
|
||||||
|
@ -764,20 +775,6 @@ int main(int argc, char** argv) {
|
||||||
if (!killPanel) {
|
if (!killPanel) {
|
||||||
killPanel = (Panel*) SignalsPanel_new(0, 0, 0, 0);
|
killPanel = (Panel*) SignalsPanel_new(0, 0, 0, 0);
|
||||||
}
|
}
|
||||||
bool anyTagged = false;
|
|
||||||
pid_t selectedPid = 0;
|
|
||||||
for (int i = 0; i < Panel_size(panel); i++) {
|
|
||||||
Process* p = (Process*) Panel_get(panel, i);
|
|
||||||
if (p->tag) {
|
|
||||||
anyTagged = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!anyTagged) {
|
|
||||||
Process* p = (Process*) Panel_getSelected(panel);
|
|
||||||
if (p) selectedPid = p->pid;
|
|
||||||
if (selectedPid == 0) break;
|
|
||||||
}
|
|
||||||
SignalsPanel_reset((SignalsPanel*) killPanel);
|
SignalsPanel_reset((SignalsPanel*) killPanel);
|
||||||
const char* fuFunctions[] = {"Send ", "Cancel ", NULL};
|
const char* fuFunctions[] = {"Send ", "Cancel ", NULL};
|
||||||
ListItem* sgn = (ListItem*) pickFromVector(panel, killPanel, 15, headerHeight, fuFunctions, defaultBar, header);
|
ListItem* sgn = (ListItem*) pickFromVector(panel, killPanel, 15, headerHeight, fuFunctions, defaultBar, header);
|
||||||
|
@ -786,18 +783,7 @@ int main(int argc, char** argv) {
|
||||||
Panel_setHeader(panel, "Sending...");
|
Panel_setHeader(panel, "Sending...");
|
||||||
Panel_draw(panel, true);
|
Panel_draw(panel, true);
|
||||||
refresh();
|
refresh();
|
||||||
if (anyTagged) {
|
foreachProcess(panel, (ForeachProcessFn) Process_sendSignal, (size_t) sgn->key, NULL);
|
||||||
for (int i = 0; i < Panel_size(panel); i++) {
|
|
||||||
Process* p = (Process*) Panel_get(panel, i);
|
|
||||||
if (p->tag) {
|
|
||||||
Process_sendSignal(p, sgn->key);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
Process* p = (Process*) Panel_getSelected(panel);
|
|
||||||
if (p->pid == selectedPid)
|
|
||||||
Process_sendSignal(p, sgn->key);
|
|
||||||
}
|
|
||||||
napms(500);
|
napms(500);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -822,21 +808,8 @@ int main(int argc, char** argv) {
|
||||||
void* set = pickFromVector(panel, affinityPanel, 15, headerHeight, fuFunctions, defaultBar, header);
|
void* set = pickFromVector(panel, affinityPanel, 15, headerHeight, fuFunctions, defaultBar, header);
|
||||||
if (set) {
|
if (set) {
|
||||||
Affinity* affinity = AffinityPanel_getAffinity(affinityPanel);
|
Affinity* affinity = AffinityPanel_getAffinity(affinityPanel);
|
||||||
bool anyTagged = false;
|
bool ok = foreachProcess(panel, (ForeachProcessFn) Process_setAffinity, (size_t) affinity, NULL);
|
||||||
bool ok = true;
|
if (!ok) beep();
|
||||||
for (int i = 0; i < Panel_size(panel); i++) {
|
|
||||||
Process* p = (Process*) Panel_get(panel, i);
|
|
||||||
if (p->tag) {
|
|
||||||
ok = Process_setAffinity(p, affinity) && ok;
|
|
||||||
anyTagged = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!anyTagged) {
|
|
||||||
Process* p = (Process*) Panel_getSelected(panel);
|
|
||||||
if (p) ok = Process_setAffinity(p, affinity) && ok;
|
|
||||||
}
|
|
||||||
if (!ok)
|
|
||||||
beep();
|
|
||||||
Affinity_delete(affinity);
|
Affinity_delete(affinity);
|
||||||
}
|
}
|
||||||
Panel_delete((Object*)affinityPanel);
|
Panel_delete((Object*)affinityPanel);
|
||||||
|
@ -878,6 +851,25 @@ int main(int argc, char** argv) {
|
||||||
refreshTimeout = 0;
|
refreshTimeout = 0;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case 'i':
|
||||||
|
{
|
||||||
|
Process* p = (Process*) Panel_getSelected(panel);
|
||||||
|
if (!p) break;
|
||||||
|
IOPriority ioprio = p->ioPriority;
|
||||||
|
Panel* ioprioPanel = IOPriorityPanel_new(ioprio);
|
||||||
|
const char* fuFunctions[] = {"Set ", "Cancel ", NULL};
|
||||||
|
void* set = pickFromVector(panel, ioprioPanel, 21, headerHeight, fuFunctions, defaultBar, header);
|
||||||
|
if (set) {
|
||||||
|
IOPriority ioprio = IOPriorityPanel_getIOPriority(ioprioPanel);
|
||||||
|
bool ok = foreachProcess(panel, (ForeachProcessFn) Process_setIOPriority, (size_t) ioprio, NULL);
|
||||||
|
if (!ok)
|
||||||
|
beep();
|
||||||
|
}
|
||||||
|
Panel_delete((Object*)ioprioPanel);
|
||||||
|
ProcessList_printHeader(pl, Panel_getHeader(panel));
|
||||||
|
refreshTimeout = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
case 'I':
|
case 'I':
|
||||||
{
|
{
|
||||||
refreshTimeout = 0;
|
refreshTimeout = 0;
|
||||||
|
@ -914,6 +906,8 @@ int main(int argc, char** argv) {
|
||||||
case KEY_F(5):
|
case KEY_F(5):
|
||||||
refreshTimeout = 0;
|
refreshTimeout = 0;
|
||||||
pl->treeView = !pl->treeView;
|
pl->treeView = !pl->treeView;
|
||||||
|
if (pl->treeView) pl->direction = 1;
|
||||||
|
ProcessList_printHeader(pl, Panel_getHeader(panel));
|
||||||
ProcessList_expandTree(pl);
|
ProcessList_expandTree(pl);
|
||||||
settings->changed = true;
|
settings->changed = true;
|
||||||
if (following != -1) continue;
|
if (following != -1) continue;
|
||||||
|
|
2
htop.h
2
htop.h
|
@ -15,6 +15,8 @@ in the source distribution for its full text.
|
||||||
|
|
||||||
#define COPYRIGHT "(C) 2004-2011 Hisham Muhammad"
|
#define COPYRIGHT "(C) 2004-2011 Hisham Muhammad"
|
||||||
|
|
||||||
|
typedef bool(*ForeachProcessFn)(Process*, size_t);
|
||||||
|
|
||||||
typedef struct IncBuffer_;
|
typedef struct IncBuffer_;
|
||||||
|
|
||||||
int main(int argc, char** argv);
|
int main(int argc, char** argv);
|
||||||
|
|
Loading…
Reference in New Issue