diff --git a/ci/ci.sh b/ci/ci.sh index cca615bc66..0751f86da8 100755 --- a/ci/ci.sh +++ b/ci/ci.sh @@ -150,8 +150,8 @@ case $HOST_TARGET in # Partially supported targets (tier 2) BASIC="empty_main integer heap_alloc libc-mem vec string btreemap" # ensures we have the basics: pre-main code, system allocator UNIX="hello 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 time hashmap random fs libc-pipe - TEST_TARGET=i686-unknown-freebsd run_tests_minimal $BASIC $UNIX time hashmap random fs libc-pipe + TEST_TARGET=x86_64-unknown-freebsd run_tests_minimal $BASIC $UNIX time hashmap random threadname pthread fs libc-pipe + TEST_TARGET=i686-unknown-freebsd run_tests_minimal $BASIC $UNIX time hashmap random threadname pthread fs libc-pipe TEST_TARGET=x86_64-unknown-illumos run_tests_minimal $BASIC $UNIX time hashmap random thread sync available-parallelism tls libc-pipe fs TEST_TARGET=x86_64-pc-solaris run_tests_minimal $BASIC $UNIX time hashmap random thread sync available-parallelism tls libc-pipe fs TEST_TARGET=aarch64-linux-android run_tests_minimal $BASIC $UNIX time hashmap random sync threadname pthread epoll eventfd diff --git a/src/shims/unix/freebsd/foreign_items.rs b/src/shims/unix/freebsd/foreign_items.rs index 5381234e28..03dbd93132 100644 --- a/src/shims/unix/freebsd/foreign_items.rs +++ b/src/shims/unix/freebsd/foreign_items.rs @@ -21,29 +21,38 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { let this = self.eval_context_mut(); match link_name.as_str() { // Threading - "pthread_set_name_np" => { + "pthread_setname_np" => { let [thread, name] = this.check_shim(abi, Conv::C, link_name, args)?; let max_len = usize::MAX; // FreeBSD does not seem to have a limit. - // FreeBSD's pthread_set_name_np does not return anything. - this.pthread_setname_np( + let res = match this.pthread_setname_np( this.read_scalar(thread)?, this.read_scalar(name)?, max_len, /* truncate */ false, - )?; + )? { + ThreadNameResult::Ok => Scalar::from_u32(0), + ThreadNameResult::NameTooLong => unreachable!(), + ThreadNameResult::ThreadNotFound => this.eval_libc("ESRCH"), + }; + this.write_scalar(res, dest)?; } - "pthread_get_name_np" => { + "pthread_getname_np" => { let [thread, name, len] = this.check_shim(abi, Conv::C, link_name, args)?; - // FreeBSD's pthread_get_name_np does not return anything - // and uses strlcpy, which truncates the resulting value, + // FreeBSD's pthread_getname_np uses strlcpy, which truncates the resulting value, // but always adds a null terminator (except for zero-sized buffers). // https://github.com/freebsd/freebsd-src/blob/c2d93a803acef634bd0eede6673aeea59e90c277/lib/libthr/thread/thr_info.c#L119-L144 - this.pthread_getname_np( + let res = match this.pthread_getname_np( this.read_scalar(thread)?, this.read_scalar(name)?, this.read_scalar(len)?, /* truncate */ true, - )?; + )? { + ThreadNameResult::Ok => Scalar::from_u32(0), + // `NameTooLong` is possible when the buffer is zero sized, + ThreadNameResult::NameTooLong => Scalar::from_u32(0), + ThreadNameResult::ThreadNotFound => this.eval_libc("ESRCH"), + }; + this.write_scalar(res, dest)?; } // File related shims diff --git a/tests/pass-dep/libc/pthread-threadname.rs b/tests/pass-dep/libc/pthread-threadname.rs index cf634bc689..6ac71b5ad1 100644 --- a/tests/pass-dep/libc/pthread-threadname.rs +++ b/tests/pass-dep/libc/pthread-threadname.rs @@ -29,12 +29,13 @@ fn main() { fn set_thread_name(name: &CStr) -> i32 { cfg_if::cfg_if! { - if #[cfg(any(target_os = "linux", target_os = "illumos", target_os = "solaris"))] { + if #[cfg(any( + target_os = "linux", + target_os = "freebsd", + 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 { @@ -47,6 +48,7 @@ fn main() { cfg_if::cfg_if! { if #[cfg(any( target_os = "linux", + target_os = "freebsd", target_os = "illumos", target_os = "solaris", target_os = "macos" @@ -54,12 +56,6 @@ fn main() { 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") } @@ -201,27 +197,25 @@ fn main() { .unwrap(); // Now set the name for a non-existing thread and verify error codes. - // (FreeBSD doesn't return an error code.) - #[cfg(not(target_os = "freebsd"))] - { - let invalid_thread = 0xdeadbeef; - let error = { - cfg_if::cfg_if! { - if #[cfg(target_os = "linux")] { - libc::ENOENT - } else { - libc::ESRCH - } + let invalid_thread = 0xdeadbeef; + let error = { + cfg_if::cfg_if! { + if #[cfg(target_os = "linux")] { + libc::ENOENT + } else { + libc::ESRCH } - }; - #[cfg(not(target_os = "macos"))] - { - // macOS has no `setname` function accepting a thread id as the first argument. - let res = unsafe { libc::pthread_setname_np(invalid_thread, [0].as_ptr()) }; - assert_eq!(res, error); } - let mut buf = [0; 64]; - let res = unsafe { libc::pthread_getname_np(invalid_thread, buf.as_mut_ptr(), buf.len()) }; + }; + + #[cfg(not(target_os = "macos"))] + { + // macOS has no `setname` function accepting a thread id as the first argument. + let res = unsafe { libc::pthread_setname_np(invalid_thread, [0].as_ptr()) }; assert_eq!(res, error); } + + let mut buf = [0; 64]; + let res = unsafe { libc::pthread_getname_np(invalid_thread, buf.as_mut_ptr(), buf.len()) }; + assert_eq!(res, error); }