From 851ee789032f5cc955890e1f7f325e2eee4662ab Mon Sep 17 00:00:00 2001 From: Jonas 'Sortie' Termansen Date: Sun, 6 Nov 2011 23:06:32 +0100 Subject: [PATCH] Added some support for blocking system calls in the kernel. --- sortix/scheduler.cpp | 2 ++ sortix/syscall.cpp | 44 +++++++++++++++++++++++++++++++++++++++++--- sortix/syscall.h | 10 ++++++++++ sortix/thread.cpp | 4 +++- sortix/thread.h | 5 +++++ sortix/x86/syscall.s | 25 +++++++++++++++++++++++++ 6 files changed, 86 insertions(+), 4 deletions(-) diff --git a/sortix/scheduler.cpp b/sortix/scheduler.cpp index 339025fe..2bf34b90 100644 --- a/sortix/scheduler.cpp +++ b/sortix/scheduler.cpp @@ -130,6 +130,8 @@ namespace Sortix currentthread = nextthread; LogEndContextSwitch(currentthread, regs); + + if ( currentthread->scfunc ) { Syscall::Resume(regs); } } void ProcessTerminated(CPU::InterruptRegisters* regs) diff --git a/sortix/syscall.cpp b/sortix/syscall.cpp index 4f7f4fdf..d624114c 100644 --- a/sortix/syscall.cpp +++ b/sortix/syscall.cpp @@ -38,7 +38,7 @@ namespace Sortix extern "C" { CPU::SyscallRegisters* syscall_state_ptr; - int system_was_incomplete; + unsigned system_was_incomplete; size_t SYSCALL_MAX = SYSCALL_MAX_NUM; void* syscall_list[SYSCALL_MAX_NUM]; } @@ -70,11 +70,13 @@ namespace Sortix void Incomplete() { + Thread* thread = CurrentThread(); + system_was_incomplete = 1; CPU::InterruptRegisters* regs = InterruptRegs(); - CurrentThread()->SaveRegisters(regs); - // TODO: Make the thread blocking if not already. + thread->SaveRegisters(regs); + Scheduler::SetThreadState(thread, Thread::State::BLOCKING); Scheduler::Switch(regs); } @@ -83,6 +85,42 @@ namespace Sortix system_was_incomplete = 1; } + void ScheduleResumption(Thread* thread) + { + Scheduler::SetThreadState(thread, Thread::State::RUNNABLE); + } + + extern "C" size_t resume_syscall(void* scfunc, size_t scsize, size_t* scstate); + + void Resume(CPU::InterruptRegisters* regs) + { + Thread* thread = CurrentThread(); + + syscall_state_ptr = (CPU::SyscallRegisters*) regs; + + ASSERT(thread->scfunc); + + size_t* scstate = thread->scstate; + size_t scsize = thread->scsize; + void* scfunc = thread->scfunc; + + system_was_incomplete = 0; + + size_t result = resume_syscall(scfunc, scsize, scstate); + + bool incomplete = (system_was_incomplete); + + system_was_incomplete = 1; + + if ( !incomplete ) + { + syscall_state_ptr->result = result; + return; + } + + Incomplete(); + } + CPU::InterruptRegisters* InterruptRegs() { return (CPU::InterruptRegisters*) syscall_state_ptr; diff --git a/sortix/syscall.h b/sortix/syscall.h index d9541aad..70048aa5 100644 --- a/sortix/syscall.h +++ b/sortix/syscall.h @@ -29,6 +29,8 @@ namespace Sortix { + class Thread; + namespace Syscall { void Init(); @@ -45,6 +47,14 @@ namespace Sortix // For when you want the syscall exit code not to modify registers. void AsIs(); + // Retries a system call by making the thread runnable and then calling + // the system call code whenever the thread is scheduled to run. + void ScheduleResumption(Thread* thread); + + // Retries a system call based on the Thread::sc* values of the current + // thread and if it succeeds, sets the proper registers. + void Resume(CPU::InterruptRegisters* regs); + CPU::InterruptRegisters* InterruptRegs(); CPU::SyscallRegisters* SyscallRegs(); } diff --git a/sortix/thread.cpp b/sortix/thread.cpp index 64604089..9928f086 100644 --- a/sortix/thread.cpp +++ b/sortix/thread.cpp @@ -44,7 +44,8 @@ namespace Sortix schedulerlistnext = NULL; state = NONE; Maxsi::Memory::Set(®isters, 0, sizeof(registers)); - ready = false; + ready = false; + scfunc = NULL; } Thread::Thread(const Thread* forkfrom) @@ -62,6 +63,7 @@ namespace Sortix nextsleepingthread = NULL; schedulerlistprev = NULL; schedulerlistnext = NULL; + scfunc = NULL; } Thread::~Thread() diff --git a/sortix/thread.h b/sortix/thread.h index e4443ec5..7537d8fb 100644 --- a/sortix/thread.h +++ b/sortix/thread.h @@ -83,6 +83,11 @@ namespace Sortix Thread* Fork(); void SaveRegisters(const CPU::InterruptRegisters* src); void LoadRegisters(CPU::InterruptRegisters* dest); + + public: + void* scfunc; + size_t scsize; + size_t scstate[8]; }; } diff --git a/sortix/x86/syscall.s b/sortix/x86/syscall.s index 2d19ed3c..11771ee4 100644 --- a/sortix/x86/syscall.s +++ b/sortix/x86/syscall.s @@ -23,6 +23,7 @@ ******************************************************************************/ .global syscall_handler +.global resume_syscall .section .text .type syscall_handler, @function @@ -109,3 +110,27 @@ return_to_userspace: # Return to user-space. iretl +.type resume_syscall, @function +resume_syscall: + pushl %ebp + movl %esp, %ebp + + movl 8(%esp), %eax + movl 16(%esp), %ecx + + pushl 28(%ecx) + pushl 24(%ecx) + pushl 20(%ecx) + pushl 16(%ecx) + pushl 12(%ecx) + pushl 8(%ecx) + pushl 4(%ecx) + pushl 0(%ecx) + + call *%eax + + addl $32, %esp + + leavel + retl +