about summary refs log tree commit diff
path: root/library/std/src
diff options
context:
space:
mode:
Diffstat (limited to 'library/std/src')
-rw-r--r--library/std/src/os/horizon/fs.rs95
-rw-r--r--library/std/src/os/horizon/mod.rs6
-rw-r--r--library/std/src/os/horizon/raw.rs70
-rw-r--r--library/std/src/os/mod.rs2
-rw-r--r--library/std/src/os/unix/mod.rs2
-rw-r--r--library/std/src/os/unix/process.rs46
-rw-r--r--library/std/src/sys/unix/alloc.rs3
-rw-r--r--library/std/src/sys/unix/args.rs3
-rw-r--r--library/std/src/sys/unix/env.rs11
-rw-r--r--library/std/src/sys/unix/fd.rs41
-rw-r--r--library/std/src/sys/unix/fs.rs25
-rw-r--r--library/std/src/sys/unix/locks/pthread_condvar.rs13
-rw-r--r--library/std/src/sys/unix/mod.rs6
-rw-r--r--library/std/src/sys/unix/os.rs8
-rw-r--r--library/std/src/sys/unix/process/mod.rs3
-rw-r--r--library/std/src/sys/unix/process/process_unsupported.rs13
-rw-r--r--library/std/src/sys/unix/rand.rs16
-rw-r--r--library/std/src/sys/unix/thread_local_dtor.rs2
-rw-r--r--library/std/src/sys/unix/thread_parker.rs2
-rw-r--r--library/std/src/sys/unix/time.rs5
-rw-r--r--library/std/src/sys_common/net.rs14
21 files changed, 300 insertions, 86 deletions
diff --git a/library/std/src/os/horizon/fs.rs b/library/std/src/os/horizon/fs.rs
new file mode 100644
index 00000000000..1325522105d
--- /dev/null
+++ b/library/std/src/os/horizon/fs.rs
@@ -0,0 +1,95 @@
+#![stable(feature = "metadata_ext", since = "1.1.0")]
+
+use crate::fs::Metadata;
+use crate::sys_common::AsInner;
+
+/// OS-specific extensions to [`fs::Metadata`].
+///
+/// [`fs::Metadata`]: crate::fs::Metadata
+#[stable(feature = "metadata_ext", since = "1.1.0")]
+pub trait MetadataExt {
+    #[stable(feature = "metadata_ext2", since = "1.8.0")]
+    fn st_dev(&self) -> u64;
+    #[stable(feature = "metadata_ext2", since = "1.8.0")]
+    fn st_ino(&self) -> u64;
+    #[stable(feature = "metadata_ext2", since = "1.8.0")]
+    fn st_mode(&self) -> u32;
+    #[stable(feature = "metadata_ext2", since = "1.8.0")]
+    fn st_nlink(&self) -> u64;
+    #[stable(feature = "metadata_ext2", since = "1.8.0")]
+    fn st_uid(&self) -> u32;
+    #[stable(feature = "metadata_ext2", since = "1.8.0")]
+    fn st_gid(&self) -> u32;
+    #[stable(feature = "metadata_ext2", since = "1.8.0")]
+    fn st_rdev(&self) -> u64;
+    #[stable(feature = "metadata_ext2", since = "1.8.0")]
+    fn st_size(&self) -> u64;
+    #[stable(feature = "metadata_ext2", since = "1.8.0")]
+    fn st_atime(&self) -> i64;
+    #[stable(feature = "metadata_ext2", since = "1.8.0")]
+    fn st_atime_nsec(&self) -> i64;
+    #[stable(feature = "metadata_ext2", since = "1.8.0")]
+    fn st_mtime(&self) -> i64;
+    #[stable(feature = "metadata_ext2", since = "1.8.0")]
+    fn st_mtime_nsec(&self) -> i64;
+    #[stable(feature = "metadata_ext2", since = "1.8.0")]
+    fn st_ctime(&self) -> i64;
+    #[stable(feature = "metadata_ext2", since = "1.8.0")]
+    fn st_ctime_nsec(&self) -> i64;
+    #[stable(feature = "metadata_ext2", since = "1.8.0")]
+    fn st_blksize(&self) -> u64;
+    #[stable(feature = "metadata_ext2", since = "1.8.0")]
+    fn st_blocks(&self) -> u64;
+}
+
+#[stable(feature = "metadata_ext", since = "1.1.0")]
+impl MetadataExt for Metadata {
+    fn st_dev(&self) -> u64 {
+        self.as_inner().as_inner().st_dev as u64
+    }
+    fn st_ino(&self) -> u64 {
+        self.as_inner().as_inner().st_ino as u64
+    }
+    fn st_mode(&self) -> u32 {
+        self.as_inner().as_inner().st_mode as u32
+    }
+    fn st_nlink(&self) -> u64 {
+        self.as_inner().as_inner().st_nlink as u64
+    }
+    fn st_uid(&self) -> u32 {
+        self.as_inner().as_inner().st_uid as u32
+    }
+    fn st_gid(&self) -> u32 {
+        self.as_inner().as_inner().st_gid as u32
+    }
+    fn st_rdev(&self) -> u64 {
+        self.as_inner().as_inner().st_rdev as u64
+    }
+    fn st_size(&self) -> u64 {
+        self.as_inner().as_inner().st_size as u64
+    }
+    fn st_atime(&self) -> i64 {
+        self.as_inner().as_inner().st_atim.tv_sec
+    }
+    fn st_atime_nsec(&self) -> i64 {
+        self.as_inner().as_inner().st_atim.tv_nsec as i64
+    }
+    fn st_mtime(&self) -> i64 {
+        self.as_inner().as_inner().st_mtim.tv_sec
+    }
+    fn st_mtime_nsec(&self) -> i64 {
+        self.as_inner().as_inner().st_mtim.tv_nsec as i64
+    }
+    fn st_ctime(&self) -> i64 {
+        self.as_inner().as_inner().st_ctim.tv_sec
+    }
+    fn st_ctime_nsec(&self) -> i64 {
+        self.as_inner().as_inner().st_ctim.tv_nsec as i64
+    }
+    fn st_blksize(&self) -> u64 {
+        self.as_inner().as_inner().st_blksize as u64
+    }
+    fn st_blocks(&self) -> u64 {
+        self.as_inner().as_inner().st_blocks as u64
+    }
+}
diff --git a/library/std/src/os/horizon/mod.rs b/library/std/src/os/horizon/mod.rs
new file mode 100644
index 00000000000..326d0ae9cb9
--- /dev/null
+++ b/library/std/src/os/horizon/mod.rs
@@ -0,0 +1,6 @@
+//! Definitions for Horizon OS
+
+#![stable(feature = "raw_ext", since = "1.1.0")]
+
+pub mod fs;
+pub(crate) mod raw;
diff --git a/library/std/src/os/horizon/raw.rs b/library/std/src/os/horizon/raw.rs
new file mode 100644
index 00000000000..929fa7db1f9
--- /dev/null
+++ b/library/std/src/os/horizon/raw.rs
@@ -0,0 +1,70 @@
+//! Horizon OS raw type definitions
+
+#![stable(feature = "raw_ext", since = "1.1.0")]
+#![deprecated(
+    since = "1.8.0",
+    note = "these type aliases are no longer supported by \
+            the standard library, the `libc` crate on \
+            crates.io should be used instead for the correct \
+            definitions"
+)]
+#![allow(deprecated)]
+
+use crate::os::raw::c_long;
+use crate::os::unix::raw::{gid_t, uid_t};
+
+#[stable(feature = "pthread_t", since = "1.8.0")]
+pub type pthread_t = libc::pthread_t;
+
+#[stable(feature = "raw_ext", since = "1.1.0")]
+pub type blkcnt_t = libc::blkcnt_t;
+
+#[stable(feature = "raw_ext", since = "1.1.0")]
+pub type blksize_t = libc::blksize_t;
+#[stable(feature = "raw_ext", since = "1.1.0")]
+pub type dev_t = libc::dev_t;
+#[stable(feature = "raw_ext", since = "1.1.0")]
+pub type ino_t = libc::ino_t;
+#[stable(feature = "raw_ext", since = "1.1.0")]
+pub type mode_t = libc::mode_t;
+#[stable(feature = "raw_ext", since = "1.1.0")]
+pub type nlink_t = libc::nlink_t;
+#[stable(feature = "raw_ext", since = "1.1.0")]
+pub type off_t = libc::off_t;
+
+#[stable(feature = "raw_ext", since = "1.1.0")]
+pub type time_t = libc::time_t;
+
+#[repr(C)]
+#[derive(Clone)]
+#[stable(feature = "raw_ext", since = "1.1.0")]
+pub struct stat {
+    #[stable(feature = "raw_ext", since = "1.1.0")]
+    pub st_dev: dev_t,
+    #[stable(feature = "raw_ext", since = "1.1.0")]
+    pub st_ino: ino_t,
+    #[stable(feature = "raw_ext", since = "1.1.0")]
+    pub st_mode: mode_t,
+    #[stable(feature = "raw_ext", since = "1.1.0")]
+    pub st_nlink: nlink_t,
+    #[stable(feature = "raw_ext", since = "1.1.0")]
+    pub st_uid: uid_t,
+    #[stable(feature = "raw_ext", since = "1.1.0")]
+    pub st_gid: gid_t,
+    #[stable(feature = "raw_ext", since = "1.1.0")]
+    pub st_rdev: dev_t,
+    #[stable(feature = "raw_ext", since = "1.1.0")]
+    pub st_size: off_t,
+    #[stable(feature = "raw_ext", since = "1.1.0")]
+    pub st_atime: time_t,
+    #[stable(feature = "raw_ext", since = "1.1.0")]
+    pub st_mtime: time_t,
+    #[stable(feature = "raw_ext", since = "1.1.0")]
+    pub st_ctime: time_t,
+    #[stable(feature = "raw_ext", since = "1.1.0")]
+    pub st_blksize: blksize_t,
+    #[stable(feature = "raw_ext", since = "1.1.0")]
+    pub st_blocks: blkcnt_t,
+    #[stable(feature = "raw_ext", since = "1.1.0")]
+    pub st_spare4: [c_long; 2usize],
+}
diff --git a/library/std/src/os/mod.rs b/library/std/src/os/mod.rs
index 029f131c40b..a1df72a8a04 100644
--- a/library/std/src/os/mod.rs
+++ b/library/std/src/os/mod.rs
@@ -123,6 +123,8 @@ pub mod freebsd;
 pub mod fuchsia;
 #[cfg(target_os = "haiku")]
 pub mod haiku;
+#[cfg(target_os = "horizon")]
+pub mod horizon;
 #[cfg(target_os = "illumos")]
 pub mod illumos;
 #[cfg(target_os = "ios")]
diff --git a/library/std/src/os/unix/mod.rs b/library/std/src/os/unix/mod.rs
index 7b8ca79eeb8..cef546487f3 100644
--- a/library/std/src/os/unix/mod.rs
+++ b/library/std/src/os/unix/mod.rs
@@ -51,6 +51,8 @@ mod platform {
     pub use crate::os::fuchsia::*;
     #[cfg(target_os = "haiku")]
     pub use crate::os::haiku::*;
+    #[cfg(target_os = "horizon")]
+    pub use crate::os::horizon::*;
     #[cfg(target_os = "illumos")]
     pub use crate::os::illumos::*;
     #[cfg(target_os = "ios")]
diff --git a/library/std/src/os/unix/process.rs b/library/std/src/os/unix/process.rs
index 3e989c85db9..5065530e8d4 100644
--- a/library/std/src/os/unix/process.rs
+++ b/library/std/src/os/unix/process.rs
@@ -12,6 +12,16 @@ use crate::sealed::Sealed;
 use crate::sys;
 use crate::sys_common::{AsInner, AsInnerMut, FromInner, IntoInner};
 
+#[cfg(not(any(target_os = "vxworks", target_os = "espidf", target_os = "horizon")))]
+type UserId = u32;
+#[cfg(not(any(target_os = "vxworks", target_os = "espidf", target_os = "horizon")))]
+type GroupId = u32;
+
+#[cfg(any(target_os = "vxworks", target_os = "espidf", target_os = "horizon"))]
+type UserId = u16;
+#[cfg(any(target_os = "vxworks", target_os = "espidf", target_os = "horizon"))]
+type GroupId = u16;
+
 /// Unix-specific extensions to the [`process::Command`] builder.
 ///
 /// This trait is sealed: it cannot be implemented outside the standard library.
@@ -22,29 +32,17 @@ pub trait CommandExt: Sealed {
     /// `setuid` call in the child process. Failure in the `setuid`
     /// call will cause the spawn to fail.
     #[stable(feature = "rust1", since = "1.0.0")]
-    fn uid(
-        &mut self,
-        #[cfg(not(any(target_os = "vxworks", target_os = "espidf")))] id: u32,
-        #[cfg(any(target_os = "vxworks", target_os = "espidf"))] id: u16,
-    ) -> &mut process::Command;
+    fn uid(&mut self, id: UserId) -> &mut process::Command;
 
     /// Similar to `uid`, but sets the group ID of the child process. This has
     /// the same semantics as the `uid` field.
     #[stable(feature = "rust1", since = "1.0.0")]
-    fn gid(
-        &mut self,
-        #[cfg(not(any(target_os = "vxworks", target_os = "espidf")))] id: u32,
-        #[cfg(any(target_os = "vxworks", target_os = "espidf"))] id: u16,
-    ) -> &mut process::Command;
+    fn gid(&mut self, id: GroupId) -> &mut process::Command;
 
     /// Sets the supplementary group IDs for the calling process. Translates to
     /// a `setgroups` call in the child process.
     #[unstable(feature = "setgroups", issue = "90747")]
-    fn groups(
-        &mut self,
-        #[cfg(not(any(target_os = "vxworks", target_os = "espidf")))] groups: &[u32],
-        #[cfg(any(target_os = "vxworks", target_os = "espidf"))] groups: &[u16],
-    ) -> &mut process::Command;
+    fn groups(&mut self, groups: &[GroupId]) -> &mut process::Command;
 
     /// Schedules a closure to be run just before the `exec` function is
     /// invoked.
@@ -158,29 +156,17 @@ pub trait CommandExt: Sealed {
 
 #[stable(feature = "rust1", since = "1.0.0")]
 impl CommandExt for process::Command {
-    fn uid(
-        &mut self,
-        #[cfg(not(any(target_os = "vxworks", target_os = "espidf")))] id: u32,
-        #[cfg(any(target_os = "vxworks", target_os = "espidf"))] id: u16,
-    ) -> &mut process::Command {
+    fn uid(&mut self, id: UserId) -> &mut process::Command {
         self.as_inner_mut().uid(id);
         self
     }
 
-    fn gid(
-        &mut self,
-        #[cfg(not(any(target_os = "vxworks", target_os = "espidf")))] id: u32,
-        #[cfg(any(target_os = "vxworks", target_os = "espidf"))] id: u16,
-    ) -> &mut process::Command {
+    fn gid(&mut self, id: GroupId) -> &mut process::Command {
         self.as_inner_mut().gid(id);
         self
     }
 
-    fn groups(
-        &mut self,
-        #[cfg(not(any(target_os = "vxworks", target_os = "espidf")))] groups: &[u32],
-        #[cfg(any(target_os = "vxworks", target_os = "espidf"))] groups: &[u16],
-    ) -> &mut process::Command {
+    fn groups(&mut self, groups: &[GroupId]) -> &mut process::Command {
         self.as_inner_mut().groups(groups);
         self
     }
diff --git a/library/std/src/sys/unix/alloc.rs b/library/std/src/sys/unix/alloc.rs
index 7c3d9573940..9d6567c9fb4 100644
--- a/library/std/src/sys/unix/alloc.rs
+++ b/library/std/src/sys/unix/alloc.rs
@@ -58,7 +58,8 @@ cfg_if::cfg_if! {
         target_os = "illumos",
         target_os = "redox",
         target_os = "solaris",
-        target_os = "espidf"
+        target_os = "espidf",
+        target_os = "horizon"
     ))] {
         #[inline]
         unsafe fn aligned_malloc(layout: &Layout) -> *mut u8 {
diff --git a/library/std/src/sys/unix/args.rs b/library/std/src/sys/unix/args.rs
index ee5e3983ac2..79964e2b238 100644
--- a/library/std/src/sys/unix/args.rs
+++ b/library/std/src/sys/unix/args.rs
@@ -68,7 +68,8 @@ impl DoubleEndedIterator for Args {
     target_os = "l4re",
     target_os = "fuchsia",
     target_os = "redox",
-    target_os = "vxworks"
+    target_os = "vxworks",
+    target_os = "horizon"
 ))]
 mod imp {
     use super::Args;
diff --git a/library/std/src/sys/unix/env.rs b/library/std/src/sys/unix/env.rs
index 60551aeb3e7..4d8391656a4 100644
--- a/library/std/src/sys/unix/env.rs
+++ b/library/std/src/sys/unix/env.rs
@@ -119,6 +119,17 @@ pub mod os {
     pub const EXE_EXTENSION: &str = "";
 }
 
+#[cfg(target_os = "horizon")]
+pub mod os {
+    pub const FAMILY: &str = "unix";
+    pub const OS: &str = "horizon";
+    pub const DLL_PREFIX: &str = "lib";
+    pub const DLL_SUFFIX: &str = ".so";
+    pub const DLL_EXTENSION: &str = "so";
+    pub const EXE_SUFFIX: &str = ".elf";
+    pub const EXE_EXTENSION: &str = "elf";
+}
+
 #[cfg(all(target_os = "emscripten", target_arch = "asmjs"))]
 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 40a64585802..137ca3a7633 100644
--- a/library/std/src/sys/unix/fd.rs
+++ b/library/std/src/sys/unix/fd.rs
@@ -9,8 +9,6 @@ use crate::os::unix::io::{AsFd, AsRawFd, BorrowedFd, FromRawFd, IntoRawFd, Owned
 use crate::sys::cvt;
 use crate::sys_common::{AsInner, FromInner, IntoInner};
 
-use libc::{c_int, c_void};
-
 #[cfg(any(
     target_os = "android",
     target_os = "linux",
@@ -38,7 +36,7 @@ pub struct FileDesc(OwnedFd);
 // larger than or equal to INT_MAX. To handle both of these the read
 // size is capped on both platforms.
 #[cfg(target_os = "macos")]
-const READ_LIMIT: usize = c_int::MAX as usize - 1;
+const READ_LIMIT: usize = libc::c_int::MAX as usize - 1;
 #[cfg(not(target_os = "macos"))]
 const READ_LIMIT: usize = libc::ssize_t::MAX as usize;
 
@@ -69,6 +67,7 @@ const fn max_iov() -> usize {
     target_os = "macos",
     target_os = "netbsd",
     target_os = "openbsd",
+    target_os = "horizon"
 )))]
 const fn max_iov() -> usize {
     16 // The minimum value required by POSIX.
@@ -79,33 +78,33 @@ impl FileDesc {
         let ret = cvt(unsafe {
             libc::read(
                 self.as_raw_fd(),
-                buf.as_mut_ptr() as *mut c_void,
+                buf.as_mut_ptr() as *mut libc::c_void,
                 cmp::min(buf.len(), READ_LIMIT),
             )
         })?;
         Ok(ret as usize)
     }
 
-    #[cfg(not(target_os = "espidf"))]
+    #[cfg(not(any(target_os = "espidf", target_os = "horizon")))]
     pub fn read_vectored(&self, bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> {
         let ret = cvt(unsafe {
             libc::readv(
                 self.as_raw_fd(),
                 bufs.as_ptr() as *const libc::iovec,
-                cmp::min(bufs.len(), max_iov()) as c_int,
+                cmp::min(bufs.len(), max_iov()) as libc::c_int,
             )
         })?;
         Ok(ret as usize)
     }
 
-    #[cfg(target_os = "espidf")]
+    #[cfg(any(target_os = "espidf", target_os = "horizon"))]
     pub fn read_vectored(&self, bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> {
         return crate::io::default_read_vectored(|b| self.read(b), bufs);
     }
 
     #[inline]
     pub fn is_read_vectored(&self) -> bool {
-        cfg!(not(target_os = "espidf"))
+        cfg!(not(any(target_os = "espidf", target_os = "horizon")))
     }
 
     pub fn read_to_end(&self, buf: &mut Vec<u8>) -> io::Result<usize> {
@@ -122,7 +121,7 @@ impl FileDesc {
         unsafe {
             cvt(pread64(
                 self.as_raw_fd(),
-                buf.as_mut_ptr() as *mut c_void,
+                buf.as_mut_ptr() as *mut libc::c_void,
                 cmp::min(buf.len(), READ_LIMIT),
                 offset as off64_t,
             ))
@@ -134,7 +133,7 @@ impl FileDesc {
         let ret = cvt(unsafe {
             libc::read(
                 self.as_raw_fd(),
-                buf.unfilled_mut().as_mut_ptr() as *mut c_void,
+                buf.unfilled_mut().as_mut_ptr() as *mut libc::c_void,
                 cmp::min(buf.remaining(), READ_LIMIT),
             )
         })?;
@@ -151,33 +150,33 @@ impl FileDesc {
         let ret = cvt(unsafe {
             libc::write(
                 self.as_raw_fd(),
-                buf.as_ptr() as *const c_void,
+                buf.as_ptr() as *const libc::c_void,
                 cmp::min(buf.len(), READ_LIMIT),
             )
         })?;
         Ok(ret as usize)
     }
 
-    #[cfg(not(target_os = "espidf"))]
+    #[cfg(not(any(target_os = "espidf", target_os = "horizon")))]
     pub fn write_vectored(&self, bufs: &[IoSlice<'_>]) -> io::Result<usize> {
         let ret = cvt(unsafe {
             libc::writev(
                 self.as_raw_fd(),
                 bufs.as_ptr() as *const libc::iovec,
-                cmp::min(bufs.len(), max_iov()) as c_int,
+                cmp::min(bufs.len(), max_iov()) as libc::c_int,
             )
         })?;
         Ok(ret as usize)
     }
 
-    #[cfg(target_os = "espidf")]
+    #[cfg(any(target_os = "espidf", target_os = "horizon"))]
     pub fn write_vectored(&self, bufs: &[IoSlice<'_>]) -> io::Result<usize> {
         return crate::io::default_write_vectored(|b| self.write(b), bufs);
     }
 
     #[inline]
     pub fn is_write_vectored(&self) -> bool {
-        cfg!(not(target_os = "espidf"))
+        cfg!(not(any(target_os = "espidf", target_os = "horizon")))
     }
 
     pub fn write_at(&self, buf: &[u8], offset: u64) -> io::Result<usize> {
@@ -189,7 +188,7 @@ impl FileDesc {
         unsafe {
             cvt(pwrite64(
                 self.as_raw_fd(),
-                buf.as_ptr() as *const c_void,
+                buf.as_ptr() as *const libc::c_void,
                 cmp::min(buf.len(), READ_LIMIT),
                 offset as off64_t,
             ))
@@ -221,7 +220,7 @@ impl FileDesc {
         }
     }
     #[cfg(any(
-        all(target_env = "newlib", not(target_os = "espidf")),
+        all(target_env = "newlib", not(any(target_os = "espidf", target_os = "horizon"))),
         target_os = "solaris",
         target_os = "illumos",
         target_os = "emscripten",
@@ -242,17 +241,17 @@ impl FileDesc {
             Ok(())
         }
     }
-    #[cfg(target_os = "espidf")]
+    #[cfg(any(target_os = "espidf", target_os = "horizon"))]
     pub fn set_cloexec(&self) -> io::Result<()> {
-        // FD_CLOEXEC is not supported in ESP-IDF but there's no need to,
-        // because ESP-IDF does not support spawning processes either.
+        // FD_CLOEXEC is not supported in ESP-IDF and Horizon OS but there's no need to,
+        // because neither supports spawning processes.
         Ok(())
     }
 
     #[cfg(target_os = "linux")]
     pub fn set_nonblocking(&self, nonblocking: bool) -> io::Result<()> {
         unsafe {
-            let v = nonblocking as c_int;
+            let v = nonblocking as libc::c_int;
             cvt(libc::ioctl(self.as_raw_fd(), libc::FIONBIO, &v))?;
             Ok(())
         }
diff --git a/library/std/src/sys/unix/fs.rs b/library/std/src/sys/unix/fs.rs
index 5d0fb079003..8b0bbd6a55c 100644
--- a/library/std/src/sys/unix/fs.rs
+++ b/library/std/src/sys/unix/fs.rs
@@ -395,7 +395,7 @@ impl FileAttr {
 
 #[cfg(not(target_os = "netbsd"))]
 impl FileAttr {
-    #[cfg(all(not(target_os = "vxworks"), not(target_os = "espidf")))]
+    #[cfg(not(any(target_os = "vxworks", target_os = "espidf", target_os = "horizon")))]
     pub fn modified(&self) -> io::Result<SystemTime> {
         #[cfg(target_pointer_width = "32")]
         cfg_has_statx! {
@@ -412,7 +412,12 @@ impl FileAttr {
         Ok(SystemTime::new(self.stat.st_mtime as i64, 0))
     }
 
-    #[cfg(all(not(target_os = "vxworks"), not(target_os = "espidf")))]
+    #[cfg(target_os = "horizon")]
+    pub fn modified(&self) -> io::Result<SystemTime> {
+        Ok(SystemTime::from(self.stat.st_mtim))
+    }
+
+    #[cfg(not(any(target_os = "vxworks", target_os = "espidf", target_os = "horizon")))]
     pub fn accessed(&self) -> io::Result<SystemTime> {
         #[cfg(target_pointer_width = "32")]
         cfg_has_statx! {
@@ -429,6 +434,11 @@ impl FileAttr {
         Ok(SystemTime::new(self.stat.st_atime as i64, 0))
     }
 
+    #[cfg(target_os = "horizon")]
+    pub fn accessed(&self) -> io::Result<SystemTime> {
+        Ok(SystemTime::from(self.stat.st_atim))
+    }
+
     #[cfg(any(
         target_os = "freebsd",
         target_os = "openbsd",
@@ -707,7 +717,8 @@ impl DirEntry {
         target_os = "fuchsia",
         target_os = "redox",
         target_os = "vxworks",
-        target_os = "espidf"
+        target_os = "espidf",
+        target_os = "horizon"
     ))]
     pub fn ino(&self) -> u64 {
         self.entry.d_ino as u64
@@ -1251,7 +1262,7 @@ pub fn link(original: &Path, link: &Path) -> io::Result<()> {
     let original = cstr(original)?;
     let link = cstr(link)?;
     cfg_if::cfg_if! {
-        if #[cfg(any(target_os = "vxworks", target_os = "redox", target_os = "android", target_os = "espidf"))] {
+        if #[cfg(any(target_os = "vxworks", target_os = "redox", target_os = "android", target_os = "espidf", target_os = "horizon"))] {
             // 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.
@@ -1549,14 +1560,14 @@ pub fn chroot(dir: &Path) -> io::Result<()> {
 
 pub use remove_dir_impl::remove_dir_all;
 
-// Fallback for REDOX and ESP-IDF (and Miri)
-#[cfg(any(target_os = "redox", target_os = "espidf", miri))]
+// Fallback for REDOX, ESP-ID, Horizon, and Miri
+#[cfg(any(target_os = "redox", target_os = "espidf", target_os = "horizon", miri))]
 mod remove_dir_impl {
     pub use crate::sys_common::fs::remove_dir_all;
 }
 
 // Modern implementation using openat(), unlinkat() and fdopendir()
-#[cfg(not(any(target_os = "redox", target_os = "espidf", miri)))]
+#[cfg(not(any(target_os = "redox", target_os = "espidf", target_os = "horizon", miri)))]
 mod remove_dir_impl {
     use super::{cstr, lstat, Dir, DirEntry, InnerReadDir, ReadDir};
     use crate::ffi::CStr;
diff --git a/library/std/src/sys/unix/locks/pthread_condvar.rs b/library/std/src/sys/unix/locks/pthread_condvar.rs
index 61c28d696bc..78f10f0534c 100644
--- a/library/std/src/sys/unix/locks/pthread_condvar.rs
+++ b/library/std/src/sys/unix/locks/pthread_condvar.rs
@@ -47,7 +47,9 @@ impl Condvar {
     // So on that platform, init() should always be called
     // Moreover, that platform does not have pthread_condattr_setclock support,
     // hence that initialization should be skipped as well
-    #[cfg(target_os = "espidf")]
+    //
+    // Similar story for the 3DS (horizon).
+    #[cfg(any(target_os = "espidf", target_os = "horizon"))]
     unsafe fn init(&mut self) {
         let r = libc::pthread_cond_init(self.inner.get(), crate::ptr::null());
         assert_eq!(r, 0);
@@ -59,7 +61,8 @@ impl Condvar {
         target_os = "l4re",
         target_os = "android",
         target_os = "redox",
-        target_os = "espidf"
+        target_os = "espidf",
+        target_os = "horizon"
     )))]
     unsafe fn init(&mut self) {
         use crate::mem::MaybeUninit;
@@ -100,7 +103,8 @@ impl Condvar {
         target_os = "macos",
         target_os = "ios",
         target_os = "android",
-        target_os = "espidf"
+        target_os = "espidf",
+        target_os = "horizon"
     )))]
     pub unsafe fn wait_timeout(&self, mutex: &Mutex, dur: Duration) -> bool {
         use crate::mem;
@@ -132,7 +136,8 @@ impl Condvar {
         target_os = "macos",
         target_os = "ios",
         target_os = "android",
-        target_os = "espidf"
+        target_os = "espidf",
+        target_os = "horizon"
     ))]
     pub unsafe fn wait_timeout(&self, mutex: &Mutex, mut dur: Duration) -> bool {
         use crate::ptr;
diff --git a/library/std/src/sys/unix/mod.rs b/library/std/src/sys/unix/mod.rs
index ddec60961f0..34a023b02c4 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) {
             target_os = "ios",
             target_os = "redox",
             target_os = "l4re",
+            target_os = "horizon",
         )))]
         'poll: {
             use crate::sys::os::errno;
@@ -131,6 +132,7 @@ pub unsafe fn init(argc: isize, argv: *const *const u8) {
             target_os = "fuchsia",
             target_os = "vxworks",
             target_os = "l4re",
+            target_os = "horizon",
         )))]
         {
             use crate::sys::os::errno;
@@ -149,7 +151,7 @@ pub unsafe fn init(argc: isize, argv: *const *const u8) {
     }
 
     unsafe fn reset_sigpipe() {
-        #[cfg(not(any(target_os = "emscripten", target_os = "fuchsia")))]
+        #[cfg(not(any(target_os = "emscripten", target_os = "fuchsia", target_os = "horizon")))]
         rtassert!(signal(libc::SIGPIPE, libc::SIG_IGN) != libc::SIG_ERR);
     }
 }
@@ -344,7 +346,7 @@ cfg_if::cfg_if! {
     }
 }
 
-#[cfg(target_os = "espidf")]
+#[cfg(any(target_os = "espidf", target_os = "horizon"))]
 mod unsupported {
     use crate::io;
 
diff --git a/library/std/src/sys/unix/os.rs b/library/std/src/sys/unix/os.rs
index 92bea9346d8..7252ad32184 100644
--- a/library/std/src/sys/unix/os.rs
+++ b/library/std/src/sys/unix/os.rs
@@ -446,7 +446,7 @@ pub fn current_exe() -> io::Result<PathBuf> {
     path.canonicalize()
 }
 
-#[cfg(target_os = "espidf")]
+#[cfg(any(target_os = "espidf", target_os = "horizon"))]
 pub fn current_exe() -> io::Result<PathBuf> {
     super::unsupported::unsupported()
 }
@@ -601,7 +601,8 @@ pub fn home_dir() -> Option<PathBuf> {
         target_os = "emscripten",
         target_os = "redox",
         target_os = "vxworks",
-        target_os = "espidf"
+        target_os = "espidf",
+        target_os = "horizon"
     ))]
     unsafe fn fallback() -> Option<OsString> {
         None
@@ -612,7 +613,8 @@ pub fn home_dir() -> Option<PathBuf> {
         target_os = "emscripten",
         target_os = "redox",
         target_os = "vxworks",
-        target_os = "espidf"
+        target_os = "espidf",
+        target_os = "horizon"
     )))]
     unsafe fn fallback() -> Option<OsString> {
         let amt = match libc::sysconf(libc::_SC_GETPW_R_SIZE_MAX) {
diff --git a/library/std/src/sys/unix/process/mod.rs b/library/std/src/sys/unix/process/mod.rs
index 0165ece849e..3701510f3a4 100644
--- a/library/std/src/sys/unix/process/mod.rs
+++ b/library/std/src/sys/unix/process/mod.rs
@@ -3,6 +3,7 @@ pub use self::process_inner::{ExitStatus, ExitStatusError, Process};
 pub use crate::ffi::OsString as EnvKey;
 pub use crate::sys_common::process::CommandEnvs;
 
+#[cfg_attr(any(target_os = "espidf", target_os = "horizon"), allow(unused))]
 mod process_common;
 
 cfg_if::cfg_if! {
@@ -13,7 +14,7 @@ cfg_if::cfg_if! {
     } else if #[cfg(target_os = "vxworks")] {
         #[path = "process_vxworks.rs"]
         mod process_inner;
-    } else if #[cfg(target_os = "espidf")] {
+    } else if #[cfg(any(target_os = "espidf", target_os = "horizon"))] {
         #[path = "process_unsupported.rs"]
         mod process_inner;
     } else {
diff --git a/library/std/src/sys/unix/process/process_unsupported.rs b/library/std/src/sys/unix/process/process_unsupported.rs
index 5db57ee9e9e..72f9f3f9ca7 100644
--- a/library/std/src/sys/unix/process/process_unsupported.rs
+++ b/library/std/src/sys/unix/process/process_unsupported.rs
@@ -1,10 +1,6 @@
 use crate::fmt;
 use crate::io;
-use crate::io::ErrorKind;
 use crate::num::NonZeroI32;
-use crate::sys;
-use crate::sys::cvt;
-use crate::sys::pipe::AnonPipe;
 use crate::sys::process::process_common::*;
 use crate::sys::unix::unsupported::*;
 use core::ffi::NonZero_c_int;
@@ -18,13 +14,13 @@ use libc::{c_int, pid_t};
 impl Command {
     pub fn spawn(
         &mut self,
-        default: Stdio,
-        needs_stdin: bool,
+        _default: Stdio,
+        _needs_stdin: bool,
     ) -> io::Result<(Process, StdioPipes)> {
         unsupported()
     }
 
-    pub fn exec(&mut self, default: Stdio) -> io::Error {
+    pub fn exec(&mut self, _default: Stdio) -> io::Error {
         unsupported_err()
     }
 }
@@ -34,7 +30,7 @@ impl Command {
 ////////////////////////////////////////////////////////////////////////////////
 
 pub struct Process {
-    handle: pid_t,
+    _handle: pid_t,
 }
 
 impl Process {
@@ -59,6 +55,7 @@ impl Process {
 pub struct ExitStatus(c_int);
 
 impl ExitStatus {
+    #[cfg_attr(target_os = "horizon", allow(unused))]
     pub fn success(&self) -> bool {
         self.code() == Some(0)
     }
diff --git a/library/std/src/sys/unix/rand.rs b/library/std/src/sys/unix/rand.rs
index ea6df724713..56d01074c20 100644
--- a/library/std/src/sys/unix/rand.rs
+++ b/library/std/src/sys/unix/rand.rs
@@ -59,17 +59,27 @@ mod imp {
         unsafe { getrandom(buf.as_mut_ptr().cast(), buf.len(), libc::GRND_NONBLOCK) }
     }
 
-    #[cfg(target_os = "espidf")]
+    #[cfg(any(target_os = "espidf", target_os = "horizon"))]
     fn getrandom(buf: &mut [u8]) -> libc::ssize_t {
         unsafe { libc::getrandom(buf.as_mut_ptr().cast(), buf.len(), 0) }
     }
 
-    #[cfg(not(any(target_os = "linux", target_os = "android", target_os = "espidf")))]
+    #[cfg(not(any(
+        target_os = "linux",
+        target_os = "android",
+        target_os = "espidf",
+        target_os = "horizon"
+    )))]
     fn getrandom_fill_bytes(_buf: &mut [u8]) -> bool {
         false
     }
 
-    #[cfg(any(target_os = "linux", target_os = "android", target_os = "espidf"))]
+    #[cfg(any(
+        target_os = "linux",
+        target_os = "android",
+        target_os = "espidf",
+        target_os = "horizon"
+    ))]
     fn getrandom_fill_bytes(v: &mut [u8]) -> bool {
         use crate::sync::atomic::{AtomicBool, Ordering};
         use crate::sys::os::errno;
diff --git a/library/std/src/sys/unix/thread_local_dtor.rs b/library/std/src/sys/unix/thread_local_dtor.rs
index c3f410353b9..6e8be2a91de 100644
--- a/library/std/src/sys/unix/thread_local_dtor.rs
+++ b/library/std/src/sys/unix/thread_local_dtor.rs
@@ -93,7 +93,7 @@ pub unsafe fn register_dtor(t: *mut u8, dtor: unsafe extern "C" fn(*mut u8)) {
     }
 }
 
-#[cfg(target_os = "vxworks")]
+#[cfg(any(target_os = "vxworks", target_os = "horizon"))]
 pub unsafe fn register_dtor(t: *mut u8, dtor: unsafe extern "C" fn(*mut u8)) {
     use crate::sys_common::thread_local_dtor::register_dtor_fallback;
     register_dtor_fallback(t, dtor);
diff --git a/library/std/src/sys/unix/thread_parker.rs b/library/std/src/sys/unix/thread_parker.rs
index 30ed2ec7f54..76278ae30f1 100644
--- a/library/std/src/sys/unix/thread_parker.rs
+++ b/library/std/src/sys/unix/thread_parker.rs
@@ -115,7 +115,7 @@ impl Parker {
                 target_os = "redox"
             ))] {
                 addr_of_mut!((*parker).cvar).write(UnsafeCell::new(libc::PTHREAD_COND_INITIALIZER));
-            } else if #[cfg(target_os = "espidf")] {
+            } else if #[cfg(any(target_os = "espidf", target_os = "horizon"))] {
                 let r = libc::pthread_cond_init(addr_of_mut!((*parker).cvar).cast(), crate::ptr::null());
                 assert_eq!(r, 0);
             } else {
diff --git a/library/std/src/sys/unix/time.rs b/library/std/src/sys/unix/time.rs
index f99c453a3a8..d114af49d26 100644
--- a/library/std/src/sys/unix/time.rs
+++ b/library/std/src/sys/unix/time.rs
@@ -18,6 +18,7 @@ pub(in crate::sys::unix) struct Timespec {
 }
 
 impl SystemTime {
+    #[cfg_attr(target_os = "horizon", allow(unused))]
     pub fn new(tv_sec: i64, tv_nsec: i64) -> SystemTime {
         SystemTime { t: Timespec::new(tv_sec, tv_nsec) }
     }
@@ -303,9 +304,9 @@ mod inner {
         }
     }
 
-    #[cfg(not(any(target_os = "dragonfly", target_os = "espidf")))]
+    #[cfg(not(any(target_os = "dragonfly", target_os = "espidf", target_os = "horizon")))]
     pub type clock_t = libc::c_int;
-    #[cfg(any(target_os = "dragonfly", target_os = "espidf"))]
+    #[cfg(any(target_os = "dragonfly", target_os = "espidf", target_os = "horizon"))]
     pub type clock_t = libc::c_ulong;
 
     impl Timespec {
diff --git a/library/std/src/sys_common/net.rs b/library/std/src/sys_common/net.rs
index 05425f4a362..f5730a2cea5 100644
--- a/library/std/src/sys_common/net.rs
+++ b/library/std/src/sys_common/net.rs
@@ -398,8 +398,20 @@ impl TcpListener {
         let (addrp, len) = addr.into_inner();
         cvt(unsafe { c::bind(sock.as_raw(), addrp, len as _) })?;
 
+        cfg_if::cfg_if! {
+            if #[cfg(target_os = "horizon")] {
+                // The 3DS doesn't support a big connection backlog. Sometimes
+                // it allows up to about 37, but other times it doesn't even
+                // accept 32. There may be a global limitation causing this.
+                let backlog = 20;
+            } else {
+                // The default for all other platforms
+                let backlog = 128;
+            }
+        }
+
         // Start listening
-        cvt(unsafe { c::listen(sock.as_raw(), 128) })?;
+        cvt(unsafe { c::listen(sock.as_raw(), backlog) })?;
         Ok(TcpListener { inner: sock })
     }