Kernel: Track the number of recursive spinlocks a thread is holding

This commit is contained in:
Bananymous 2025-06-06 06:51:15 +03:00
parent 56db0efe58
commit 81ff71a97f
3 changed files with 70 additions and 33 deletions

View File

@ -43,36 +43,11 @@ namespace Kernel
public: public:
RecursiveSpinLock() = default; RecursiveSpinLock() = default;
InterruptState lock() InterruptState lock();
{
auto state = Processor::get_interrupt_state();
Processor::set_interrupt_state(InterruptState::Disabled);
auto id = Processor::current_id().as_u32(); bool try_lock_interrupts_disabled();
ProcessorID::value_type expected = PROCESSOR_NONE.as_u32(); void unlock(InterruptState state);
while (!m_locker.compare_exchange(expected, id, BAN::MemoryOrder::memory_order_acq_rel))
{
if (expected == id)
break;
Processor::pause();
expected = PROCESSOR_NONE.as_u32();
}
m_lock_depth++;
return state;
}
void unlock(InterruptState state)
{
ASSERT(Processor::get_interrupt_state() == InterruptState::Disabled);
ASSERT(current_processor_has_lock());
ASSERT(m_lock_depth > 0);
if (--m_lock_depth == 0)
m_locker.store(PROCESSOR_NONE.as_u32(), BAN::MemoryOrder::memory_order_release);
Processor::set_interrupt_state(state);
}
uint32_t lock_depth() const { return m_lock_depth; } uint32_t lock_depth() const { return m_lock_depth; }

View File

@ -377,6 +377,9 @@ namespace Kernel::ACPI::AML
return result; return result;
} }
// FIXME: WHY TF IS THIS USING OVER 1 KiB of stack
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wstack-usage="
static BAN::ErrorOr<Node> parse_logical_op(ParseContext& context) static BAN::ErrorOr<Node> parse_logical_op(ParseContext& context)
{ {
dprintln_if(AML_DUMP_FUNCTION_CALLS, "parse_logical_op"); dprintln_if(AML_DUMP_FUNCTION_CALLS, "parse_logical_op");
@ -467,6 +470,7 @@ namespace Kernel::ACPI::AML
return result; return result;
} }
#pragma GCC diagnostic pop
static BAN::ErrorOr<Node> parse_index_op(ParseContext& context); static BAN::ErrorOr<Node> parse_index_op(ParseContext& context);
@ -1537,6 +1541,9 @@ namespace Kernel::ACPI::AML
return result; return result;
} }
// FIXME: WHY TF IS THIS USING OVER 1 KiB of stack
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wstack-usage="
static BAN::ErrorOr<Node> parse_explicit_conversion(ParseContext& context) static BAN::ErrorOr<Node> parse_explicit_conversion(ParseContext& context)
{ {
dprintln_if(AML_DUMP_FUNCTION_CALLS, "parse_explicit_conversion"); dprintln_if(AML_DUMP_FUNCTION_CALLS, "parse_explicit_conversion");
@ -1689,6 +1696,7 @@ namespace Kernel::ACPI::AML
return result; return result;
} }
#pragma GCC diagnostic pop
static BAN::ErrorOr<Node> parse_to_string_op(ParseContext& context) static BAN::ErrorOr<Node> parse_to_string_op(ParseContext& context)
{ {
@ -2750,7 +2758,9 @@ namespace Kernel::ACPI::AML
return method_call(scope, method, BAN::move(args)); return method_call(scope, method, BAN::move(args));
} }
// FIXME: WHY TF IS THIS USING OVER 2 KiB of stack
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wstack-usage="
BAN::ErrorOr<Node> parse_node(ParseContext& context, bool return_ref) BAN::ErrorOr<Node> parse_node(ParseContext& context, bool return_ref)
{ {
if (context.aml_data.empty()) if (context.aml_data.empty())
@ -2961,13 +2971,11 @@ namespace Kernel::ACPI::AML
reference.as.reference->ref_count++; reference.as.reference->ref_count++;
return reference; return reference;
} }
#pragma GCC diagnostic pop
// FIXME: WHY TF IS THIS USING ALMOST 2 KiB of stack // FIXME: WHY TF IS THIS USING ALMOST 2 KiB of stack
#pragma GCC diagnostic push #pragma GCC diagnostic push
#if defined(__GNUC__) && !defined(__clang__)
#pragma GCC diagnostic ignored "-Wstack-usage=" #pragma GCC diagnostic ignored "-Wstack-usage="
#endif
BAN::ErrorOr<ExecutionFlowResult> parse_node_or_execution_flow(ParseContext& context) BAN::ErrorOr<ExecutionFlowResult> parse_node_or_execution_flow(ParseContext& context)
{ {
if (context.aml_data.empty()) if (context.aml_data.empty())
@ -3103,7 +3111,6 @@ namespace Kernel::ACPI::AML
.elem2 = BAN::move(node) .elem2 = BAN::move(node)
}; };
} }
#pragma GCC diagnostic pop #pragma GCC diagnostic pop
BAN::ErrorOr<NameString> NameString::from_string(BAN::StringView name) BAN::ErrorOr<NameString> NameString::from_string(BAN::StringView name)

View File

@ -52,4 +52,59 @@ namespace Kernel
Processor::set_interrupt_state(state); Processor::set_interrupt_state(state);
} }
InterruptState RecursiveSpinLock::lock()
{
auto state = Processor::get_interrupt_state();
Processor::set_interrupt_state(InterruptState::Disabled);
auto id = Processor::current_id().as_u32();
ProcessorID::value_type expected = PROCESSOR_NONE.as_u32();
while (!m_locker.compare_exchange(expected, id, BAN::MemoryOrder::memory_order_acq_rel))
{
if (expected == id)
break;
Processor::pause();
expected = PROCESSOR_NONE.as_u32();
}
m_lock_depth++;
if (Thread::current_tid())
Thread::current().add_spinlock();
return state;
}
bool RecursiveSpinLock::try_lock_interrupts_disabled()
{
ASSERT(Processor::get_interrupt_state() == InterruptState::Disabled);
auto id = Processor::current_id().as_u32();
ProcessorID::value_type expected = PROCESSOR_NONE.as_u32();
if (!m_locker.compare_exchange(expected, id, BAN::MemoryOrder::memory_order_acq_rel))
if (expected != id)
return false;
m_lock_depth++;
if (Thread::current_tid())
Thread::current().add_spinlock();
return true;
}
void RecursiveSpinLock::unlock(InterruptState state)
{
ASSERT(Processor::get_interrupt_state() == InterruptState::Disabled);
ASSERT(current_processor_has_lock());
ASSERT(m_lock_depth > 0);
if (--m_lock_depth == 0)
m_locker.store(PROCESSOR_NONE.as_u32(), BAN::MemoryOrder::memory_order_release);
if (Thread::current_tid())
Thread::current().remove_spinlock();
Processor::set_interrupt_state(state);
}
} }