1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-07-24 17:57:35 +00:00

Kernel: Fix race conditions processing async device requests

This commit is contained in:
Tom 2021-02-06 16:59:32 -07:00 committed by Andreas Kling
parent 8177f2474b
commit 5ccc3637e3
4 changed files with 23 additions and 41 deletions

View file

@ -91,15 +91,11 @@ void AsyncDeviceRequest::add_sub_request(NonnullRefPtr<AsyncDeviceRequest> sub_r
VERIFY(sub_request->m_parent_request == nullptr); VERIFY(sub_request->m_parent_request == nullptr);
sub_request->m_parent_request = this; sub_request->m_parent_request = this;
bool should_start; ScopedSpinLock lock(m_lock);
{ VERIFY(!is_completed_result(m_result));
ScopedSpinLock lock(m_lock); m_sub_requests_pending.append(sub_request);
VERIFY(!is_completed_result(m_result)); if (m_result == Started)
m_sub_requests_pending.append(sub_request); sub_request->do_start(move(lock));
should_start = (m_result == Started);
}
if (should_start)
sub_request->do_start();
} }
void AsyncDeviceRequest::sub_request_finished(AsyncDeviceRequest& sub_request) void AsyncDeviceRequest::sub_request_finished(AsyncDeviceRequest& sub_request)

View file

@ -78,9 +78,14 @@ public:
[[nodiscard]] RequestWaitResult wait(Time* = nullptr); [[nodiscard]] RequestWaitResult wait(Time* = nullptr);
void do_start(Badge<Device>) void do_start(ScopedSpinLock<SpinLock<u8>>&& requests_lock)
{ {
do_start(); if (is_completed_result(m_result))
return;
m_result = Started;
requests_lock.unlock();
start();
} }
void complete(RequestResult result); void complete(RequestResult result);
@ -137,17 +142,6 @@ private:
void sub_request_finished(AsyncDeviceRequest&); void sub_request_finished(AsyncDeviceRequest&);
void request_finished(); void request_finished();
void do_start()
{
{
ScopedSpinLock lock(m_lock);
if (is_completed_result(m_result))
return;
m_result = Started;
}
start();
}
bool in_target_context(const UserOrKernelBuffer& buffer) const bool in_target_context(const UserOrKernelBuffer& buffer) const
{ {
if (buffer.is_kernel_buffer()) if (buffer.is_kernel_buffer())

View file

@ -82,20 +82,15 @@ String Device::absolute_path(const FileDescription&) const
void Device::process_next_queued_request(Badge<AsyncDeviceRequest>, const AsyncDeviceRequest& completed_request) void Device::process_next_queued_request(Badge<AsyncDeviceRequest>, const AsyncDeviceRequest& completed_request)
{ {
AsyncDeviceRequest* next_request = nullptr; ScopedSpinLock lock(m_requests_lock);
VERIFY(!m_requests.is_empty());
{ VERIFY(m_requests.first().ptr() == &completed_request);
ScopedSpinLock lock(m_requests_lock); m_requests.remove(m_requests.begin());
VERIFY(!m_requests.is_empty()); if (!m_requests.is_empty()) {
VERIFY(m_requests.first().ptr() == &completed_request); auto* next_request = m_requests.first().ptr();
m_requests.remove(m_requests.begin()); next_request->do_start(move(lock));
if (!m_requests.is_empty())
next_request = m_requests.first().ptr();
} }
if (next_request)
next_request->start();
evaluate_block_conditions(); evaluate_block_conditions();
} }

View file

@ -72,14 +72,11 @@ public:
NonnullRefPtr<AsyncRequestType> make_request(Args&&... args) NonnullRefPtr<AsyncRequestType> make_request(Args&&... args)
{ {
auto request = adopt(*new AsyncRequestType(*this, forward<Args>(args)...)); auto request = adopt(*new AsyncRequestType(*this, forward<Args>(args)...));
bool was_empty; ScopedSpinLock lock(m_requests_lock);
{ bool was_empty = m_requests.is_empty();
ScopedSpinLock lock(m_requests_lock); m_requests.append(request);
was_empty = m_requests.is_empty();
m_requests.append(request);
}
if (was_empty) if (was_empty)
request->do_start({}); request->do_start(move(lock));
return request; return request;
} }