Const init pthread_atfork; export in pthread.h

`pthread_atfork` should be exported in pthread.h according to the
standard. We only exported our function in unistd.h. `glibc` exports it
in both pthread.h and unistd.h whereas musl only exports it in pthread.h
(which is standards compliant).

I exported it in both headers. Cbindgen doesn't seem to reexport `pub
use` so I declared the function twice. We might have to reexamine our
`pub use` to check what's exported and what isn't.
This commit is contained in:
Josh Megnauth
2025-09-01 08:14:04 -04:00
committed by Josh Megnauth
parent 3a08d40c67
commit 51bc7f7d2c
2 changed files with 42 additions and 38 deletions
+32 -3
View File
@@ -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<extern "C" fn()>; 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 <https://pubs.opengroup.org/onlinepubs/9799919799/functions/pthread_atfork.html>.
#[no_mangle]
pub extern "C" fn pthread_atfork(
prepare: Option<extern "C" fn()>,
parent: Option<extern "C" fn()>,
child: Option<extern "C" fn()>,
) -> 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))
+10 -35
View File
@@ -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.
// <https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/unistd.h.html>.
@@ -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<extern "C" fn()>; 3]> = None;
unsafe fn init_fork_hooks<'a>() -> &'a mut [LinkedList<extern "C" fn()>; 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<extern "C" fn()>,
parent: Option<extern "C" fn()>,
child: Option<extern "C" fn()>,
) -> c_int;
}
/// See <https://pubs.opengroup.org/onlinepubs/9799919799/functions/fork.html>.
@@ -413,7 +411,6 @@ pub extern "C" fn fdatasync(fildes: c_int) -> c_int {
/// See <https://pubs.opengroup.org/onlinepubs/9799919799/functions/fork.html>.
#[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 <https://pubs.opengroup.org/onlinepubs/9799919799/functions/pthread_atfork.html>.
///
/// TODO: specified in `pthread.h` in modern POSIX
#[no_mangle]
pub extern "C" fn pthread_atfork(
prepare: Option<extern "C" fn()>,
parent: Option<extern "C" fn()>,
child: Option<extern "C" fn()>,
) -> 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 <https://pubs.opengroup.org/onlinepubs/9799919799/functions/write.html>.
#[no_mangle]
pub unsafe extern "C" fn pwrite(