mirror of
https://github.com/RGBCube/serenity
synced 2025-06-01 03:08:13 +00:00
Kernel: Allow Lock to block from BlockCondition
This enables the Lock class to block a thread even while the thread is working on a BlockCondition. A thread can still only be either blocked by a Lock or a BlockCondition. This also establishes a linked list of threads that are blocked by a Lock and unblocking directly unlocks threads and wakes them directly.
This commit is contained in:
parent
d9fb93c5ce
commit
026ffa343d
8 changed files with 442 additions and 267 deletions
|
@ -436,7 +436,7 @@ PageFaultResponse Region::handle_fault(const PageFault& fault, ScopedSpinLock<Re
|
|||
remap_vmobject_page(translate_to_vmobject_page(page_index_in_region));
|
||||
return PageFaultResponse::Continue;
|
||||
}
|
||||
return handle_zero_fault(page_index_in_region);
|
||||
return handle_zero_fault(page_index_in_region, mm_lock);
|
||||
#else
|
||||
dbgln("BUG! Unexpected NP fault at {}", fault.vaddr());
|
||||
return PageFaultResponse::ShouldCrash;
|
||||
|
@ -448,7 +448,7 @@ PageFaultResponse Region::handle_fault(const PageFault& fault, ScopedSpinLock<Re
|
|||
auto* phys_page = physical_page(page_index_in_region);
|
||||
if (phys_page->is_shared_zero_page() || phys_page->is_lazy_committed_page()) {
|
||||
dbgln_if(PAGE_FAULT_DEBUG, "NP(zero) fault in Region({})[{}] at {}", this, page_index_in_region, fault.vaddr());
|
||||
return handle_zero_fault(page_index_in_region);
|
||||
return handle_zero_fault(page_index_in_region, mm_lock);
|
||||
}
|
||||
return handle_cow_fault(page_index_in_region);
|
||||
}
|
||||
|
@ -456,12 +456,29 @@ PageFaultResponse Region::handle_fault(const PageFault& fault, ScopedSpinLock<Re
|
|||
return PageFaultResponse::ShouldCrash;
|
||||
}
|
||||
|
||||
PageFaultResponse Region::handle_zero_fault(size_t page_index_in_region)
|
||||
PageFaultResponse Region::handle_zero_fault(size_t page_index_in_region, ScopedSpinLock<RecursiveSpinLock>& mm_lock)
|
||||
{
|
||||
VERIFY_INTERRUPTS_DISABLED();
|
||||
VERIFY(vmobject().is_anonymous());
|
||||
|
||||
Locker locker(vmobject().m_paging_lock);
|
||||
bool can_lock = Thread::current() && !g_scheduler_lock.own_lock();
|
||||
if (can_lock) {
|
||||
// TODO: This seems rather weird. If we don't have a current thread
|
||||
// then we're in the Kernel in early initialization still. So we
|
||||
// can't actually wait on the paging lock. And if we currently
|
||||
// own the scheduler lock and we trigger zero faults, we also
|
||||
// can't really wait. But do we actually need to wait here?
|
||||
mm_lock.unlock();
|
||||
VERIFY(!s_mm_lock.own_lock());
|
||||
|
||||
vmobject().m_paging_lock.lock();
|
||||
|
||||
mm_lock.lock();
|
||||
}
|
||||
ScopeGuard guard([&]() {
|
||||
if (can_lock)
|
||||
vmobject().m_paging_lock.unlock();
|
||||
});
|
||||
|
||||
auto& page_slot = physical_page_slot(page_index_in_region);
|
||||
auto page_index_in_vmobject = translate_to_vmobject_page(page_index_in_region);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue