mirror of
https://github.com/RGBCube/serenity
synced 2025-05-31 10:38:11 +00:00
Scheduler: Allow reentry into block()
With the presence of signal handlers, it is possible that a thread might be blocked multiple times. Picture for instance a signal handler using read(), or wait() while the thread is already blocked elsewhere before the handler is invoked. To fix this, we turn m_blocker into a chain of handlers. Each block() call now prepends to the list, and unblocking will only consider the most recent (first) blocker in the chain. Fixes #309
This commit is contained in:
parent
a9db382f0e
commit
dea7f937bf
3 changed files with 37 additions and 17 deletions
|
@ -221,8 +221,8 @@ void Thread::consider_unblock(time_t now_sec, long now_usec)
|
|||
/* don't know, don't care */
|
||||
return;
|
||||
case Thread::Blocked:
|
||||
ASSERT(m_blocker);
|
||||
if (m_blocker->should_unblock(*this, now_sec, now_usec))
|
||||
ASSERT(!m_blockers.is_empty());
|
||||
if (m_blockers.first()->should_unblock(*this, now_sec, now_usec))
|
||||
unblock();
|
||||
return;
|
||||
case Thread::Skip1SchedulerPass:
|
||||
|
@ -307,8 +307,8 @@ bool Scheduler::pick_next()
|
|||
return IterationDecision::Continue;
|
||||
if (was_blocked) {
|
||||
dbgprintf("Unblock %s(%u) due to signal\n", thread.process().name().characters(), thread.pid());
|
||||
ASSERT(thread.m_blocker);
|
||||
thread.m_blocker->set_interrupted_by_signal();
|
||||
ASSERT(!thread.m_blockers.is_empty());
|
||||
thread.m_blockers.first()->set_interrupted_by_signal();
|
||||
thread.unblock();
|
||||
}
|
||||
return IterationDecision::Continue;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue