Correctly set up TLS on Redox and other fixes for pthread_clone
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
//! dl-tls implementation for Redox
|
||||
|
||||
use ld_so::tcb::Tcb;
|
||||
use platform::types::*;
|
||||
|
||||
#[repr(C)]
|
||||
|
||||
+2
-2
@@ -199,7 +199,7 @@ impl Linker {
|
||||
if let Some(name_res) = elf.dynstrtab.get(sym.st_name) {
|
||||
let name = name_res?;
|
||||
let value = mmap.as_ptr() as usize + sym.st_value as usize;
|
||||
//println!(" global {}: {:x?} = {:#x}", name, sym, value);
|
||||
// println!(" global {}: {:x?} = {:#x}", name, sym, value);
|
||||
globals.insert(name, value);
|
||||
}
|
||||
}
|
||||
@@ -356,7 +356,7 @@ impl Linker {
|
||||
};
|
||||
|
||||
let set_u64 = |value| {
|
||||
//println!(" set_u64 {:#x}", value);
|
||||
// println!(" set_u64 {:#x}", value);
|
||||
unsafe { *(ptr as *mut u64) = value; }
|
||||
};
|
||||
|
||||
|
||||
+14
-11
@@ -3,7 +3,7 @@ use core::{mem, ptr, slice};
|
||||
use core::ops::Range;
|
||||
use goblin::error::{Error, Result};
|
||||
|
||||
use header::sys_mman;
|
||||
use header::{sys_mman, unistd};
|
||||
|
||||
use super::PAGE_SIZE;
|
||||
|
||||
@@ -36,17 +36,17 @@ impl Master {
|
||||
#[repr(C)]
|
||||
pub struct Tcb {
|
||||
/// Pointer to the end of static TLS. Must be the first member
|
||||
tls_end: *mut u8,
|
||||
pub tls_end: *mut u8,
|
||||
/// Size of the memory allocated for the static TLS in bytes (multiple of PAGE_SIZE)
|
||||
tls_len: usize,
|
||||
pub tls_len: usize,
|
||||
/// Pointer to this structure
|
||||
tcb_ptr: *mut Tcb,
|
||||
pub tcb_ptr: *mut Tcb,
|
||||
/// Size of the memory allocated for this structure in bytes (should be PAGE_SIZE)
|
||||
tcb_len: usize,
|
||||
pub tcb_len: usize,
|
||||
/// Pointer to a list of initial TLS data
|
||||
masters_ptr: *mut Master,
|
||||
pub masters_ptr: *mut Master,
|
||||
/// Size of the masters list in bytes (multiple of mem::size_of::<Master>())
|
||||
masters_len: usize,
|
||||
pub masters_len: usize,
|
||||
}
|
||||
|
||||
impl Tcb {
|
||||
@@ -55,7 +55,7 @@ impl Tcb {
|
||||
let (tls, tcb_page) = Self::os_new(size)?;
|
||||
|
||||
let tcb_ptr = tcb_page.as_mut_ptr() as *mut Self;
|
||||
ptr::write(tcb_ptr, Tcb {
|
||||
ptr::write(tcb_ptr, Self {
|
||||
tls_end: tls.as_mut_ptr().add(tls.len()),
|
||||
tls_len: tls.len(),
|
||||
tcb_ptr: tcb_ptr,
|
||||
@@ -171,11 +171,14 @@ impl Tcb {
|
||||
/// OS specific code to create a new TLS and TCB - Redox
|
||||
#[cfg(target_os = "redox")]
|
||||
unsafe fn os_new(size: usize) -> Result<(&'static mut [u8], &'static mut [u8])> {
|
||||
//TODO: better method of finding fs offset
|
||||
let pid = unistd::getpid();
|
||||
let tcb_addr = 0xB000_0000 + pid as usize * PAGE_SIZE;
|
||||
let tls = Self::map(size)?;
|
||||
Ok((
|
||||
tls,
|
||||
//TODO: Consider allocating TCB as part of TLS
|
||||
slice::from_raw_parts_mut(0xB000_0000 as *mut u8, PAGE_SIZE)
|
||||
slice::from_raw_parts_mut(tcb_addr as *mut u8, PAGE_SIZE)
|
||||
))
|
||||
}
|
||||
|
||||
@@ -185,10 +188,10 @@ impl Tcb {
|
||||
unsafe fn arch_read(offset: usize) -> usize {
|
||||
let value;
|
||||
asm!("
|
||||
mov rax, [fs:rdi]
|
||||
mov rax, fs:[rdi]
|
||||
"
|
||||
: "={rax}"(value)
|
||||
: "{rax}"(offset)
|
||||
: "{rdi}"(offset)
|
||||
:
|
||||
: "intel"
|
||||
);
|
||||
|
||||
@@ -343,9 +343,16 @@ impl Pal for Sys {
|
||||
test rax, rax
|
||||
jnz .parent
|
||||
|
||||
# Call entry point
|
||||
pop rdi
|
||||
# Load registers
|
||||
pop rax
|
||||
pop rdi
|
||||
pop rsi
|
||||
pop rdx
|
||||
pop rcx
|
||||
pop r8
|
||||
pop r9
|
||||
|
||||
# Call entry point
|
||||
call rax
|
||||
|
||||
# Exit
|
||||
|
||||
+64
-34
@@ -7,6 +7,7 @@ use core::{intrinsics, ptr};
|
||||
|
||||
use header::sys_mman;
|
||||
use header::time::timespec;
|
||||
use ld_so::tcb::{Tcb, Master};
|
||||
use mutex::{FUTEX_WAIT, FUTEX_WAKE};
|
||||
use platform::types::{c_int, c_uint, c_void, pid_t, size_t};
|
||||
use platform::{Pal, Sys};
|
||||
@@ -58,6 +59,27 @@ pub unsafe extern "C" fn pte_osInit() -> pte_osResult {
|
||||
PTE_OS_OK
|
||||
}
|
||||
|
||||
/// A shim to wrap thread entry points in logic to set up TLS, for example
|
||||
unsafe extern "C" fn pte_osThreadShim(
|
||||
entryPoint: pte_osThreadEntryPoint,
|
||||
argv: *mut c_void,
|
||||
mutex: pte_osMutexHandle,
|
||||
tls_size: usize,
|
||||
tls_masters_ptr: *mut Master,
|
||||
tls_masters_len: usize
|
||||
) {
|
||||
let mut tcb = Tcb::new(tls_size).unwrap();
|
||||
tcb.masters_ptr = tls_masters_ptr;
|
||||
tcb.masters_len = tls_masters_len;
|
||||
tcb.copy_masters().unwrap();
|
||||
tcb.activate();
|
||||
|
||||
// Wait until pte_osThreadStart
|
||||
pte_osMutexLock(mutex);
|
||||
entryPoint(argv);
|
||||
pte_osThreadExit();
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn pte_osThreadCreate(
|
||||
entryPoint: pte_osThreadEntryPoint,
|
||||
@@ -66,6 +88,9 @@ pub unsafe extern "C" fn pte_osThreadCreate(
|
||||
argv: *mut c_void,
|
||||
ppte_osThreadHandle: *mut pte_osThreadHandle,
|
||||
) -> pte_osResult {
|
||||
// Create a locked mutex, unlocked by pte_osThreadStart
|
||||
let mutex: pte_osMutexHandle = Box::into_raw(Box::new(2));
|
||||
|
||||
let stack_size = if stackSize == 0 {
|
||||
1024 * 1024
|
||||
} else {
|
||||
@@ -85,45 +110,50 @@ pub unsafe extern "C" fn pte_osThreadCreate(
|
||||
let stack_end = stack_base.add(stack_size);
|
||||
let mut stack = stack_end as *mut usize;
|
||||
{
|
||||
stack = stack.offset(-1);
|
||||
*stack = entryPoint as usize;
|
||||
let mut push = |value: usize| {
|
||||
stack = stack.offset(-1);
|
||||
*stack = value;
|
||||
};
|
||||
|
||||
stack = stack.offset(-1);
|
||||
*stack = argv as usize;
|
||||
}
|
||||
|
||||
// Create a locked mutex, unlocked by pte_osThreadStart
|
||||
let mutex = Box::into_raw(Box::new(2));
|
||||
{
|
||||
let id = Sys::pte_clone(stack);
|
||||
if id < 0 {
|
||||
return PTE_OS_GENERAL_FAILURE;
|
||||
}
|
||||
|
||||
if id == 0 {
|
||||
// Wait until pte_osThreadStart
|
||||
pte_osMutexLock(mutex);
|
||||
entryPoint(argv);
|
||||
pte_osThreadExit();
|
||||
if let Some(tcb) = Tcb::current() {
|
||||
push(tcb.masters_len);
|
||||
push(tcb.masters_ptr as usize);
|
||||
push(tcb.tls_len);
|
||||
} else {
|
||||
pte_osMutexLock(&mut pid_mutexes_lock);
|
||||
if pid_mutexes.is_none() {
|
||||
pid_mutexes = Some(BTreeMap::new());
|
||||
}
|
||||
pid_mutexes.as_mut().unwrap().insert(id, mutex);
|
||||
pte_osMutexUnlock(&mut pid_mutexes_lock);
|
||||
|
||||
pte_osMutexLock(&mut pid_stacks_lock);
|
||||
if pid_stacks.is_none() {
|
||||
pid_stacks = Some(BTreeMap::new());
|
||||
}
|
||||
pid_stacks.as_mut().unwrap().insert(id, (stack_base, stack_size));
|
||||
pte_osMutexUnlock(&mut pid_stacks_lock);
|
||||
|
||||
*ppte_osThreadHandle = id;
|
||||
push(0);
|
||||
push(0);
|
||||
push(0);
|
||||
}
|
||||
|
||||
push(mutex as usize);
|
||||
|
||||
push(argv as usize);
|
||||
push(entryPoint as usize);
|
||||
|
||||
push(pte_osThreadShim as usize);
|
||||
}
|
||||
|
||||
let id = Sys::pte_clone(stack);
|
||||
if id < 0 {
|
||||
return PTE_OS_GENERAL_FAILURE;
|
||||
}
|
||||
|
||||
pte_osMutexLock(&mut pid_mutexes_lock);
|
||||
if pid_mutexes.is_none() {
|
||||
pid_mutexes = Some(BTreeMap::new());
|
||||
}
|
||||
pid_mutexes.as_mut().unwrap().insert(id, mutex);
|
||||
pte_osMutexUnlock(&mut pid_mutexes_lock);
|
||||
|
||||
pte_osMutexLock(&mut pid_stacks_lock);
|
||||
if pid_stacks.is_none() {
|
||||
pid_stacks = Some(BTreeMap::new());
|
||||
}
|
||||
pid_stacks.as_mut().unwrap().insert(id, (stack_base, stack_size));
|
||||
pte_osMutexUnlock(&mut pid_stacks_lock);
|
||||
|
||||
*ppte_osThreadHandle = id;
|
||||
|
||||
PTE_OS_OK
|
||||
}
|
||||
|
||||
|
||||
@@ -832,9 +832,16 @@ impl Pal for Sys {
|
||||
test rax, rax
|
||||
jnz .parent
|
||||
|
||||
# Call entry point
|
||||
pop rdi
|
||||
# Load registers
|
||||
pop rax
|
||||
pop rdi
|
||||
pop rsi
|
||||
pop rdx
|
||||
pop rcx
|
||||
pop r8
|
||||
pop r9
|
||||
|
||||
# Call entry point
|
||||
call rax
|
||||
|
||||
# Exit
|
||||
|
||||
Reference in New Issue
Block a user