Skip to content

add Android pthread support #3889

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
Sep 15, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -216,9 +216,9 @@ degree documented below):
- For every other target with OS `linux`, `macos`, or `windows`, Miri should generally work, but we
make no promises and we don't run tests for such targets.
- We have unofficial support (not maintained by the Miri team itself) for some further operating systems.
- `solaris` / `illumos`: maintained by @devnexen. Supports `std::{env, thread, sync}`, but not `std::fs`.
- `freebsd`: **maintainer wanted**. Supports `std::env` and parts of `std::{thread, fs}`, but not `std::sync`.
- `android`: **maintainer wanted**. Support very incomplete, but a basic "hello world" works.
- `solaris` / `illumos`: maintained by @devnexen. Support very incomplete, but a basic "hello world" works.
- `wasm`: **maintainer wanted**. Support very incomplete, not even standard output works, but an empty `main` function works.
- For targets on other operating systems, Miri might fail before even reaching the `main` function.

Expand Down
10 changes: 5 additions & 5 deletions ci/ci.sh
Original file line number Diff line number Diff line change
Expand Up @@ -150,11 +150,11 @@ case $HOST_TARGET in
# Partially supported targets (tier 2)
BASIC="empty_main integer vec string btreemap hello hashmap heap_alloc align" # ensures we have the basics: stdout/stderr, system allocator, randomness (for HashMap initialization)
UNIX="panic/panic panic/unwind concurrency/simple atomic libc-mem libc-misc libc-random env num_cpus" # the things that are very similar across all Unixes, and hence easily supported there
TEST_TARGET=x86_64-unknown-freebsd run_tests_minimal $BASIC $UNIX threadname pthread libc-time fs
TEST_TARGET=i686-unknown-freebsd run_tests_minimal $BASIC $UNIX threadname pthread libc-time fs
TEST_TARGET=x86_64-unknown-illumos run_tests_minimal $BASIC $UNIX threadname pthread sync available-parallelism libc-time tls
TEST_TARGET=x86_64-pc-solaris run_tests_minimal $BASIC $UNIX threadname pthread sync available-parallelism libc-time tls
TEST_TARGET=aarch64-linux-android run_tests_minimal $BASIC $UNIX
TEST_TARGET=x86_64-unknown-freebsd run_tests_minimal $BASIC $UNIX threadname pthread time fs
TEST_TARGET=i686-unknown-freebsd run_tests_minimal $BASIC $UNIX threadname pthread time fs
TEST_TARGET=x86_64-unknown-illumos run_tests_minimal $BASIC $UNIX thread sync available-parallelism time tls
TEST_TARGET=x86_64-pc-solaris run_tests_minimal $BASIC $UNIX thread sync available-parallelism time tls
TEST_TARGET=aarch64-linux-android run_tests_minimal $BASIC $UNIX pthread --skip threadname --skip pthread_cond_timedwait
TEST_TARGET=wasm32-wasip2 run_tests_minimal empty_main wasm heap_alloc libc-mem
TEST_TARGET=wasm32-unknown-unknown run_tests_minimal empty_main wasm
TEST_TARGET=thumbv7em-none-eabihf run_tests_minimal no_std
Expand Down
12 changes: 6 additions & 6 deletions src/shims/unix/sync.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ use crate::*;
#[inline]
fn mutexattr_kind_offset<'tcx>(ecx: &MiriInterpCx<'tcx>) -> InterpResult<'tcx, u64> {
Ok(match &*ecx.tcx.sess.target.os {
"linux" | "illumos" | "solaris" | "macos" | "freebsd" => 0,
"linux" | "illumos" | "solaris" | "macos" | "freebsd" | "android" => 0,
os => throw_unsup_format!("`pthread_mutexattr` is not supported on {os}"),
})
}
Expand Down Expand Up @@ -76,7 +76,7 @@ fn mutex_id_offset<'tcx>(ecx: &MiriInterpCx<'tcx>) -> InterpResult<'tcx, u64> {
// When adding a new OS, make sure we also support all its static initializers in
// `mutex_kind_from_static_initializer`!
let offset = match &*ecx.tcx.sess.target.os {
"linux" | "illumos" | "solaris" | "freebsd" => 0,
"linux" | "illumos" | "solaris" | "freebsd" | "android" => 0,
// macOS stores a signature in the first bytes, so we have to move to offset 4.
"macos" => 4,
os => throw_unsup_format!("`pthread_mutex` is not supported on {os}"),
Expand Down Expand Up @@ -105,7 +105,7 @@ fn mutex_id_offset<'tcx>(ecx: &MiriInterpCx<'tcx>) -> InterpResult<'tcx, u64> {
check_static_initializer("PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP");
check_static_initializer("PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP");
}
"illumos" | "solaris" | "macos" | "freebsd" => {
"illumos" | "solaris" | "macos" | "freebsd" | "android" => {
// No non-standard initializers.
}
os => throw_unsup_format!("`pthread_mutex` is not supported on {os}"),
Expand Down Expand Up @@ -216,7 +216,7 @@ pub struct AdditionalRwLockData {

fn rwlock_id_offset<'tcx>(ecx: &MiriInterpCx<'tcx>) -> InterpResult<'tcx, u64> {
let offset = match &*ecx.tcx.sess.target.os {
"linux" | "illumos" | "solaris" | "freebsd" => 0,
"linux" | "illumos" | "solaris" | "freebsd" | "android" => 0,
// macOS stores a signature in the first bytes, so we have to move to offset 4.
"macos" => 4,
os => throw_unsup_format!("`pthread_rwlock` is not supported on {os}"),
Expand Down Expand Up @@ -269,7 +269,7 @@ fn rwlock_get_id<'tcx>(
#[inline]
fn condattr_clock_offset<'tcx>(ecx: &MiriInterpCx<'tcx>) -> InterpResult<'tcx, u64> {
Ok(match &*ecx.tcx.sess.target.os {
"linux" | "illumos" | "solaris" | "freebsd" => 0,
"linux" | "illumos" | "solaris" | "freebsd" | "android" => 0,
// macOS does not have a clock attribute.
os => throw_unsup_format!("`pthread_condattr` clock field is not supported on {os}"),
})
Expand Down Expand Up @@ -321,7 +321,7 @@ fn condattr_set_clock_id<'tcx>(

fn cond_id_offset<'tcx>(ecx: &MiriInterpCx<'tcx>) -> InterpResult<'tcx, u64> {
let offset = match &*ecx.tcx.sess.target.os {
"linux" | "illumos" | "solaris" | "freebsd" => 0,
"linux" | "illumos" | "solaris" | "freebsd" | "android" => 0,
// macOS stores a signature in the first bytes, so we have to move to offset 4.
"macos" => 4,
os => throw_unsup_format!("`pthread_cond` is not supported on {os}"),
Expand Down
1 change: 1 addition & 0 deletions test_dependencies/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions test_dependencies/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ edition = "2021"
# all dependencies (and their transitive ones) listed here can be used in `tests/`.
libc = "0.2"
num_cpus = "1.10.1"
cfg-if = "1"

getrandom_01 = { package = "getrandom", version = "0.1" }
getrandom_02 = { package = "getrandom", version = "0.2", features = ["js"] }
Expand Down
55 changes: 37 additions & 18 deletions tests/pass-dep/libc/pthread-threadname.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,16 +10,42 @@ fn main() {
.collect::<String>();

fn set_thread_name(name: &CStr) -> i32 {
#[cfg(any(target_os = "linux", target_os = "illumos", target_os = "solaris"))]
return unsafe { libc::pthread_setname_np(libc::pthread_self(), name.as_ptr().cast()) };
#[cfg(target_os = "freebsd")]
unsafe {
// pthread_set_name_np does not return anything
libc::pthread_set_name_np(libc::pthread_self(), name.as_ptr().cast());
return 0;
};
#[cfg(target_os = "macos")]
return unsafe { libc::pthread_setname_np(name.as_ptr().cast()) };
cfg_if::cfg_if! {
if #[cfg(any(target_os = "linux", target_os = "illumos", target_os = "solaris"))] {
unsafe { libc::pthread_setname_np(libc::pthread_self(), name.as_ptr().cast()) }
} else if #[cfg(target_os = "freebsd")] {
// pthread_set_name_np does not return anything
unsafe { libc::pthread_set_name_np(libc::pthread_self(), name.as_ptr().cast()) };
0
} else if #[cfg(target_os = "macos")] {
unsafe { libc::pthread_setname_np(name.as_ptr().cast()) }
} else {
compile_error!("set_thread_name not supported for this OS")
}
}
}

fn get_thread_name(name: &mut [u8]) -> i32 {
cfg_if::cfg_if! {
if #[cfg(any(
target_os = "linux",
target_os = "illumos",
target_os = "solaris",
target_os = "macos"
))] {
unsafe {
libc::pthread_getname_np(libc::pthread_self(), name.as_mut_ptr().cast(), name.len())
}
} else if #[cfg(target_os = "freebsd")] {
// pthread_get_name_np does not return anything
unsafe {
libc::pthread_get_name_np(libc::pthread_self(), name.as_mut_ptr().cast(), name.len())
};
0
} else {
compile_error!("get_thread_name not supported for this OS")
}
}
}

let result = thread::Builder::new().name(long_name.clone()).spawn(move || {
Expand All @@ -28,14 +54,7 @@ fn main() {

// But the system is limited -- make sure we successfully set a truncation.
let mut buf = vec![0u8; long_name.len() + 1];
#[cfg(not(target_os = "freebsd"))]
unsafe {
libc::pthread_getname_np(libc::pthread_self(), buf.as_mut_ptr().cast(), buf.len())
};
#[cfg(target_os = "freebsd")]
unsafe {
libc::pthread_get_name_np(libc::pthread_self(), buf.as_mut_ptr().cast(), buf.len())
};
assert_eq!(get_thread_name(&mut buf), 0);
let cstr = CStr::from_bytes_until_nul(&buf).unwrap();
assert!(cstr.to_bytes().len() >= 15, "name is too short: len={}", cstr.to_bytes().len()); // POSIX seems to promise at least 15 chars
assert!(long_name.as_bytes().starts_with(cstr.to_bytes()));
Expand Down
4 changes: 2 additions & 2 deletions tests/pass/shims/time-with-isolation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,9 +41,9 @@ fn test_block_for_one_second() {
/// Ensures that we get the same behavior across all targets.
fn test_deterministic() {
let begin = Instant::now();
for _ in 0..100_000 {}
for _ in 0..10_000 {}
let time = begin.elapsed();
println!("The loop took around {}s", time.as_secs());
println!("The loop took around {}ms", time.as_millis());
println!("(It's fine for this number to change when you `--bless` this test.)")
}

Expand Down
2 changes: 1 addition & 1 deletion tests/pass/shims/time-with-isolation.stdout
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
The loop took around 12s
The loop took around 1250ms
(It's fine for this number to change when you `--bless` this test.)