1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-07-25 21:17:44 +00:00

Kernel: Make Thread refcounted

Similar to Process, we need to make Thread refcounted. This will solve
problems that will appear once we schedule threads on more than one
processor. This allows us to hold onto threads without necessarily
holding the scheduler lock for the entire duration.
This commit is contained in:
Tom 2020-09-27 08:53:35 -06:00 committed by Andreas Kling
parent 079486ed7e
commit 838d9fa251
14 changed files with 136 additions and 90 deletions

View file

@ -40,8 +40,12 @@ int Process::sys$donate(pid_t tid)
REQUIRE_PROMISE(stdio);
if (tid < 0)
return -EINVAL;
InterruptDisabler disabler;
auto* thread = Thread::from_tid(tid);
// We don't strictly need to grab the scheduler lock here, but it
// will close a race where we can find the thread but it disappears
// before we call Scheduler::donate_to.
ScopedSpinLock lock(g_scheduler_lock);
auto thread = Thread::from_tid(tid);
if (!thread || thread->pid() != pid())
return -ESRCH;
Scheduler::donate_to(thread, "sys$donate");
@ -55,8 +59,11 @@ int Process::sys$sched_setparam(int pid, Userspace<const struct sched_param*> us
if (!copy_from_user(&desired_param, user_param))
return -EFAULT;
InterruptDisabler disabler;
if (desired_param.sched_priority < THREAD_PRIORITY_MIN || desired_param.sched_priority > THREAD_PRIORITY_MAX)
return -EINVAL;
auto* peer = Thread::current();
ScopedSpinLock lock(g_scheduler_lock);
if (pid != 0)
peer = Thread::from_tid(pid);
@ -66,9 +73,6 @@ int Process::sys$sched_setparam(int pid, Userspace<const struct sched_param*> us
if (!is_superuser() && m_euid != peer->process().m_uid && m_uid != peer->process().m_uid)
return -EPERM;
if (desired_param.sched_priority < THREAD_PRIORITY_MIN || desired_param.sched_priority > THREAD_PRIORITY_MAX)
return -EINVAL;
peer->set_priority((u32)desired_param.sched_priority);
return 0;
}
@ -76,22 +80,27 @@ int Process::sys$sched_setparam(int pid, Userspace<const struct sched_param*> us
int Process::sys$sched_getparam(pid_t pid, Userspace<struct sched_param*> user_param)
{
REQUIRE_PROMISE(proc);
InterruptDisabler disabler;
auto* peer = Thread::current();
if (pid != 0) {
// FIXME: PID/TID BUG
// The entire process is supposed to be affected.
peer = Thread::from_tid(pid);
int priority;
{
auto* peer = Thread::current();
ScopedSpinLock lock(g_scheduler_lock);
if (pid != 0) {
// FIXME: PID/TID BUG
// The entire process is supposed to be affected.
peer = Thread::from_tid(pid);
}
if (!peer)
return -ESRCH;
if (!is_superuser() && m_euid != peer->process().m_uid && m_uid != peer->process().m_uid)
return -EPERM;
priority = (int)peer->priority();
}
if (!peer)
return -ESRCH;
if (!is_superuser() && m_euid != peer->process().m_uid && m_uid != peer->process().m_uid)
return -EPERM;
struct sched_param param {
(int)peer->priority()
priority
};
if (!copy_to_user(user_param, &param))
return -EFAULT;
@ -103,8 +112,8 @@ int Process::sys$set_thread_boost(pid_t tid, int amount)
REQUIRE_PROMISE(proc);
if (amount < 0 || amount > 20)
return -EINVAL;
InterruptDisabler disabler;
auto* thread = Thread::from_tid(tid);
ScopedSpinLock lock(g_scheduler_lock);
auto thread = Thread::from_tid(tid);
if (!thread)
return -ESRCH;
if (thread->state() == Thread::State::Dead || thread->state() == Thread::State::Dying)