forked from Bananymous/banan-os
				
			
							parent
							
								
									94d2090777
								
							
						
					
					
						commit
						b68d5a5833
					
				|  | @ -51,6 +51,9 @@ namespace Kernel | |||
| 		BAN::ErrorOr<Process*> fork(uintptr_t rsp, uintptr_t rip); | ||||
| 		BAN::ErrorOr<void> exec(BAN::StringView path, const char* const* argv, const char* const* envp); | ||||
| 
 | ||||
| 		int block_until_exit(); | ||||
| 		BAN::ErrorOr<pid_t> wait(pid_t pid, int* stat_loc, int options); | ||||
| 
 | ||||
| 		BAN::ErrorOr<int> open(BAN::StringView, int); | ||||
| 		BAN::ErrorOr<void> close(int fd); | ||||
| 		BAN::ErrorOr<size_t> read(int fd, void* buffer, size_t count); | ||||
|  | @ -105,6 +108,15 @@ namespace Kernel | |||
| 		OpenFileDescription& open_file_description(int); | ||||
| 		BAN::ErrorOr<int> get_free_fd(); | ||||
| 
 | ||||
| 
 | ||||
| 		struct ExitStatus | ||||
| 		{ | ||||
| 			Semaphore semaphore; | ||||
| 			int exit_code { 0 }; | ||||
| 			bool exited { false }; | ||||
| 			int waiting { 0 }; | ||||
| 		}; | ||||
| 
 | ||||
| 		BAN::Vector<OpenFileDescription> m_open_files; | ||||
| 		BAN::Vector<VirtualRange*> m_mapped_ranges; | ||||
| 
 | ||||
|  | @ -118,6 +130,7 @@ namespace Kernel | |||
| 		BAN::UniqPtr<GeneralAllocator> m_general_allocator; | ||||
| 
 | ||||
| 		userspace_entry_t m_userspace_entry; | ||||
| 		ExitStatus m_exit_status; | ||||
| 
 | ||||
| 		BAN::UniqPtr<PageTable> m_page_table; | ||||
| 		TTY* m_tty { nullptr }; | ||||
|  |  | |||
|  | @ -117,6 +117,15 @@ namespace Kernel | |||
| 	void Process::exit() | ||||
| 	{ | ||||
| 		m_lock.lock(); | ||||
| 		m_exit_status.exited = true; | ||||
| 		while (m_exit_status.waiting > 0) | ||||
| 		{ | ||||
| 			m_exit_status.semaphore.unblock(); | ||||
| 			m_lock.unlock(); | ||||
| 			// TODO: add proper software reschedule
 | ||||
| 			Scheduler::get().set_current_thread_sleeping(0); | ||||
| 		} | ||||
| 		m_lock.lock(); | ||||
| 
 | ||||
| 		m_threads.clear(); | ||||
| 		for (auto& open_fd : m_open_files) | ||||
|  | @ -249,6 +258,52 @@ namespace Kernel | |||
| 		ASSERT_NOT_REACHED(); | ||||
| 	} | ||||
| 
 | ||||
| 	int Process::block_until_exit() | ||||
| 	{ | ||||
| 		ASSERT(s_process_lock.is_locked()); | ||||
| 		ASSERT(this != &Process::current()); | ||||
| 
 | ||||
| 		s_process_lock.unlock(); | ||||
| 
 | ||||
| 		m_lock.lock(); | ||||
| 		m_exit_status.waiting++; | ||||
| 		while (!m_exit_status.exited) | ||||
| 		{ | ||||
| 			m_lock.unlock(); | ||||
| 			m_exit_status.semaphore.block(); | ||||
| 			m_lock.lock(); | ||||
| 		} | ||||
| 
 | ||||
| 		int ret = m_exit_status.exit_code; | ||||
| 		m_exit_status.waiting--; | ||||
| 		m_lock.unlock(); | ||||
| 
 | ||||
| 		s_process_lock.lock(); | ||||
| 
 | ||||
| 		return ret; | ||||
| 	} | ||||
| 
 | ||||
| 	BAN::ErrorOr<pid_t> Process::wait(pid_t pid, int* stat_loc, int options) | ||||
| 	{ | ||||
| 		Process* target = nullptr; | ||||
| 
 | ||||
| 		// FIXME: support options
 | ||||
| 		if (options) | ||||
| 			return BAN::Error::from_errno(EINVAL); | ||||
| 
 | ||||
| 		LockGuard _(s_process_lock); | ||||
| 		for (auto* process : s_processes) | ||||
| 			if (process->pid() == pid) | ||||
| 				target = process; | ||||
| 
 | ||||
| 		if (target == nullptr) | ||||
| 			return BAN::Error::from_errno(ECHILD); | ||||
| 
 | ||||
| 		pid_t ret = target->pid(); | ||||
| 		*stat_loc = target->block_until_exit(); | ||||
| 
 | ||||
| 		return ret; | ||||
| 	} | ||||
| 
 | ||||
| 	void Process::load_elf(LibELF::ELF& elf) | ||||
| 	{ | ||||
|  |  | |||
|  | @ -120,6 +120,14 @@ namespace Kernel | |||
| 		ASSERT_NOT_REACHED(); | ||||
| 	} | ||||
| 
 | ||||
| 	long sys_wait(pid_t pid, int* stat_loc, int options) | ||||
| 	{ | ||||
| 		auto ret = Process::current().wait(pid, stat_loc, options); | ||||
| 		if (ret.is_error()) | ||||
| 			return -ret.error().get_error_code(); | ||||
| 		return ret.value(); | ||||
| 	} | ||||
| 
 | ||||
| 	extern "C" long sys_fork_trampoline(); | ||||
| 
 | ||||
| 	extern "C" long cpp_syscall_handler(int syscall, uintptr_t arg1, uintptr_t arg2, uintptr_t arg3, uintptr_t arg4, uintptr_t arg5) | ||||
|  | @ -182,6 +190,9 @@ namespace Kernel | |||
| 		case SYS_EXEC: | ||||
| 			ret = sys_exec((const char*)arg1, (const char* const*)arg2, (const char* const*)arg3); | ||||
| 			break; | ||||
| 		case SYS_WAIT: | ||||
| 			ret = sys_wait((pid_t)arg1, (int*)arg2, (int)arg3); | ||||
| 			break; | ||||
| 		default: | ||||
| 			Kernel::panic("Unknown syscall {}", syscall); | ||||
| 		} | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue