Kernel: Scheduler sleeping is working
We have to disable optimization for one function, but I'm working on a fix
This commit is contained in:
		
							parent
							
								
									b8ee77eb78
								
							
						
					
					
						commit
						0b62729887
					
				|  | @ -24,11 +24,11 @@ | |||
| namespace PIT | ||||
| { | ||||
| 
 | ||||
| 	static uint64_t s_system_time = 0; | ||||
| 	static volatile uint64_t s_system_time = 0; | ||||
| 
 | ||||
| 	void irq_handler() | ||||
| 	{ | ||||
| 		s_system_time++; | ||||
| 		s_system_time = s_system_time + 1; | ||||
| 		Kernel::Scheduler::get().reschedule(); | ||||
| 	} | ||||
| 
 | ||||
|  | @ -55,7 +55,10 @@ namespace PIT | |||
| 	{ | ||||
| 		if (ms == 0) | ||||
| 			return; | ||||
| 		Kernel::Scheduler::get().set_current_thread_sleeping(ms); | ||||
| 		uint64_t wake_time = s_system_time + ms; | ||||
| 		Kernel::Scheduler::get().set_current_thread_sleeping(wake_time); | ||||
| 		if (s_system_time < wake_time) | ||||
| 			dwarnln("sleep woke {} ms too soon", wake_time - s_system_time); | ||||
| 	} | ||||
| 
 | ||||
| } | ||||
|  |  | |||
|  | @ -54,9 +54,9 @@ namespace Kernel | |||
| 		ASSERT_NOT_REACHED(); | ||||
| 	} | ||||
| 
 | ||||
| 	BAN::RefCounted<Thread> Scheduler::current_thread() | ||||
| 	Thread& Scheduler::current_thread() | ||||
| 	{ | ||||
| 		return m_current_thread ? m_current_thread->thread : m_idle_thread; | ||||
| 		return m_current_thread ? *m_current_thread->thread : *m_idle_thread; | ||||
| 	} | ||||
| 
 | ||||
| 	void Scheduler::reschedule() | ||||
|  | @ -68,13 +68,11 @@ namespace Kernel | |||
| 			return; | ||||
| 		m_last_reschedule = PIT::ms_since_boot(); | ||||
| 		 | ||||
| 		if (!m_sleeping_threads.empty()) | ||||
| 			m_sleeping_threads.front().wake_delta--; | ||||
| 		wake_threads(); | ||||
| 
 | ||||
| 		if (save_current_thread()) | ||||
| 			return; | ||||
| 		get_next_thread(); | ||||
| 		advance_current_thread(); | ||||
| 		execute_current_thread(); | ||||
| 		ASSERT_NOT_REACHED(); | ||||
| 	} | ||||
|  | @ -83,7 +81,8 @@ namespace Kernel | |||
| 	{ | ||||
| 		VERIFY_CLI(); | ||||
| 
 | ||||
| 		while (!m_sleeping_threads.empty() && m_sleeping_threads.front().wake_delta == 0) | ||||
| 		uint64_t current_time = PIT::ms_since_boot(); | ||||
| 		while (!m_sleeping_threads.empty() && m_sleeping_threads.front().wake_time <= current_time) | ||||
| 		{ | ||||
| 			auto thread = m_sleeping_threads.front().thread; | ||||
| 			m_sleeping_threads.remove(m_sleeping_threads.begin()); | ||||
|  | @ -109,7 +108,7 @@ namespace Kernel | |||
| 		return {}; | ||||
| 	} | ||||
| 
 | ||||
| 	void Scheduler::get_next_thread() | ||||
| 	void Scheduler::advance_current_thread() | ||||
| 	{ | ||||
| 		VERIFY_CLI(); | ||||
| 
 | ||||
|  | @ -118,11 +117,29 @@ namespace Kernel | |||
| 			m_current_thread = {}; | ||||
| 			return; | ||||
| 		} | ||||
| 
 | ||||
| 		if (!m_current_thread || ++m_current_thread == m_active_threads.end()) | ||||
| 			m_current_thread = m_active_threads.begin(); | ||||
| 	} | ||||
| 
 | ||||
| 	void Scheduler::remove_and_advance_current_thread() | ||||
| 	{ | ||||
| 		VERIFY_CLI(); | ||||
| 
 | ||||
| 		ASSERT(m_current_thread); | ||||
| 
 | ||||
| 		if (m_active_threads.size() == 1) | ||||
| 		{ | ||||
| 			m_active_threads.remove(m_current_thread); | ||||
| 			m_current_thread = {}; | ||||
| 		} | ||||
| 		else | ||||
| 		{ | ||||
| 			auto temp = m_current_thread; | ||||
| 			advance_current_thread(); | ||||
| 			m_active_threads.remove(temp); | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	// NOTE: this is declared always inline, so we don't corrupt the stack
 | ||||
| 	//       after getting the rsp
 | ||||
| 	ALWAYS_INLINE bool Scheduler::save_current_thread() | ||||
|  | @ -138,75 +155,67 @@ namespace Kernel | |||
| 		} | ||||
| 		read_rsp(rsp); | ||||
| 
 | ||||
| 		auto current = current_thread(); | ||||
| 		current->set_rip(rip); | ||||
| 		current->set_rsp(rsp); | ||||
| 		auto& current = current_thread(); | ||||
| 		current.set_rip(rip); | ||||
| 		current.set_rsp(rsp); | ||||
| 		return false; | ||||
| 	} | ||||
| 
 | ||||
| 	void Scheduler::execute_current_thread() | ||||
| 	{ | ||||
| 		VERIFY_CLI(); | ||||
| 		 | ||||
| 		auto& current = current_thread(); | ||||
| 
 | ||||
| 		auto current = current_thread(); | ||||
| 
 | ||||
| 		if (current->started()) | ||||
| 		if (current.started()) | ||||
| 		{ | ||||
| 			continue_thread(current->rsp(), current->rip()); | ||||
| 			continue_thread(current.rsp(), current.rip()); | ||||
| 		} | ||||
| 		else | ||||
| 		{ | ||||
| 			current->set_started(); | ||||
| 			start_thread(current->function(), current->rsp(), current->rip()); | ||||
| 			current.set_started(); | ||||
| 			start_thread(current.function(), current.rsp(), current.rip()); | ||||
| 		} | ||||
| 
 | ||||
| 		ASSERT_NOT_REACHED(); | ||||
| 	} | ||||
| 
 | ||||
| 	void Scheduler::set_current_thread_sleeping(uint64_t wake_delta) | ||||
| #pragma GCC push_options | ||||
| #pragma GCC optimize("O0") | ||||
| 	void Scheduler::set_current_thread_sleeping(uint64_t wake_time) | ||||
| 	{ | ||||
| 		DISABLE_INTERRUPTS(); | ||||
| 
 | ||||
| 		ASSERT(m_current_thread); | ||||
| 
 | ||||
| 		auto current = m_current_thread->thread; | ||||
| 		auto sleeping = m_current_thread->thread; | ||||
| 
 | ||||
| 		auto temp = m_current_thread; | ||||
| 		if (save_current_thread()) | ||||
| 			return; | ||||
| 		get_next_thread(); | ||||
| 		m_active_threads.remove(temp); | ||||
| 		remove_and_advance_current_thread(); | ||||
| 
 | ||||
| 		auto it = m_sleeping_threads.begin(); | ||||
| 
 | ||||
| 		for (; it != m_sleeping_threads.end(); it++) | ||||
| 		{ | ||||
| 			if (wake_delta <= it->wake_delta) | ||||
| 			if (wake_time <= it->wake_time) | ||||
| 				break; | ||||
| 			wake_delta -= it->wake_delta; | ||||
| 		} | ||||
| 
 | ||||
| 		if (it != m_sleeping_threads.end()) | ||||
| 			it->wake_delta -= wake_delta; | ||||
| 
 | ||||
| 		// This should work as we released enough memory from active thread
 | ||||
| 		static_assert(sizeof(ActiveThread) == sizeof(SleepingThread)); | ||||
| 		MUST(m_sleeping_threads.insert(it, { current, wake_delta })); | ||||
| 		MUST(m_sleeping_threads.emplace(it, sleeping, wake_time)); | ||||
| 		sleeping.clear(); | ||||
| 
 | ||||
| 		execute_current_thread(); | ||||
| 		ASSERT_NOT_REACHED(); | ||||
| 	} | ||||
| #pragma GCC pop_options | ||||
| 
 | ||||
| 	void Scheduler::set_current_thread_done() | ||||
| 	{ | ||||
| 		DISABLE_INTERRUPTS(); | ||||
| 
 | ||||
| 		ASSERT(m_current_thread); | ||||
| 		remove_and_advance_current_thread(); | ||||
| 
 | ||||
| 		auto temp = m_current_thread; | ||||
| 		get_next_thread(); | ||||
| 		m_active_threads.remove(temp); | ||||
| 	 | ||||
| 		execute_current_thread(); | ||||
| 		ASSERT_NOT_REACHED(); | ||||
| 	} | ||||
|  |  | |||
|  | @ -59,8 +59,7 @@ namespace Kernel | |||
| 		TTY_PRINT("{}", m_prompt); | ||||
| 		for (;;) | ||||
| 		{ | ||||
| 			//PIT::sleep(1); // sleep until next reschedule
 | ||||
| 			asm volatile("hlt"); | ||||
| 			PIT::sleep(1); // sleep until next reschedule
 | ||||
| 			Input::update(); | ||||
| 		} | ||||
| 	} | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue