forked from Bananymous/banan-os
				
			Kernel: Cleanup process creation for userspace
This commit is contained in:
		
							parent
							
								
									8001493df3
								
							
						
					
					
						commit
						1406a75a92
					
				| 
						 | 
					@ -23,13 +23,13 @@ namespace Kernel
 | 
				
			||||||
		using entry_t = Thread::entry_t;
 | 
							using entry_t = Thread::entry_t;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	public:
 | 
						public:
 | 
				
			||||||
		static BAN::ErrorOr<Process*> create_kernel(entry_t, void*);
 | 
							static Process* create_kernel(entry_t, void*);
 | 
				
			||||||
		static BAN::ErrorOr<Process*> create_userspace(BAN::StringView);
 | 
							static BAN::ErrorOr<Process*> create_userspace(BAN::StringView);
 | 
				
			||||||
		~Process();
 | 
							~Process();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		[[noreturn]] void exit();
 | 
							[[noreturn]] void exit();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		BAN::ErrorOr<Thread*> add_thread(entry_t, void*);
 | 
							void add_thread(Thread*);
 | 
				
			||||||
		void on_thread_exit(Thread&);
 | 
							void on_thread_exit(Thread&);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		BAN::ErrorOr<void> init_stdio();
 | 
							BAN::ErrorOr<void> init_stdio();
 | 
				
			||||||
| 
						 | 
					@ -60,6 +60,7 @@ namespace Kernel
 | 
				
			||||||
	private:
 | 
						private:
 | 
				
			||||||
		Process(pid_t);
 | 
							Process(pid_t);
 | 
				
			||||||
		static Process* create_process();
 | 
							static Process* create_process();
 | 
				
			||||||
 | 
							static void register_process(Process*);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		BAN::ErrorOr<BAN::String> absolute_path_of(BAN::StringView) const;
 | 
							BAN::ErrorOr<BAN::String> absolute_path_of(BAN::StringView) const;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -27,6 +27,7 @@ namespace Kernel
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	public:
 | 
						public:
 | 
				
			||||||
		static BAN::ErrorOr<Thread*> create(entry_t, void*, Process*);
 | 
							static BAN::ErrorOr<Thread*> create(entry_t, void*, Process*);
 | 
				
			||||||
 | 
							static BAN::ErrorOr<Thread*> create_userspace(uintptr_t, Process*);
 | 
				
			||||||
		~Thread();
 | 
							~Thread();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		void jump_userspace(uintptr_t rip);
 | 
							void jump_userspace(uintptr_t rip);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -60,7 +60,7 @@ namespace Kernel
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	void DeviceManager::initialize_updater()
 | 
						void DeviceManager::initialize_updater()
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		MUST(Process::create_kernel(
 | 
							Process::create_kernel(
 | 
				
			||||||
			[](void*)
 | 
								[](void*)
 | 
				
			||||||
			{
 | 
								{
 | 
				
			||||||
				while (true)
 | 
									while (true)
 | 
				
			||||||
| 
						 | 
					@ -68,7 +68,7 @@ namespace Kernel
 | 
				
			||||||
					DeviceManager::get().update();
 | 
										DeviceManager::get().update();
 | 
				
			||||||
					PIT::sleep(1);
 | 
										PIT::sleep(1);
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
			}, nullptr)
 | 
								}, nullptr
 | 
				
			||||||
		);
 | 
							);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -20,19 +20,26 @@ namespace Kernel
 | 
				
			||||||
		static pid_t s_next_pid = 1;
 | 
							static pid_t s_next_pid = 1;
 | 
				
			||||||
		auto* process = new Process(s_next_pid++);
 | 
							auto* process = new Process(s_next_pid++);
 | 
				
			||||||
		ASSERT(process);
 | 
							ASSERT(process);
 | 
				
			||||||
 | 
							return process;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						void Process::register_process(Process* process)
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
		s_process_lock.lock();
 | 
							s_process_lock.lock();
 | 
				
			||||||
		MUST(s_processes.push_back(process));
 | 
							MUST(s_processes.push_back(process));
 | 
				
			||||||
		s_process_lock.unlock();
 | 
							s_process_lock.unlock();
 | 
				
			||||||
		
 | 
							
 | 
				
			||||||
		return process;
 | 
							for (auto* thread : process->m_threads)
 | 
				
			||||||
 | 
								MUST(Scheduler::get().add_thread(thread));
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	BAN::ErrorOr<Process*> Process::create_kernel(entry_t entry, void* data)
 | 
						Process* Process::create_kernel(entry_t entry, void* data)
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		auto* process = create_process();
 | 
							auto* process = create_process();
 | 
				
			||||||
		TRY(process->m_working_directory.push_back('/'));
 | 
							MUST(process->m_working_directory.push_back('/'));
 | 
				
			||||||
		TRY(process->add_thread(entry, data));
 | 
							auto* thread = MUST(Thread::create(entry, data, process));
 | 
				
			||||||
 | 
							process->add_thread(thread);
 | 
				
			||||||
 | 
							register_process(process);
 | 
				
			||||||
		return process;
 | 
							return process;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -41,8 +48,8 @@ namespace Kernel
 | 
				
			||||||
		auto* elf = TRY(LibELF::ELF::load_from_file(path));	
 | 
							auto* elf = TRY(LibELF::ELF::load_from_file(path));	
 | 
				
			||||||
		
 | 
							
 | 
				
			||||||
		auto* process = create_process();
 | 
							auto* process = create_process();
 | 
				
			||||||
		TRY(process->m_working_directory.push_back('/'));
 | 
							MUST(process->m_working_directory.push_back('/'));
 | 
				
			||||||
		TRY(process->init_stdio());
 | 
							MUST(process->init_stdio());
 | 
				
			||||||
		process->m_mmu = new MMU();
 | 
							process->m_mmu = new MMU();
 | 
				
			||||||
		ASSERT(process->m_mmu);
 | 
							ASSERT(process->m_mmu);
 | 
				
			||||||
		
 | 
							
 | 
				
			||||||
| 
						 | 
					@ -65,16 +72,9 @@ namespace Kernel
 | 
				
			||||||
					process->m_mmu->map_page_at(addr, page * 4096, MMU::Flags::UserSupervisor | MMU::Flags::ReadWrite | MMU::Flags::Present);
 | 
										process->m_mmu->map_page_at(addr, page * 4096, MMU::Flags::UserSupervisor | MMU::Flags::ReadWrite | MMU::Flags::Present);
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
				process->m_mmu->load();
 | 
									process->m_mmu->load();
 | 
				
			||||||
				memset((void*)elf_program_header.p_vaddr, 0, elf_program_header.p_memsz);
 | 
					 | 
				
			||||||
				memcpy((void*)elf_program_header.p_vaddr, elf->data() + elf_program_header.p_offset, elf_program_header.p_filesz);
 | 
									memcpy((void*)elf_program_header.p_vaddr, elf->data() + elf_program_header.p_offset, elf_program_header.p_filesz);
 | 
				
			||||||
 | 
									memset((void*)(elf_program_header.p_vaddr + elf_program_header.p_filesz), 0, elf_program_header.p_memsz);
 | 
				
			||||||
				Process::current().mmu().load();
 | 
									Process::current().mmu().load();
 | 
				
			||||||
 | 
					 | 
				
			||||||
				dwarnln("mapped {8H}->{8H} to {8H}->{8H}",
 | 
					 | 
				
			||||||
					elf_program_header.p_offset,
 | 
					 | 
				
			||||||
					elf_program_header.p_offset + elf_program_header.p_filesz,
 | 
					 | 
				
			||||||
					elf_program_header.p_vaddr,
 | 
					 | 
				
			||||||
					elf_program_header.p_vaddr + elf_program_header.p_memsz
 | 
					 | 
				
			||||||
				);
 | 
					 | 
				
			||||||
				break;
 | 
									break;
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			default:
 | 
								default:
 | 
				
			||||||
| 
						 | 
					@ -82,19 +82,12 @@ namespace Kernel
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		TRY(process->add_thread(
 | 
							auto* thread = MUST(Thread::create_userspace(elf_file_header.e_entry, process));
 | 
				
			||||||
			[](void* entry)
 | 
							process->add_thread(thread);
 | 
				
			||||||
			{
 | 
					 | 
				
			||||||
				Thread& current = Thread::current();
 | 
					 | 
				
			||||||
				current.process().m_mmu->map_range(current.stack_base(), current.stack_size(), MMU::Flags::UserSupervisor | MMU::Flags::ReadWrite | MMU::Flags::Present);
 | 
					 | 
				
			||||||
				current.process().m_mmu->load();
 | 
					 | 
				
			||||||
				current.jump_userspace((uintptr_t)entry);
 | 
					 | 
				
			||||||
				ASSERT_NOT_REACHED();
 | 
					 | 
				
			||||||
			}, (void*)elf_file_header.e_entry
 | 
					 | 
				
			||||||
		));
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
		delete elf;
 | 
							delete elf;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							register_process(process);
 | 
				
			||||||
		return process;
 | 
							return process;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -109,19 +102,10 @@ namespace Kernel
 | 
				
			||||||
			exit();
 | 
								exit();
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	BAN::ErrorOr<Thread*> Process::add_thread(entry_t entry, void* data)
 | 
						void Process::add_thread(Thread* thread)
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		Thread* thread = TRY(Thread::create(entry, data, this));
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		LockGuard _(m_lock);
 | 
							LockGuard _(m_lock);
 | 
				
			||||||
		TRY(m_threads.push_back(thread));
 | 
							MUST(m_threads.push_back(thread));
 | 
				
			||||||
		if (auto res = Scheduler::get().add_thread(thread); res.is_error())
 | 
					 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			m_threads.pop_back();
 | 
					 | 
				
			||||||
			return res.release_error();
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		return thread;
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	void Process::on_thread_exit(Thread& thread)
 | 
						void Process::on_thread_exit(Thread& thread)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -327,18 +327,6 @@ argument_done:
 | 
				
			||||||
		if (arguments.empty())
 | 
							if (arguments.empty())
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		else if (arguments.front() == "oof")
 | 
					 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			SpinLock lock;
 | 
					 | 
				
			||||||
			for (int i = 0; i < 100; i++)
 | 
					 | 
				
			||||||
			{
 | 
					 | 
				
			||||||
				lock.lock();
 | 
					 | 
				
			||||||
				MUST(Process::create_kernel([](void*) { MUST(Process::current().init_stdio()); TTY_PRINTLN("####"); Process::current().exit(); }, nullptr));
 | 
					 | 
				
			||||||
				PIT::sleep(5);
 | 
					 | 
				
			||||||
				kmalloc_dump_info();
 | 
					 | 
				
			||||||
				lock.unlock();
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		else if (arguments.front() == "date")
 | 
							else if (arguments.front() == "date")
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
| 
						 | 
					@ -410,7 +398,9 @@ argument_done:
 | 
				
			||||||
			SpinLock spinlock;
 | 
								SpinLock spinlock;
 | 
				
			||||||
			thread_data_t thread_data = { this, spinlock, arguments };
 | 
								thread_data_t thread_data = { this, spinlock, arguments };
 | 
				
			||||||
			spinlock.lock();
 | 
								spinlock.lock();
 | 
				
			||||||
			TRY(Process::current().add_thread(function, &thread_data));
 | 
					
 | 
				
			||||||
 | 
								auto* thread = TRY(Thread::create(function, &thread_data, &Process::current()));
 | 
				
			||||||
 | 
								Process::current().add_thread(thread);
 | 
				
			||||||
			while (spinlock.is_locked());
 | 
								while (spinlock.is_locked());
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		else if (arguments.front() == "memory")
 | 
							else if (arguments.front() == "memory")
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -55,7 +55,7 @@ namespace Kernel
 | 
				
			||||||
		m_name = BAN::String::formatted("tty{}", minor(m_rdev));
 | 
							m_name = BAN::String::formatted("tty{}", minor(m_rdev));
 | 
				
			||||||
		DeviceManager::get().add_device(this);
 | 
							DeviceManager::get().add_device(this);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		MUST(Process::create_kernel(
 | 
							Process::create_kernel(
 | 
				
			||||||
			[](void* tty_)
 | 
								[](void* tty_)
 | 
				
			||||||
			{
 | 
								{
 | 
				
			||||||
				TTY* tty = (TTY*)tty_;
 | 
									TTY* tty = (TTY*)tty_;
 | 
				
			||||||
| 
						 | 
					@ -66,7 +66,7 @@ namespace Kernel
 | 
				
			||||||
					MUST(Process::current().read(fd, &event, sizeof(event)));
 | 
										MUST(Process::current().read(fd, &event, sizeof(event)));
 | 
				
			||||||
					tty->on_key(event);
 | 
										tty->on_key(event);
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
			}, this)
 | 
								}, this
 | 
				
			||||||
		);
 | 
							);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -29,6 +29,19 @@ namespace Kernel
 | 
				
			||||||
		return thread;
 | 
							return thread;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						BAN::ErrorOr<Thread*> Thread::create_userspace(uintptr_t entry, Process* process)
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							Thread* thread = TRY(Thread::create(
 | 
				
			||||||
 | 
								[](void* entry)
 | 
				
			||||||
 | 
								{
 | 
				
			||||||
 | 
									Thread::current().jump_userspace((uintptr_t)entry);
 | 
				
			||||||
 | 
									ASSERT_NOT_REACHED();
 | 
				
			||||||
 | 
								}, (void*)entry, process
 | 
				
			||||||
 | 
							));
 | 
				
			||||||
 | 
							process->mmu().map_range(thread->stack_base(), thread->stack_size(), MMU::Flags::UserSupervisor | MMU::Flags::ReadWrite | MMU::Flags::Present);
 | 
				
			||||||
 | 
							return thread;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	Thread::Thread(pid_t tid, Process* process)
 | 
						Thread::Thread(pid_t tid, Process* process)
 | 
				
			||||||
		: m_tid(tid), m_process(process)
 | 
							: m_tid(tid), m_process(process)
 | 
				
			||||||
	{}
 | 
						{}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -102,9 +102,6 @@ namespace BAN::Formatter
 | 
				
			||||||
extern "C" uintptr_t g_kernel_start;
 | 
					extern "C" uintptr_t g_kernel_start;
 | 
				
			||||||
extern "C" uintptr_t g_kernel_end;
 | 
					extern "C" uintptr_t g_kernel_end;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
extern void userspace_entry();
 | 
					 | 
				
			||||||
static void jump_userspace();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static void init2(void*);
 | 
					static void init2(void*);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
extern "C" void kernel_main()
 | 
					extern "C" void kernel_main()
 | 
				
			||||||
| 
						 | 
					@ -162,7 +159,7 @@ extern "C" void kernel_main()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	MUST(Scheduler::initialize());
 | 
						MUST(Scheduler::initialize());
 | 
				
			||||||
	Scheduler& scheduler = Scheduler::get();
 | 
						Scheduler& scheduler = Scheduler::get();
 | 
				
			||||||
	MUST(Process::create_kernel(init2, tty1));
 | 
						Process::create_kernel(init2, tty1);
 | 
				
			||||||
	scheduler.start();
 | 
						scheduler.start();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	ASSERT_NOT_REACHED();
 | 
						ASSERT_NOT_REACHED();
 | 
				
			||||||
| 
						 | 
					@ -183,10 +180,10 @@ static void init2(void* tty1)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	((TTY*)tty1)->initialize_device();
 | 
						((TTY*)tty1)->initialize_device();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	jump_userspace();
 | 
						MUST(Process::create_userspace("/bin/test"sv));
 | 
				
			||||||
	return;
 | 
						return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	MUST(Process::create_kernel(
 | 
						Process::create_kernel(
 | 
				
			||||||
		[](void*) 
 | 
							[](void*) 
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			MUST(Process::current().init_stdio());
 | 
								MUST(Process::current().init_stdio());
 | 
				
			||||||
| 
						 | 
					@ -194,14 +191,5 @@ static void init2(void* tty1)
 | 
				
			||||||
			ASSERT(shell);
 | 
								ASSERT(shell);
 | 
				
			||||||
			shell->run();
 | 
								shell->run();
 | 
				
			||||||
		}, nullptr
 | 
							}, nullptr
 | 
				
			||||||
	));
 | 
						);
 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static void jump_userspace()
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	using namespace Kernel;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	MMU::get().map_range((uintptr_t)&g_kernel_start, (uintptr_t)&g_kernel_end - (uintptr_t)&g_kernel_start, MMU::Flags::UserSupervisor | MMU::Flags::Present);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	MUST(Process::create_userspace("/bin/test"sv));
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in New Issue