summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRobin Burchell <robin+git@viroteck.net>2019-05-29 23:20:51 +0200
committerAndreas Kling <awesomekling@gmail.com>2019-05-30 02:57:15 +0200
commit9cd0f6ffac0e22185455b884a9fcf0f810ac6da6 (patch)
treefb79a0609975ab93a9b7c719f1c61622a9b2cd15
parentb160677e9e766b50a89210b6b645a8ba1cd1b7bd (diff)
downloadserenity-9cd0f6ffac0e22185455b884a9fcf0f810ac6da6.zip
Kernel/LibC: Implement sched_* functionality to set/get process priority
Right now, we allow anything inside a user to raise or lower any other process's priority. This feels simple enough to me. Linux disallows raising, but that's annoying in practice.
-rw-r--r--Kernel/Process.cpp43
-rw-r--r--Kernel/Process.h4
-rw-r--r--Kernel/Syscall.cpp4
-rw-r--r--Kernel/Syscall.h4
-rw-r--r--Kernel/UnixTypes.h4
-rw-r--r--LibC/sched.cpp24
-rw-r--r--LibC/sched.h15
-rw-r--r--LibC/unistd.h6
8 files changed, 103 insertions, 1 deletions
diff --git a/Kernel/Process.cpp b/Kernel/Process.cpp
index befb1b8ffc..4008da535f 100644
--- a/Kernel/Process.cpp
+++ b/Kernel/Process.cpp
@@ -2282,6 +2282,49 @@ int Process::sys$getpeername(int sockfd, sockaddr* addr, socklen_t* addrlen)
return 0;
}
+int Process::sys$sched_setparam(pid_t pid, const struct sched_param* param)
+{
+ if (!validate_read_typed(param))
+ return -EFAULT;
+
+ InterruptDisabler disabler;
+ auto* peer = this;
+ if (pid != 0)
+ peer = Process::from_pid(pid);
+
+ if (!peer)
+ return -ESRCH;
+
+ if (!is_superuser() && m_euid != peer->m_uid && m_uid != peer->m_uid)
+ return -EPERM;
+
+ if (param->sched_priority < Process::FirstPriority || param->sched_priority > Process::LastPriority)
+ return -EINVAL;
+
+ peer->set_priority(Priority(param->sched_priority));
+ return 0;
+}
+
+int Process::sys$sched_getparam(pid_t pid, struct sched_param* param)
+{
+ if (!validate_read_typed(param))
+ return -EFAULT;
+
+ InterruptDisabler disabler;
+ auto* peer = this;
+ if (pid != 0)
+ peer = Process::from_pid(pid);
+
+ if (!peer)
+ return -ESRCH;
+
+ if (!is_superuser() && m_euid != peer->m_uid && m_uid != peer->m_uid)
+ return -EPERM;
+
+ param->sched_priority = peer->priority();
+ return 0;
+}
+
int Process::sys$getsockopt(const Syscall::SC_getsockopt_params* params)
{
if (!validate_read_typed(params))
diff --git a/Kernel/Process.h b/Kernel/Process.h
index 242219d889..9496e9898e 100644
--- a/Kernel/Process.h
+++ b/Kernel/Process.h
@@ -40,9 +40,11 @@ public:
enum Priority
{
IdlePriority,
+ FirstPriority = IdlePriority,
LowPriority,
NormalPriority,
HighPriority,
+ LastPriority = HighPriority,
};
enum RingLevel
@@ -186,6 +188,8 @@ public:
int sys$setsockopt(const Syscall::SC_setsockopt_params*);
int sys$getsockname(int sockfd, sockaddr* addr, socklen_t* addrlen);
int sys$getpeername(int sockfd, sockaddr* addr, socklen_t* addrlen);
+ int sys$sched_setparam(pid_t pid, const struct sched_param* param);
+ int sys$sched_getparam(pid_t pid, struct sched_param* param);
int sys$restore_signal_mask(dword mask);
int sys$create_thread(int (*)(void*), void*);
void sys$exit_thread(int code);
diff --git a/Kernel/Syscall.cpp b/Kernel/Syscall.cpp
index 94b8ea6c97..49ade71a3c 100644
--- a/Kernel/Syscall.cpp
+++ b/Kernel/Syscall.cpp
@@ -276,6 +276,10 @@ static dword handle(RegisterDump& regs, dword function, dword arg1, dword arg2,
return current->process().sys$getsockname((int)arg1, (sockaddr*)arg2, (socklen_t*)arg3);
case Syscall::SC_getpeername:
return current->process().sys$getpeername((int)arg1, (sockaddr*)arg2, (socklen_t*)arg3);
+ case Syscall::SC_sched_setparam:
+ return current->process().sys$sched_setparam((pid_t)arg1, (struct sched_param*)arg2);
+ case Syscall::SC_sched_getparam:
+ return current->process().sys$sched_setparam((pid_t)arg1, (struct sched_param*)arg2);
default:
kprintf("<%u> int0x82: Unknown function %u requested {%x, %x, %x}\n", current->process().pid(), function, arg1, arg2, arg3);
return -ENOSYS;
diff --git a/Kernel/Syscall.h b/Kernel/Syscall.h
index c6ff1bc686..2428a74cec 100644
--- a/Kernel/Syscall.h
+++ b/Kernel/Syscall.h
@@ -105,7 +105,9 @@
__ENUMERATE_SYSCALL(writev) \
__ENUMERATE_SYSCALL(beep) \
__ENUMERATE_SYSCALL(getsockname) \
- __ENUMERATE_SYSCALL(getpeername)
+ __ENUMERATE_SYSCALL(getpeername) \
+ __ENUMERATE_SYSCALL(sched_setparam) \
+ __ENUMERATE_SYSCALL(sched_getparam)
namespace Syscall {
diff --git a/Kernel/UnixTypes.h b/Kernel/UnixTypes.h
index 3654638cf5..c79f7b0a82 100644
--- a/Kernel/UnixTypes.h
+++ b/Kernel/UnixTypes.h
@@ -400,3 +400,7 @@ struct iovec {
void* iov_base;
size_t iov_len;
};
+
+struct sched_param {
+ int sched_priority;
+};
diff --git a/LibC/sched.cpp b/LibC/sched.cpp
index ce48add522..b083595cc9 100644
--- a/LibC/sched.cpp
+++ b/LibC/sched.cpp
@@ -10,5 +10,29 @@ int sched_yield()
__RETURN_WITH_ERRNO(rc, rc, -1);
}
+int sched_get_priority_min(int policy)
+{
+ (void)policy;
+ return 0; // Idle
+}
+
+int sched_get_priority_max(int policy)
+{
+ (void)policy;
+ return 3; // High
+}
+
+int sched_setparam(pid_t pid, const struct sched_param *param)
+{
+ int rc = syscall(SC_sched_setparam, pid, param);
+ __RETURN_WITH_ERRNO(rc, rc, -1);
+}
+
+int sched_getparam(pid_t pid, struct sched_param *param)
+{
+ int rc = syscall(SC_sched_getparam, pid, param);
+ __RETURN_WITH_ERRNO(rc, rc, -1);
+}
+
}
diff --git a/LibC/sched.h b/LibC/sched.h
index 5c472a27b7..d1be1fdda0 100644
--- a/LibC/sched.h
+++ b/LibC/sched.h
@@ -1,9 +1,24 @@
#pragma once
+#include <sys/types.h>
#include <sys/cdefs.h>
__BEGIN_DECLS
int sched_yield();
+struct sched_param {
+ int sched_priority;
+};
+
+#define SCHED_FIFO 0
+#define SCHED_RR 1
+#define SCHED_OTHER 2
+#define SCHED_BATCH 3
+
+int sched_get_priority_min(int policy);
+int sched_get_priority_max(int policy);
+int sched_setparam(pid_t pid, const struct sched_param *param);
+int sched_getparam(pid_t pid, struct sched_param *param);
+
__END_DECLS
diff --git a/LibC/unistd.h b/LibC/unistd.h
index 994fde0c1a..0ea910c299 100644
--- a/LibC/unistd.h
+++ b/LibC/unistd.h
@@ -107,4 +107,10 @@ enum
#define X_OK 1
#define F_OK 0
+/*
+ * We aren't fully compliant (don't support policies, and don't have a wide
+ * range of values), but we do have process priorities.
+ */
+#define _POSIX_PRIORITY_SCHEDULING
+
__END_DECLS