Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 1 addition & 2 deletions Kernel/Net/Intel/E1000NetworkAdapter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -466,8 +466,7 @@ void E1000NetworkAdapter::send_raw(ReadonlyBytes payload)

if (descriptor.status == 0) {
// Someone is still using the descriptor, let's wait until it's free.
Spinlock<LockRank::None> dummy;
m_wait_queue.wait_until(dummy, [&descriptor]() {
m_wait_queue.wait_until([&descriptor]() {
return descriptor.status == 0;
})
.release_value_but_fixme_should_propagate_errors();
Expand Down
44 changes: 44 additions & 0 deletions Kernel/Tasks/WaitQueue.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,43 @@ class WaitQueue {
friend class Waiter;
class Waiter {
public:
template<CallableAs<bool> F>
ErrorOr<void> wait_until(WaitQueue& wait_queue, F should_wake)
{
bool was_interrupted = false;

SpinlockLocker scheduler_lock(g_scheduler_lock);

while (true) {
prepare(wait_queue);

if (should_wake())
break;
if (was_interrupted = Thread::current()->was_interrupted(); was_interrupted)
break;

scheduler_lock.unlock();

maybe_block();

scheduler_lock.lock();
}

clear();

scheduler_lock.unlock();

// This is always cleared since the thread might have been both interrupted and woken up.
// If both of those occurred during the same cycle, then we won't report the interrupt,
// but we still need to clear it.
Thread::current()->clear_interrupted();
if (was_interrupted) {
return EINTR;
}

return {};
}

template<LockRank Rank, CallableAs<bool> F>
ErrorOr<void> wait_until(WaitQueue& wait_queue, Spinlock<Rank>& lock, F should_wake)
{
Expand Down Expand Up @@ -124,6 +161,13 @@ class WaitQueue {
void notify_all();
void notify_one();

template<CallableAs<bool> F>
ErrorOr<void> wait_until(F should_wake)
{
Waiter waiter;
return waiter.wait_until(*this, move(should_wake));
}

template<LockRank Rank, CallableAs<bool> F>
ErrorOr<void> wait_until(Spinlock<Rank>& lock, F should_wake)
{
Expand Down
Loading