Kernel: Thread creation now takes void(*)() as entry and void* as data
This simplifies threading for the future and gets rid of (undefined?) cast of member function pointer to address
This commit is contained in:
		
							parent
							
								
									8dbece9119
								
							
						
					
					
						commit
						af854ec9e1
					
				|  | @ -9,18 +9,13 @@ exit_thread_trampoline: | ||||||
| 	pushl (%esp) | 	pushl (%esp) | ||||||
| 	ret | 	ret | ||||||
| 
 | 
 | ||||||
| # void start_thread(uint32_t function, uint32_t esp, uint32_t eip) | # void start_thread(uint32_t esp, uint32_t eip) | ||||||
| .global start_thread
 | .global start_thread
 | ||||||
| start_thread: | start_thread: | ||||||
| 	movl 4(%esp), %eax | 	movl 8(%esp), %ecx | ||||||
| 	movl 12(%esp), %ecx | 	movl 4(%esp), %esp | ||||||
| 	movl 8(%esp), %esp |  | ||||||
| 
 |  | ||||||
| 	pushl %eax |  | ||||||
| 	pushl $exit_thread_trampoline |  | ||||||
| 
 |  | ||||||
| 	movl $0, %ebp | 	movl $0, %ebp | ||||||
| 
 | 	pushl $exit_thread_trampoline | ||||||
| 	sti | 	sti | ||||||
| 	jmp *%ecx | 	jmp *%ecx | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -8,14 +8,15 @@ exit_thread_trampoline: | ||||||
| 	movq 8(%rsp), %rdi | 	movq 8(%rsp), %rdi | ||||||
| 	ret | 	ret | ||||||
| 
 | 
 | ||||||
| # void start_thread(uint64_t function, uint64_t rsp, uint64_t rip) | # void start_thread(uint64_t rsp, uint64_t rip) | ||||||
| .global start_thread
 | .global start_thread
 | ||||||
| start_thread: | start_thread: | ||||||
| 	movq %rsi, %rsp | 	movq %rdi, %rsp | ||||||
|  | 	popq %rdi | ||||||
| 	movq $0, %rbp | 	movq $0, %rbp | ||||||
| 	pushq $exit_thread_trampoline | 	pushq $exit_thread_trampoline | ||||||
| 	sti | 	sti | ||||||
| 	jmp *%rdx | 	jmp *%rsi | ||||||
| 
 | 
 | ||||||
| # void continue_thread(uint64_t rsp, uint64_t rip) | # void continue_thread(uint64_t rsp, uint64_t rip) | ||||||
| .global continue_thread
 | .global continue_thread
 | ||||||
|  |  | ||||||
|  | @ -9,7 +9,10 @@ namespace Kernel | ||||||
| 	class Thread : public BAN::RefCounted<Thread> | 	class Thread : public BAN::RefCounted<Thread> | ||||||
| 	{ | 	{ | ||||||
| 	public: | 	public: | ||||||
| 		static BAN::ErrorOr<BAN::RefPtr<Thread>> create(const BAN::Function<void()>&); | 		using entry_t = void(*)(void*); | ||||||
|  | 
 | ||||||
|  | 	public: | ||||||
|  | 		static BAN::ErrorOr<BAN::RefPtr<Thread>> create(entry_t, void* = nullptr); | ||||||
| 		~Thread(); | 		~Thread(); | ||||||
| 
 | 
 | ||||||
| 		uint32_t tid() const { return m_tid; } | 		uint32_t tid() const { return m_tid; } | ||||||
|  | @ -22,10 +25,9 @@ namespace Kernel | ||||||
| 		void set_started() { m_started = true; } | 		void set_started() { m_started = true; } | ||||||
| 		bool started() const { return m_started; } | 		bool started() const { return m_started; } | ||||||
| 
 | 
 | ||||||
| 		const BAN::Function<void()>* function() const { return &m_function; } |  | ||||||
| 
 |  | ||||||
| 	private: | 	private: | ||||||
| 		Thread(const BAN::Function<void()>&); | 		Thread(); | ||||||
|  | 		BAN::ErrorOr<void> initialize(entry_t, void*); | ||||||
| 		void on_exit(); | 		void on_exit(); | ||||||
| 		 | 		 | ||||||
| 	private: | 	private: | ||||||
|  | @ -35,8 +37,6 @@ namespace Kernel | ||||||
| 		const uint32_t	m_tid			= 0; | 		const uint32_t	m_tid			= 0; | ||||||
| 		bool			m_started		= false; | 		bool			m_started		= false; | ||||||
| 
 | 
 | ||||||
| 		BAN::Function<void()> m_function; |  | ||||||
| 
 |  | ||||||
| 		friend class BAN::RefPtr<Thread>; | 		friend class BAN::RefPtr<Thread>; | ||||||
| 	}; | 	}; | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -15,7 +15,7 @@ | ||||||
| namespace Kernel | namespace Kernel | ||||||
| { | { | ||||||
| 
 | 
 | ||||||
| 	extern "C" void start_thread(const BAN::Function<void()>* function, uintptr_t rsp, uintptr_t rip); | 	extern "C" void start_thread(uintptr_t rsp, uintptr_t rip); | ||||||
| 	extern "C" void continue_thread(uintptr_t rsp, uintptr_t rip); | 	extern "C" void continue_thread(uintptr_t rsp, uintptr_t rip); | ||||||
| 	extern "C" uintptr_t read_rip(); | 	extern "C" uintptr_t read_rip(); | ||||||
| 
 | 
 | ||||||
|  | @ -26,7 +26,7 @@ namespace Kernel | ||||||
| 		ASSERT(s_instance == nullptr); | 		ASSERT(s_instance == nullptr); | ||||||
| 		s_instance = new Scheduler(); | 		s_instance = new Scheduler(); | ||||||
| 		ASSERT(s_instance); | 		ASSERT(s_instance); | ||||||
| 		s_instance->m_idle_thread = TRY(Thread::create([] { for (;;) asm volatile("hlt"); })); | 		s_instance->m_idle_thread = TRY(Thread::create([](void*) { for (;;) asm volatile("hlt"); })); | ||||||
| 		return {}; | 		return {}; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | @ -159,7 +159,7 @@ namespace Kernel | ||||||
| 		else | 		else | ||||||
| 		{ | 		{ | ||||||
| 			current.set_started(); | 			current.set_started(); | ||||||
| 			start_thread(current.function(), current.rsp(), current.rip()); | 			start_thread(current.rsp(), current.rip()); | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		ASSERT_NOT_REACHED(); | 		ASSERT_NOT_REACHED(); | ||||||
|  |  | ||||||
|  | @ -178,24 +178,32 @@ argument_done: | ||||||
| 		} | 		} | ||||||
| 		else if (arguments.front() == "thread") | 		else if (arguments.front() == "thread") | ||||||
| 		{ | 		{ | ||||||
| 			static SpinLock s_thread_spinlock; | 			struct thread_data_t | ||||||
|  | 			{ | ||||||
|  | 				Shell* shell; | ||||||
|  | 				SpinLock& lock; | ||||||
|  | 				const Vector<String>& arguments; | ||||||
|  | 			}; | ||||||
| 			 | 			 | ||||||
| 			s_thread_spinlock.lock(); | 			auto function = [](void* data) | ||||||
|  | 			{ | ||||||
|  | 				thread_data_t* thread_data = (thread_data_t*)data; | ||||||
|  | 				Shell* shell = thread_data->shell; | ||||||
|  | 				auto args = thread_data->arguments; | ||||||
|  | 				thread_data->lock.unlock(); | ||||||
| 
 | 
 | ||||||
| 			auto thread = TRY(Thread::create( | 				args.remove(0); | ||||||
| 				[this, &arguments] | 				PIT::sleep(5000); | ||||||
| 				{ |  | ||||||
| 					auto args = arguments; |  | ||||||
| 					args.remove(0); |  | ||||||
| 					s_thread_spinlock.unlock(); |  | ||||||
| 					PIT::sleep(5000); |  | ||||||
| 					if (auto res = process_command(args); res.is_error()) |  | ||||||
| 						TTY_PRINTLN("{}", res.error()); |  | ||||||
| 				} |  | ||||||
| 			)); |  | ||||||
| 			TRY(Scheduler::get().add_thread(thread)); |  | ||||||
| 
 | 
 | ||||||
| 			while (s_thread_spinlock.is_locked()); | 				if (auto res = shell->process_command(args); res.is_error()) | ||||||
|  | 					Formatter::println([&](char c) { shell->m_tty->putchar(c); }, "{}", res.error()); | ||||||
|  | 			}; | ||||||
|  | 
 | ||||||
|  | 			SpinLock spinlock; | ||||||
|  | 			thread_data_t thread_data = { this, spinlock, arguments }; | ||||||
|  | 			spinlock.lock(); | ||||||
|  | 			TRY(Scheduler::get().add_thread(TRY(Thread::create(function, &thread_data)))); | ||||||
|  | 			while (spinlock.is_locked()); | ||||||
| 		} | 		} | ||||||
| 		else if (arguments.front() == "memory") | 		else if (arguments.front() == "memory") | ||||||
| 		{ | 		{ | ||||||
|  |  | ||||||
|  | @ -21,33 +21,34 @@ namespace Kernel | ||||||
| 		memcpy((void*)rsp, (void*)&value, size); | 		memcpy((void*)rsp, (void*)&value, size); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 
 | 	BAN::ErrorOr<BAN::RefPtr<Thread>> Thread::create(entry_t entry, void* data) | ||||||
| 	BAN::ErrorOr<BAN::RefPtr<Thread>> Thread::create(const BAN::Function<void()>& function) |  | ||||||
| 	{ | 	{ | ||||||
| 		return BAN::RefPtr<Thread>::create(function); | 		auto thread = TRY(BAN::RefPtr<Thread>::create()); | ||||||
|  | 		TRY(thread->initialize(entry, data)); | ||||||
|  | 		return thread; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	Thread::Thread(const BAN::Function<void()>& function) | 	Thread::Thread() | ||||||
| 		: m_tid(s_next_tid++) | 		: m_tid(s_next_tid++) | ||||||
| 		, m_function(function) | 	{} | ||||||
|  | 
 | ||||||
|  | 	BAN::ErrorOr<void> Thread::initialize(entry_t entry, void* data) | ||||||
| 	{ | 	{ | ||||||
| 		m_stack_base = kmalloc(thread_stack_size, PAGE_SIZE); | 		m_stack_base = kmalloc(thread_stack_size, PAGE_SIZE); | ||||||
| 		ASSERT(m_stack_base); | 		if (m_stack_base == nullptr) | ||||||
| 
 | 			return BAN::Error::from_errno(ENOMEM); | ||||||
| 		m_rsp = (uintptr_t)m_stack_base + thread_stack_size; | 		m_rsp = (uintptr_t)m_stack_base + thread_stack_size; | ||||||
| 
 | 		m_rip = (uintptr_t)entry; | ||||||
| #pragma GCC diagnostic push |  | ||||||
| #pragma GCC diagnostic ignored "-Wpmf-conversions" |  | ||||||
| 		m_rip = (uintptr_t)(void*)&BAN::Function<void()>::operator(); |  | ||||||
| #pragma GCC diagnostic pop |  | ||||||
| 
 | 
 | ||||||
| 		write_to_stack<sizeof(void*)>(m_rsp, this); | 		write_to_stack<sizeof(void*)>(m_rsp, this); | ||||||
| 		write_to_stack<sizeof(void*)>(m_rsp, &Thread::on_exit); | 		write_to_stack<sizeof(void*)>(m_rsp, &Thread::on_exit); | ||||||
|  | 		write_to_stack<sizeof(void*)>(m_rsp, data); | ||||||
|  | 
 | ||||||
|  | 		return {}; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	Thread::~Thread() | 	Thread::~Thread() | ||||||
| 	{ | 	{ | ||||||
| 		dprintln("thread {} destruct", tid()); |  | ||||||
| 		kfree(m_stack_base); | 		kfree(m_stack_base); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -125,7 +125,7 @@ extern "C" void kernel_main() | ||||||
| 	MUST(Scheduler::initialize()); | 	MUST(Scheduler::initialize()); | ||||||
| 	Scheduler& scheduler = Scheduler::get(); | 	Scheduler& scheduler = Scheduler::get(); | ||||||
| 	MUST(scheduler.add_thread(MUST(Thread::create( | 	MUST(scheduler.add_thread(MUST(Thread::create( | ||||||
| 		[terminal_driver] | 		[](void* terminal_driver) | ||||||
| 		{ | 		{ | ||||||
| 			MUST(VirtualFileSystem::initialize()); | 			MUST(VirtualFileSystem::initialize()); | ||||||
| 
 | 
 | ||||||
|  | @ -133,16 +133,16 @@ extern "C" void kernel_main() | ||||||
| 			if (font_or_error.is_error()) | 			if (font_or_error.is_error()) | ||||||
| 				dprintln("{}", font_or_error.error()); | 				dprintln("{}", font_or_error.error()); | ||||||
| 			else | 			else | ||||||
| 				terminal_driver->set_font(font_or_error.release_value()); | 				((TerminalDriver*)terminal_driver)->set_font(font_or_error.release_value()); | ||||||
| 		} | 		}, terminal_driver | ||||||
| 	)))); | 	)))); | ||||||
| 	MUST(scheduler.add_thread(MUST(Thread::create( | 	MUST(scheduler.add_thread(MUST(Thread::create( | ||||||
| 		[tty1] | 		[](void* tty) | ||||||
| 		{ | 		{ | ||||||
| 			Shell* shell = new Shell(tty1); | 			Shell* shell = new Shell((TTY*)tty); | ||||||
| 			ASSERT(shell); | 			ASSERT(shell); | ||||||
| 			shell->run(); | 			shell->run(); | ||||||
| 		} | 		}, tty1 | ||||||
| 	)))); | 	)))); | ||||||
| 	scheduler.start(); | 	scheduler.start(); | ||||||
| 	ASSERT(false); | 	ASSERT(false); | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue