diff --git a/AffinityPanel.c b/AffinityPanel.c index 729eec42..8c406fb3 100644 --- a/AffinityPanel.c +++ b/AffinityPanel.c @@ -50,7 +50,7 @@ Panel* AffinityPanel_new(ProcessList* pl, Affinity* affinity) { } else { mode = false; } - Panel_add(this, (Object*) CheckItem_new(strdup(number), NULL, mode)); + Panel_add(this, (Object*) CheckItem_new(strdup(number), NULL, mode)); } return this; } diff --git a/CRT.c b/CRT.c index 880f4dd1..97f2144e 100644 --- a/CRT.c +++ b/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"); #ifdef HAVE_EXECINFO_H 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); 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:"); diff --git a/ChangeLog b/ChangeLog index 5185f7ad..45b4edbb 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,6 +1,7 @@ What's new in version 1.0.2 +* Add IO priority support ('i' key) * Avoid deleting .htoprc if it is a symlink * BUGFIX: Fix crashes when process list is empty diff --git a/IOPriority.c b/IOPriority.c new file mode 100644 index 00000000..7b197436 --- /dev/null +++ b/IOPriority.c @@ -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 +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) + +}*/ + diff --git a/IOPriority.h b/IOPriority.h new file mode 100644 index 00000000..d69e30d5 --- /dev/null +++ b/IOPriority.h @@ -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 +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 diff --git a/IOPriorityPanel.c b/IOPriorityPanel.c new file mode 100644 index 00000000..bc80b7dc --- /dev/null +++ b/IOPriorityPanel.c @@ -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 ); +} diff --git a/IOPriorityPanel.h b/IOPriorityPanel.h new file mode 100644 index 00000000..f87af4e4 --- /dev/null +++ b/IOPriorityPanel.h @@ -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 diff --git a/Makefile.am b/Makefile.am index a1ff7d65..05a72e7e 100644 --- a/Makefile.am +++ b/Makefile.am @@ -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 \ LoadAverageMeter.c MemoryMeter.c Meter.c MetersPanel.c Object.c Panel.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 \ -HostnameMeter.c OpenFilesScreen.c Affinity.c +HostnameMeter.c OpenFilesScreen.c Affinity.c IOPriority.c myhtopheaders = AvailableColumnsPanel.h AvailableMetersPanel.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 \ BatteryMeter.h Meter.h MetersPanel.h Object.h Panel.h ProcessList.h RichString.h \ ScreenManager.h Settings.h SignalsPanel.h String.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 diff --git a/Process.c b/Process.c index 68edd70e..9cc5c001 100644 --- a/Process.c +++ b/Process.c @@ -26,6 +26,7 @@ in the source distribution for its full text. #include #include #include +#include #ifdef HAVE_LIBHWLOC #include @@ -41,6 +42,7 @@ in the source distribution for its full text. /*{ #include "Object.h" #include "Affinity.h" +#include "IOPriority.h" #include #ifndef Process_isKernelThread @@ -73,6 +75,7 @@ typedef enum ProcessField_ { #ifdef HAVE_CGROUP CGROUP, #endif + IO_PRIORITY, LAST_PROCESSFIELD } ProcessField; @@ -111,6 +114,7 @@ typedef struct Process_ { long int priority; long int nice; long int nlwp; + IOPriority ioPriority; char starttime_show[8]; time_t starttime_ctime; #ifdef DEBUG @@ -199,6 +203,7 @@ const char *Process_fieldNames[] = { #ifdef HAVE_CGROUP "CGROUP", #endif + "IO_PRIORITY", "*** report bug! ***" }; @@ -224,6 +229,7 @@ const char *Process_fieldTitles[] = { #ifdef HAVE_CGROUP " CGROUP ", #endif + "IO ", "*** report bug! ***" }; @@ -507,7 +513,24 @@ static void Process_writeField(Process* this, RichString* str, ProcessField fiel #ifdef HAVE_CGROUP case CGROUP: snprintf(buffer, n, "%-10s ", this->cgroup); break; #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: snprintf(buffer, n, "- "); } @@ -572,6 +595,31 @@ bool Process_setPriority(Process* this, int priority) { 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 Affinity* Process_getAffinity(Process* this) { @@ -631,8 +679,8 @@ bool Process_setAffinity(Process* this, Affinity* affinity) { #endif -void Process_sendSignal(Process* this, int sgn) { - kill(this->pid, sgn); +void Process_sendSignal(Process* this, size_t sgn) { + kill(this->pid, (int) sgn); } int Process_pidCompare(const void* v1, const void* v2) { @@ -729,7 +777,8 @@ int Process_compare(const void* v1, const void* v2) { case CGROUP: return strcmp(p1->cgroup ? p1->cgroup : "", p2->cgroup ? p2->cgroup : ""); #endif - + case IO_PRIORITY: + return Process_effectiveIOPriority(p1) - Process_effectiveIOPriority(p2); default: return (p1->pid - p2->pid); } diff --git a/Process.h b/Process.h index 2c3e0c33..c5f59346 100644 --- a/Process.h +++ b/Process.h @@ -21,6 +21,7 @@ in the source distribution for its full text. #include "Object.h" #include "Affinity.h" +#include "IOPriority.h" #include #ifndef Process_isKernelThread @@ -53,6 +54,7 @@ typedef enum ProcessField_ { #ifdef HAVE_CGROUP CGROUP, #endif + IO_PRIORITY, LAST_PROCESSFIELD } ProcessField; @@ -91,6 +93,7 @@ typedef struct Process_ { long int priority; long int nice; long int nlwp; + IOPriority ioPriority; char starttime_show[8]; time_t starttime_ctime; #ifdef DEBUG @@ -175,6 +178,22 @@ void Process_toggleTag(Process* this); 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 Affinity* Process_getAffinity(Process* this); @@ -189,7 +208,7 @@ bool Process_setAffinity(Process* this, Affinity* affinity); #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); diff --git a/ProcessList.c b/ProcessList.c index 14a8b29c..268793f2 100644 --- a/ProcessList.c +++ b/ProcessList.c @@ -268,7 +268,7 @@ void ProcessList_printHeader(ProcessList* this, RichString* header) { ProcessField* fields = this->fields; for (int i = 0; fields[i]; 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); else 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); if (! ProcessList_readStatFile(process, dirname, name, command)) goto errorReadingProcess; + Process_updateIOPriority(process); float percent_cpu = (process->utime + process->stime - lasttimes) / period * 100.0; process->percent_cpu = MAX(MIN(percent_cpu, cpus*100.0), 0.0); if (isnan(process->percent_cpu)) process->percent_cpu = 0.0; diff --git a/configure.ac b/configure.ac index 639d048d..ff6901b1 100644 --- a/configure.ac +++ b/configure.ac @@ -2,7 +2,7 @@ # Process this file with autoconf to produce a configure script. 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 AC_USE_SYSTEM_EXTENSIONS diff --git a/htop.c b/htop.c index c8f42e11..44aa8579 100644 --- a/htop.c +++ b/htop.c @@ -22,6 +22,7 @@ in the source distribution for its full text. #include "TraceScreen.h" #include "OpenFilesScreen.h" #include "AffinityPanel.h" +#include "IOPriorityPanel.h" #include #include @@ -124,18 +125,18 @@ static void showHelp(ProcessList* pl) { mvaddstr(12, 0, " F4 \\: incremental name filtering K: hide/show kernel threads"); mvaddstr(13, 0, " Space: tag processes F: cursor follows process"); mvaddstr(14, 0, " U: untag all processes + -: expand/collapse tree"); - mvaddstr(15, 0, " F9 k: kill process/tagged processes P: sort by CPU%"); - mvaddstr(16, 0, " ] F7: higher priority (root only) M: sort by MEM%"); - mvaddstr(17, 0, " [ F8: lower priority (+ nice) T: sort by TIME"); + 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) i: set IO priority"); + mvaddstr(17, 0, " [ F8: lower priority (+ nice) I: invert sort order"); #if (HAVE_LIBHWLOC || HAVE_NATIVE_AFFINITY) 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 #endif - mvaddstr(18, 0, " I: invert sort order"); - mvaddstr(19, 0, " F2 S: setup F6 >: select sort column"); - mvaddstr(20, 0, " F1 h: show this help screen l: list open files with lsof"); - mvaddstr(21, 0, " F10 q: quit s: trace syscalls with strace"); + mvaddstr(18, 0, " 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 s: trace syscalls with strace"); + mvaddstr(21, 0, " F10 q: quit"); attrset(CRT_colors[HELP_BOLD]); 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(13, 0, " Space"); mvaddstr(13,40, " F"); mvaddstr(14, 0, " U"); mvaddstr(14,40, " + -"); - mvaddstr(15, 0, " F9 k"); mvaddstr(15,40, " P"); - mvaddstr(16, 0, " ] F7"); mvaddstr(16,40, " M"); - mvaddstr(17, 0, " [ F8"); mvaddstr(17,40, " T"); - mvaddstr(18,40, " I"); + mvaddstr(15, 0, " F9 k"); mvaddstr(15,40, "P M T"); + mvaddstr(16, 0, " ] F7"); mvaddstr(16,40, " i"); + mvaddstr(17, 0, " [ F8"); mvaddstr(17,40, " I"); + mvaddstr(18,40, " F6 >"); #if (HAVE_LIBHWLOC || HAVE_NATIVE_AFFINITY) if (pl->cpuCount > 1) mvaddstr(18, 0, " a:"); #endif - mvaddstr(19, 0, " F2 S"); mvaddstr(19,40, " F6 >"); - mvaddstr(20, 0, " ? F1 h"); mvaddstr(20,40, " l"); - mvaddstr(21, 0, " F10 q"); mvaddstr(21,40, " s"); + mvaddstr(19, 0, " F2 S"); mvaddstr(19,40, " l"); + mvaddstr(20, 0, " ? F1 h"); mvaddstr(20,40, " s"); + mvaddstr(21, 0, " F10 q"); attrset(CRT_colors[DEFAULT_COLOR]); attrset(CRT_colors[HELP_BOLD]); @@ -178,20 +179,30 @@ static void Setup_run(Settings* settings, const Header* header) { 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 anyTagged = false; for (int i = 0; i < Panel_size(panel); i++) { Process* p = (Process*) Panel_get(panel, i); if (p->tag) { - ok = Process_setPriority(p, p->nice + delta) && ok; + ok = fn(p, arg) && ok; anyTagged = true; } } if (!anyTagged) { 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) beep(); return anyTagged; @@ -764,20 +775,6 @@ int main(int argc, char** argv) { if (!killPanel) { 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); const char* fuFunctions[] = {"Send ", "Cancel ", NULL}; 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_draw(panel, true); refresh(); - if (anyTagged) { - 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); - } + foreachProcess(panel, (ForeachProcessFn) Process_sendSignal, (size_t) sgn->key, NULL); napms(500); } } @@ -822,21 +808,8 @@ int main(int argc, char** argv) { void* set = pickFromVector(panel, affinityPanel, 15, headerHeight, fuFunctions, defaultBar, header); if (set) { Affinity* affinity = AffinityPanel_getAffinity(affinityPanel); - bool anyTagged = false; - bool ok = true; - 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(); + bool ok = foreachProcess(panel, (ForeachProcessFn) Process_setAffinity, (size_t) affinity, NULL); + if (!ok) beep(); Affinity_delete(affinity); } Panel_delete((Object*)affinityPanel); @@ -878,6 +851,25 @@ int main(int argc, char** argv) { refreshTimeout = 0; 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': { refreshTimeout = 0; @@ -914,6 +906,8 @@ int main(int argc, char** argv) { case KEY_F(5): refreshTimeout = 0; pl->treeView = !pl->treeView; + if (pl->treeView) pl->direction = 1; + ProcessList_printHeader(pl, Panel_getHeader(panel)); ProcessList_expandTree(pl); settings->changed = true; if (following != -1) continue; diff --git a/htop.h b/htop.h index 227f36d3..8d8ed7ed 100644 --- a/htop.h +++ b/htop.h @@ -15,6 +15,8 @@ in the source distribution for its full text. #define COPYRIGHT "(C) 2004-2011 Hisham Muhammad" +typedef bool(*ForeachProcessFn)(Process*, size_t); + typedef struct IncBuffer_; int main(int argc, char** argv);