Added some support for blocking system calls in the kernel.

This commit is contained in:
Jonas 'Sortie' Termansen 2011-11-06 23:06:32 +01:00
parent cfd7648ca9
commit 851ee78903
6 changed files with 86 additions and 4 deletions

View File

@ -130,6 +130,8 @@ namespace Sortix
currentthread = nextthread; currentthread = nextthread;
LogEndContextSwitch(currentthread, regs); LogEndContextSwitch(currentthread, regs);
if ( currentthread->scfunc ) { Syscall::Resume(regs); }
} }
void ProcessTerminated(CPU::InterruptRegisters* regs) void ProcessTerminated(CPU::InterruptRegisters* regs)

View File

@ -38,7 +38,7 @@ namespace Sortix
extern "C" extern "C"
{ {
CPU::SyscallRegisters* syscall_state_ptr; CPU::SyscallRegisters* syscall_state_ptr;
int system_was_incomplete; unsigned system_was_incomplete;
size_t SYSCALL_MAX = SYSCALL_MAX_NUM; size_t SYSCALL_MAX = SYSCALL_MAX_NUM;
void* syscall_list[SYSCALL_MAX_NUM]; void* syscall_list[SYSCALL_MAX_NUM];
} }
@ -70,11 +70,13 @@ namespace Sortix
void Incomplete() void Incomplete()
{ {
Thread* thread = CurrentThread();
system_was_incomplete = 1; system_was_incomplete = 1;
CPU::InterruptRegisters* regs = InterruptRegs(); CPU::InterruptRegisters* regs = InterruptRegs();
CurrentThread()->SaveRegisters(regs); thread->SaveRegisters(regs);
// TODO: Make the thread blocking if not already. Scheduler::SetThreadState(thread, Thread::State::BLOCKING);
Scheduler::Switch(regs); Scheduler::Switch(regs);
} }
@ -83,6 +85,42 @@ namespace Sortix
system_was_incomplete = 1; 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() CPU::InterruptRegisters* InterruptRegs()
{ {
return (CPU::InterruptRegisters*) syscall_state_ptr; return (CPU::InterruptRegisters*) syscall_state_ptr;

View File

@ -29,6 +29,8 @@
namespace Sortix namespace Sortix
{ {
class Thread;
namespace Syscall namespace Syscall
{ {
void Init(); void Init();
@ -45,6 +47,14 @@ namespace Sortix
// For when you want the syscall exit code not to modify registers. // For when you want the syscall exit code not to modify registers.
void AsIs(); 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::InterruptRegisters* InterruptRegs();
CPU::SyscallRegisters* SyscallRegs(); CPU::SyscallRegisters* SyscallRegs();
} }

View File

@ -45,6 +45,7 @@ namespace Sortix
state = NONE; state = NONE;
Maxsi::Memory::Set(&registers, 0, sizeof(registers)); Maxsi::Memory::Set(&registers, 0, sizeof(registers));
ready = false; ready = false;
scfunc = NULL;
} }
Thread::Thread(const Thread* forkfrom) Thread::Thread(const Thread* forkfrom)
@ -62,6 +63,7 @@ namespace Sortix
nextsleepingthread = NULL; nextsleepingthread = NULL;
schedulerlistprev = NULL; schedulerlistprev = NULL;
schedulerlistnext = NULL; schedulerlistnext = NULL;
scfunc = NULL;
} }
Thread::~Thread() Thread::~Thread()

View File

@ -84,6 +84,11 @@ namespace Sortix
void SaveRegisters(const CPU::InterruptRegisters* src); void SaveRegisters(const CPU::InterruptRegisters* src);
void LoadRegisters(CPU::InterruptRegisters* dest); void LoadRegisters(CPU::InterruptRegisters* dest);
public:
void* scfunc;
size_t scsize;
size_t scstate[8];
}; };
} }

View File

@ -23,6 +23,7 @@
******************************************************************************/ ******************************************************************************/
.global syscall_handler .global syscall_handler
.global resume_syscall
.section .text .section .text
.type syscall_handler, @function .type syscall_handler, @function
@ -109,3 +110,27 @@ return_to_userspace:
# Return to user-space. # Return to user-space.
iretl 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