mirror of
https://github.com/fish-shell/fish-shell.git
synced 2024-11-28 20:34:07 +08:00
Move thread stuff out of common.rs (#9745)
is_main_thread() and co were previously ported to threads.rs, so remove the duplicate code and move everything else related to threads there as well. No need for common.rs to be as long as our old common.cpp! I left #[deprecated] stubs in common.rs to help redirect anyone porting code over that we can remove after the port has finished. Additionally, the fork guards had previously been left as a todo!() item but I ported that over. They're all called from the now-central threads::init() function so there isn't a need to call each individual thread-management-fn manually. The decision was made a while back to try and embrace/use the native rust thread functionality and utilities so the manual thread management code has been ripped out and was replaced with code that marshals the native rust values instead. The values won't line up with what the C++ code sees, but it never lined up anyway since each was using a separate counter to keep track of the values.
This commit is contained in:
parent
30ae715183
commit
ff28f29e8f
|
@ -22,7 +22,6 @@ use cxx::{CxxWString, UniquePtr};
|
|||
use libc::{EINTR, EIO, O_WRONLY, SIGTTOU, SIG_IGN, STDERR_FILENO, STDIN_FILENO, STDOUT_FILENO};
|
||||
use num_traits::ToPrimitive;
|
||||
use once_cell::sync::Lazy;
|
||||
use std::cell::RefCell;
|
||||
use std::env;
|
||||
use std::ffi::{CString, OsString};
|
||||
use std::mem::{self, ManuallyDrop};
|
||||
|
@ -32,7 +31,7 @@ use std::os::unix::prelude::OsStringExt;
|
|||
use std::path::PathBuf;
|
||||
use std::rc::Rc;
|
||||
use std::str::FromStr;
|
||||
use std::sync::atomic::{AtomicI32, AtomicU32, AtomicU64, Ordering};
|
||||
use std::sync::atomic::{AtomicI32, AtomicU32, Ordering};
|
||||
use std::sync::Mutex;
|
||||
use std::time;
|
||||
use widestring_suffix::widestrs;
|
||||
|
@ -1201,34 +1200,14 @@ pub fn should_suppress_stderr_for_tests() -> bool {
|
|||
unsafe { !PROGRAM_NAME.is_empty() && *PROGRAM_NAME != TESTS_PROGRAM_NAME }
|
||||
}
|
||||
|
||||
fn assert_is_main_thread() {
|
||||
assert!(is_main_thread() || THREAD_ASSERTS_CFG_FOR_TESTING.load());
|
||||
#[deprecated(note = "Use threads::assert_is_main_thread() instead")]
|
||||
pub fn assert_is_main_thread() {
|
||||
crate::threads::assert_is_main_thread()
|
||||
}
|
||||
|
||||
fn assert_is_background_thread() {
|
||||
assert!(!is_main_thread() || THREAD_ASSERTS_CFG_FOR_TESTING.load());
|
||||
}
|
||||
|
||||
static THREAD_ASSERTS_CFG_FOR_TESTING: RelaxedAtomicBool = RelaxedAtomicBool::new(false);
|
||||
|
||||
thread_local! {
|
||||
static TL_TID: RefCell<u64> = RefCell::new(0);
|
||||
}
|
||||
|
||||
static S_LAST_THREAD_ID: AtomicU64 = AtomicU64::new(0);
|
||||
fn next_thread_id() -> u64 {
|
||||
// Note 0 is an invalid thread id.
|
||||
// Note fetch_add is a CAS which returns the value *before* the modification.
|
||||
1 + S_LAST_THREAD_ID.fetch_add(1, Ordering::Relaxed)
|
||||
}
|
||||
|
||||
fn thread_id() -> u64 {
|
||||
TL_TID.with(|tid| {
|
||||
if *tid.borrow() == 0 {
|
||||
*tid.borrow_mut() = next_thread_id()
|
||||
}
|
||||
*tid.borrow()
|
||||
})
|
||||
#[deprecated(note = "Use threads::assert_is_background_thread() instead")]
|
||||
pub fn assert_is_background_thread() {
|
||||
crate::threads::assert_is_background_thread()
|
||||
}
|
||||
|
||||
/// Format the specified size (in bytes, kilobytes, etc.) into the specified stringbuffer.
|
||||
|
@ -1584,32 +1563,29 @@ pub fn timef() -> Timepoint {
|
|||
}
|
||||
}
|
||||
|
||||
#[deprecated(note = "Use threads::is_main_thread() instead")]
|
||||
pub fn is_main_thread() -> bool {
|
||||
crate::threads::is_main_thread()
|
||||
}
|
||||
|
||||
/// Call the following function early in main to set the main thread. This is our replacement for
|
||||
/// pthread_main_np().
|
||||
#[deprecated(note = "This function is no longer called manually!")]
|
||||
pub fn set_main_thread() {
|
||||
// Just call thread_id() once to force increment of thread_id.
|
||||
let tid = thread_id();
|
||||
assert!(tid == 1, "main thread should have thread ID 1");
|
||||
}
|
||||
|
||||
pub fn is_main_thread() -> bool {
|
||||
thread_id() == 1
|
||||
eprintln!("set_main_thread() is removed in favor of `main_thread_id()` and co. in threads.rs!")
|
||||
}
|
||||
|
||||
#[deprecated(note = "Use threads::configure_thread_assertions_for_testing() instead")]
|
||||
pub fn configure_thread_assertions_for_testing() {
|
||||
THREAD_ASSERTS_CFG_FOR_TESTING.store(true)
|
||||
crate::threads::configure_thread_assertions_for_testing();
|
||||
}
|
||||
|
||||
/// This allows us to notice when we've forked.
|
||||
static IS_FORKED_PROC: RelaxedAtomicBool = RelaxedAtomicBool::new(false);
|
||||
|
||||
pub fn setup_fork_guards() {
|
||||
IS_FORKED_PROC.store(false);
|
||||
todo!();
|
||||
}
|
||||
#[deprecated(note = "This should no longer be called manually")]
|
||||
pub fn setup_fork_guards() {}
|
||||
|
||||
#[deprecated(note = "Use threads::is_forked_child() instead")]
|
||||
pub fn is_forked_child() -> bool {
|
||||
IS_FORKED_PROC.load()
|
||||
crate::threads::is_forked_child()
|
||||
}
|
||||
|
||||
/// Be able to restore the term's foreground process group.
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
//! ported directly from the cpp code so we can use rust threads instead of using pthreads.
|
||||
|
||||
use crate::flog::{FloggableDebug, FLOG};
|
||||
use std::sync::atomic::{AtomicBool, Ordering};
|
||||
use std::thread::{self, ThreadId};
|
||||
|
||||
impl FloggableDebug for ThreadId {}
|
||||
|
@ -16,6 +17,10 @@ impl FloggableDebug for ThreadId {}
|
|||
|
||||
/// The thread id of the main thread, as set by [`init()`] at startup.
|
||||
static mut MAIN_THREAD_ID: Option<ThreadId> = None;
|
||||
/// Used to bypass thread assertions when testing.
|
||||
static THREAD_ASSERTS_CFG_FOR_TESTING: AtomicBool = AtomicBool::new(false);
|
||||
/// This allows us to notice when we've forked.
|
||||
static IS_FORKED_PROC: AtomicBool = AtomicBool::new(false);
|
||||
|
||||
/// Initialize some global static variables. Must be called at startup from the main thread.
|
||||
pub fn init() {
|
||||
|
@ -25,6 +30,14 @@ pub fn init() {
|
|||
}
|
||||
MAIN_THREAD_ID = Some(thread::current().id());
|
||||
}
|
||||
|
||||
extern "C" fn child_post_fork() {
|
||||
IS_FORKED_PROC.store(true, Ordering::Relaxed);
|
||||
}
|
||||
unsafe {
|
||||
let result = libc::pthread_atfork(None, None, Some(child_post_fork));
|
||||
assert_eq!(result, 0, "pthread_atfork() failure: {}", errno::errno());
|
||||
}
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
|
@ -40,6 +53,11 @@ fn main_thread_id() -> ThreadId {
|
|||
}
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub fn is_main_thread() -> bool {
|
||||
thread::current().id() == main_thread_id()
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub fn assert_is_main_thread() {
|
||||
#[cold]
|
||||
|
@ -47,7 +65,7 @@ pub fn assert_is_main_thread() {
|
|||
panic!("Function is not running on the main thread!");
|
||||
}
|
||||
|
||||
if thread::current().id() != main_thread_id() {
|
||||
if !is_main_thread() && !THREAD_ASSERTS_CFG_FOR_TESTING.load(Ordering::Relaxed) {
|
||||
not_main_thread();
|
||||
}
|
||||
}
|
||||
|
@ -59,11 +77,19 @@ pub fn assert_is_background_thread() {
|
|||
panic!("Function is not allowed to be called on the main thread!");
|
||||
}
|
||||
|
||||
if thread::current().id() == main_thread_id() {
|
||||
if is_main_thread() && !THREAD_ASSERTS_CFG_FOR_TESTING.load(Ordering::Relaxed) {
|
||||
not_background_thread();
|
||||
}
|
||||
}
|
||||
|
||||
pub fn configure_thread_assertions_for_testing() {
|
||||
THREAD_ASSERTS_CFG_FOR_TESTING.store(true, Ordering::Relaxed);
|
||||
}
|
||||
|
||||
pub fn is_forked_child() -> bool {
|
||||
IS_FORKED_PROC.load(Ordering::Relaxed)
|
||||
}
|
||||
|
||||
/// The rusty version of `iothreads::make_detached_pthread()`. We will probably need a
|
||||
/// `spawn_scoped` version of the same to handle some more advanced borrow cases safely, and maybe
|
||||
/// an unsafe version that doesn't do any lifetime checking akin to
|
||||
|
|
Loading…
Reference in New Issue
Block a user