summaryrefslogtreecommitdiffstats
path: root/Scheduling.c
diff options
context:
space:
mode:
authorChristian Göttsche <cgzones@googlemail.com>2023-01-10 19:40:04 +0100
committerBenBE <BenBE@geshi.org>2023-02-05 00:17:33 +0100
commitda494896914a327476ab7e0298619d742a6205d4 (patch)
tree700db7b14d148c492b1fb0295462fee2214239ed /Scheduling.c
parentf1da8cfa28cce46cc7a4ab1661be35e2173155ab (diff)
Add support for scheduling policies
Add a process column for scheduling policy to show the current scheduling policy of the process. Add a the ability to change the scheduling policy of a process via the key 'Y'. Currently implemented on Linux and FreeBSD only but should be portable, since sched_getscheduler(2) is part of POSIX.1-2001. Closes: #1161
Diffstat (limited to 'Scheduling.c')
-rw-r--r--Scheduling.c154
1 files changed, 154 insertions, 0 deletions
diff --git a/Scheduling.c b/Scheduling.c
new file mode 100644
index 00000000..5ca49ae2
--- /dev/null
+++ b/Scheduling.c
@@ -0,0 +1,154 @@
+/*
+htop - Scheduling.c
+(C) 2023 htop dev team
+Released under the GNU GPLv2+, see the COPYING file
+in the source distribution for its full text.
+*/
+
+#include "Scheduling.h"
+#include "EnvScreen.h"
+
+#ifdef SCHEDULER_SUPPORT
+
+#include <errno.h>
+
+#include "FunctionBar.h"
+#include "ListItem.h"
+#include "Macros.h"
+#include "Object.h"
+#include "Panel.h"
+#include "XUtils.h"
+
+
+static const SchedulingPolicy policies[] = {
+ [SCHED_OTHER] = { "Other", SCHED_OTHER, false },
+#ifdef SCHED_BATCH
+ [SCHED_BATCH] = { "Batch", SCHED_BATCH, false },
+#endif
+#ifdef SCHED_IDLE
+ [SCHED_IDLE] = { "Idle", SCHED_IDLE, false },
+#endif
+ [SCHED_FIFO] = { "FiFo", SCHED_FIFO, true },
+ [SCHED_RR] = { "RoundRobin", SCHED_RR, true },
+};
+
+#ifdef SCHED_RESET_ON_FORK
+static bool reset_on_fork = false;
+#endif
+
+
+Panel* Scheduling_newPolicyPanel(int preSelectedPolicy) {
+ Panel* this = Panel_new(0, 0, 0, 0, Class(ListItem), true, FunctionBar_newEnterEsc("Select ", "Cancel "));
+ Panel_setHeader(this, "New policy:");
+
+#ifdef SCHED_RESET_ON_FORK
+ Panel_add(this, (Object*) ListItem_new(reset_on_fork ? "Reset on fork: on" : "Reset on fork: off", -1));
+#endif
+
+ for (unsigned i = 0; i < ARRAYSIZE(policies); i++) {
+ if (!policies[i].name)
+ continue;
+
+ Panel_add(this, (Object*) ListItem_new(policies[i].name, policies[i].id));
+ if (policies[i].id == preSelectedPolicy)
+ Panel_setSelected(this, i);
+ }
+
+ return this;
+}
+
+void Scheduling_togglePolicyPanelResetOnFork(Panel* schedPanel) {
+#ifdef SCHED_RESET_ON_FORK
+ reset_on_fork = !reset_on_fork;
+
+ ListItem* item = (ListItem*) Panel_get(schedPanel, 0);
+
+ free_and_xStrdup(&item->value, reset_on_fork ? "Reset on fork: on" : "Reset on fork: off");
+#else
+ (void)schedPanel;
+#endif
+}
+
+Panel* Scheduling_newPriorityPanel(int policy, int preSelectedPriority) {
+ if (policy < 0 || (unsigned)policy >= ARRAYSIZE(policies) || policies[policy].name == NULL)
+ return NULL;
+
+ if (!policies[policy].prioritySupport)
+ return NULL;
+
+ int min = sched_get_priority_min(policy);
+ if (min < 0)
+ return NULL;
+ int max = sched_get_priority_max(policy);
+ if (max < 0 )
+ return NULL;
+
+ Panel* this = Panel_new(0, 0, 0, 0, Class(ListItem), true, FunctionBar_newEnterEsc("Select ", "Cancel "));
+ Panel_setHeader(this, "Priority:");
+
+ for (int i = min; i <= max; i++) {
+ char buf[16];
+ xSnprintf(buf, sizeof(buf), "%d", i);
+ Panel_add(this, (Object*) ListItem_new(buf, i));
+ if (i == preSelectedPriority)
+ Panel_setSelected(this, i);
+ }
+
+ return this;
+}
+
+bool Scheduling_setPolicy(Process* proc, Arg arg) {
+ const SchedulingArg* sarg = arg.v;
+ int policy = sarg->policy;
+
+ assert(policy >= 0);
+ assert((unsigned)policy < ARRAYSIZE(policies));
+ assert(policies[policy].name);
+
+ const struct sched_param param = { .sched_priority = policies[policy].prioritySupport ? sarg->priority : 0 };
+
+ #ifdef SCHED_RESET_ON_FORK
+ if (reset_on_fork)
+ policy &= SCHED_RESET_ON_FORK;
+ #endif
+
+ int r = sched_setscheduler(proc->pid, policy, &param);
+
+ /* POSIX says on success the previous scheduling policy should be returned,
+ * but Linux always returns 0. */
+ return r != -1;
+}
+
+const char* Scheduling_formatPolicy(int policy) {
+#ifdef SCHED_RESET_ON_FORK
+ policy = policy & ~SCHED_RESET_ON_FORK;
+#endif
+
+ switch (policy) {
+ case SCHED_OTHER:
+ return "OTHER";
+ case SCHED_FIFO:
+ return "FIFO";
+ case SCHED_RR:
+ return "RR";
+#ifdef SCHED_BATCH
+ case SCHED_BATCH:
+ return "BATCH";
+#endif
+#ifdef SCHED_IDLE
+ case SCHED_IDLE:
+ return "IDLE";
+#endif
+#ifdef SCHED_DEADLINE
+ case SCHED_DEADLINE:
+ return "EDF";
+#endif
+ default:
+ return "???";
+ }
+}
+
+void Scheduling_readProcessPolicy(Process* proc) {
+ proc->scheduling_policy = sched_getscheduler(proc->pid);
+}
+#endif /* SCHEDULER_SUPPORT */

© 2014-2024 Faster IT GmbH | imprint | privacy policy