diff --git a/definitions/objects/thread.def b/definitions/objects/thread.def index 1d5fab8..9113ae1 100644 --- a/definitions/objects/thread.def +++ b/definitions/objects/thread.def @@ -2,6 +2,8 @@ object thread : kobject { uid 11f23e593d5761bd method create [constructor] { + param process object process + param stack_top address param entrypoint address } diff --git a/src/kernel/objects/process.cpp b/src/kernel/objects/process.cpp index 300e601..e908091 100644 --- a/src/kernel/objects/process.cpp +++ b/src/kernel/objects/process.cpp @@ -86,7 +86,7 @@ process::update() } thread * -process::create_thread(uint8_t priority, bool user) +process::create_thread(uintptr_t rsp3, uint8_t priority) { if (priority == default_priority) priority = scheduler::default_priority; @@ -94,17 +94,8 @@ process::create_thread(uint8_t priority, bool user) thread *th = new thread(*this, priority); kassert(th, "Failed to create thread!"); - if (user) { - uintptr_t stack_top = stacks_top - (m_threads.count() * stack_size); - - vm_flags flags = vm_flags::zero|vm_flags::write; - vm_area *vma = new vm_area_open(stack_size, flags); - m_space.add(stack_top - stack_size, vma); - - // Space for null frame - because the page gets zeroed on - // allocation, just pointing rsp here does the trick - th->tcb()->rsp3 = stack_top - 2 * sizeof(uint64_t); - } + if (rsp3) + th->tcb()->rsp3 = rsp3; m_threads.append(th); scheduler::get().add_thread(th->tcb()); diff --git a/src/kernel/objects/process.h b/src/kernel/objects/process.h index f1586cb..7fcdf0c 100644 --- a/src/kernel/objects/process.h +++ b/src/kernel/objects/process.h @@ -43,10 +43,10 @@ public: vm_space & space() { return m_space; } /// Create a new thread in this process + /// \args rsp3 If non-zero, sets the ring3 stack pointer to this value /// \args priority The new thread's scheduling priority - /// \args user If true, create a userspace stack for this thread /// \returns The newly created thread object - thread * create_thread(uint8_t priorty = default_priority, bool user = true); + thread * create_thread(uintptr_t rsp3 = 0, uint8_t priorty = default_priority); /// Start tracking an object with a handle. /// \args obj The object this handle refers to diff --git a/src/kernel/objects/thread.cpp b/src/kernel/objects/thread.cpp index 473486d..d363272 100644 --- a/src/kernel/objects/thread.cpp +++ b/src/kernel/objects/thread.cpp @@ -172,14 +172,15 @@ thread::add_thunk_user(uintptr_t rip3, uintptr_t rip0, uint64_t flags) // b) come out of the kernel/user trampoline and start executing // in user mode at rip - m_tcb.rsp -= sizeof(uintptr_t) * 8; - uintptr_t *stack = reinterpret_cast(m_tcb.rsp); flags |= 0x200; + m_tcb.rflags3 = flags; - stack[7] = rip3; // return rip in rcx - stack[6] = m_tcb.rsp3; // rbp - stack[5] = 0xbbbbbbbb; // rbx - stack[4] = flags; // r11 sets RFLAGS + m_tcb.rsp -= sizeof(uintptr_t) * 7; + uintptr_t *stack = reinterpret_cast(m_tcb.rsp); + + stack[6] = rip3; // return rip in rcx + stack[5] = m_tcb.rsp3; // rbp + stack[4] = 0xbbbbbbbb; // rbx stack[3] = 0x12121212; // r12 stack[2] = 0x13131313; // r13 stack[1] = 0x14141414; // r14 diff --git a/src/kernel/scheduler.cpp b/src/kernel/scheduler.cpp index 592cc31..f042360 100644 --- a/src/kernel/scheduler.cpp +++ b/src/kernel/scheduler.cpp @@ -70,7 +70,7 @@ inline T * push(uintptr_t &rsp, size_t size = sizeof(T)) { void scheduler::create_kernel_task(void (*task)(), uint8_t priority, bool constant) { - thread *th = process::kernel_process().create_thread(priority, false); + thread *th = process::kernel_process().create_thread(0, priority); auto *tcb = th->tcb(); th->add_thunk_kernel(reinterpret_cast(task)); diff --git a/src/kernel/syscalls/thread.cpp b/src/kernel/syscalls/thread.cpp index 52a2633..242c393 100644 --- a/src/kernel/syscalls/thread.cpp +++ b/src/kernel/syscalls/thread.cpp @@ -9,19 +9,22 @@ namespace syscalls { j6_status_t -thread_create(j6_handle_t *handle, uintptr_t entrypoint) +thread_create(j6_handle_t *handle, j6_handle_t proc, uintptr_t stack_top, uintptr_t entrypoint) { - thread &parent = thread::current(); - process &p = parent.parent(); + thread &parent_th = thread::current(); + process &parent_pr = parent_th.parent(); - thread *child = p.create_thread(); + process *owner = get_handle(proc); + if (!owner) return j6_err_invalid_arg; + + thread *child = owner->create_thread(stack_top); child->add_thunk_user(entrypoint); *handle = child->self_handle(); child->clear_state(thread::state::loading); child->set_state(thread::state::ready); - log::debug(logs::task, "Thread %llx spawned new thread %llx, handle %d", - parent.koid(), child->koid(), *handle); + log::debug(logs::task, "Thread %llx:%llx spawned new thread %llx:%llx", + parent_pr.koid(), parent_th.koid(), owner->koid(), child->koid()); return j6_status_ok; }