diff options
author | Tom <tomut@yahoo.com> | 2020-11-29 16:05:27 -0700 |
---|---|---|
committer | Andreas Kling <kling@serenityos.org> | 2020-11-30 13:17:02 +0100 |
commit | 046d6855f5e8a5039b319a47c3018a16d4c2f960 (patch) | |
tree | 9021179989bea74ec7d14a4c30d77eb2b2609f23 /Kernel/Syscalls/waitid.cpp | |
parent | 6a620562cc7298c2f591a06817ff560c9ef1deac (diff) | |
download | serenity-046d6855f5e8a5039b319a47c3018a16d4c2f960.zip |
Kernel: Move block condition evaluation out of the Scheduler
This makes the Scheduler a lot leaner by not having to evaluate
block conditions every time it is invoked. Instead evaluate them as
the states change, and unblock threads at that point.
This also implements some more waitid/waitpid/wait features and
behavior. For example, WUNTRACED and WNOWAIT are now supported. And
wait will now not return EINTR when SIGCHLD is delivered at the
same time.
Diffstat (limited to 'Kernel/Syscalls/waitid.cpp')
-rw-r--r-- | Kernel/Syscalls/waitid.cpp | 74 |
1 files changed, 10 insertions, 64 deletions
diff --git a/Kernel/Syscalls/waitid.cpp b/Kernel/Syscalls/waitid.cpp index 9e75ba376e..f98cdb6d85 100644 --- a/Kernel/Syscalls/waitid.cpp +++ b/Kernel/Syscalls/waitid.cpp @@ -32,74 +32,20 @@ namespace Kernel { KResultOr<siginfo_t> Process::do_waitid(idtype_t idtype, int id, int options) { - if (idtype == P_PID) { - ScopedSpinLock lock(g_processes_lock); - if (idtype == P_PID && !Process::from_pid(id)) - return KResult(-ECHILD); - // FIXME: Race: After 'lock' releases, the 'id' process might vanish. - // If that is not a problem, why check for it? - // If it is a problem, let's fix it! (Eventually.) - } - - ProcessID waitee_pid { 0 }; - - // FIXME: WaitBlocker should support idtype/id specs directly. - if (idtype == P_ALL) { - waitee_pid = -1; - } else if (idtype == P_PID) { - waitee_pid = id; - } else { - // FIXME: Implement other PID specs. + switch (idtype) { + case P_ALL: + case P_PID: + case P_PGID: + break; + default: return KResult(-EINVAL); } - if (Thread::current()->block<Thread::WaitBlocker>(nullptr, options, waitee_pid).was_interrupted()) + KResultOr<siginfo_t> result = KResult(KSuccess); + if (Thread::current()->block<Thread::WaitBlocker>(nullptr, options, idtype, id, result).was_interrupted()) return KResult(-EINTR); - - ScopedSpinLock lock(g_processes_lock); - - // NOTE: If waitee was -1, m_waitee_pid will have been filled in by the scheduler. - auto waitee_process = Process::from_pid(waitee_pid); - if (!waitee_process) - return KResult(-ECHILD); - - ASSERT(waitee_process); - if (waitee_process->is_dead()) { - return reap(*waitee_process); - } else { - // FIXME: PID/TID BUG - // Make sure to hold the scheduler lock so that we operate on a consistent state - ScopedSpinLock scheduler_lock(g_scheduler_lock); - auto waitee_thread = Thread::from_tid(waitee_pid.value()); - if (!waitee_thread) - return KResult(-ECHILD); - ASSERT((options & WNOHANG) || waitee_thread->state() == Thread::State::Stopped); - siginfo_t siginfo; - memset(&siginfo, 0, sizeof(siginfo)); - siginfo.si_signo = SIGCHLD; - siginfo.si_pid = waitee_process->pid().value(); - siginfo.si_uid = waitee_process->uid(); - - switch (waitee_thread->state()) { - case Thread::State::Stopped: - siginfo.si_code = CLD_STOPPED; - break; - case Thread::State::Running: - case Thread::State::Runnable: - case Thread::State::Blocked: - case Thread::State::Dying: - case Thread::State::Dead: - case Thread::State::Queued: - siginfo.si_code = CLD_CONTINUED; - break; - default: - ASSERT_NOT_REACHED(); - break; - } - - siginfo.si_status = waitee_thread->m_stop_signal; - return siginfo; - } + ASSERT(!result.is_error() || (options & WNOHANG) || result.error() != KSuccess); + return result; } pid_t Process::sys$waitid(Userspace<const Syscall::SC_waitid_params*> user_params) |