diff options
-rw-r--r-- | Kernel/Process.cpp | 43 | ||||
-rw-r--r-- | Kernel/Process.h | 4 | ||||
-rw-r--r-- | Kernel/Syscall.cpp | 4 | ||||
-rw-r--r-- | Kernel/Syscall.h | 4 | ||||
-rw-r--r-- | Kernel/UnixTypes.h | 4 | ||||
-rw-r--r-- | LibC/sched.cpp | 24 | ||||
-rw-r--r-- | LibC/sched.h | 15 | ||||
-rw-r--r-- | LibC/unistd.h | 6 |
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 |