Utilize ThreadLocal

This commit is contained in:
Ruihan Li
2024-12-01 09:19:03 +08:00
committed by Tate, Hongliang Tian
parent 38fcaaf749
commit 0bfe7aceb8
13 changed files with 186 additions and 122 deletions

View File

@ -90,9 +90,9 @@ fn do_execve(
) -> Result<()> {
let Context {
process,
thread_local,
posix_thread,
thread: _,
task: _,
..
} = ctx;
let executable_path = elf_file.abs_path();
@ -107,7 +107,7 @@ fn do_execve(
Some(ThreadName::new_from_executable_path(&executable_path)?);
// clear ctid
// FIXME: should we clear ctid when execve?
*posix_thread.clear_child_tid().lock() = 0;
thread_local.clear_child_tid().set(0);
// Ensure that the file descriptors with the close-on-exec flag are closed.
// FIXME: This is just wrong if the file table is shared with other processes.
@ -123,10 +123,10 @@ fn do_execve(
// After the program has been successfully loaded, the virtual memory of the current process
// is initialized. Hence, it is necessary to clear the previously recorded robust list.
*posix_thread.robust_list().lock() = None;
*thread_local.robust_list().borrow_mut() = None;
debug!("load elf in execve succeeds");
let credentials = ctx.posix_thread.credentials_mut();
let credentials = posix_thread.credentials_mut();
set_uid_from_elf(process, &credentials, &elf_file)?;
set_gid_from_elf(process, &credentials, &elf_file)?;
credentials.set_keep_capabilities(false);

View File

@ -9,16 +9,17 @@ use crate::{prelude::*, process::signal::c_types::ucontext_t};
pub fn sys_rt_sigreturn(ctx: &Context, user_ctx: &mut UserContext) -> Result<SyscallReturn> {
let Context {
process: _,
thread_local,
posix_thread,
thread: _,
task: _,
..
} = ctx;
let mut sig_context = posix_thread.sig_context().lock();
if (*sig_context).is_none() {
return_errno_with_message!(Errno::EINVAL, "sigreturn should not been called");
}
let sig_context_addr = sig_context.unwrap();
let Some(sig_context_addr) = thread_local.sig_context().get() else {
return_errno_with_message!(
Errno::EINVAL,
"`sigreturn` cannot be called outside the signal context"
);
};
// FIXME: This assertion is not always true, if RESTORER flag is not presented.
// In this case, we will put restorer code on user stack, then the assertion will fail.
// However, for most glibc applications, the restorer codes is provided by glibc and RESTORER flag is set.
@ -27,7 +28,7 @@ pub fn sys_rt_sigreturn(ctx: &Context, user_ctx: &mut UserContext) -> Result<Sys
let ucontext = ctx.user_space().read_val::<ucontext_t>(sig_context_addr)?;
// If the sig stack is active and used by current handler, decrease handler counter.
if let Some(sig_stack) = posix_thread.sig_stack().lock().as_mut() {
if let Some(sig_stack) = &mut *thread_local.sig_stack().borrow_mut() {
let rsp = user_ctx.stack_pointer();
if rsp >= sig_stack.base() && rsp <= sig_stack.base() + sig_stack.size() {
sig_stack.decrease_handler_counter();
@ -36,15 +37,16 @@ pub fn sys_rt_sigreturn(ctx: &Context, user_ctx: &mut UserContext) -> Result<Sys
// Set previous ucontext address
if ucontext.uc_link == 0 {
*sig_context = None;
thread_local.sig_context().set(None);
} else {
*sig_context = Some(ucontext.uc_link);
thread_local.sig_context().set(Some(ucontext.uc_link));
};
ucontext
.uc_mcontext
.inner
.gp_regs
.copy_to_raw(user_ctx.general_regs_mut());
// unblock sig mask
let sig_mask = ucontext.uc_sigmask;
let old_mask = posix_thread.sig_mask().load(Ordering::Relaxed);

View File

@ -12,15 +12,18 @@ pub fn sys_set_robust_list(
"robust list head ptr: 0x{:x}, len = {}",
robust_list_head_ptr, len
);
if len != core::mem::size_of::<RobustListHead>() {
return_errno_with_message!(
Errno::EINVAL,
"The len is not equal to the size of robust list head"
"the length is not equal to the size of the robust list head"
);
}
let robust_list_head: RobustListHead = ctx.user_space().read_val(robust_list_head_ptr)?;
debug!("{:x?}", robust_list_head);
let mut robust_list = ctx.posix_thread.robust_list().lock();
*robust_list = Some(robust_list_head);
debug!("robust list head: {:x?}", robust_list_head);
*ctx.thread_local.robust_list().borrow_mut() = Some(robust_list_head);
Ok(SyscallReturn::Return(0))
}

View File

@ -5,14 +5,16 @@ use crate::prelude::*;
pub fn sys_set_tid_address(tidptr: Vaddr, ctx: &Context) -> Result<SyscallReturn> {
debug!("tidptr = 0x{:x}", tidptr);
let mut clear_child_tid = ctx.posix_thread.clear_child_tid().lock();
if *clear_child_tid != 0 {
let clear_child_tid = ctx.thread_local.clear_child_tid().get();
if clear_child_tid != 0 {
// According to manuals at https://man7.org/linux/man-pages/man2/set_tid_address.2.html
// We need to write 0 to clear_child_tid and do futex wake
todo!()
} else {
*clear_child_tid = tidptr;
}
ctx.thread_local.set_child_tid().set(clear_child_tid);
let tid = ctx.posix_thread.tid();
Ok(SyscallReturn::Return(tid as _))
}

View File

@ -16,10 +16,7 @@ pub fn sys_sigaltstack(
sig_stack_addr, old_sig_stack_addr
);
let old_stack = {
let sig_stack = ctx.posix_thread.sig_stack().lock();
sig_stack.clone()
};
let old_stack = ctx.thread_local.sig_stack().borrow().clone();
get_old_stack(old_sig_stack_addr, old_stack.as_ref(), ctx)?;
set_new_stack(sig_stack_addr, old_stack.as_ref(), ctx)?;
@ -73,7 +70,7 @@ fn set_new_stack(sig_stack_addr: Vaddr, old_stack: Option<&SigStack>, ctx: &Cont
debug!("new_stack = {:?}", new_stack);
*ctx.posix_thread.sig_stack().lock() = Some(new_stack);
*ctx.thread_local.sig_stack().borrow_mut() = Some(new_stack);
Ok(())
}