mirror of
https://github.com/RGBCube/serenity
synced 2025-05-28 02:45:07 +00:00
Kernel: Port wait to ThreadBlocker
This commit is contained in:
parent
4f9ae9b970
commit
782e4ee6e1
4 changed files with 43 additions and 31 deletions
|
@ -1441,16 +1441,15 @@ pid_t Process::sys$waitpid(pid_t waitee, int* wstatus, int options)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
current->m_waitee_pid = waitee;
|
pid_t waitee_pid = waitee;
|
||||||
current->m_wait_options = options;
|
current->block(*new Thread::ThreadBlockerWait(options, waitee_pid));
|
||||||
current->block(Thread::State::BlockedWait);
|
|
||||||
if (current->m_was_interrupted_while_blocked)
|
if (current->m_was_interrupted_while_blocked)
|
||||||
return -EINTR;
|
return -EINTR;
|
||||||
|
|
||||||
InterruptDisabler disabler;
|
InterruptDisabler disabler;
|
||||||
|
|
||||||
// NOTE: If waitee was -1, m_waitee_pid will have been filled in by the scheduler.
|
// NOTE: If waitee was -1, m_waitee_pid will have been filled in by the scheduler.
|
||||||
Process* waitee_process = Process::from_pid(current->m_waitee_pid);
|
Process* waitee_process = Process::from_pid(waitee_pid);
|
||||||
ASSERT(waitee_process);
|
ASSERT(waitee_process);
|
||||||
if (waitee_process->is_dead()) {
|
if (waitee_process->is_dead()) {
|
||||||
exit_status = reap(*waitee_process);
|
exit_status = reap(*waitee_process);
|
||||||
|
@ -1458,7 +1457,7 @@ pid_t Process::sys$waitpid(pid_t waitee, int* wstatus, int options)
|
||||||
ASSERT(waitee_process->main_thread().state() == Thread::State::Stopped);
|
ASSERT(waitee_process->main_thread().state() == Thread::State::Stopped);
|
||||||
exit_status = 0x7f;
|
exit_status = 0x7f;
|
||||||
}
|
}
|
||||||
return current->m_waitee_pid;
|
return waitee_pid;
|
||||||
}
|
}
|
||||||
|
|
||||||
enum class KernelMemoryCheckResult {
|
enum class KernelMemoryCheckResult {
|
||||||
|
|
|
@ -172,11 +172,39 @@ bool Thread::ThreadBlockerSelect::should_unblock(Thread& thread, time_t now_sec,
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Thread::ThreadBlockerWait::ThreadBlockerWait(int wait_options, pid_t& waitee_pid)
|
||||||
|
: m_wait_options(wait_options)
|
||||||
|
, m_waitee_pid(waitee_pid)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Thread::ThreadBlockerWait::should_unblock(Thread& thread, time_t, long)
|
||||||
|
{
|
||||||
|
bool should_unblock = false;
|
||||||
|
thread.process().for_each_child([&](Process& child) {
|
||||||
|
if (m_waitee_pid != -1 && m_waitee_pid != child.pid())
|
||||||
|
return IterationDecision::Continue;
|
||||||
|
|
||||||
|
bool child_exited = child.is_dead();
|
||||||
|
bool child_stopped = child.main_thread().state() == Thread::State::Stopped;
|
||||||
|
|
||||||
|
bool wait_finished = ((m_wait_options & WEXITED) && child_exited)
|
||||||
|
|| ((m_wait_options & WSTOPPED) && child_stopped);
|
||||||
|
|
||||||
|
if (!wait_finished)
|
||||||
|
return IterationDecision::Continue;
|
||||||
|
|
||||||
|
m_waitee_pid = child.pid();
|
||||||
|
should_unblock = true;
|
||||||
|
return IterationDecision::Break;
|
||||||
|
});
|
||||||
|
return should_unblock;
|
||||||
|
}
|
||||||
|
|
||||||
// Called by the scheduler on threads that are blocked for some reason.
|
// Called by the scheduler on threads that are blocked for some reason.
|
||||||
// Make a decision as to whether to unblock them or not.
|
// Make a decision as to whether to unblock them or not.
|
||||||
void Thread::consider_unblock(time_t now_sec, long now_usec)
|
void Thread::consider_unblock(time_t now_sec, long now_usec)
|
||||||
{
|
{
|
||||||
auto& process = this->process();
|
|
||||||
switch (state()) {
|
switch (state()) {
|
||||||
case Thread::__Begin_Blocked_States__:
|
case Thread::__Begin_Blocked_States__:
|
||||||
case Thread::__End_Blocked_States__:
|
case Thread::__End_Blocked_States__:
|
||||||
|
@ -191,25 +219,6 @@ void Thread::consider_unblock(time_t now_sec, long now_usec)
|
||||||
case Thread::BlockedSignal:
|
case Thread::BlockedSignal:
|
||||||
/* don't know, don't care */
|
/* don't know, don't care */
|
||||||
return;
|
return;
|
||||||
case Thread::BlockedWait:
|
|
||||||
process.for_each_child([&](Process& child) {
|
|
||||||
if (waitee_pid() != -1 && waitee_pid() != child.pid())
|
|
||||||
return IterationDecision::Continue;
|
|
||||||
|
|
||||||
bool child_exited = child.is_dead();
|
|
||||||
bool child_stopped = child.main_thread().state() == Thread::State::Stopped;
|
|
||||||
|
|
||||||
bool wait_finished = ((m_wait_options & WEXITED) && child_exited)
|
|
||||||
|| ((m_wait_options & WSTOPPED) && child_stopped);
|
|
||||||
|
|
||||||
if (!wait_finished)
|
|
||||||
return IterationDecision::Continue;
|
|
||||||
|
|
||||||
m_waitee_pid = child.pid();
|
|
||||||
unblock();
|
|
||||||
return IterationDecision::Break;
|
|
||||||
});
|
|
||||||
return;
|
|
||||||
case Thread::BlockedCondition:
|
case Thread::BlockedCondition:
|
||||||
ASSERT(m_blocker);
|
ASSERT(m_blocker);
|
||||||
if (m_blocker->should_unblock(*this, now_sec, now_usec)) {
|
if (m_blocker->should_unblock(*this, now_sec, now_usec)) {
|
||||||
|
|
|
@ -162,8 +162,6 @@ const char* to_string(Thread::State state)
|
||||||
return "Skip1";
|
return "Skip1";
|
||||||
case Thread::Skip0SchedulerPasses:
|
case Thread::Skip0SchedulerPasses:
|
||||||
return "Skip0";
|
return "Skip0";
|
||||||
case Thread::BlockedWait:
|
|
||||||
return "Wait";
|
|
||||||
case Thread::BlockedSignal:
|
case Thread::BlockedSignal:
|
||||||
return "Signal";
|
return "Signal";
|
||||||
case Thread::BlockedLurking:
|
case Thread::BlockedLurking:
|
||||||
|
|
|
@ -65,7 +65,6 @@ public:
|
||||||
|
|
||||||
__Begin_Blocked_States__,
|
__Begin_Blocked_States__,
|
||||||
BlockedLurking,
|
BlockedLurking,
|
||||||
BlockedWait,
|
|
||||||
BlockedSignal,
|
BlockedSignal,
|
||||||
BlockedCondition,
|
BlockedCondition,
|
||||||
__End_Blocked_States__
|
__End_Blocked_States__
|
||||||
|
@ -147,6 +146,16 @@ public:
|
||||||
const Vector<int>& m_select_exceptional_fds;
|
const Vector<int>& m_select_exceptional_fds;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class ThreadBlockerWait : public ThreadBlocker {
|
||||||
|
public:
|
||||||
|
ThreadBlockerWait(int wait_options, pid_t& waitee_pid);
|
||||||
|
virtual bool should_unblock(Thread&, time_t, long) override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
int m_wait_options { 0 };
|
||||||
|
pid_t& m_waitee_pid;
|
||||||
|
};
|
||||||
|
|
||||||
void did_schedule() { ++m_times_scheduled; }
|
void did_schedule() { ++m_times_scheduled; }
|
||||||
u32 times_scheduled() const { return m_times_scheduled; }
|
u32 times_scheduled() const { return m_times_scheduled; }
|
||||||
|
|
||||||
|
@ -164,7 +173,6 @@ public:
|
||||||
TSS32& tss() { return m_tss; }
|
TSS32& tss() { return m_tss; }
|
||||||
State state() const { return m_state; }
|
State state() const { return m_state; }
|
||||||
u32 ticks() const { return m_ticks; }
|
u32 ticks() const { return m_ticks; }
|
||||||
pid_t waitee_pid() const { return m_waitee_pid; }
|
|
||||||
|
|
||||||
u64 sleep(u32 ticks);
|
u64 sleep(u32 ticks);
|
||||||
void block(Thread::State);
|
void block(Thread::State);
|
||||||
|
@ -250,8 +258,6 @@ private:
|
||||||
u32 m_kernel_stack_base { 0 };
|
u32 m_kernel_stack_base { 0 };
|
||||||
RefPtr<Region> m_kernel_stack_region;
|
RefPtr<Region> m_kernel_stack_region;
|
||||||
RefPtr<Region> m_kernel_stack_for_signal_handler_region;
|
RefPtr<Region> m_kernel_stack_for_signal_handler_region;
|
||||||
pid_t m_waitee_pid { -1 };
|
|
||||||
int m_wait_options { 0 };
|
|
||||||
SignalActionData m_signal_action_data[32];
|
SignalActionData m_signal_action_data[32];
|
||||||
Region* m_signal_stack_user_region { nullptr };
|
Region* m_signal_stack_user_region { nullptr };
|
||||||
OwnPtr<ThreadBlocker> m_blocker;
|
OwnPtr<ThreadBlocker> m_blocker;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue