Kernel: Cleanup returns from any kind on interrupts
This commit is contained in:
		
							parent
							
								
									13852e865c
								
							
						
					
					
						commit
						217dbca7b7
					
				|  | @ -138,7 +138,10 @@ namespace IDT | |||
| 
 | ||||
| 	extern "C" void cpp_isr_handler(uint64_t isr, uint64_t error, Kernel::InterruptStack& interrupt_stack, const Registers* regs) | ||||
| 	{ | ||||
| 		Kernel::Thread::current().save_sse(); | ||||
| 		bool from_userspace = (interrupt_stack.cs & 0b11) == 0b11; | ||||
| 
 | ||||
| 		if (from_userspace) | ||||
| 			Kernel::Thread::current().save_sse(); | ||||
| 
 | ||||
| 		pid_t tid = Kernel::Scheduler::current_tid(); | ||||
| 		pid_t pid = tid ? Kernel::Process::current().pid() : 0; | ||||
|  | @ -198,22 +201,23 @@ namespace IDT | |||
| 			Kernel::panic("Unhandled exception"); | ||||
| 		} | ||||
| 
 | ||||
| 		switch (Kernel::Thread::current().state()) | ||||
| 		{ | ||||
| 		case Kernel::Thread::State::Terminating: | ||||
| 			ASSERT_NOT_REACHED(); | ||||
| 		case Kernel::Thread::State::Terminated: | ||||
| 		// Don't continue exection when terminated
 | ||||
| 		if (Kernel::Thread::current().state() == Kernel::Thread::State::Terminated) | ||||
| 			Kernel::Scheduler::get().execute_current_thread(); | ||||
| 		default: | ||||
| 			break; | ||||
| 		 | ||||
| 		if (from_userspace) | ||||
| 		{ | ||||
| 			ASSERT(Kernel::Thread::current().state() != Kernel::Thread::State::Terminating); | ||||
| 			Kernel::Thread::current().load_sse(); | ||||
| 		} | ||||
| 
 | ||||
| 		Kernel::Thread::current().load_sse(); | ||||
| 	} | ||||
| 
 | ||||
| 	extern "C" void cpp_irq_handler(uint64_t irq, Kernel::InterruptStack& interrupt_stack) | ||||
| 	{ | ||||
| 		Kernel::Thread::current().save_sse(); | ||||
| 		bool from_userspace = (interrupt_stack.cs & 0b11) & 0b11; | ||||
| 
 | ||||
| 		if (from_userspace) | ||||
| 			Kernel::Thread::current().save_sse(); | ||||
| 
 | ||||
| 		if (Kernel::Scheduler::current_tid()) | ||||
| 		{ | ||||
|  | @ -239,17 +243,15 @@ namespace IDT | |||
| 
 | ||||
| 		Kernel::Scheduler::get().reschedule_if_idling(); | ||||
| 
 | ||||
| 		switch (Kernel::Thread::current().state()) | ||||
| 		{ | ||||
| 		case Kernel::Thread::State::Terminating: | ||||
| 			ASSERT_NOT_REACHED(); | ||||
| 		case Kernel::Thread::State::Terminated: | ||||
| 		// Don't continue exection when terminated
 | ||||
| 		if (Kernel::Thread::current().state() == Kernel::Thread::State::Terminated) | ||||
| 			Kernel::Scheduler::get().execute_current_thread(); | ||||
| 		default: | ||||
| 			break; | ||||
| 		} | ||||
| 
 | ||||
| 		Kernel::Thread::current().load_sse(); | ||||
| 		if (from_userspace) | ||||
| 		{ | ||||
| 			ASSERT(Kernel::Thread::current().state() != Kernel::Thread::State::Terminating); | ||||
| 			Kernel::Thread::current().load_sse(); | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	static void flush_idt() | ||||
|  |  | |||
|  | @ -43,7 +43,7 @@ namespace Kernel | |||
| 		~Process(); | ||||
| 		void cleanup_function(); | ||||
| 
 | ||||
| 		void exit(int status); | ||||
| 		void exit(int status, int signal); | ||||
| 
 | ||||
| 		void add_thread(Thread*); | ||||
| 		void on_thread_exit(Thread&); | ||||
|  |  | |||
|  | @ -116,7 +116,6 @@ namespace Kernel | |||
| 
 | ||||
| 		alignas(16) uint8_t m_sse_storage[512]; | ||||
| 
 | ||||
| 		friend class TerminateBlocker; | ||||
| 		friend class Scheduler; | ||||
| 	}; | ||||
| 	 | ||||
|  |  | |||
|  | @ -14,6 +14,7 @@ | |||
| #include <fcntl.h> | ||||
| #include <stdio.h> | ||||
| #include <sys/sysmacros.h> | ||||
| #include <sys/wait.h> | ||||
| 
 | ||||
| namespace Kernel | ||||
| { | ||||
|  | @ -178,17 +179,17 @@ namespace Kernel | |||
| 		ASSERT_NOT_REACHED(); | ||||
| 	} | ||||
| 
 | ||||
| 	void Process::exit(int status) | ||||
| 	void Process::exit(int status, int signal) | ||||
| 	{ | ||||
| 		LockGuard _(m_lock); | ||||
| 		m_exit_status.exit_code = status; | ||||
| 		m_exit_status.exit_code = __WGENEXITCODE(status, signal); | ||||
| 		for (auto* thread : m_threads) | ||||
| 			thread->set_terminating(); | ||||
| 	} | ||||
| 
 | ||||
| 	BAN::ErrorOr<long> Process::sys_exit(int status) | ||||
| 	{ | ||||
| 		exit(status); | ||||
| 		exit(status, 0); | ||||
| 		Thread::TerminateBlocker _(Thread::current()); | ||||
| 		ASSERT_NOT_REACHED(); | ||||
| 	} | ||||
|  | @ -427,11 +428,8 @@ namespace Kernel | |||
| 
 | ||||
| 	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) | ||||
|  | @ -445,8 +443,6 @@ namespace Kernel | |||
| 		m_exit_status.waiting--; | ||||
| 		m_lock.unlock(); | ||||
| 
 | ||||
| 		s_process_lock.lock(); | ||||
| 
 | ||||
| 		return ret; | ||||
| 	} | ||||
| 
 | ||||
|  | @ -458,10 +454,12 @@ namespace Kernel | |||
| 		if (options) | ||||
| 			return BAN::Error::from_errno(EINVAL); | ||||
| 
 | ||||
| 		LockGuard _(s_process_lock); | ||||
| 		for (auto* process : s_processes) | ||||
| 			if (process->pid() == pid) | ||||
| 				target = process; | ||||
| 		{ | ||||
| 			LockGuard _(s_process_lock); | ||||
| 			for (auto* process : s_processes) | ||||
| 				if (process->pid() == pid) | ||||
| 					target = process; | ||||
| 		} | ||||
| 
 | ||||
| 		if (target == nullptr) | ||||
| 			return BAN::Error::from_errno(ECHILD); | ||||
|  | @ -580,7 +578,6 @@ namespace Kernel | |||
| 
 | ||||
| 	BAN::ErrorOr<long> Process::sys_read(int fd, void* buffer, size_t count) | ||||
| 	{ | ||||
| 		Thread::TerminateBlocker blocker(Thread::current()); | ||||
| 		LockGuard _(m_lock); | ||||
| 		return TRY(m_open_file_descriptors.read(fd, buffer, count)); | ||||
| 	} | ||||
|  |  | |||
|  | @ -21,6 +21,8 @@ namespace Kernel | |||
| 
 | ||||
| 	extern "C" long cpp_syscall_handler(int syscall, uintptr_t arg1, uintptr_t arg2, uintptr_t arg3, uintptr_t arg4, uintptr_t arg5, InterruptStack& interrupt_stack) | ||||
| 	{ | ||||
| 		ASSERT((interrupt_stack.cs & 0b11) == 0b11); | ||||
| 
 | ||||
| 		Thread::current().set_return_rsp(interrupt_stack.rsp); | ||||
| 		Thread::current().set_return_rip(interrupt_stack.rip); | ||||
| 
 | ||||
|  | @ -175,16 +177,11 @@ namespace Kernel | |||
| 
 | ||||
| 		asm volatile("cli"); | ||||
| 
 | ||||
| 		switch (Thread::current().state()) | ||||
| 		{ | ||||
| 		case Thread::State::Terminating: | ||||
| 			ASSERT_NOT_REACHED(); | ||||
| 		case Thread::State::Terminated: | ||||
| 			Scheduler::get().execute_current_thread(); | ||||
| 		default: | ||||
| 			break; | ||||
| 		} | ||||
| 		// Don't continue exection when terminated
 | ||||
| 		if (Kernel::Thread::current().state() == Kernel::Thread::State::Terminated) | ||||
| 			Kernel::Scheduler::get().execute_current_thread(); | ||||
| 
 | ||||
| 		ASSERT(Kernel::Thread::current().state() != Kernel::Thread::State::Terminating); | ||||
| 		Thread::current().load_sse(); | ||||
| 
 | ||||
| 		if (ret.is_error()) | ||||
|  |  | |||
|  | @ -29,36 +29,32 @@ namespace Kernel | |||
| 	Thread::TerminateBlocker::TerminateBlocker(Thread& thread) | ||||
| 		: m_thread(thread) | ||||
| 	{ | ||||
| 		CriticalScope _; | ||||
| 
 | ||||
| 		if (m_thread.state() == State::Executing || m_thread.m_terminate_blockers > 0) | ||||
| 		{ | ||||
| 			CriticalScope _; | ||||
| 
 | ||||
| 			if (m_thread.state() == State::Executing || m_thread.m_terminate_blockers > 0) | ||||
| 			{ | ||||
| 				m_thread.m_terminate_blockers++; | ||||
| 				return; | ||||
| 			} | ||||
| 
 | ||||
| 			if (m_thread.state() == State::Terminating && m_thread.m_terminate_blockers == 0) | ||||
| 				m_thread.m_state = State::Terminated; | ||||
| 			m_thread.m_terminate_blockers++; | ||||
| 			return; | ||||
| 		} | ||||
| 
 | ||||
| 		if (m_thread.state() == State::Terminating && m_thread.m_terminate_blockers == 0) | ||||
| 			m_thread.m_state = State::Terminated; | ||||
| 				 | ||||
| 		while (true) | ||||
| 			Scheduler::get().reschedule(); | ||||
| 	} | ||||
| 
 | ||||
| 	Thread::TerminateBlocker::~TerminateBlocker() | ||||
| 	{ | ||||
| 		{ | ||||
| 			CriticalScope _; | ||||
| 	 | ||||
| 			m_thread.m_terminate_blockers--; | ||||
| 		CriticalScope _; | ||||
| 
 | ||||
| 			if (m_thread.state() == State::Executing || m_thread.m_terminate_blockers > 0) | ||||
| 				return; | ||||
| 		m_thread.m_terminate_blockers--; | ||||
| 
 | ||||
| 			if (m_thread.state() == State::Terminating && m_thread.m_terminate_blockers == 0) | ||||
| 				m_thread.m_state = State::Terminated; | ||||
| 		} | ||||
| 		if (m_thread.state() == State::Executing || m_thread.m_terminate_blockers > 0) | ||||
| 			return; | ||||
| 
 | ||||
| 		if (m_thread.state() == State::Terminating && m_thread.m_terminate_blockers == 0) | ||||
| 			m_thread.m_state = State::Terminated; | ||||
| 
 | ||||
| 		while (true) | ||||
| 			Scheduler::get().reschedule(); | ||||
|  | @ -299,11 +295,8 @@ namespace Kernel | |||
| 				case SIGTRAP: | ||||
| 				case SIGXCPU: | ||||
| 				case SIGXFSZ: | ||||
| 				{ | ||||
| 					auto message = BAN::String::formatted("killed by signal {}\n", signal); | ||||
| 					(void)process().tty().write(0, message.data(), message.size()); | ||||
| 				} | ||||
| 				// fall through
 | ||||
| 					process().exit(128 + signal, signal | 0x80); | ||||
| 					break; | ||||
| 
 | ||||
| 				// Abnormal termination of the process
 | ||||
| 				case SIGALRM: | ||||
|  | @ -317,10 +310,8 @@ namespace Kernel | |||
| 				case SIGPOLL: | ||||
| 				case SIGPROF: | ||||
| 				case SIGVTALRM: | ||||
| 				{ | ||||
| 					process().exit(128 + signal); | ||||
| 					process().exit(128 + signal, signal); | ||||
| 					break; | ||||
| 				} | ||||
| 
 | ||||
| 				// Ignore the signal
 | ||||
| 				case SIGCHLD: | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue