Skip to content

Commit

Permalink
Kernel/LibC: Implement sched_* functionality to set/get process priority
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
rburchell authored and awesomekling committed May 30, 2019
1 parent b160677 commit 9cd0f6f
Show file tree
Hide file tree
Showing 8 changed files with 103 additions and 1 deletion.
43 changes: 43 additions & 0 deletions Kernel/Process.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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))
Expand Down
4 changes: 4 additions & 0 deletions Kernel/Process.h
Original file line number Diff line number Diff line change
Expand Up @@ -40,9 +40,11 @@ class Process : public InlineLinkedListNode<Process>
enum Priority
{
IdlePriority,
FirstPriority = IdlePriority,
LowPriority,
NormalPriority,
HighPriority,
LastPriority = HighPriority,
};

enum RingLevel
Expand Down Expand Up @@ -186,6 +188,8 @@ class Process : public InlineLinkedListNode<Process>
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);
Expand Down
4 changes: 4 additions & 0 deletions Kernel/Syscall.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
4 changes: 3 additions & 1 deletion Kernel/Syscall.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 {

Expand Down
4 changes: 4 additions & 0 deletions Kernel/UnixTypes.h
Original file line number Diff line number Diff line change
Expand Up @@ -400,3 +400,7 @@ struct iovec {
void* iov_base;
size_t iov_len;
};

struct sched_param {
int sched_priority;
};
24 changes: 24 additions & 0 deletions LibC/sched.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}

}

15 changes: 15 additions & 0 deletions LibC/sched.h
Original file line number Diff line number Diff line change
@@ -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
6 changes: 6 additions & 0 deletions LibC/unistd.h
Original file line number Diff line number Diff line change
Expand Up @@ -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

0 comments on commit 9cd0f6f

Please sign in to comment.