Skip to content

Commit

Permalink
Libuser: save main thread's handle in TLS
Browse files Browse the repository at this point in the history
Create a special TLS context for the main thread, which lives
in the `.data`, put its thread handle there, and make its
TLS region point to it.
  • Loading branch information
Orycterope committed Jun 17, 2019
1 parent d1b9b6f commit 145e24c
Show file tree
Hide file tree
Showing 2 changed files with 47 additions and 4 deletions.
14 changes: 10 additions & 4 deletions libuser/src/crt0/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,6 @@
//! This module is a minimal RT0 handling the entry point of the application.
//! It handles relocation, clean the bss and then finally call start_main.
use core::ptr;

mod relocation;

/// Executable entrypoint. Handle relocations and calls real_start.
Expand All @@ -23,6 +21,10 @@ pub unsafe extern fn start() {
_start_shim:
pop eax
// Save our thread handle passed by the kernel
// `esi` is callee-saved
mov esi, ecx
// Save eip_pos address
mov ecx, eax
Expand All @@ -42,6 +44,10 @@ pub unsafe extern fn start() {
push ebx
call clean_bss
// Init TLS
push esi
call init_main_thread
call real_start
");
}
Expand All @@ -59,5 +65,5 @@ pub unsafe extern fn clean_bss(module_header: *const relocation::ModuleHeader) {
let bss_end_address = module_header_address.add(module_header.bss_end_off as usize) as *mut u8;

let count = bss_end_address as usize - bss_start_address as usize;
ptr::write_bytes(bss_start_address, 0, count);
}
core::ptr::write_bytes(bss_start_address, 0, count);
}
37 changes: 37 additions & 0 deletions libuser/src/threads.rs
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,27 @@ impl fmt::Debug for ThreadContext {
}
}

/// Context of the main thread. Instead of allocating it at startup, this one lives in the `.data`.
///
/// The handle of the main thread is stored to it at startup.
///
/// ## Mock values:
///
/// Because the main thread is started by the kernel and not libuser, we don't have control or
/// even knowledge of most of the fields that should be in our context. Because of this, we choose
/// to put mock values instead.
/// This includes:
///
/// * `.entry_point`: unused, we are started by the kernel
/// * `.arg`: unused
/// * `.stack`: our stack is not allocated by us, and we don't know its size.
static MAIN_THREAD_CONTEXT: ThreadContext = ThreadContext {
entry_point: |_| { },
arg: 0,
stack: None,
thread_handle: Once::new(), // will be initialized at startup.
};

/// Get a pointer to this thread's [TLS] region pointed to by `gs`, translated to the flat-memory model.
#[inline]
fn get_my_tls_region() -> *mut TLS {
Expand Down Expand Up @@ -230,3 +251,19 @@ impl Drop for Thread {
// body: when the main thread (or the last thread alive?) exits.
}
}

/// Initialisation of the main thread's thread local structures:
///
/// When a main thread starts, the kernel puts the handle of its own thread in one of its registers.
/// The main thread should perform relocations, and then call this function, which will:
///
/// * put the main thread's handle in [MAIN_THREAD_CONTEXT].
/// * save a pointer to it in its [TLS].
/// * perform copy of `.tdata` and `.tbss` for the main thread.
#[no_mangle] // called from asm
pub extern fn init_main_thread(handle: ThreadHandle) {
// save the handle in our context
MAIN_THREAD_CONTEXT.thread_handle.call_once(|| handle);
// save the address of our context in our TLS region
unsafe { (*get_my_tls_region()).ptr_thread_context = &MAIN_THREAD_CONTEXT as *const ThreadContext as usize };
}

0 comments on commit 145e24c

Please sign in to comment.