diff --git a/libc/Makefile b/libc/Makefile index 6c9e4c9b..38354c9e 100644 --- a/libc/Makefile +++ b/libc/Makefile @@ -308,6 +308,8 @@ sys/mman/mmap.o \ sys/mman/mprotect.o \ sys/mman/munmap.o \ sys/readdirents/readdirents.o \ +sys/resource/getpriority.o \ +sys/resource/setpriority.o \ sys/select/select.o \ sys/socket/accept4.o \ sys/socket/accept.o \ diff --git a/libc/include/sys/resource.h b/libc/include/sys/resource.h new file mode 100644 index 00000000..e14dc32e --- /dev/null +++ b/libc/include/sys/resource.h @@ -0,0 +1,40 @@ +/******************************************************************************* + + Copyright(C) Jonas 'Sortie' Termansen 2013. + + This file is part of the Sortix C Library. + + The Sortix C Library is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation, either version 3 of the License, or (at your + option) any later version. + + The Sortix C Library is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with the Sortix C Library. If not, see . + + sys/resource.h + Resource limits and operations. + +*******************************************************************************/ + +#ifndef INCLUDE_SYS_RESOURCE_H +#define INCLUDE_SYS_RESOURCE_H + +#include +#include + +__BEGIN_DECLS + +@include(id_t.h) + +int getpriority(int, id_t); +int setpriority(int, id_t, int); + +__END_DECLS + +#endif diff --git a/libc/sys/resource/getpriority.cpp b/libc/sys/resource/getpriority.cpp new file mode 100644 index 00000000..5d8615d5 --- /dev/null +++ b/libc/sys/resource/getpriority.cpp @@ -0,0 +1,33 @@ +/******************************************************************************* + + Copyright(C) Jonas 'Sortie' Termansen 2013. + + This file is part of the Sortix C Library. + + The Sortix C Library is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation, either version 3 of the License, or (at your + option) any later version. + + The Sortix C Library is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with the Sortix C Library. If not, see . + + sys/resource/getpriority.cpp + Get the scheduling priority of a process, process group, or user. + +*******************************************************************************/ + +#include +#include + +DEFN_SYSCALL2(int, sys_getpriority, SYSCALL_GETPRIORITY, int, id_t); + +extern "C" int getpriority(int which, id_t who) +{ + return sys_getpriority(which, who); +} diff --git a/libc/sys/resource/setpriority.cpp b/libc/sys/resource/setpriority.cpp new file mode 100644 index 00000000..a63c30da --- /dev/null +++ b/libc/sys/resource/setpriority.cpp @@ -0,0 +1,33 @@ +/******************************************************************************* + + Copyright(C) Jonas 'Sortie' Termansen 2013. + + This file is part of the Sortix C Library. + + The Sortix C Library is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation, either version 3 of the License, or (at your + option) any later version. + + The Sortix C Library is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with the Sortix C Library. If not, see . + + sys/resource/setpriority.cpp + Set the scheduling priority of a process, process group, or user. + +*******************************************************************************/ + +#include +#include + +DEFN_SYSCALL3(int, sys_setpriority, SYSCALL_SETPRIORITY, int, id_t, int); + +extern "C" int setpriority(int which, id_t who, int prio) +{ + return sys_setpriority(which, who, prio); +} diff --git a/sortix/Makefile b/sortix/Makefile index 8c1df59f..8564890c 100644 --- a/sortix/Makefile +++ b/sortix/Makefile @@ -116,6 +116,7 @@ pipe.o \ poll.o \ process.o \ refcount.o \ +resource.o \ scheduler.o \ segment.o \ serialterminal.o \ diff --git a/sortix/include/sortix/kernel/process.h b/sortix/include/sortix/kernel/process.h index 8bb2010c..e8403d41 100644 --- a/sortix/include/sortix/kernel/process.h +++ b/sortix/include/sortix/kernel/process.h @@ -74,6 +74,10 @@ public: addr_t addrspace; pid_t pid; +public: + kthread_mutex_t nicelock; + int nice; + public: kthread_mutex_t idlock; uid_t uid, euid; diff --git a/sortix/include/sortix/resource.h b/sortix/include/sortix/resource.h new file mode 100644 index 00000000..9adc821f --- /dev/null +++ b/sortix/include/sortix/resource.h @@ -0,0 +1,38 @@ +/******************************************************************************* + + Copyright(C) Jonas 'Sortie' Termansen 2013. + + This file is part of the Sortix C Library. + + The Sortix C Library is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation, either version 3 of the License, or (at your + option) any later version. + + The Sortix C Library is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with the Sortix C Library. If not, see . + + sortix/resource.h + Resource limits and operations. + +*******************************************************************************/ + +#ifndef INCLUDE_SORTIX_RESOURCE_H +#define INCLUDE_SORTIX_RESOURCE_H + +#include + +__BEGIN_DECLS + +#define PRIO_PROCESS 0 +#define PRIO_PGRP 1 +#define PRIO_USER 2 + +__END_DECLS + +#endif diff --git a/sortix/include/sortix/syscallnum.h b/sortix/include/sortix/syscallnum.h index 5d40a09d..3dbc5f07 100644 --- a/sortix/include/sortix/syscallnum.h +++ b/sortix/include/sortix/syscallnum.h @@ -140,6 +140,8 @@ #define SYSCALL_MMAP_WRAPPER 116 #define SYSCALL_MPROTECT 117 #define SYSCALL_MUNMAP 118 -#define SYSCALL_MAX_NUM 119 /* index of highest constant + 1 */ +#define SYSCALL_GETPRIORITY 119 +#define SYSCALL_SETPRIORITY 120 +#define SYSCALL_MAX_NUM 121 /* index of highest constant + 1 */ #endif diff --git a/sortix/kernel.cpp b/sortix/kernel.cpp index 0db4ca5a..aba91fc1 100644 --- a/sortix/kernel.cpp +++ b/sortix/kernel.cpp @@ -73,6 +73,7 @@ #include "uart.h" #include "logterminal.h" #include "vgatextbuffer.h" +#include "resource.h" #include "serialterminal.h" #include "textterminal.h" #include "elf.h" @@ -553,6 +554,9 @@ static void BootThread(void* /*user*/) // Initialize the kernel information query syscall. Info::Init(); + // Initialize resource system calls. + Resource::Init(); + // Initialize the Video Driver framework. Video::Init(textbufhandle); diff --git a/sortix/process.cpp b/sortix/process.cpp index 6c6f764a..9106aba2 100644 --- a/sortix/process.cpp +++ b/sortix/process.cpp @@ -103,6 +103,8 @@ Process::Process() uid = euid = 0; gid = egid = 0; umask = 0022; + nicelock = KTHREAD_MUTEX_INITIALIZER; + nice = 0; Time::InitializeProcessClocks(this); alarm_timer.Attach(Time::GetClock(CLOCK_MONOTONIC)); Put(this); @@ -647,6 +649,10 @@ Process* Process::Fork() kthread_mutex_unlock(&groupchildlock); // Initialize everything that is safe and can't fail. + kthread_mutex_lock(&nicelock); + clone->nice = nice; + kthread_mutex_unlock(&nicelock); + kthread_mutex_lock(&ptrlock); clone->root = root; clone->cwd = cwd; diff --git a/sortix/resource.cpp b/sortix/resource.cpp new file mode 100644 index 00000000..3b264032 --- /dev/null +++ b/sortix/resource.cpp @@ -0,0 +1,158 @@ +/******************************************************************************* + + Copyright(C) Jonas 'Sortie' Termansen 2013. + + This file is part of Sortix. + + Sortix is free software: you can redistribute it and/or modify it under the + terms of the GNU General Public License as published by the Free Software + Foundation, either version 3 of the License, or (at your option) any later + version. + + Sortix is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. See the GNU General Public License for more + details. + + You should have received a copy of the GNU General Public License along with + Sortix. If not, see . + + resource.cpp + Resource limits and operations. + +*******************************************************************************/ + +#include + +#include +#include + +#include + +#include +#include +#include + +#include "resource.h" + +namespace Sortix { +namespace Resource { + +static int GetProcessPriority(pid_t who) +{ + if ( who < 0 ) + return errno = EINVAL, -1; + // TODO: If who isn't the current process, then it could self-destruct at + // any time while we use it; there is no safe way to do this yet. + Process* process = who ? Process::Get(who) : CurrentProcess(); + if ( !process ) + return errno = ESRCH, -1; + ScopedLock lock(&process->nicelock); + return process->nice; +} + +static int SetProcessPriority(pid_t who, int prio) +{ + if ( who < 0 ) + return errno = EINVAL, -1; + // TODO: If who isn't the current process, then it could self-destruct at + // any time while we use it; there is no safe way to do this yet. + Process* process = who ? Process::Get(who) : CurrentProcess(); + if ( !process ) + return errno = ESRCH, -1; + ScopedLock lock(&process->nicelock); + process->nice = prio; + return 0; +} + +static Process* CurrentProcessGroup() +{ + Process* process = CurrentProcess(); + ScopedLock lock(&process->groupchildlock); + // TODO: The process group can change when this call returns, additionally + // the current process leader could self-destruct. + return process->group; +} + +static int GetProcessGroupPriority(pid_t who) +{ + if ( who < 0 ) + return errno = EINVAL, -1; + // TODO: If who isn't the current process, then it could self-destruct at + // any time while we use it; there is no safe way to do this yet. + Process* group = who ? Process::Get(who) : CurrentProcessGroup(); + if ( !group ) + return errno = ESRCH, -1; + int lowest = INT_MAX; + ScopedLock group_parent_lock(&group->groupparentlock); + for ( Process* process = group->groupfirst; process; process = process->groupnext ) + { + ScopedLock lock(&process->nicelock); + if ( process->nice < lowest ) + lowest = process->nice; + } + return lowest; +} + +static int SetProcessGroupPriority(pid_t who, int prio) +{ + if ( who < 0 ) + return errno = EINVAL, -1; + // TODO: If who isn't the current process, then it could self-destruct at + // any time while we use it; there is no safe way to do this yet. + Process* group = who ? Process::Get(who) : CurrentProcessGroup(); + if ( !group ) + return errno = ESRCH, -1; + ScopedLock group_parent_lock(&group->groupparentlock); + for ( Process* process = group->groupfirst; process; process = process->groupnext ) + { + ScopedLock lock(&process->nicelock); + process->nice = prio; + } + return 0; +} + +static int GetUserPriority(uid_t /*who*/) +{ + // TODO: There is currently no easy way to iterate all processes without + // dire race conditions being possible. + return errno = ENOSYS, -1; +} + +static int SetUserPriority(uid_t /*who*/, int /*prio*/) +{ + // TODO: There is currently no easy way to iterate all processes without + // dire race conditions being possible. + return errno = ENOSYS, -1; +} + +static int sys_getpriority(int which, id_t who) +{ + switch ( which ) + { + case PRIO_PROCESS: return GetProcessPriority(who); + case PRIO_PGRP: return GetProcessGroupPriority(who); + case PRIO_USER: return GetUserPriority(who); + default: return errno = EINVAL, -1; + } +} + +static int sys_setpriority(int which, id_t who, int prio) +{ + switch ( which ) + { + case PRIO_PROCESS: return SetProcessPriority(who, prio); + case PRIO_PGRP: return SetProcessGroupPriority(who, prio); + case PRIO_USER: return SetUserPriority(who, prio); + default: return errno = EINVAL, -1; + } +} + +void Init() +{ + Syscall::Register(SYSCALL_GETPRIORITY, (void*) sys_getpriority); + Syscall::Register(SYSCALL_SETPRIORITY, (void*) sys_setpriority); +} + +} // namespace Resource +} // namespace Sortix diff --git a/sortix/resource.h b/sortix/resource.h new file mode 100644 index 00000000..7648703b --- /dev/null +++ b/sortix/resource.h @@ -0,0 +1,36 @@ +/******************************************************************************* + + Copyright(C) Jonas 'Sortie' Termansen 2013. + + This file is part of Sortix. + + Sortix is free software: you can redistribute it and/or modify it under the + terms of the GNU General Public License as published by the Free Software + Foundation, either version 3 of the License, or (at your option) any later + version. + + Sortix is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. See the GNU General Public License for more + details. + + You should have received a copy of the GNU General Public License along with + Sortix. If not, see . + + resource.h + Resource limits and operations. + +*******************************************************************************/ + +#ifndef SORTIX_RESOURCE_H +#define SORTIX_RESOURCE_H + +namespace Sortix { +namespace Resource { + +void Init(); + +} // namespace Resource +} // namespace Sortix + +#endif