summaryrefslogtreecommitdiffstats
path: root/library/std/src/sys/unix
diff options
context:
space:
mode:
Diffstat (limited to 'library/std/src/sys/unix')
-rw-r--r--library/std/src/sys/unix/args.rs4
-rw-r--r--library/std/src/sys/unix/env.rs11
-rw-r--r--library/std/src/sys/unix/fd.rs17
-rw-r--r--library/std/src/sys/unix/fs.rs75
-rw-r--r--library/std/src/sys/unix/kernel_copy.rs4
-rw-r--r--library/std/src/sys/unix/l4re.rs6
-rw-r--r--library/std/src/sys/unix/locks/pthread_condvar.rs3
-rw-r--r--library/std/src/sys/unix/mod.rs15
-rw-r--r--library/std/src/sys/unix/net.rs8
-rw-r--r--library/std/src/sys/unix/os.rs12
-rw-r--r--library/std/src/sys/unix/os_str.rs13
-rw-r--r--library/std/src/sys/unix/os_str/tests.rs9
-rw-r--r--library/std/src/sys/unix/path.rs2
-rw-r--r--library/std/src/sys/unix/process/process_common.rs4
-rw-r--r--library/std/src/sys/unix/process/process_unix.rs152
-rw-r--r--library/std/src/sys/unix/process/process_vxworks.rs7
-rw-r--r--library/std/src/sys/unix/rand.rs3
-rw-r--r--library/std/src/sys/unix/thread.rs34
-rw-r--r--library/std/src/sys/unix/thread_parking/pthread.rs6
-rw-r--r--library/std/src/sys/unix/time.rs6
-rw-r--r--library/std/src/sys/unix/weak.rs4
21 files changed, 315 insertions, 80 deletions
diff --git a/library/std/src/sys/unix/args.rs b/library/std/src/sys/unix/args.rs
index 9ed4d9c1e..eafd6821f 100644
--- a/library/std/src/sys/unix/args.rs
+++ b/library/std/src/sys/unix/args.rs
@@ -168,7 +168,7 @@ mod imp {
}
}
-#[cfg(any(target_os = "macos", target_os = "ios", target_os = "watchos"))]
+#[cfg(any(target_os = "macos", target_os = "ios", target_os = "tvos", target_os = "watchos"))]
mod imp {
use super::Args;
use crate::ffi::CStr;
@@ -209,7 +209,7 @@ mod imp {
// for i in (0..[args count])
// res.push([args objectAtIndex:i])
// res
- #[cfg(any(target_os = "ios", target_os = "watchos"))]
+ #[cfg(any(target_os = "ios", target_os = "tvos", target_os = "watchos"))]
pub fn args() -> Args {
use crate::ffi::OsString;
use crate::mem;
diff --git a/library/std/src/sys/unix/env.rs b/library/std/src/sys/unix/env.rs
index 8c3ef88d8..929e9dae7 100644
--- a/library/std/src/sys/unix/env.rs
+++ b/library/std/src/sys/unix/env.rs
@@ -31,6 +31,17 @@ pub mod os {
pub const EXE_EXTENSION: &str = "";
}
+#[cfg(target_os = "tvos")]
+pub mod os {
+ pub const FAMILY: &str = "unix";
+ pub const OS: &str = "tvos";
+ pub const DLL_PREFIX: &str = "lib";
+ pub const DLL_SUFFIX: &str = ".dylib";
+ pub const DLL_EXTENSION: &str = "dylib";
+ pub const EXE_SUFFIX: &str = "";
+ pub const EXE_EXTENSION: &str = "";
+}
+
#[cfg(target_os = "watchos")]
pub mod os {
pub const FAMILY: &str = "unix";
diff --git a/library/std/src/sys/unix/fd.rs b/library/std/src/sys/unix/fd.rs
index cb630eede..85e020ae4 100644
--- a/library/std/src/sys/unix/fd.rs
+++ b/library/std/src/sys/unix/fd.rs
@@ -44,6 +44,7 @@ const READ_LIMIT: usize = libc::ssize_t::MAX as usize;
target_os = "dragonfly",
target_os = "freebsd",
target_os = "ios",
+ target_os = "tvos",
target_os = "macos",
target_os = "netbsd",
target_os = "openbsd",
@@ -69,6 +70,7 @@ const fn max_iov() -> usize {
target_os = "emscripten",
target_os = "freebsd",
target_os = "ios",
+ target_os = "tvos",
target_os = "linux",
target_os = "macos",
target_os = "netbsd",
@@ -181,6 +183,7 @@ impl FileDesc {
target_os = "fuchsia",
target_os = "illumos",
target_os = "ios",
+ target_os = "tvos",
target_os = "linux",
target_os = "macos",
target_os = "netbsd",
@@ -222,6 +225,7 @@ impl FileDesc {
#[cfg(any(
all(target_os = "android", target_pointer_width = "32"),
target_os = "ios",
+ target_os = "tvos",
target_os = "macos",
))]
pub fn read_vectored_at(&self, bufs: &mut [IoSliceMut<'_>], offset: u64) -> io::Result<usize> {
@@ -320,6 +324,7 @@ impl FileDesc {
target_os = "fuchsia",
target_os = "illumos",
target_os = "ios",
+ target_os = "tvos",
target_os = "linux",
target_os = "macos",
target_os = "netbsd",
@@ -361,6 +366,7 @@ impl FileDesc {
#[cfg(any(
all(target_os = "android", target_pointer_width = "32"),
target_os = "ios",
+ target_os = "tvos",
target_os = "macos",
))]
pub fn write_vectored_at(&self, bufs: &[IoSlice<'_>], offset: u64) -> io::Result<usize> {
@@ -402,7 +408,10 @@ impl FileDesc {
}
}
#[cfg(any(
- all(target_env = "newlib", not(any(target_os = "espidf", target_os = "horizon"))),
+ all(
+ target_env = "newlib",
+ not(any(target_os = "espidf", target_os = "horizon", target_os = "vita"))
+ ),
target_os = "solaris",
target_os = "illumos",
target_os = "emscripten",
@@ -424,10 +433,10 @@ impl FileDesc {
Ok(())
}
}
- #[cfg(any(target_os = "espidf", target_os = "horizon"))]
+ #[cfg(any(target_os = "espidf", target_os = "horizon", target_os = "vita"))]
pub fn set_cloexec(&self) -> io::Result<()> {
- // FD_CLOEXEC is not supported in ESP-IDF and Horizon OS but there's no need to,
- // because neither supports spawning processes.
+ // FD_CLOEXEC is not supported in ESP-IDF, Horizon OS and Vita but there's no need to,
+ // because none of them supports spawning processes.
Ok(())
}
diff --git a/library/std/src/sys/unix/fs.rs b/library/std/src/sys/unix/fs.rs
index 09e9ae272..fbc7f04ce 100644
--- a/library/std/src/sys/unix/fs.rs
+++ b/library/std/src/sys/unix/fs.rs
@@ -15,6 +15,7 @@ use crate::mem;
target_os = "redox",
target_os = "illumos",
target_os = "nto",
+ target_os = "vita",
))]
use crate::mem::MaybeUninit;
use crate::os::unix::io::{AsFd, AsRawFd, BorrowedFd, FromRawFd, IntoRawFd};
@@ -31,6 +32,7 @@ use crate::sys_common::{AsInner, AsInnerMut, FromInner, IntoInner};
all(target_os = "linux", target_env = "gnu"),
target_os = "macos",
target_os = "ios",
+ target_os = "tvos",
target_os = "watchos",
))]
use crate::sys::weak::syscall;
@@ -42,6 +44,7 @@ use libc::{c_int, mode_t};
#[cfg(any(
target_os = "macos",
target_os = "ios",
+ target_os = "tvos",
target_os = "watchos",
target_os = "solaris",
all(target_os = "linux", target_env = "gnu")
@@ -58,6 +61,7 @@ use libc::fstatat64;
target_os = "redox",
target_os = "illumos",
target_os = "nto",
+ target_os = "vita",
))]
use libc::readdir as readdir64;
#[cfg(target_os = "linux")]
@@ -74,6 +78,7 @@ use libc::readdir64_r;
target_os = "fuchsia",
target_os = "redox",
target_os = "nto",
+ target_os = "vita",
)))]
use libc::readdir_r as readdir64_r;
#[cfg(target_os = "android")]
@@ -283,6 +288,7 @@ unsafe impl Sync for Dir {}
target_os = "fuchsia",
target_os = "redox",
target_os = "nto",
+ target_os = "vita"
))]
pub struct DirEntry {
dir: Arc<InnerReadDir>,
@@ -304,10 +310,16 @@ pub struct DirEntry {
target_os = "fuchsia",
target_os = "redox",
target_os = "nto",
+ target_os = "vita",
))]
struct dirent64_min {
d_ino: u64,
- #[cfg(not(any(target_os = "solaris", target_os = "illumos", target_os = "nto")))]
+ #[cfg(not(any(
+ target_os = "solaris",
+ target_os = "illumos",
+ target_os = "nto",
+ target_os = "vita"
+ )))]
d_type: u8,
}
@@ -319,6 +331,7 @@ struct dirent64_min {
target_os = "fuchsia",
target_os = "redox",
target_os = "nto",
+ target_os = "vita",
)))]
pub struct DirEntry {
dir: Arc<InnerReadDir>,
@@ -349,7 +362,7 @@ pub struct FilePermissions {
pub struct FileTimes {
accessed: Option<SystemTime>,
modified: Option<SystemTime>,
- #[cfg(any(target_os = "macos", target_os = "ios", target_os = "watchos"))]
+ #[cfg(any(target_os = "macos", target_os = "ios", target_os = "watchos", target_os = "tvos"))]
created: Option<SystemTime>,
}
@@ -508,6 +521,7 @@ impl FileAttr {
target_os = "openbsd",
target_os = "macos",
target_os = "ios",
+ target_os = "tvos",
target_os = "watchos",
))]
pub fn created(&self) -> io::Result<SystemTime> {
@@ -519,7 +533,9 @@ impl FileAttr {
target_os = "openbsd",
target_os = "macos",
target_os = "ios",
+ target_os = "tvos",
target_os = "watchos",
+ target_os = "vita",
)))]
pub fn created(&self) -> io::Result<SystemTime> {
cfg_has_statx! {
@@ -541,6 +557,11 @@ impl FileAttr {
currently",
))
}
+
+ #[cfg(target_os = "vita")]
+ pub fn created(&self) -> io::Result<SystemTime> {
+ Ok(SystemTime::new(self.stat.st_ctime as i64, 0))
+ }
}
#[cfg(target_os = "nto")]
@@ -594,7 +615,7 @@ impl FileTimes {
self.modified = Some(t);
}
- #[cfg(any(target_os = "macos", target_os = "ios", target_os = "watchos"))]
+ #[cfg(any(target_os = "macos", target_os = "ios", target_os = "watchos", target_os = "tvos"))]
pub fn set_created(&mut self, t: SystemTime) {
self.created = Some(t);
}
@@ -645,6 +666,7 @@ impl Iterator for ReadDir {
target_os = "redox",
target_os = "illumos",
target_os = "nto",
+ target_os = "vita",
))]
fn next(&mut self) -> Option<io::Result<DirEntry>> {
if self.end_of_stream {
@@ -725,6 +747,7 @@ impl Iterator for ReadDir {
continue;
}
+ #[cfg(not(target_os = "vita"))]
let entry = dirent64_min {
d_ino: *offset_ptr!(entry_ptr, d_ino) as u64,
#[cfg(not(any(
@@ -735,6 +758,9 @@ impl Iterator for ReadDir {
d_type: *offset_ptr!(entry_ptr, d_type) as u8,
};
+ #[cfg(target_os = "vita")]
+ let entry = dirent64_min { d_ino: 0u64 };
+
return Some(Ok(DirEntry {
entry,
name: name.to_owned(),
@@ -752,6 +778,7 @@ impl Iterator for ReadDir {
target_os = "redox",
target_os = "illumos",
target_os = "nto",
+ target_os = "vita",
)))]
fn next(&mut self) -> Option<io::Result<DirEntry>> {
if self.end_of_stream {
@@ -842,6 +869,7 @@ impl DirEntry {
target_os = "haiku",
target_os = "vxworks",
target_os = "nto",
+ target_os = "vita",
))]
pub fn file_type(&self) -> io::Result<FileType> {
self.metadata().map(|m| m.file_type())
@@ -853,6 +881,7 @@ impl DirEntry {
target_os = "haiku",
target_os = "vxworks",
target_os = "nto",
+ target_os = "vita",
)))]
pub fn file_type(&self) -> io::Result<FileType> {
match self.entry.d_type {
@@ -870,6 +899,7 @@ impl DirEntry {
#[cfg(any(
target_os = "macos",
target_os = "ios",
+ target_os = "tvos",
target_os = "watchos",
target_os = "linux",
target_os = "emscripten",
@@ -903,6 +933,7 @@ impl DirEntry {
#[cfg(any(
target_os = "macos",
target_os = "ios",
+ target_os = "tvos",
target_os = "watchos",
target_os = "netbsd",
target_os = "openbsd",
@@ -921,6 +952,7 @@ impl DirEntry {
#[cfg(not(any(
target_os = "macos",
target_os = "ios",
+ target_os = "tvos",
target_os = "watchos",
target_os = "netbsd",
target_os = "openbsd",
@@ -939,6 +971,7 @@ impl DirEntry {
target_os = "fuchsia",
target_os = "redox",
target_os = "nto",
+ target_os = "vita",
)))]
fn name_cstr(&self) -> &CStr {
unsafe { CStr::from_ptr(self.entry.d_name.as_ptr()) }
@@ -951,6 +984,7 @@ impl DirEntry {
target_os = "fuchsia",
target_os = "redox",
target_os = "nto",
+ target_os = "vita",
))]
fn name_cstr(&self) -> &CStr {
&self.name
@@ -1080,11 +1114,21 @@ impl File {
cvt_r(|| unsafe { os_fsync(self.as_raw_fd()) })?;
return Ok(());
- #[cfg(any(target_os = "macos", target_os = "ios", target_os = "watchos"))]
+ #[cfg(any(
+ target_os = "macos",
+ target_os = "ios",
+ target_os = "tvos",
+ target_os = "watchos",
+ ))]
unsafe fn os_fsync(fd: c_int) -> c_int {
libc::fcntl(fd, libc::F_FULLFSYNC)
}
- #[cfg(not(any(target_os = "macos", target_os = "ios", target_os = "watchos")))]
+ #[cfg(not(any(
+ target_os = "macos",
+ target_os = "ios",
+ target_os = "tvos",
+ target_os = "watchos",
+ )))]
unsafe fn os_fsync(fd: c_int) -> c_int {
libc::fsync(fd)
}
@@ -1094,7 +1138,12 @@ impl File {
cvt_r(|| unsafe { os_datasync(self.as_raw_fd()) })?;
return Ok(());
- #[cfg(any(target_os = "macos", target_os = "ios", target_os = "watchos"))]
+ #[cfg(any(
+ target_os = "macos",
+ target_os = "ios",
+ target_os = "tvos",
+ target_os = "watchos",
+ ))]
unsafe fn os_datasync(fd: c_int) -> c_int {
libc::fcntl(fd, libc::F_FULLFSYNC)
}
@@ -1113,6 +1162,7 @@ impl File {
target_os = "android",
target_os = "freebsd",
target_os = "ios",
+ target_os = "tvos",
target_os = "linux",
target_os = "macos",
target_os = "netbsd",
@@ -1222,7 +1272,7 @@ impl File {
io::ErrorKind::Unsupported,
"setting file times not supported",
))
- } else if #[cfg(any(target_os = "macos", target_os = "ios", target_os = "watchos"))] {
+ } else if #[cfg(any(target_os = "macos", target_os = "ios", target_os = "tvos", target_os = "watchos"))] {
let mut buf = [mem::MaybeUninit::<libc::timespec>::uninit(); 3];
let mut num_times = 0;
let mut attrlist: libc::attrlist = unsafe { mem::zeroed() };
@@ -1543,7 +1593,7 @@ pub fn link(original: &Path, link: &Path) -> io::Result<()> {
run_path_with_cstr(original, |original| {
run_path_with_cstr(link, |link| {
cfg_if::cfg_if! {
- if #[cfg(any(target_os = "vxworks", target_os = "redox", target_os = "android", target_os = "espidf", target_os = "horizon"))] {
+ if #[cfg(any(target_os = "vxworks", target_os = "redox", target_os = "android", target_os = "espidf", target_os = "horizon", target_os = "vita"))] {
// VxWorks, Redox and ESP-IDF lack `linkat`, so use `link` instead. POSIX leaves
// it implementation-defined whether `link` follows symlinks, so rely on the
// `symlink_hard_link` test in library/std/src/fs/tests.rs to check the behavior.
@@ -1666,6 +1716,8 @@ fn open_to_and_set_permissions(
.truncate(true)
.open(to)?;
let writer_metadata = writer.metadata()?;
+ // fchmod is broken on vita
+ #[cfg(not(target_os = "vita"))]
if writer_metadata.is_file() {
// Set the correct file permissions, in case the file already existed.
// Don't set the permissions on already existing non-files like
@@ -1680,6 +1732,7 @@ fn open_to_and_set_permissions(
target_os = "android",
target_os = "macos",
target_os = "ios",
+ target_os = "tvos",
target_os = "watchos",
)))]
pub fn copy(from: &Path, to: &Path) -> io::Result<u64> {
@@ -1707,7 +1760,7 @@ pub fn copy(from: &Path, to: &Path) -> io::Result<u64> {
}
}
-#[cfg(any(target_os = "macos", target_os = "ios", target_os = "watchos"))]
+#[cfg(any(target_os = "macos", target_os = "ios", target_os = "tvos", target_os = "watchos"))]
pub fn copy(from: &Path, to: &Path) -> io::Result<u64> {
use crate::sync::atomic::{AtomicBool, Ordering};
@@ -1844,11 +1897,12 @@ pub fn chroot(dir: &Path) -> io::Result<()> {
pub use remove_dir_impl::remove_dir_all;
-// Fallback for REDOX, ESP-ID, Horizon, and Miri
+// Fallback for REDOX, ESP-ID, Horizon, Vita and Miri
#[cfg(any(
target_os = "redox",
target_os = "espidf",
target_os = "horizon",
+ target_os = "vita",
target_os = "nto",
miri
))]
@@ -1861,6 +1915,7 @@ mod remove_dir_impl {
target_os = "redox",
target_os = "espidf",
target_os = "horizon",
+ target_os = "vita",
target_os = "nto",
miri
)))]
diff --git a/library/std/src/sys/unix/kernel_copy.rs b/library/std/src/sys/unix/kernel_copy.rs
index 16c8e0c0e..7d49bbdcb 100644
--- a/library/std/src/sys/unix/kernel_copy.rs
+++ b/library/std/src/sys/unix/kernel_copy.rs
@@ -466,7 +466,7 @@ impl<T: CopyRead> CopyRead for Take<T> {
}
}
-impl<T: CopyRead> CopyRead for BufReader<T> {
+impl<T: ?Sized + CopyRead> CopyRead for BufReader<T> {
fn drain_to<W: Write>(&mut self, writer: &mut W, outer_limit: u64) -> Result<u64> {
let buf = self.buffer();
let buf = &buf[0..min(buf.len(), outer_limit.try_into().unwrap_or(usize::MAX))];
@@ -495,7 +495,7 @@ impl<T: CopyRead> CopyRead for BufReader<T> {
}
}
-impl<T: CopyWrite> CopyWrite for BufWriter<T> {
+impl<T: ?Sized + CopyWrite> CopyWrite for BufWriter<T> {
fn properties(&self) -> CopyParams {
self.get_ref().properties()
}
diff --git a/library/std/src/sys/unix/l4re.rs b/library/std/src/sys/unix/l4re.rs
index ee016887e..fe9559f2a 100644
--- a/library/std/src/sys/unix/l4re.rs
+++ b/library/std/src/sys/unix/l4re.rs
@@ -10,7 +10,7 @@ macro_rules! unimpl {
pub mod net {
#![allow(warnings)]
use crate::fmt;
- use crate::io::{self, IoSlice, IoSliceMut};
+ use crate::io::{self, BorrowedCursor, IoSlice, IoSliceMut};
use crate::net::{Ipv4Addr, Ipv6Addr, Shutdown, SocketAddr};
use crate::os::unix::io::{AsFd, AsRawFd, BorrowedFd, FromRawFd, IntoRawFd, RawFd};
use crate::sys::fd::FileDesc;
@@ -218,6 +218,10 @@ pub mod net {
unimpl!();
}
+ pub fn read_buf(&self, _: BorrowedCursor<'_>) -> io::Result<()> {
+ unimpl!();
+ }
+
pub fn read_vectored(&self, _: &mut [IoSliceMut<'_>]) -> io::Result<usize> {
unimpl!();
}
diff --git a/library/std/src/sys/unix/locks/pthread_condvar.rs b/library/std/src/sys/unix/locks/pthread_condvar.rs
index 192fa216d..2dc1b0c60 100644
--- a/library/std/src/sys/unix/locks/pthread_condvar.rs
+++ b/library/std/src/sys/unix/locks/pthread_condvar.rs
@@ -32,6 +32,7 @@ impl LazyInit for AllocatedCondvar {
if #[cfg(any(
target_os = "macos",
target_os = "ios",
+ target_os = "tvos",
target_os = "watchos",
target_os = "l4re",
target_os = "android",
@@ -124,6 +125,7 @@ impl Condvar {
#[cfg(not(any(
target_os = "macos",
target_os = "ios",
+ target_os = "tvos",
target_os = "watchos",
target_os = "android",
target_os = "espidf",
@@ -158,6 +160,7 @@ impl Condvar {
#[cfg(any(
target_os = "macos",
target_os = "ios",
+ target_os = "tvos",
target_os = "watchos",
target_os = "android",
target_os = "espidf",
diff --git a/library/std/src/sys/unix/mod.rs b/library/std/src/sys/unix/mod.rs
index bb9e65e68..326f1481e 100644
--- a/library/std/src/sys/unix/mod.rs
+++ b/library/std/src/sys/unix/mod.rs
@@ -88,6 +88,7 @@ pub unsafe fn init(argc: isize, argv: *const *const u8, sigpipe: u8) {
// The poll on Darwin doesn't set POLLNVAL for closed fds.
target_os = "macos",
target_os = "ios",
+ target_os = "tvos",
target_os = "watchos",
target_os = "redox",
target_os = "l4re",
@@ -164,12 +165,7 @@ pub unsafe fn init(argc: isize, argv: *const *const u8, sigpipe: u8) {
}
unsafe fn reset_sigpipe(#[allow(unused_variables)] sigpipe: u8) {
- #[cfg(not(any(
- target_os = "emscripten",
- target_os = "fuchsia",
- target_os = "horizon",
- target_os = "vita"
- )))]
+ #[cfg(not(any(target_os = "emscripten", target_os = "fuchsia", target_os = "horizon")))]
{
// We don't want to add this as a public type to std, nor do we
// want to `include!` a file from the compiler (which would break
@@ -207,7 +203,6 @@ pub unsafe fn init(argc: isize, argv: *const *const u8, sigpipe: u8) {
target_os = "emscripten",
target_os = "fuchsia",
target_os = "horizon",
- target_os = "vita"
)))]
static UNIX_SIGPIPE_ATTR_SPECIFIED: crate::sync::atomic::AtomicBool =
crate::sync::atomic::AtomicBool::new(false);
@@ -217,7 +212,6 @@ static UNIX_SIGPIPE_ATTR_SPECIFIED: crate::sync::atomic::AtomicBool =
target_os = "emscripten",
target_os = "fuchsia",
target_os = "horizon",
- target_os = "vita",
)))]
pub(crate) fn unix_sigpipe_attr_specified() -> bool {
UNIX_SIGPIPE_ATTR_SPECIFIED.load(crate::sync::atomic::Ordering::Relaxed)
@@ -395,7 +389,7 @@ cfg_if::cfg_if! {
} else if #[cfg(target_os = "macos")] {
#[link(name = "System")]
extern "C" {}
- } else if #[cfg(any(target_os = "ios", target_os = "watchos"))] {
+ } else if #[cfg(any(target_os = "ios", target_os = "tvos", target_os = "watchos"))] {
#[link(name = "System")]
#[link(name = "objc")]
#[link(name = "Security", kind = "framework")]
@@ -408,6 +402,9 @@ cfg_if::cfg_if! {
} else if #[cfg(all(target_os = "linux", target_env = "uclibc"))] {
#[link(name = "dl")]
extern "C" {}
+ } else if #[cfg(target_os = "vita")] {
+ #[link(name = "pthread", kind = "static", modifiers = "-bundle")]
+ extern "C" {}
}
}
diff --git a/library/std/src/sys/unix/net.rs b/library/std/src/sys/unix/net.rs
index 39edb136c..7258c222a 100644
--- a/library/std/src/sys/unix/net.rs
+++ b/library/std/src/sys/unix/net.rs
@@ -454,12 +454,18 @@ impl Socket {
Ok(passcred != 0)
}
- #[cfg(not(any(target_os = "solaris", target_os = "illumos")))]
+ #[cfg(not(any(target_os = "solaris", target_os = "illumos", target_os = "vita")))]
pub fn set_nonblocking(&self, nonblocking: bool) -> io::Result<()> {
let mut nonblocking = nonblocking as libc::c_int;
cvt(unsafe { libc::ioctl(self.as_raw_fd(), libc::FIONBIO, &mut nonblocking) }).map(drop)
}
+ #[cfg(target_os = "vita")]
+ pub fn set_nonblocking(&self, nonblocking: bool) -> io::Result<()> {
+ let option = nonblocking as libc::c_int;
+ setsockopt(self, libc::SOL_SOCKET, libc::SO_NONBLOCK, option)
+ }
+
#[cfg(any(target_os = "solaris", target_os = "illumos"))]
pub fn set_nonblocking(&self, nonblocking: bool) -> io::Result<()> {
// FIONBIO is inadequate for sockets on illumos/Solaris, so use the
diff --git a/library/std/src/sys/unix/os.rs b/library/std/src/sys/unix/os.rs
index 8edfd3313..a68c14758 100644
--- a/library/std/src/sys/unix/os.rs
+++ b/library/std/src/sys/unix/os.rs
@@ -63,7 +63,13 @@ extern "C" {
#[cfg_attr(any(target_os = "solaris", target_os = "illumos"), link_name = "___errno")]
#[cfg_attr(target_os = "nto", link_name = "__get_errno_ptr")]
#[cfg_attr(
- any(target_os = "macos", target_os = "ios", target_os = "freebsd", target_os = "watchos"),
+ any(
+ target_os = "macos",
+ target_os = "ios",
+ target_os = "tvos",
+ target_os = "freebsd",
+ target_os = "watchos"
+ ),
link_name = "__error"
)]
#[cfg_attr(target_os = "haiku", link_name = "_errnop")]
@@ -375,7 +381,7 @@ pub fn current_exe() -> io::Result<PathBuf> {
Ok(PathBuf::from(OsString::from_vec(e)))
}
-#[cfg(any(target_os = "macos", target_os = "ios", target_os = "watchos"))]
+#[cfg(any(target_os = "macos", target_os = "ios", target_os = "tvos", target_os = "watchos"))]
pub fn current_exe() -> io::Result<PathBuf> {
unsafe {
let mut sz: u32 = 0;
@@ -609,6 +615,7 @@ pub fn home_dir() -> Option<PathBuf> {
#[cfg(any(
target_os = "android",
target_os = "ios",
+ target_os = "tvos",
target_os = "watchos",
target_os = "emscripten",
target_os = "redox",
@@ -623,6 +630,7 @@ pub fn home_dir() -> Option<PathBuf> {
#[cfg(not(any(
target_os = "android",
target_os = "ios",
+ target_os = "tvos",
target_os = "watchos",
target_os = "emscripten",
target_os = "redox",
diff --git a/library/std/src/sys/unix/os_str.rs b/library/std/src/sys/unix/os_str.rs
index 488217f39..f7333fd5a 100644
--- a/library/std/src/sys/unix/os_str.rs
+++ b/library/std/src/sys/unix/os_str.rs
@@ -193,17 +193,22 @@ impl Buf {
impl Slice {
#[inline]
- fn from_u8_slice(s: &[u8]) -> &Slice {
+ pub fn as_os_str_bytes(&self) -> &[u8] {
+ &self.inner
+ }
+
+ #[inline]
+ pub unsafe fn from_os_str_bytes_unchecked(s: &[u8]) -> &Slice {
unsafe { mem::transmute(s) }
}
#[inline]
pub fn from_str(s: &str) -> &Slice {
- Slice::from_u8_slice(s.as_bytes())
+ unsafe { Slice::from_os_str_bytes_unchecked(s.as_bytes()) }
}
- pub fn to_str(&self) -> Option<&str> {
- str::from_utf8(&self.inner).ok()
+ pub fn to_str(&self) -> Result<&str, crate::str::Utf8Error> {
+ str::from_utf8(&self.inner)
}
pub fn to_string_lossy(&self) -> Cow<'_, str> {
diff --git a/library/std/src/sys/unix/os_str/tests.rs b/library/std/src/sys/unix/os_str/tests.rs
index 22ba0c923..91bc0e61a 100644
--- a/library/std/src/sys/unix/os_str/tests.rs
+++ b/library/std/src/sys/unix/os_str/tests.rs
@@ -2,7 +2,7 @@ use super::*;
#[test]
fn slice_debug_output() {
- let input = Slice::from_u8_slice(b"\xF0hello,\tworld");
+ let input = unsafe { Slice::from_os_str_bytes_unchecked(b"\xF0hello,\tworld") };
let expected = r#""\xF0hello,\tworld""#;
let output = format!("{input:?}");
@@ -11,8 +11,7 @@ fn slice_debug_output() {
#[test]
fn display() {
- assert_eq!(
- "Hello\u{FFFD}\u{FFFD} There\u{FFFD} Goodbye",
- Slice::from_u8_slice(b"Hello\xC0\x80 There\xE6\x83 Goodbye").to_string(),
- );
+ assert_eq!("Hello\u{FFFD}\u{FFFD} There\u{FFFD} Goodbye", unsafe {
+ Slice::from_os_str_bytes_unchecked(b"Hello\xC0\x80 There\xE6\x83 Goodbye").to_string()
+ },);
}
diff --git a/library/std/src/sys/unix/path.rs b/library/std/src/sys/unix/path.rs
index a98a69e2d..935245f63 100644
--- a/library/std/src/sys/unix/path.rs
+++ b/library/std/src/sys/unix/path.rs
@@ -30,7 +30,7 @@ pub(crate) fn absolute(path: &Path) -> io::Result<PathBuf> {
// Get the components, skipping the redundant leading "." component if it exists.
let mut components = path.strip_prefix(".").unwrap_or(path).components();
- let path_os = path.as_os_str().bytes();
+ let path_os = path.as_os_str().as_os_str_bytes();
let mut normalized = if path.is_absolute() {
// "If a pathname begins with two successive <slash> characters, the
diff --git a/library/std/src/sys/unix/process/process_common.rs b/library/std/src/sys/unix/process/process_common.rs
index afd03d79c..640648e87 100644
--- a/library/std/src/sys/unix/process/process_common.rs
+++ b/library/std/src/sys/unix/process/process_common.rs
@@ -164,9 +164,9 @@ pub enum ProgramKind {
impl ProgramKind {
fn new(program: &OsStr) -> Self {
- if program.bytes().starts_with(b"/") {
+ if program.as_os_str_bytes().starts_with(b"/") {
Self::Absolute
- } else if program.bytes().contains(&b'/') {
+ } else if program.as_os_str_bytes().contains(&b'/') {
// If the program has more than one component in it, it is a relative path.
Self::Relative
} else {
diff --git a/library/std/src/sys/unix/process/process_unix.rs b/library/std/src/sys/unix/process/process_unix.rs
index 612d43fe2..0ce93af66 100644
--- a/library/std/src/sys/unix/process/process_unix.rs
+++ b/library/std/src/sys/unix/process/process_unix.rs
@@ -15,6 +15,8 @@ use crate::sys::weak::raw_syscall;
#[cfg(any(
target_os = "macos",
+ target_os = "watchos",
+ target_os = "tvos",
target_os = "freebsd",
all(target_os = "linux", target_env = "gnu"),
all(target_os = "linux", target_env = "musl"),
@@ -28,15 +30,38 @@ use libc::RTP_ID as pid_t;
#[cfg(not(target_os = "vxworks"))]
use libc::{c_int, pid_t};
-#[cfg(not(any(target_os = "vxworks", target_os = "l4re")))]
+#[cfg(not(any(
+ target_os = "vxworks",
+ target_os = "l4re",
+ target_os = "tvos",
+ target_os = "watchos",
+)))]
use libc::{gid_t, uid_t};
cfg_if::cfg_if! {
if #[cfg(all(target_os = "nto", target_env = "nto71"))] {
use crate::thread;
use libc::{c_char, posix_spawn_file_actions_t, posix_spawnattr_t};
- // arbitrary number of tries:
- const MAX_FORKSPAWN_TRIES: u32 = 4;
+ use crate::time::Duration;
+ use crate::sync::LazyLock;
+ // Get smallest amount of time we can sleep.
+ // Return a common value if it cannot be determined.
+ fn get_clock_resolution() -> Duration {
+ static MIN_DELAY: LazyLock<Duration, fn() -> Duration> = LazyLock::new(|| {
+ let mut mindelay = libc::timespec { tv_sec: 0, tv_nsec: 0 };
+ if unsafe { libc::clock_getres(libc::CLOCK_MONOTONIC, &mut mindelay) } == 0
+ {
+ Duration::from_nanos(mindelay.tv_nsec as u64)
+ } else {
+ Duration::from_millis(1)
+ }
+ });
+ *MIN_DELAY
+ }
+ // Arbitrary minimum sleep duration for retrying fork/spawn
+ const MIN_FORKSPAWN_SLEEP: Duration = Duration::from_nanos(1);
+ // Maximum duration of sleeping before giving up and returning an error
+ const MAX_FORKSPAWN_SLEEP: Duration = Duration::from_millis(1000);
}
}
@@ -66,7 +91,6 @@ impl Command {
if let Some(ret) = self.posix_spawn(&theirs, envp.as_ref())? {
return Ok((ret, ours));
}
-
let (input, output) = sys::pipe::anon_pipe()?;
// Whatever happens after the fork is almost for sure going to touch or
@@ -148,9 +172,31 @@ impl Command {
crate::sys_common::process::wait_with_output(proc, pipes)
}
+ // WatchOS and TVOS headers mark the `fork`/`exec*` functions with
+ // `__WATCHOS_PROHIBITED __TVOS_PROHIBITED`, and indicate that the
+ // `posix_spawn*` functions should be used instead. It isn't entirely clear
+ // what `PROHIBITED` means here (e.g. if calls to these functions are
+ // allowed to exist in dead code), but it sounds bad, so we go out of our
+ // way to avoid that all-together.
+ #[cfg(any(target_os = "tvos", target_os = "watchos"))]
+ const ERR_APPLE_TV_WATCH_NO_FORK_EXEC: Error = io::const_io_error!(
+ ErrorKind::Unsupported,
+ "`fork`+`exec`-based process spawning is not supported on this target",
+ );
+
+ #[cfg(any(target_os = "tvos", target_os = "watchos"))]
+ unsafe fn do_fork(&mut self) -> Result<(pid_t, pid_t), io::Error> {
+ return Err(Self::ERR_APPLE_TV_WATCH_NO_FORK_EXEC);
+ }
+
// Attempts to fork the process. If successful, returns Ok((0, -1))
// in the child, and Ok((child_pid, -1)) in the parent.
- #[cfg(not(any(target_os = "linux", all(target_os = "nto", target_env = "nto71"))))]
+ #[cfg(not(any(
+ target_os = "linux",
+ target_os = "watchos",
+ target_os = "tvos",
+ all(target_os = "nto", target_env = "nto71"),
+ )))]
unsafe fn do_fork(&mut self) -> Result<(pid_t, pid_t), io::Error> {
cvt(libc::fork()).map(|res| (res, -1))
}
@@ -163,12 +209,25 @@ impl Command {
unsafe fn do_fork(&mut self) -> Result<(pid_t, pid_t), io::Error> {
use crate::sys::os::errno;
- let mut tries_left = MAX_FORKSPAWN_TRIES;
+ let mut delay = MIN_FORKSPAWN_SLEEP;
+
loop {
let r = libc::fork();
- if r == -1 as libc::pid_t && tries_left > 0 && errno() as libc::c_int == libc::EBADF {
- thread::yield_now();
- tries_left -= 1;
+ if r == -1 as libc::pid_t && errno() as libc::c_int == libc::EBADF {
+ if delay < get_clock_resolution() {
+ // We cannot sleep this short (it would be longer).
+ // Yield instead.
+ thread::yield_now();
+ } else if delay < MAX_FORKSPAWN_SLEEP {
+ thread::sleep(delay);
+ } else {
+ return Err(io::const_io_error!(
+ ErrorKind::WouldBlock,
+ "forking returned EBADF too often",
+ ));
+ }
+ delay *= 2;
+ continue;
} else {
return cvt(r).map(|res| (res, -1));
}
@@ -308,6 +367,7 @@ impl Command {
// allocation). Instead we just close it manually. This will never
// have the drop glue anyway because this code never returns (the
// child will either exec() or invoke libc::exit)
+ #[cfg(not(any(target_os = "tvos", target_os = "watchos")))]
unsafe fn do_exec(
&mut self,
stdio: ChildPipes,
@@ -414,8 +474,19 @@ impl Command {
Err(io::Error::last_os_error())
}
+ #[cfg(any(target_os = "tvos", target_os = "watchos"))]
+ unsafe fn do_exec(
+ &mut self,
+ _stdio: ChildPipes,
+ _maybe_envp: Option<&CStringArray>,
+ ) -> Result<!, io::Error> {
+ return Err(Self::ERR_APPLE_TV_WATCH_NO_FORK_EXEC);
+ }
+
#[cfg(not(any(
target_os = "macos",
+ target_os = "tvos",
+ target_os = "watchos",
target_os = "freebsd",
all(target_os = "linux", target_env = "gnu"),
all(target_os = "linux", target_env = "musl"),
@@ -433,6 +504,9 @@ impl Command {
// directly.
#[cfg(any(
target_os = "macos",
+ // FIXME: `target_os = "ios"`?
+ target_os = "tvos",
+ target_os = "watchos",
target_os = "freebsd",
all(target_os = "linux", target_env = "gnu"),
all(target_os = "linux", target_env = "musl"),
@@ -480,17 +554,28 @@ impl Command {
attrp: *const posix_spawnattr_t,
argv: *const *mut c_char,
envp: *const *mut c_char,
- ) -> i32 {
- let mut tries_left = MAX_FORKSPAWN_TRIES;
+ ) -> io::Result<i32> {
+ let mut delay = MIN_FORKSPAWN_SLEEP;
loop {
match libc::posix_spawnp(pid, file, file_actions, attrp, argv, envp) {
- libc::EBADF if tries_left > 0 => {
- thread::yield_now();
- tries_left -= 1;
+ libc::EBADF => {
+ if delay < get_clock_resolution() {
+ // We cannot sleep this short (it would be longer).
+ // Yield instead.
+ thread::yield_now();
+ } else if delay < MAX_FORKSPAWN_SLEEP {
+ thread::sleep(delay);
+ } else {
+ return Err(io::const_io_error!(
+ ErrorKind::WouldBlock,
+ "posix_spawnp returned EBADF too often",
+ ));
+ }
+ delay *= 2;
continue;
}
r => {
- return r;
+ return Ok(r);
}
}
}
@@ -508,7 +593,7 @@ impl Command {
}
let addchdir = match self.get_cwd() {
Some(cwd) => {
- if cfg!(target_os = "macos") {
+ if cfg!(any(target_os = "macos", target_os = "tvos", target_os = "watchos")) {
// There is a bug in macOS where a relative executable
// path like "../myprogram" will cause `posix_spawn` to
// successfully launch the program, but erroneously return
@@ -620,14 +705,20 @@ impl Command {
let spawn_fn = libc::posix_spawnp;
#[cfg(target_os = "nto")]
let spawn_fn = retrying_libc_posix_spawnp;
- cvt_nz(spawn_fn(
+
+ let spawn_res = spawn_fn(
&mut p.pid,
self.get_program_cstr().as_ptr(),
file_actions.0.as_ptr(),
attrs.0.as_ptr(),
self.get_argv().as_ptr() as *const _,
envp as *const _,
- ))?;
+ );
+
+ #[cfg(target_os = "nto")]
+ let spawn_res = spawn_res?;
+
+ cvt_nz(spawn_res)?;
Ok(Some(p))
}
}
@@ -671,12 +762,9 @@ impl Process {
pub fn kill(&mut self) -> io::Result<()> {
// If we've already waited on this process then the pid can be recycled
// and used for another process, and we probably shouldn't be killing
- // random processes, so just return an error.
+ // random processes, so return Ok because the process has exited already.
if self.status.is_some() {
- Err(io::const_io_error!(
- ErrorKind::InvalidInput,
- "invalid argument: can't kill an exited process",
- ))
+ Ok(())
} else {
cvt(unsafe { libc::kill(self.pid, libc::SIGKILL) }).map(drop)
}
@@ -788,31 +876,47 @@ fn signal_string(signal: i32) -> &'static str {
libc::SIGILL => " (SIGILL)",
libc::SIGTRAP => " (SIGTRAP)",
libc::SIGABRT => " (SIGABRT)",
+ #[cfg(not(target_os = "l4re"))]
libc::SIGBUS => " (SIGBUS)",
libc::SIGFPE => " (SIGFPE)",
libc::SIGKILL => " (SIGKILL)",
+ #[cfg(not(target_os = "l4re"))]
libc::SIGUSR1 => " (SIGUSR1)",
libc::SIGSEGV => " (SIGSEGV)",
+ #[cfg(not(target_os = "l4re"))]
libc::SIGUSR2 => " (SIGUSR2)",
libc::SIGPIPE => " (SIGPIPE)",
libc::SIGALRM => " (SIGALRM)",
libc::SIGTERM => " (SIGTERM)",
+ #[cfg(not(target_os = "l4re"))]
libc::SIGCHLD => " (SIGCHLD)",
+ #[cfg(not(target_os = "l4re"))]
libc::SIGCONT => " (SIGCONT)",
+ #[cfg(not(target_os = "l4re"))]
libc::SIGSTOP => " (SIGSTOP)",
+ #[cfg(not(target_os = "l4re"))]
libc::SIGTSTP => " (SIGTSTP)",
+ #[cfg(not(target_os = "l4re"))]
libc::SIGTTIN => " (SIGTTIN)",
+ #[cfg(not(target_os = "l4re"))]
libc::SIGTTOU => " (SIGTTOU)",
+ #[cfg(not(target_os = "l4re"))]
libc::SIGURG => " (SIGURG)",
+ #[cfg(not(target_os = "l4re"))]
libc::SIGXCPU => " (SIGXCPU)",
+ #[cfg(not(target_os = "l4re"))]
libc::SIGXFSZ => " (SIGXFSZ)",
+ #[cfg(not(target_os = "l4re"))]
libc::SIGVTALRM => " (SIGVTALRM)",
+ #[cfg(not(target_os = "l4re"))]
libc::SIGPROF => " (SIGPROF)",
+ #[cfg(not(target_os = "l4re"))]
libc::SIGWINCH => " (SIGWINCH)",
- #[cfg(not(target_os = "haiku"))]
+ #[cfg(not(any(target_os = "haiku", target_os = "l4re")))]
libc::SIGIO => " (SIGIO)",
#[cfg(target_os = "haiku")]
libc::SIGPOLL => " (SIGPOLL)",
+ #[cfg(not(target_os = "l4re"))]
libc::SIGSYS => " (SIGSYS)",
// For information on Linux signals, run `man 7 signal`
#[cfg(all(
diff --git a/library/std/src/sys/unix/process/process_vxworks.rs b/library/std/src/sys/unix/process/process_vxworks.rs
index c40e7ada0..f70d3cb39 100644
--- a/library/std/src/sys/unix/process/process_vxworks.rs
+++ b/library/std/src/sys/unix/process/process_vxworks.rs
@@ -144,12 +144,9 @@ impl Process {
pub fn kill(&mut self) -> io::Result<()> {
// If we've already waited on this process then the pid can be recycled
// and used for another process, and we probably shouldn't be killing
- // random processes, so just return an error.
+ // random processes, so return Ok because the process has exited already.
if self.status.is_some() {
- Err(io::const_io_error!(
- ErrorKind::InvalidInput,
- "invalid argument: can't kill an exited process",
- ))
+ Ok(())
} else {
cvt(unsafe { libc::kill(self.pid, libc::SIGKILL) }).map(drop)
}
diff --git a/library/std/src/sys/unix/rand.rs b/library/std/src/sys/unix/rand.rs
index d8b63546b..d471be33e 100644
--- a/library/std/src/sys/unix/rand.rs
+++ b/library/std/src/sys/unix/rand.rs
@@ -14,6 +14,7 @@ pub fn hashmap_random_keys() -> (u64, u64) {
unix,
not(target_os = "macos"),
not(target_os = "ios"),
+ not(target_os = "tvos"),
not(target_os = "watchos"),
not(target_os = "openbsd"),
not(target_os = "freebsd"),
@@ -198,7 +199,7 @@ mod imp {
// once per thread in `hashmap_random_keys`. Therefore `SecRandomCopyBytes` is
// only used on iOS where direct access to `/dev/urandom` is blocked by the
// sandbox.
-#[cfg(any(target_os = "ios", target_os = "watchos"))]
+#[cfg(any(target_os = "ios", target_os = "tvos", target_os = "watchos"))]
mod imp {
use crate::io;
use crate::ptr;
diff --git a/library/std/src/sys/unix/thread.rs b/library/std/src/sys/unix/thread.rs
index 7307d9b2c..4f2d9cf36 100644
--- a/library/std/src/sys/unix/thread.rs
+++ b/library/std/src/sys/unix/thread.rs
@@ -150,7 +150,7 @@ impl Thread {
}
}
- #[cfg(any(target_os = "macos", target_os = "ios", target_os = "watchos"))]
+ #[cfg(any(target_os = "macos", target_os = "ios", target_os = "tvos", target_os = "watchos"))]
pub fn set_name(name: &CStr) {
unsafe {
let name = truncate_cstr::<{ libc::MAXTHREADNAMESIZE }>(name);
@@ -284,7 +284,13 @@ impl Drop for Thread {
}
}
-#[cfg(any(target_os = "linux", target_os = "macos", target_os = "ios", target_os = "watchos"))]
+#[cfg(any(
+ target_os = "linux",
+ target_os = "macos",
+ target_os = "ios",
+ target_os = "tvos",
+ target_os = "watchos",
+))]
fn truncate_cstr<const MAX_WITH_NUL: usize>(cstr: &CStr) -> [libc::c_char; MAX_WITH_NUL] {
let mut result = [0; MAX_WITH_NUL];
for (src, dst) in cstr.to_bytes().iter().zip(&mut result[..MAX_WITH_NUL - 1]) {
@@ -300,6 +306,7 @@ pub fn available_parallelism() -> io::Result<NonZeroUsize> {
target_os = "emscripten",
target_os = "fuchsia",
target_os = "ios",
+ target_os = "tvos",
target_os = "linux",
target_os = "macos",
target_os = "solaris",
@@ -345,6 +352,29 @@ pub fn available_parallelism() -> io::Result<NonZeroUsize> {
}
}
+ #[cfg(target_os = "netbsd")]
+ {
+ unsafe {
+ let set = libc::_cpuset_create();
+ if !set.is_null() {
+ let mut count: usize = 0;
+ if libc::pthread_getaffinity_np(libc::pthread_self(), libc::_cpuset_size(set), set) == 0 {
+ for i in 0..u64::MAX {
+ match libc::_cpuset_isset(i, set) {
+ -1 => break,
+ 0 => continue,
+ _ => count = count + 1,
+ }
+ }
+ }
+ libc::_cpuset_destroy(set);
+ if let Some(count) = NonZeroUsize::new(count) {
+ return Ok(count);
+ }
+ }
+ }
+ }
+
let mut cpus: libc::c_uint = 0;
let mut cpus_size = crate::mem::size_of_val(&cpus);
diff --git a/library/std/src/sys/unix/thread_parking/pthread.rs b/library/std/src/sys/unix/thread_parking/pthread.rs
index 43046ed07..ae805d843 100644
--- a/library/std/src/sys/unix/thread_parking/pthread.rs
+++ b/library/std/src/sys/unix/thread_parking/pthread.rs
@@ -46,6 +46,7 @@ unsafe fn wait_timeout(
#[cfg(any(
target_os = "macos",
target_os = "ios",
+ target_os = "tvos",
target_os = "watchos",
target_os = "espidf",
target_os = "horizon",
@@ -73,6 +74,7 @@ unsafe fn wait_timeout(
#[cfg(not(any(
target_os = "macos",
target_os = "ios",
+ target_os = "tvos",
target_os = "watchos",
target_os = "espidf",
target_os = "horizon",
@@ -120,10 +122,12 @@ impl Parker {
if #[cfg(any(
target_os = "macos",
target_os = "ios",
+ target_os = "tvos",
target_os = "watchos",
target_os = "l4re",
target_os = "android",
- target_os = "redox"
+ target_os = "redox",
+ target_os = "vita",
))] {
addr_of_mut!((*parker).cvar).write(UnsafeCell::new(libc::PTHREAD_COND_INITIALIZER));
} else if #[cfg(any(target_os = "espidf", target_os = "horizon"))] {
diff --git a/library/std/src/sys/unix/time.rs b/library/std/src/sys/unix/time.rs
index a9fbc7ab1..17b4130c2 100644
--- a/library/std/src/sys/unix/time.rs
+++ b/library/std/src/sys/unix/time.rs
@@ -219,7 +219,8 @@ impl From<__timespec64> for Timespec {
#[cfg(any(
all(target_os = "macos", any(not(target_arch = "aarch64"))),
target_os = "ios",
- target_os = "watchos"
+ target_os = "watchos",
+ target_os = "tvos"
))]
mod inner {
use crate::sync::atomic::{AtomicU64, Ordering};
@@ -339,7 +340,8 @@ mod inner {
#[cfg(not(any(
all(target_os = "macos", any(not(target_arch = "aarch64"))),
target_os = "ios",
- target_os = "watchos"
+ target_os = "watchos",
+ target_os = "tvos"
)))]
mod inner {
use crate::fmt;
diff --git a/library/std/src/sys/unix/weak.rs b/library/std/src/sys/unix/weak.rs
index 62ffee70b..61088ff16 100644
--- a/library/std/src/sys/unix/weak.rs
+++ b/library/std/src/sys/unix/weak.rs
@@ -28,7 +28,7 @@ use crate::ptr;
use crate::sync::atomic::{self, AtomicPtr, Ordering};
// We can use true weak linkage on ELF targets.
-#[cfg(not(any(target_os = "macos", target_os = "ios")))]
+#[cfg(not(any(target_os = "macos", target_os = "ios", target_os = "tvos")))]
pub(crate) macro weak {
(fn $name:ident($($t:ty),*) -> $ret:ty) => (
let ref $name: ExternWeak<unsafe extern "C" fn($($t),*) -> $ret> = {
@@ -43,7 +43,7 @@ pub(crate) macro weak {
}
// On non-ELF targets, use the dlsym approximation of weak linkage.
-#[cfg(any(target_os = "macos", target_os = "ios"))]
+#[cfg(any(target_os = "macos", target_os = "ios", target_os = "tvos"))]
pub(crate) use self::dlsym as weak;
pub(crate) struct ExternWeak<F: Copy> {