forked from Bananymous/banan-os
				
			Kernel: Track the number of recursive spinlocks a thread is holding
This commit is contained in:
		
							parent
							
								
									56db0efe58
								
							
						
					
					
						commit
						81ff71a97f
					
				|  | @ -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; } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -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) | ||||||
|  |  | ||||||
|  | @ -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); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
| } | } | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue