1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-05-31 07:28:11 +00:00

Kernel: Some futex improvements

This adds support for FUTEX_WAKE_OP, FUTEX_WAIT_BITSET, FUTEX_WAKE_BITSET,
FUTEX_REQUEUE, and FUTEX_CMP_REQUEUE, as well well as global and private
futex and absolute/relative timeouts against the appropriate clock. This
also changes the implementation so that kernel resources are only used when
a thread is blocked on a futex.

Global futexes are implemented as offsets in VMObjects, so that different
processes can share a futex against the same VMObject despite potentially
being mapped at different virtual addresses.
This commit is contained in:
Tom 2020-12-21 23:21:58 -07:00 committed by Andreas Kling
parent 7581b64705
commit 1d621ab172
23 changed files with 928 additions and 63 deletions

View file

@ -71,14 +71,15 @@ void WaitQueue::wake_one()
m_wake_requested = !did_unblock_one;
}
void WaitQueue::wake_n(u32 wake_count)
u32 WaitQueue::wake_n(u32 wake_count)
{
if (wake_count == 0)
return; // should we assert instead?
return 0; // should we assert instaed?
ScopedSpinLock lock(m_lock);
#ifdef WAITQUEUE_DEBUG
dbg() << "WaitQueue @ " << this << ": wake_n(" << wake_count << ")";
#endif
u32 did_wake = 0;
bool did_unblock_some = do_unblock([&](Thread::Blocker& b, void* data, bool& stop_iterating) {
ASSERT(data);
ASSERT(b.blocker_type() == Thread::Blocker::Type::Queue);
@ -86,23 +87,25 @@ void WaitQueue::wake_n(u32 wake_count)
#ifdef WAITQUEUE_DEBUG
dbg() << "WaitQueue @ " << this << ": wake_n unblocking " << *static_cast<Thread*>(data);
#endif
ASSERT(wake_count > 0);
ASSERT(did_wake < wake_count);
if (blocker.unblock()) {
if (--wake_count == 0)
if (++did_wake >= wake_count)
stop_iterating = true;
return true;
}
return false;
});
m_wake_requested = !did_unblock_some;
return did_wake;
}
void WaitQueue::wake_all()
u32 WaitQueue::wake_all()
{
ScopedSpinLock lock(m_lock);
#ifdef WAITQUEUE_DEBUG
dbg() << "WaitQueue @ " << this << ": wake_all";
#endif
u32 did_wake = 0;
bool did_unblock_any = do_unblock([&](Thread::Blocker& b, void* data, bool&) {
ASSERT(data);
ASSERT(b.blocker_type() == Thread::Blocker::Type::Queue);
@ -110,11 +113,14 @@ void WaitQueue::wake_all()
#ifdef WAITQUEUE_DEBUG
dbg() << "WaitQueue @ " << this << ": wake_all unblocking " << *static_cast<Thread*>(data);
#endif
bool did_unblock = blocker.unblock();
ASSERT(did_unblock);
return true;
if (blocker.unblock()) {
did_wake++;
return true;
}
return false;
});
m_wake_requested = !did_unblock_any;
return did_wake;
}
}