mirror of
https://gitlab.com/sortix/sortix.git
synced 2023-02-13 20:55:38 -05:00
Clean up kernel thread creation code.
This commit is contained in:
parent
a24ecf4b83
commit
7b3e2fa229
8 changed files with 185 additions and 270 deletions
|
@ -50,7 +50,6 @@ ifdef X86FAMILY
|
||||||
x86-family/gdt.o \
|
x86-family/gdt.o \
|
||||||
x86-family/idt.o \
|
x86-family/idt.o \
|
||||||
$(CPU)/syscall.o \
|
$(CPU)/syscall.o \
|
||||||
$(CPU)/thread.o \
|
|
||||||
$(CPU)/process.o \
|
$(CPU)/process.o \
|
||||||
x86-family/cmos.o \
|
x86-family/cmos.o \
|
||||||
x86-family/time.o \
|
x86-family/time.o \
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
|
|
||||||
Copyright(C) Jonas 'Sortie' Termansen 2012.
|
Copyright(C) Jonas 'Sortie' Termansen 2012, 2014.
|
||||||
|
|
||||||
This file is part of Sortix.
|
This file is part of Sortix.
|
||||||
|
|
||||||
|
@ -34,7 +34,7 @@ namespace Sortix {
|
||||||
extern "C" {
|
extern "C" {
|
||||||
|
|
||||||
inline static void kthread_yield(void) { asm volatile ("int $129"); }
|
inline static void kthread_yield(void) { asm volatile ("int $129"); }
|
||||||
__attribute__((noreturn)) void kthread_exit(void* param = NULL);
|
__attribute__((noreturn)) void kthread_exit();
|
||||||
typedef unsigned kthread_mutex_t;
|
typedef unsigned kthread_mutex_t;
|
||||||
const kthread_mutex_t KTHREAD_MUTEX_INITIALIZER = 0;
|
const kthread_mutex_t KTHREAD_MUTEX_INITIALIZER = 0;
|
||||||
unsigned kthread_mutex_trylock(kthread_mutex_t* mutex);
|
unsigned kthread_mutex_trylock(kthread_mutex_t* mutex);
|
||||||
|
|
|
@ -34,59 +34,39 @@
|
||||||
#include <sortix/kernel/scheduler.h>
|
#include <sortix/kernel/scheduler.h>
|
||||||
#include <sortix/kernel/signal.h>
|
#include <sortix/kernel/signal.h>
|
||||||
|
|
||||||
typedef struct multiboot_info multiboot_info_t;
|
|
||||||
|
|
||||||
namespace Sortix {
|
namespace Sortix {
|
||||||
|
|
||||||
class Process;
|
class Process;
|
||||||
class Thread;
|
class Thread;
|
||||||
|
|
||||||
extern "C" void KernelInit(unsigned long magic, multiboot_info_t* bootinfo);
|
|
||||||
|
|
||||||
typedef void (*ThreadEntry)(void* user);
|
|
||||||
|
|
||||||
// Simply exits the kernel thread.
|
|
||||||
__attribute__((noreturn)) void KernelThreadExit();
|
|
||||||
|
|
||||||
// Internally used as a kernel thread entry point that exits the thread
|
|
||||||
// upon the actual thread entry returning.
|
|
||||||
extern "C" __attribute__((noreturn))
|
|
||||||
void BootstrapKernelThread(void* user, ThreadEntry entry);
|
|
||||||
|
|
||||||
// These functions create a new kernel process but doesn't start it.
|
// These functions create a new kernel process but doesn't start it.
|
||||||
Thread* CreateKernelThread(Process* process, CPU::InterruptRegisters* regs,
|
Thread* CreateKernelThread(Process* process, CPU::InterruptRegisters* regs,
|
||||||
unsigned long fsbase, unsigned long gsbase);
|
unsigned long fsbase, unsigned long gsbase);
|
||||||
Thread* CreateKernelThread(Process* process, ThreadEntry entry, void* user,
|
Thread* CreateKernelThread(Process* process, void (*entry)(void*), void* user,
|
||||||
size_t stacksize = 0);
|
size_t stacksize = 0);
|
||||||
Thread* CreateKernelThread(ThreadEntry entry, void* user, size_t stacksize = 0);
|
Thread* CreateKernelThread(void (*entry)(void*), void* user, size_t stacksize = 0);
|
||||||
|
|
||||||
// This function can be used to start a thread from the above functions.
|
// This function can be used to start a thread from the above functions.
|
||||||
void StartKernelThread(Thread* thread);
|
void StartKernelThread(Thread* thread);
|
||||||
|
|
||||||
// Alternatively, these functions both create and start the thread.
|
// Alternatively, these functions both create and start the thread.
|
||||||
Thread* RunKernelThread(Process* process, CPU::InterruptRegisters* regs);
|
Thread* RunKernelThread(Process* process, CPU::InterruptRegisters* regs);
|
||||||
Thread* RunKernelThread(Process* process, ThreadEntry entry, void* user,
|
Thread* RunKernelThread(Process* process, void (*entry)(void*), void* user,
|
||||||
size_t stacksize = 0);
|
size_t stacksize = 0);
|
||||||
Thread* RunKernelThread(ThreadEntry entry, void* user, size_t stacksize = 0);
|
Thread* RunKernelThread(void (*entry)(void*), void* user, size_t stacksize = 0);
|
||||||
|
|
||||||
void SetupKernelThreadRegs(CPU::InterruptRegisters* regs, ThreadEntry entry,
|
|
||||||
void* user, addr_t stack, size_t stacksize);
|
|
||||||
|
|
||||||
class Thread
|
class Thread
|
||||||
{
|
{
|
||||||
friend Thread* CreateKernelThread(Process* process,
|
friend Thread* CreateKernelThread(Process* process,
|
||||||
CPU::InterruptRegisters* regs,
|
CPU::InterruptRegisters* regs,
|
||||||
unsigned long fsbase, unsigned long gsbase);
|
unsigned long fsbase, unsigned long gsbase);
|
||||||
friend void KernelInit(unsigned long magic, multiboot_info_t* bootinfo);
|
|
||||||
friend void UpdatePendingSignals(Thread* thread);
|
friend void UpdatePendingSignals(Thread* thread);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
static void Init();
|
static void Init();
|
||||||
|
|
||||||
private:
|
|
||||||
Thread();
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
Thread();
|
||||||
~Thread();
|
~Thread();
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
|
|
||||||
Copyright(C) Jonas 'Sortie' Termansen 2012.
|
Copyright(C) Jonas 'Sortie' Termansen 2012, 2014.
|
||||||
|
|
||||||
This file is part of Sortix.
|
This file is part of Sortix.
|
||||||
|
|
||||||
|
@ -42,7 +42,7 @@ static void kthread_do_kill_thread(void* user)
|
||||||
delete thread;
|
delete thread;
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" void kthread_exit(void* /*param*/)
|
extern "C" void kthread_exit()
|
||||||
{
|
{
|
||||||
Worker::Schedule(kthread_do_kill_thread, CurrentThread());
|
Worker::Schedule(kthread_do_kill_thread, CurrentThread());
|
||||||
Scheduler::ExitThread();
|
Scheduler::ExitThread();
|
||||||
|
|
|
@ -82,6 +82,100 @@ Thread::~Thread()
|
||||||
delete[] (uint8_t*) kernelstackpos;
|
delete[] (uint8_t*) kernelstackpos;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Thread::SaveRegisters(const CPU::InterruptRegisters* src)
|
||||||
|
{
|
||||||
|
#if defined(__i386__)
|
||||||
|
registers.eip = src->eip;
|
||||||
|
registers.esp = src->esp;
|
||||||
|
registers.eax = src->eax;
|
||||||
|
registers.ebx = src->ebx;
|
||||||
|
registers.ecx = src->ecx;
|
||||||
|
registers.edx = src->edx;
|
||||||
|
registers.edi = src->edi;
|
||||||
|
registers.esi = src->esi;
|
||||||
|
registers.ebp = src->ebp;
|
||||||
|
registers.cs = src->cs;
|
||||||
|
registers.ds = src->ds;
|
||||||
|
registers.ss = src->ss;
|
||||||
|
registers.eflags = src->eflags;
|
||||||
|
registers.kerrno = src->kerrno;
|
||||||
|
registers.signal_pending = src->signal_pending;
|
||||||
|
#elif defined(__x86_64__)
|
||||||
|
registers.rip = src->rip;
|
||||||
|
registers.rsp = src->rsp;
|
||||||
|
registers.rax = src->rax;
|
||||||
|
registers.rbx = src->rbx;
|
||||||
|
registers.rcx = src->rcx;
|
||||||
|
registers.rdx = src->rdx;
|
||||||
|
registers.rdi = src->rdi;
|
||||||
|
registers.rsi = src->rsi;
|
||||||
|
registers.rbp = src->rbp;
|
||||||
|
registers.r8 = src->r8;
|
||||||
|
registers.r9 = src->r9;
|
||||||
|
registers.r10 = src->r10;
|
||||||
|
registers.r11 = src->r11;
|
||||||
|
registers.r12 = src->r12;
|
||||||
|
registers.r13 = src->r13;
|
||||||
|
registers.r14 = src->r14;
|
||||||
|
registers.r15 = src->r15;
|
||||||
|
registers.cs = src->cs;
|
||||||
|
registers.ds = src->ds;
|
||||||
|
registers.ss = src->ss;
|
||||||
|
registers.rflags = src->rflags;
|
||||||
|
registers.kerrno = src->kerrno;
|
||||||
|
registers.signal_pending = src->signal_pending;
|
||||||
|
#else
|
||||||
|
#warning "You need to add register saving support"
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void Thread::LoadRegisters(CPU::InterruptRegisters* dest)
|
||||||
|
{
|
||||||
|
#if defined(__i386__)
|
||||||
|
dest->eip = registers.eip;
|
||||||
|
dest->esp = registers.esp;
|
||||||
|
dest->eax = registers.eax;
|
||||||
|
dest->ebx = registers.ebx;
|
||||||
|
dest->ecx = registers.ecx;
|
||||||
|
dest->edx = registers.edx;
|
||||||
|
dest->edi = registers.edi;
|
||||||
|
dest->esi = registers.esi;
|
||||||
|
dest->ebp = registers.ebp;
|
||||||
|
dest->cs = registers.cs;
|
||||||
|
dest->ds = registers.ds;
|
||||||
|
dest->ss = registers.ss;
|
||||||
|
dest->eflags = registers.eflags;
|
||||||
|
dest->kerrno = registers.kerrno;
|
||||||
|
dest->signal_pending = registers.signal_pending;
|
||||||
|
#elif defined(__x86_64__)
|
||||||
|
dest->rip = registers.rip;
|
||||||
|
dest->rsp = registers.rsp;
|
||||||
|
dest->rax = registers.rax;
|
||||||
|
dest->rbx = registers.rbx;
|
||||||
|
dest->rcx = registers.rcx;
|
||||||
|
dest->rdx = registers.rdx;
|
||||||
|
dest->rdi = registers.rdi;
|
||||||
|
dest->rsi = registers.rsi;
|
||||||
|
dest->rbp = registers.rbp;
|
||||||
|
dest->r8 = registers.r8;
|
||||||
|
dest->r9 = registers.r9;
|
||||||
|
dest->r10 = registers.r10;
|
||||||
|
dest->r11 = registers.r11;
|
||||||
|
dest->r12 = registers.r12;
|
||||||
|
dest->r13 = registers.r13;
|
||||||
|
dest->r14 = registers.r14;
|
||||||
|
dest->r15 = registers.r15;
|
||||||
|
dest->cs = registers.cs;
|
||||||
|
dest->ds = registers.ds;
|
||||||
|
dest->ss = registers.ss;
|
||||||
|
dest->rflags = registers.rflags;
|
||||||
|
dest->kerrno = registers.kerrno;
|
||||||
|
dest->signal_pending = registers.signal_pending;
|
||||||
|
#else
|
||||||
|
#warning "You need to add register loading support"
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
addr_t Thread::SwitchAddressSpace(addr_t newaddrspace)
|
addr_t Thread::SwitchAddressSpace(addr_t newaddrspace)
|
||||||
{
|
{
|
||||||
bool wasenabled = Interrupt::SetEnabled(false);
|
bool wasenabled = Interrupt::SetEnabled(false);
|
||||||
|
@ -92,12 +186,6 @@ addr_t Thread::SwitchAddressSpace(addr_t newaddrspace)
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" void BootstrapKernelThread(void* user, ThreadEntry entry)
|
|
||||||
{
|
|
||||||
entry(user);
|
|
||||||
kthread_exit();
|
|
||||||
}
|
|
||||||
|
|
||||||
Thread* CreateKernelThread(Process* process, CPU::InterruptRegisters* regs,
|
Thread* CreateKernelThread(Process* process, CPU::InterruptRegisters* regs,
|
||||||
unsigned long fsbase, unsigned long gsbase)
|
unsigned long fsbase, unsigned long gsbase)
|
||||||
{
|
{
|
||||||
|
@ -133,7 +221,83 @@ Thread* CreateKernelThread(Process* process, CPU::InterruptRegisters* regs,
|
||||||
return thread;
|
return thread;
|
||||||
}
|
}
|
||||||
|
|
||||||
Thread* CreateKernelThread(Process* process, ThreadEntry entry, void* user,
|
static void SetupKernelThreadRegs(CPU::InterruptRegisters* regs,
|
||||||
|
void (*entry)(void*),
|
||||||
|
void* user,
|
||||||
|
uintptr_t stack,
|
||||||
|
size_t stack_size)
|
||||||
|
{
|
||||||
|
#if defined(__i386__)
|
||||||
|
uintptr_t* stack_values = (uintptr_t*) (stack + stack_size);
|
||||||
|
|
||||||
|
assert(!((uintptr_t) stack_values & 3UL));
|
||||||
|
assert(4 * sizeof(uintptr_t) <= stack_size);
|
||||||
|
|
||||||
|
stack_values[-1] = (uintptr_t) 0; /* null eip */
|
||||||
|
stack_values[-2] = (uintptr_t) 0; /* null ebp */
|
||||||
|
stack_values[-3] = (uintptr_t) user; /* thread parameter */
|
||||||
|
stack_values[-4] = (uintptr_t) kthread_exit; /* return to kthread_exit */
|
||||||
|
|
||||||
|
regs->eip = (uintptr_t) entry;
|
||||||
|
regs->esp = (uintptr_t) (stack_values - 4);
|
||||||
|
regs->eax = 0;
|
||||||
|
regs->ebx = 0;
|
||||||
|
regs->ecx = 0;
|
||||||
|
regs->edx = 0;
|
||||||
|
regs->edi = 0;
|
||||||
|
regs->esi = 0;
|
||||||
|
regs->ebp = (uintptr_t) (stack_values - 2);
|
||||||
|
regs->cs = KCS | KRPL;
|
||||||
|
regs->ds = KDS | KRPL;
|
||||||
|
regs->ss = KDS | KRPL;
|
||||||
|
regs->eflags = FLAGS_RESERVED1 | FLAGS_INTERRUPT | FLAGS_ID;
|
||||||
|
regs->kerrno = 0;
|
||||||
|
regs->signal_pending = 0;
|
||||||
|
#elif defined(__x86_64__)
|
||||||
|
if ( (stack & 15UL) == 8 && 8 <= stack_size )
|
||||||
|
{
|
||||||
|
stack += 8;
|
||||||
|
stack_size -= 8;
|
||||||
|
}
|
||||||
|
|
||||||
|
uintptr_t* stack_values = (uintptr_t*) (stack + stack_size);
|
||||||
|
|
||||||
|
assert(!((uintptr_t) stack_values & 15UL));
|
||||||
|
assert(3 * sizeof(uintptr_t) <= stack_size);
|
||||||
|
|
||||||
|
stack_values[-1] = (uintptr_t) 0; /* null rip */
|
||||||
|
stack_values[-2] = (uintptr_t) 0; /* null rbp */
|
||||||
|
stack_values[-3] = (uintptr_t) kthread_exit; /* return to kthread_exit */
|
||||||
|
|
||||||
|
regs->rip = (uintptr_t) entry;
|
||||||
|
regs->rsp = (uintptr_t) (stack_values - 3);
|
||||||
|
regs->rax = 0;
|
||||||
|
regs->rbx = 0;
|
||||||
|
regs->rcx = 0;
|
||||||
|
regs->rdx = 0;
|
||||||
|
regs->rdi = (uintptr_t) user;
|
||||||
|
regs->rsi = 0;
|
||||||
|
regs->rbp = 0;
|
||||||
|
regs->r8 = 0;
|
||||||
|
regs->r9 = 0;
|
||||||
|
regs->r10 = 0;
|
||||||
|
regs->r11 = 0;
|
||||||
|
regs->r12 = 0;
|
||||||
|
regs->r13 = 0;
|
||||||
|
regs->r14 = 0;
|
||||||
|
regs->r15 = 0;
|
||||||
|
regs->cs = KCS | KRPL;
|
||||||
|
regs->ds = KDS | KRPL;
|
||||||
|
regs->ss = KDS | KRPL;
|
||||||
|
regs->rflags = FLAGS_RESERVED1 | FLAGS_INTERRUPT | FLAGS_ID;
|
||||||
|
regs->kerrno = 0;
|
||||||
|
regs->signal_pending = 0;
|
||||||
|
#else
|
||||||
|
#warning "You need to add thread register initialization support"
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
Thread* CreateKernelThread(Process* process, void (*entry)(void*), void* user,
|
||||||
size_t stacksize)
|
size_t stacksize)
|
||||||
{
|
{
|
||||||
const size_t DEFAULT_KERNEL_STACK_SIZE = 8 * 1024UL;
|
const size_t DEFAULT_KERNEL_STACK_SIZE = 8 * 1024UL;
|
||||||
|
@ -144,19 +308,19 @@ Thread* CreateKernelThread(Process* process, ThreadEntry entry, void* user,
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
CPU::InterruptRegisters regs;
|
CPU::InterruptRegisters regs;
|
||||||
SetupKernelThreadRegs(®s, entry, user, (addr_t) stack, stacksize);
|
SetupKernelThreadRegs(®s, entry, user, (uintptr_t) stack, stacksize);
|
||||||
|
|
||||||
Thread* thread = CreateKernelThread(process, ®s, 0, 0);
|
Thread* thread = CreateKernelThread(process, ®s, 0, 0);
|
||||||
if ( !thread ) { delete[] stack; return NULL; }
|
if ( !thread ) { delete[] stack; return NULL; }
|
||||||
|
|
||||||
thread->kernelstackpos = (addr_t) stack;
|
thread->kernelstackpos = (uintptr_t) stack;
|
||||||
thread->kernelstacksize = stacksize;
|
thread->kernelstacksize = stacksize;
|
||||||
thread->kernelstackmalloced = true;
|
thread->kernelstackmalloced = true;
|
||||||
|
|
||||||
return thread;
|
return thread;
|
||||||
}
|
}
|
||||||
|
|
||||||
Thread* CreateKernelThread(ThreadEntry entry, void* user, size_t stacksize)
|
Thread* CreateKernelThread(void (*entry)(void*), void* user, size_t stacksize)
|
||||||
{
|
{
|
||||||
return CreateKernelThread(CurrentProcess(), entry, user, stacksize);
|
return CreateKernelThread(CurrentProcess(), entry, user, stacksize);
|
||||||
}
|
}
|
||||||
|
@ -175,7 +339,7 @@ Thread* RunKernelThread(Process* process, CPU::InterruptRegisters* regs)
|
||||||
return thread;
|
return thread;
|
||||||
}
|
}
|
||||||
|
|
||||||
Thread* RunKernelThread(Process* process, ThreadEntry entry, void* user,
|
Thread* RunKernelThread(Process* process, void (*entry)(void*), void* user,
|
||||||
size_t stacksize)
|
size_t stacksize)
|
||||||
{
|
{
|
||||||
Thread* thread = CreateKernelThread(process, entry, user, stacksize);
|
Thread* thread = CreateKernelThread(process, entry, user, stacksize);
|
||||||
|
@ -185,7 +349,7 @@ Thread* RunKernelThread(Process* process, ThreadEntry entry, void* user,
|
||||||
return thread;
|
return thread;
|
||||||
}
|
}
|
||||||
|
|
||||||
Thread* RunKernelThread(ThreadEntry entry, void* user, size_t stacksize)
|
Thread* RunKernelThread(void (*entry)(void*), void* user, size_t stacksize)
|
||||||
{
|
{
|
||||||
Thread* thread = CreateKernelThread(entry, user, stacksize);
|
Thread* thread = CreateKernelThread(entry, user, stacksize);
|
||||||
if ( !thread )
|
if ( !thread )
|
||||||
|
|
|
@ -1,120 +0,0 @@
|
||||||
/*******************************************************************************
|
|
||||||
|
|
||||||
Copyright(C) Jonas 'Sortie' Termansen 2011, 2012, 2014.
|
|
||||||
|
|
||||||
This file is part of Sortix.
|
|
||||||
|
|
||||||
Sortix is free software: you can redistribute it and/or modify it under the
|
|
||||||
terms of the GNU General Public License as published by the Free Software
|
|
||||||
Foundation, either version 3 of the License, or (at your option) any later
|
|
||||||
version.
|
|
||||||
|
|
||||||
Sortix is distributed in the hope that it will be useful, but WITHOUT ANY
|
|
||||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
|
||||||
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
|
||||||
details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License along with
|
|
||||||
Sortix. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
|
|
||||||
x64/thread.cpp
|
|
||||||
x64 specific parts of thread.cpp.
|
|
||||||
|
|
||||||
*******************************************************************************/
|
|
||||||
|
|
||||||
#include <stddef.h>
|
|
||||||
#include <stdint.h>
|
|
||||||
|
|
||||||
#include <sortix/kernel/kernel.h>
|
|
||||||
#include <sortix/kernel/thread.h>
|
|
||||||
|
|
||||||
namespace Sortix {
|
|
||||||
|
|
||||||
void Thread::SaveRegisters(const CPU::InterruptRegisters* src)
|
|
||||||
{
|
|
||||||
registers.rip = src->rip;
|
|
||||||
registers.rsp = src->rsp;
|
|
||||||
registers.rax = src->rax;
|
|
||||||
registers.rbx = src->rbx;
|
|
||||||
registers.rcx = src->rcx;
|
|
||||||
registers.rdx = src->rdx;
|
|
||||||
registers.rdi = src->rdi;
|
|
||||||
registers.rsi = src->rsi;
|
|
||||||
registers.rbp = src->rbp;
|
|
||||||
registers.r8 = src->r8;
|
|
||||||
registers.r9 = src->r9;
|
|
||||||
registers.r10 = src->r10;
|
|
||||||
registers.r11 = src->r11;
|
|
||||||
registers.r12 = src->r12;
|
|
||||||
registers.r13 = src->r13;
|
|
||||||
registers.r14 = src->r14;
|
|
||||||
registers.r15 = src->r15;
|
|
||||||
registers.cs = src->cs;
|
|
||||||
registers.ds = src->ds;
|
|
||||||
registers.ss = src->ss;
|
|
||||||
registers.rflags = src->rflags;
|
|
||||||
registers.kerrno = src->kerrno;
|
|
||||||
registers.signal_pending = src->signal_pending;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Thread::LoadRegisters(CPU::InterruptRegisters* dest)
|
|
||||||
{
|
|
||||||
dest->rip = registers.rip;
|
|
||||||
dest->rsp = registers.rsp;
|
|
||||||
dest->rax = registers.rax;
|
|
||||||
dest->rbx = registers.rbx;
|
|
||||||
dest->rcx = registers.rcx;
|
|
||||||
dest->rdx = registers.rdx;
|
|
||||||
dest->rdi = registers.rdi;
|
|
||||||
dest->rsi = registers.rsi;
|
|
||||||
dest->rbp = registers.rbp;
|
|
||||||
dest->r8 = registers.r8;
|
|
||||||
dest->r9 = registers.r9;
|
|
||||||
dest->r10 = registers.r10;
|
|
||||||
dest->r11 = registers.r11;
|
|
||||||
dest->r12 = registers.r12;
|
|
||||||
dest->r13 = registers.r13;
|
|
||||||
dest->r14 = registers.r14;
|
|
||||||
dest->r15 = registers.r15;
|
|
||||||
dest->cs = registers.cs;
|
|
||||||
dest->ds = registers.ds;
|
|
||||||
dest->ss = registers.ss;
|
|
||||||
dest->rflags = registers.rflags;
|
|
||||||
dest->kerrno = registers.kerrno;
|
|
||||||
dest->signal_pending = registers.signal_pending;
|
|
||||||
}
|
|
||||||
|
|
||||||
void SetupKernelThreadRegs(CPU::InterruptRegisters* regs, ThreadEntry entry,
|
|
||||||
void* user, addr_t stack, size_t stacksize)
|
|
||||||
{
|
|
||||||
// Instead of directly calling the desired entry point, we call a small
|
|
||||||
// stub that calls it for us and then destroys the kernel thread if
|
|
||||||
// the entry function returns. Note that since we use a register based
|
|
||||||
// calling convention, we call BootstrapKernelThread directly.
|
|
||||||
regs->rip = (addr_t) BootstrapKernelThread;
|
|
||||||
regs->rsp = stack + stacksize - sizeof(size_t);
|
|
||||||
*((size_t*) regs->rsp) = 0; /* back tracing stops at NULL rip */
|
|
||||||
regs->rax = 0;
|
|
||||||
regs->rbx = 0;
|
|
||||||
regs->rcx = 0;
|
|
||||||
regs->rdx = 0;
|
|
||||||
regs->rdi = (addr_t) user;
|
|
||||||
regs->rsi = (addr_t) entry;
|
|
||||||
regs->rbp = 0;
|
|
||||||
regs->r8 = 0;
|
|
||||||
regs->r9 = 0;
|
|
||||||
regs->r10 = 0;
|
|
||||||
regs->r11 = 0;
|
|
||||||
regs->r12 = 0;
|
|
||||||
regs->r13 = 0;
|
|
||||||
regs->r14 = 0;
|
|
||||||
regs->r15 = 0;
|
|
||||||
regs->cs = KCS | KRPL;
|
|
||||||
regs->ds = KDS | KRPL;
|
|
||||||
regs->ss = KDS | KRPL;
|
|
||||||
regs->rflags = FLAGS_RESERVED1 | FLAGS_INTERRUPT | FLAGS_ID;
|
|
||||||
regs->kerrno = 0;
|
|
||||||
regs->signal_pending = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace Sortix
|
|
|
@ -90,12 +90,3 @@ kthread_mutex_unlock:
|
||||||
leavel
|
leavel
|
||||||
retl
|
retl
|
||||||
.size kthread_mutex_lock_signal, . - kthread_mutex_lock_signal
|
.size kthread_mutex_lock_signal, . - kthread_mutex_lock_signal
|
||||||
|
|
||||||
.global asm_call_BootstrapKernelThread
|
|
||||||
.type asm_call_BootstrapKernelThread, @function
|
|
||||||
asm_call_BootstrapKernelThread:
|
|
||||||
pushl %esi
|
|
||||||
pushl %edi
|
|
||||||
call BootstrapKernelThread
|
|
||||||
# BootstrapKernelThread is noreturn, no need for code here.
|
|
||||||
.size asm_call_BootstrapKernelThread, . - asm_call_BootstrapKernelThread
|
|
||||||
|
|
|
@ -1,99 +0,0 @@
|
||||||
/*******************************************************************************
|
|
||||||
|
|
||||||
Copyright(C) Jonas 'Sortie' Termansen 2011, 2012, 2014.
|
|
||||||
|
|
||||||
This file is part of Sortix.
|
|
||||||
|
|
||||||
Sortix is free software: you can redistribute it and/or modify it under the
|
|
||||||
terms of the GNU General Public License as published by the Free Software
|
|
||||||
Foundation, either version 3 of the License, or (at your option) any later
|
|
||||||
version.
|
|
||||||
|
|
||||||
Sortix is distributed in the hope that it will be useful, but WITHOUT ANY
|
|
||||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
|
||||||
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
|
||||||
details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License along with
|
|
||||||
Sortix. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
|
|
||||||
x86/thread.cpp
|
|
||||||
x86 specific parts of thread.cpp.
|
|
||||||
|
|
||||||
*******************************************************************************/
|
|
||||||
|
|
||||||
#include <stddef.h>
|
|
||||||
#include <stdint.h>
|
|
||||||
|
|
||||||
#include <sortix/kernel/kernel.h>
|
|
||||||
#include <sortix/kernel/thread.h>
|
|
||||||
|
|
||||||
namespace Sortix {
|
|
||||||
|
|
||||||
void Thread::SaveRegisters(const CPU::InterruptRegisters* src)
|
|
||||||
{
|
|
||||||
registers.eip = src->eip;
|
|
||||||
registers.esp = src->esp;
|
|
||||||
registers.eax = src->eax;
|
|
||||||
registers.ebx = src->ebx;
|
|
||||||
registers.ecx = src->ecx;
|
|
||||||
registers.edx = src->edx;
|
|
||||||
registers.edi = src->edi;
|
|
||||||
registers.esi = src->esi;
|
|
||||||
registers.ebp = src->ebp;
|
|
||||||
registers.cs = src->cs;
|
|
||||||
registers.ds = src->ds;
|
|
||||||
registers.ss = src->ss;
|
|
||||||
registers.eflags = src->eflags;
|
|
||||||
registers.kerrno = src->kerrno;
|
|
||||||
registers.signal_pending = src->signal_pending;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Thread::LoadRegisters(CPU::InterruptRegisters* dest)
|
|
||||||
{
|
|
||||||
dest->eip = registers.eip;
|
|
||||||
dest->esp = registers.esp;
|
|
||||||
dest->eax = registers.eax;
|
|
||||||
dest->ebx = registers.ebx;
|
|
||||||
dest->ecx = registers.ecx;
|
|
||||||
dest->edx = registers.edx;
|
|
||||||
dest->edi = registers.edi;
|
|
||||||
dest->esi = registers.esi;
|
|
||||||
dest->ebp = registers.ebp;
|
|
||||||
dest->cs = registers.cs;
|
|
||||||
dest->ds = registers.ds;
|
|
||||||
dest->ss = registers.ss;
|
|
||||||
dest->eflags = registers.eflags;
|
|
||||||
dest->kerrno = registers.kerrno;
|
|
||||||
dest->signal_pending = registers.signal_pending;
|
|
||||||
}
|
|
||||||
|
|
||||||
extern "C" void asm_call_BootstrapKernelThread(void);
|
|
||||||
|
|
||||||
void SetupKernelThreadRegs(CPU::InterruptRegisters* regs, ThreadEntry entry,
|
|
||||||
void* user, addr_t stack, size_t stacksize)
|
|
||||||
{
|
|
||||||
// Instead of directly calling the desired entry point, we call a small
|
|
||||||
// stub that calls it for us and then destroys the kernel thread if
|
|
||||||
// the entry function returns. Note that since we use a stack based
|
|
||||||
// calling convention, we go through a proxy that uses %edi and %esi
|
|
||||||
// as parameters and pushes them to the stack and then does the call.
|
|
||||||
regs->eip = (addr_t) asm_call_BootstrapKernelThread;
|
|
||||||
regs->esp = stack + stacksize - sizeof(size_t);
|
|
||||||
*((size_t*) regs->esp) = 0; /* back tracing stops at NULL rip */
|
|
||||||
regs->eax = 0;
|
|
||||||
regs->ebx = 0;
|
|
||||||
regs->ecx = 0;
|
|
||||||
regs->edx = 0;
|
|
||||||
regs->edi = (addr_t) user;
|
|
||||||
regs->esi = (addr_t) entry;
|
|
||||||
regs->ebp = 0;
|
|
||||||
regs->cs = KCS | KRPL;
|
|
||||||
regs->ds = KDS | KRPL;
|
|
||||||
regs->ss = KDS | KRPL;
|
|
||||||
regs->eflags = FLAGS_RESERVED1 | FLAGS_INTERRUPT | FLAGS_ID;
|
|
||||||
regs->kerrno = 0;
|
|
||||||
regs->signal_pending = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace Sortix
|
|
Loading…
Reference in a new issue