Skip to content

Commit

Permalink
Simplified clone, removed thread children, musl 1.1.24 support
Browse files Browse the repository at this point in the history
  • Loading branch information
fwsGonzo committed Feb 9, 2020
1 parent 2ce2f94 commit 9ceff78
Show file tree
Hide file tree
Showing 14 changed files with 227 additions and 205 deletions.
34 changes: 16 additions & 18 deletions api/kernel/threads.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,20 +16,18 @@
namespace kernel
{
struct Thread {
long tid;
int tid;
bool migrated = false;
bool yielded = false;
Thread* parent;
void* my_tls;
void* my_stack;
// for returning to this Thread
void* stored_stack = nullptr;
bool migrated = false;
bool yielded = false;
// address zeroed when exiting
void* clear_tid = nullptr;
// children, detached when exited
std::vector<Thread*> children;

void init(long tid, Thread* parent, void* stack);
void init(int tid, Thread* parent, void* stack);
void exit();
void suspend(bool yielded, void* ret_stack);
void set_tls(void* newtls);
Expand All @@ -43,7 +41,7 @@ namespace kernel

struct ThreadManager
{
std::map<long, kernel::Thread*> threads;
std::map<int, kernel::Thread*> threads;
std::deque<Thread*> suspended;
Thread* main_thread = nullptr;
Thread* next_thread = nullptr;
Expand All @@ -53,10 +51,10 @@ namespace kernel
static ThreadManager& get() noexcept;
static ThreadManager& get(int cpu);

Thread* detach(long tid);
Thread* detach(int tid);
void attach(Thread* thread);

bool has_thread(long tid) const noexcept { return threads.find(tid) != threads.end(); }
bool has_thread(int tid) const noexcept { return threads.find(tid) != threads.end(); }
void insert_thread(Thread* thread);
void erase_thread_safely(Thread* thread);

Expand All @@ -70,36 +68,36 @@ namespace kernel
{
Thread* thread;
# ifdef ARCH_x86_64
asm("movq %%fs:(0x10), %0" : "=r" (thread));
asm("movq %%fs:(48), %0" : "=r" (thread));
# elif defined(ARCH_i686)
asm("movq %%gs:(0x08), %0" : "=r" (thread));
asm("movq %%gs:(24), %0" : "=r" (thread));
# elif defined(ARCH_aarch64)
// TODO: fixme, find actual TP offset for aarch64 threads
char* tp;
asm("mrs %0, tpidr_el0" : "=r" (tp));
thread = (Thread*) &tp[0x10];
thread = (Thread*) &tp[48];
# else
#error "Implement me"
# endif
return thread;
}

Thread* get_thread(long tid); /* or nullptr */
Thread* get_thread(int tid); /* or nullptr */

inline long get_tid() {
inline int get_tid() {
return get_thread()->tid;
}

long get_last_thread_id() noexcept;
int get_last_thread_id() noexcept;

void* get_thread_area();
void set_thread_area(void*);

Thread* thread_create(Thread* parent, int flags, void* ctid, void* ptid, void* stack) noexcept;
Thread* thread_create(Thread* parent, long flags, void* ctid, void* ptid, void* stack) noexcept;

void resume(long tid);
void resume(int tid);

Thread* setup_main_thread(long tid = 0);
Thread* setup_main_thread(int tid = 0);
void setup_automatic_thread_multiprocessing();
}

Expand Down
1 change: 1 addition & 0 deletions src/arch/x86_64/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ set(ARCH_OBJECTS
apic_asm.asm
apic_longmode.asm
arch_start.asm
clone.cpp
exceptions.asm
interrupts.asm
fiber_asm.asm
Expand Down
113 changes: 0 additions & 113 deletions src/arch/x86_64/__syscall_entry.asm
Original file line number Diff line number Diff line change
@@ -1,61 +1,8 @@
global __syscall_entry:function
global __clone_helper:function
global __clone_return:function
global __migrate_resume:function
extern syscall_entry

;; x86_64 / System V ABI calling convention
%define arg1 rdi
%define arg2 rsi
%define arg3 rdx
%define arg4 rcx
%define arg5 r8
%define arg6 r9

%macro PUSHAQ 0
;;push rax
push rcx
push rdx
push rdi
push rsi
push r8
push r9
push r10
push r11
;; extra
push rbx
push rbp
push r12
push r13
push r14
push r15
%endmacro
%macro POPAQ 0
pop r15
pop r14
pop r13
pop r12
pop rbp
pop rbx
;; ^ extra
pop r11
pop r10
pop r9
pop r8
pop rsi
pop rdi
pop rdx
pop rcx
;;pop rax
%endmacro


SECTION .text
__syscall_entry:
;; clone syscall
cmp rax, 56
je __clone_helper

;; store return address
push rcx
;; Convert back from syscall conventions
Expand All @@ -70,63 +17,3 @@ __syscall_entry:
;; return to rcx
pop rcx
jmp QWORD rcx

__clone_helper:
PUSHAQ
sub rsp, 0x8 ;; alignment

;; R13: thread callback
push r9
;; R12: old stack
push rsp
;; r11: temp nexti
mov r11, rcx
;; R9: TLS data
mov r9, r8
;; R8: void* ctid
mov r8, r10
;; RCX: void* ptid
mov rcx, rdx
;; RDX: void* stack
mov rdx, rsi
;; RSI: unsigned long flags
mov rsi, rdi
;; RDI: next instruction
mov rdi, r11

;; call clone so that kernel can create the thread data
extern syscall_clone
call syscall_clone
;; remove old rsp
add rsp, 0x18
__clone_resume:
;; return value preserved
POPAQ
PUSHAQ
push rbp
push rax ;; store thread id

;; switch stack
mov rsp, rsi
;; zero return value
xor rax, rax
;; return back
jmp QWORD rcx

__clone_return:
mov rsp, rdi

pop rax ;; restore thread id
pop rbp
POPAQ
;;
jmp QWORD rcx

__migrate_resume:
mov rsp, rdi

;; restore saved registers
POPAQ
;; rax zero (child thread)
xor rax, rax
jmp QWORD rcx
70 changes: 70 additions & 0 deletions src/arch/x86_64/clone.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
#include <arch/x86/cpu.hpp>
#include <kernel/threads.hpp>
#include <os.hpp>
#include <common>
#include <kprint>

extern "C" {
long syscall_SYS_set_thread_area(void* u_info);
void __clone_return(void* stack);
}

extern "C"
long clone_helper(
void* callback,
void* stack,
unsigned long flags,
void* userdata,
void* ptid,
void* newtls,
void* ctid,
void* old_stack)
{
// NOTE: using printf is completely forbidden in this function
auto* parent = kernel::get_thread();

auto* thread = kernel::thread_create(parent, flags, ctid, ptid, stack);

//#define VERBOSE_CLONE_FUNCTION
#ifdef VERBOSE_CLONE_FUNCTION
extern int __thread_list_lock;
kprintf("clone syscall creating thread %d\n", thread->tid);
kprintf("-> callback: %p\n", callback);
kprintf("-> stack: %p\n", stack);
kprintf("-> flags: %#lx\n", flags);
kprintf("-> argument: %p\n", userdata);
kprintf("-> ptid: %p\n", ptid);
kprintf("-> ctid: %p vs %p\n", ctid, nullptr);
kprintf("-> tls: %p vs %p\n", newtls, *(void**) newtls);
kprintf("-> old thread: %p\n", parent);
kprintf("-> old stack: %p\n", old_stack);
kprintf("-> old tls: %p (%p)\n", kernel::get_thread_area(), parent->my_tls);
#endif

// write tid on the top of the old stack (for parent)
*(uintptr_t*) old_stack = thread->tid;
//*(int*) ctid = thread->tid;

// set TLS location (and set self)
thread->set_tls(newtls);

auto& tman = kernel::ThreadManager::get();
if (tman.on_new_thread != nullptr) {
// potentially get child stolen by migration callback
thread = tman.on_new_thread(tman, thread);
}

if (thread) {
THPRINT("Suspending parent thread %p tid=%d stack=%p and entering %d\n",
parent, parent->tid, old_stack, thread->tid);
// suspend parent thread (not yielded)
parent->suspend(false, old_stack);
// continue on child
kernel::set_thread_area(thread->my_tls);
return thread->tid;
}
THPRINT("Returning to parent thread stack=%p\n", old_stack);
// continue with parent
__clone_return(old_stack);
__builtin_unreachable();
}
Loading

0 comments on commit 9ceff78

Please sign in to comment.