diff --git a/src/header/pthread/mod.rs b/src/header/pthread/mod.rs index ce58695290..a00692b987 100644 --- a/src/header/pthread/mod.rs +++ b/src/header/pthread/mod.rs @@ -1,5 +1,6 @@ //! pthread.h implementation for Redox, following https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/pthread.h.html +use alloc::collections::LinkedList; use core::{cell::Cell, ptr::NonNull}; use crate::{ @@ -72,6 +73,12 @@ pub use self::attr::*; pub mod barrier; pub use self::barrier::*; +pub mod cond; +pub use self::cond::*; + +#[thread_local] +pub static mut fork_hooks: [LinkedList; 3] = [const { LinkedList::new() }; 3]; + #[no_mangle] pub unsafe extern "C" fn pthread_cancel(thread: pthread_t) -> c_int { match pthread::cancel(&*thread.cast()) { @@ -80,9 +87,6 @@ pub unsafe extern "C" fn pthread_cancel(thread: pthread_t) -> c_int { } } -pub mod cond; -pub use self::cond::*; - #[no_mangle] pub unsafe extern "C" fn pthread_create( pthread: *mut pthread_t, @@ -114,6 +118,31 @@ pub extern "C" fn pthread_equal(pthread1: pthread_t, pthread2: pthread_t) -> c_i core::ptr::eq(pthread1, pthread2).into() } +/// See . +#[no_mangle] +pub extern "C" fn pthread_atfork( + prepare: Option, + parent: Option, + child: Option, +) -> c_int { + if let Some(prepare) = prepare { + unsafe { + fork_hooks[0].push_back(prepare); + } + } + if let Some(parent) = parent { + unsafe { + fork_hooks[1].push_back(parent); + } + } + if let Some(child) = child { + unsafe { + fork_hooks[2].push_back(child); + } + } + 0 +} + #[no_mangle] pub unsafe extern "C" fn pthread_exit(retval: *mut c_void) -> ! { pthread::exit_current_thread(pthread::Retval(retval)) diff --git a/src/header/unistd/mod.rs b/src/header/unistd/mod.rs index d9b6700f34..2ba89019ff 100644 --- a/src/header/unistd/mod.rs +++ b/src/header/unistd/mod.rs @@ -22,9 +22,8 @@ use crate::{ platform::{self, types::*, Pal, Sys, ERRNO}, }; -use alloc::collections::LinkedList; - pub use self::{brk::*, getopt::*, getpass::getpass, pathconf::*, sysconf::*}; +pub use crate::header::pthread::fork_hooks; // Inclusion of ctermid() prototype marked as obsolescent since Issue 7, cf. // . @@ -104,16 +103,15 @@ pub const _CS_POSIX_V7_LPBIG_OFFBIG_LDFLAGS: c_int = 1145; pub const _CS_POSIX_V7_LPBIG_OFFBIG_LIBS: c_int = 1146; pub const _CS_POSIX_V7_LPBIG_OFFBIG_LINTFLAGS: c_int = 1147; -#[thread_local] -pub static mut fork_hooks_static: Option<[LinkedList; 3]> = None; - -unsafe fn init_fork_hooks<'a>() -> &'a mut [LinkedList; 3] { - // Transmute the lifetime so we can return here. Should be safe as - // long as one does not access the original fork_hooks. - mem::transmute( - fork_hooks_static - .get_or_insert_with(|| [LinkedList::new(), LinkedList::new(), LinkedList::new()]), - ) +// Re-exported from pthread.h. `pthread_atfork` should be in pthread.h according to the +// standard, but glibc exports it here as well. We ONLY exported it in unistd.h till recently. +extern "C" { + #[no_mangle] + pub fn pthread_atfork( + prepare: Option, + parent: Option, + child: Option, + ) -> c_int; } /// See . @@ -413,7 +411,6 @@ pub extern "C" fn fdatasync(fildes: c_int) -> c_int { /// See . #[no_mangle] pub unsafe extern "C" fn fork() -> pid_t { - let fork_hooks = init_fork_hooks(); for prepare in &fork_hooks[0] { prepare(); } @@ -792,28 +789,6 @@ pub unsafe extern "C" fn pread( .or_minus_one_errno() } -/// See . -/// -/// TODO: specified in `pthread.h` in modern POSIX -#[no_mangle] -pub extern "C" fn pthread_atfork( - prepare: Option, - parent: Option, - child: Option, -) -> c_int { - let fork_hooks = unsafe { init_fork_hooks() }; - if let Some(prepare) = prepare { - fork_hooks[0].push_back(prepare); - } - if let Some(parent) = parent { - fork_hooks[1].push_back(parent); - } - if let Some(child) = child { - fork_hooks[2].push_back(child); - } - 0 -} - /// See . #[no_mangle] pub unsafe extern "C" fn pwrite(