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:
parent
8177f2474b
commit
5ccc3637e3
4 changed files with 23 additions and 41 deletions
|
@ -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)
|
||||||
|
|
|
@ -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())
|
||||||
|
|
|
@ -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();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue