mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-22 06:44:35 +00:00
Auto merge of #106673 - flba-eb:add_qnx_nto_stdlib, r=workingjubilee
Add support for QNX Neutrino to standard library This change: - adds standard library support for QNX Neutrino (7.1). - upgrades `libc` to version `0.2.139` which supports QNX Neutrino `@gh-tr` ⚠️ Backtraces on QNX require https://github.com/rust-lang/backtrace-rs/pull/507 which is not yet merged! (But everything else works without these changes) ⚠️ Tested mainly with a x86_64 virtual machine (see qnx-nto.md) and partially with an aarch64 hardware (some tests fail due to constrained resources).
This commit is contained in:
commit
864b6258fc
@ -2319,9 +2319,9 @@ checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55"
|
||||
|
||||
[[package]]
|
||||
name = "libc"
|
||||
version = "0.2.138"
|
||||
version = "0.2.139"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "db6d7e329c562c5dfab7a46a2afabc8b987ab9a4834c9d1ca04dc54c1546cef8"
|
||||
checksum = "201de327520df007757c1f0adce6e827fe8562fbc28bfd9c15571c66ca1f5f79"
|
||||
dependencies = [
|
||||
"rustc-std-workspace-core",
|
||||
]
|
||||
|
@ -144,6 +144,7 @@ mod c_char_definition {
|
||||
)
|
||||
),
|
||||
all(target_os = "fuchsia", target_arch = "aarch64"),
|
||||
all(target_os = "nto", target_arch = "aarch64"),
|
||||
target_os = "horizon"
|
||||
))] {
|
||||
pub type c_char = u8;
|
||||
|
@ -15,7 +15,7 @@ cfg-if = { version = "1.0", features = ['rustc-dep-of-std'] }
|
||||
panic_unwind = { path = "../panic_unwind", optional = true }
|
||||
panic_abort = { path = "../panic_abort" }
|
||||
core = { path = "../core" }
|
||||
libc = { version = "0.2.138", default-features = false, features = ['rustc-dep-of-std'] }
|
||||
libc = { version = "0.2.139", default-features = false, features = ['rustc-dep-of-std'] }
|
||||
compiler_builtins = { version = "0.1.87" }
|
||||
profiler_builtins = { path = "../profiler_builtins", optional = true }
|
||||
unwind = { path = "../unwind" }
|
||||
|
@ -31,6 +31,7 @@ fn main() {
|
||||
|| target.contains("espidf")
|
||||
|| target.contains("solid")
|
||||
|| target.contains("nintendo-3ds")
|
||||
|| target.contains("nto")
|
||||
{
|
||||
// These platforms don't have any special requirements.
|
||||
} else {
|
||||
|
@ -670,7 +670,10 @@ fn debug() {
|
||||
// FIXME: re-enabled openbsd tests once their socket timeout code
|
||||
// no longer has rounding errors.
|
||||
// VxWorks ignores SO_SNDTIMEO.
|
||||
#[cfg_attr(any(target_os = "netbsd", target_os = "openbsd", target_os = "vxworks"), ignore)]
|
||||
#[cfg_attr(
|
||||
any(target_os = "netbsd", target_os = "openbsd", target_os = "vxworks", target_os = "nto"),
|
||||
ignore
|
||||
)]
|
||||
#[cfg_attr(target_env = "sgx", ignore)] // FIXME: https://github.com/fortanix/rust-sgx/issues/31
|
||||
#[test]
|
||||
fn timeouts() {
|
||||
|
@ -180,7 +180,10 @@ fn debug() {
|
||||
// FIXME: re-enabled openbsd/netbsd tests once their socket timeout code
|
||||
// no longer has rounding errors.
|
||||
// VxWorks ignores SO_SNDTIMEO.
|
||||
#[cfg_attr(any(target_os = "netbsd", target_os = "openbsd", target_os = "vxworks"), ignore)]
|
||||
#[cfg_attr(
|
||||
any(target_os = "netbsd", target_os = "openbsd", target_os = "vxworks", target_os = "nto"),
|
||||
ignore
|
||||
)]
|
||||
#[test]
|
||||
fn timeouts() {
|
||||
let addr = next_test_ip4();
|
||||
|
@ -127,6 +127,8 @@ pub mod l4re;
|
||||
pub mod macos;
|
||||
#[cfg(target_os = "netbsd")]
|
||||
pub mod netbsd;
|
||||
#[cfg(target_os = "nto")]
|
||||
pub mod nto;
|
||||
#[cfg(target_os = "openbsd")]
|
||||
pub mod openbsd;
|
||||
#[cfg(target_os = "redox")]
|
||||
|
92
library/std/src/os/nto/fs.rs
Normal file
92
library/std/src/os/nto/fs.rs
Normal file
@ -0,0 +1,92 @@
|
||||
#![stable(feature = "metadata_ext", since = "1.1.0")]
|
||||
|
||||
use crate::fs::Metadata;
|
||||
use crate::sys_common::AsInner;
|
||||
|
||||
#[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 as i64
|
||||
}
|
||||
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 as i64
|
||||
}
|
||||
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 as i64
|
||||
}
|
||||
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
|
||||
}
|
||||
}
|
4
library/std/src/os/nto/mod.rs
Normal file
4
library/std/src/os/nto/mod.rs
Normal file
@ -0,0 +1,4 @@
|
||||
#![stable(feature = "raw_ext", since = "1.1.0")]
|
||||
|
||||
pub mod fs;
|
||||
pub(super) mod raw;
|
40
library/std/src/os/nto/raw.rs
Normal file
40
library/std/src/os/nto/raw.rs
Normal file
@ -0,0 +1,40 @@
|
||||
#![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_int;
|
||||
|
||||
#[stable(feature = "raw_ext", since = "1.1.0")]
|
||||
pub type dev_t = u32;
|
||||
#[stable(feature = "raw_ext", since = "1.1.0")]
|
||||
pub type mode_t = u32;
|
||||
|
||||
#[stable(feature = "pthread_t", since = "1.8.0")]
|
||||
pub type pthread_t = c_int;
|
||||
|
||||
#[doc(inline)]
|
||||
#[stable(feature = "raw_ext", since = "1.1.0")]
|
||||
pub use self::arch::{blkcnt_t, blksize_t, ino_t, nlink_t, off_t, time_t};
|
||||
|
||||
mod arch {
|
||||
use crate::os::raw::c_long;
|
||||
|
||||
#[stable(feature = "raw_ext", since = "1.1.0")]
|
||||
pub type blkcnt_t = i64;
|
||||
#[stable(feature = "raw_ext", since = "1.1.0")]
|
||||
pub type blksize_t = i32;
|
||||
#[stable(feature = "raw_ext", since = "1.1.0")]
|
||||
pub type ino_t = u64;
|
||||
#[stable(feature = "raw_ext", since = "1.1.0")]
|
||||
pub type nlink_t = u32;
|
||||
#[stable(feature = "raw_ext", since = "1.1.0")]
|
||||
pub type off_t = i64;
|
||||
#[stable(feature = "raw_ext", since = "1.1.0")]
|
||||
pub type time_t = c_long;
|
||||
}
|
@ -65,6 +65,8 @@ mod platform {
|
||||
pub use crate::os::macos::*;
|
||||
#[cfg(target_os = "netbsd")]
|
||||
pub use crate::os::netbsd::*;
|
||||
#[cfg(target_os = "nto")]
|
||||
pub use crate::os::nto::*;
|
||||
#[cfg(target_os = "openbsd")]
|
||||
pub use crate::os::openbsd::*;
|
||||
#[cfg(target_os = "redox")]
|
||||
@ -95,7 +97,8 @@ pub mod thread;
|
||||
target_os = "watchos",
|
||||
target_os = "macos",
|
||||
target_os = "netbsd",
|
||||
target_os = "openbsd"
|
||||
target_os = "openbsd",
|
||||
target_os = "nto",
|
||||
))]
|
||||
pub mod ucred;
|
||||
|
||||
|
@ -19,7 +19,8 @@ use crate::{fmt, io};
|
||||
target_os = "freebsd",
|
||||
target_os = "openbsd",
|
||||
target_os = "netbsd",
|
||||
target_os = "haiku"
|
||||
target_os = "haiku",
|
||||
target_os = "nto",
|
||||
))]
|
||||
use libc::MSG_NOSIGNAL;
|
||||
#[cfg(not(any(
|
||||
@ -29,7 +30,8 @@ use libc::MSG_NOSIGNAL;
|
||||
target_os = "freebsd",
|
||||
target_os = "openbsd",
|
||||
target_os = "netbsd",
|
||||
target_os = "haiku"
|
||||
target_os = "haiku",
|
||||
target_os = "nto",
|
||||
)))]
|
||||
const MSG_NOSIGNAL: libc::c_int = 0x0;
|
||||
|
||||
|
@ -167,6 +167,7 @@ fn long_path() {
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(not(target_os = "nto"))]
|
||||
fn timeouts() {
|
||||
let dir = tmpdir();
|
||||
let socket_path = dir.path().join("sock");
|
||||
|
@ -12,15 +12,23 @@ 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;
|
||||
use cfg_if::cfg_if;
|
||||
|
||||
#[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;
|
||||
cfg_if! {
|
||||
if #[cfg(any(target_os = "vxworks", target_os = "espidf", target_os = "horizon"))] {
|
||||
type UserId = u16;
|
||||
type GroupId = u16;
|
||||
} else if #[cfg(target_os = "nto")] {
|
||||
// Both IDs are signed, see `sys/target_nto.h` of the QNX Neutrino SDP.
|
||||
// Only positive values should be used, see e.g.
|
||||
// https://www.qnx.com/developers/docs/7.1/#com.qnx.doc.neutrino.lib_ref/topic/s/setuid.html
|
||||
type UserId = i32;
|
||||
type GroupId = i32;
|
||||
} else {
|
||||
type UserId = u32;
|
||||
type GroupId = u32;
|
||||
}
|
||||
}
|
||||
|
||||
/// Unix-specific extensions to the [`process::Command`] builder.
|
||||
///
|
||||
|
@ -79,7 +79,8 @@ pub mod impl_linux {
|
||||
target_os = "dragonfly",
|
||||
target_os = "freebsd",
|
||||
target_os = "openbsd",
|
||||
target_os = "netbsd"
|
||||
target_os = "netbsd",
|
||||
target_os = "nto",
|
||||
))]
|
||||
pub mod impl_bsd {
|
||||
use super::UCred;
|
||||
|
@ -69,7 +69,8 @@ impl DoubleEndedIterator for Args {
|
||||
target_os = "fuchsia",
|
||||
target_os = "redox",
|
||||
target_os = "vxworks",
|
||||
target_os = "horizon"
|
||||
target_os = "horizon",
|
||||
target_os = "nto",
|
||||
))]
|
||||
mod imp {
|
||||
use super::Args;
|
||||
|
@ -185,6 +185,17 @@ pub mod os {
|
||||
pub const EXE_EXTENSION: &str = "";
|
||||
}
|
||||
|
||||
#[cfg(target_os = "nto")]
|
||||
pub mod os {
|
||||
pub const FAMILY: &str = "unix";
|
||||
pub const OS: &str = "nto";
|
||||
pub const DLL_PREFIX: &str = "lib";
|
||||
pub const DLL_SUFFIX: &str = ".so";
|
||||
pub const DLL_EXTENSION: &str = "so";
|
||||
pub const EXE_SUFFIX: &str = "";
|
||||
pub const EXE_EXTENSION: &str = "";
|
||||
}
|
||||
|
||||
#[cfg(target_os = "redox")]
|
||||
pub mod os {
|
||||
pub const FAMILY: &str = "unix";
|
||||
|
@ -53,7 +53,12 @@ const fn max_iov() -> usize {
|
||||
libc::IOV_MAX as usize
|
||||
}
|
||||
|
||||
#[cfg(any(target_os = "android", target_os = "emscripten", target_os = "linux"))]
|
||||
#[cfg(any(
|
||||
target_os = "android",
|
||||
target_os = "emscripten",
|
||||
target_os = "linux",
|
||||
target_os = "nto",
|
||||
))]
|
||||
const fn max_iov() -> usize {
|
||||
libc::UIO_MAXIOV as usize
|
||||
}
|
||||
@ -67,6 +72,7 @@ const fn max_iov() -> usize {
|
||||
target_os = "linux",
|
||||
target_os = "macos",
|
||||
target_os = "netbsd",
|
||||
target_os = "nto",
|
||||
target_os = "openbsd",
|
||||
target_os = "horizon",
|
||||
target_os = "watchos",
|
||||
@ -207,7 +213,8 @@ impl FileDesc {
|
||||
target_os = "linux",
|
||||
target_os = "haiku",
|
||||
target_os = "redox",
|
||||
target_os = "vxworks"
|
||||
target_os = "vxworks",
|
||||
target_os = "nto",
|
||||
)))]
|
||||
pub fn set_cloexec(&self) -> io::Result<()> {
|
||||
unsafe {
|
||||
@ -225,7 +232,8 @@ impl FileDesc {
|
||||
target_os = "linux",
|
||||
target_os = "haiku",
|
||||
target_os = "redox",
|
||||
target_os = "vxworks"
|
||||
target_os = "vxworks",
|
||||
target_os = "nto",
|
||||
))]
|
||||
pub fn set_cloexec(&self) -> io::Result<()> {
|
||||
unsafe {
|
||||
|
@ -13,7 +13,8 @@ use crate::mem;
|
||||
target_os = "solaris",
|
||||
target_os = "fuchsia",
|
||||
target_os = "redox",
|
||||
target_os = "illumos"
|
||||
target_os = "illumos",
|
||||
target_os = "nto",
|
||||
))]
|
||||
use crate::mem::MaybeUninit;
|
||||
use crate::os::unix::io::{AsFd, AsRawFd, BorrowedFd, FromRawFd, IntoRawFd};
|
||||
@ -54,7 +55,8 @@ use libc::fstatat64;
|
||||
target_os = "solaris",
|
||||
target_os = "fuchsia",
|
||||
target_os = "redox",
|
||||
target_os = "illumos"
|
||||
target_os = "illumos",
|
||||
target_os = "nto",
|
||||
))]
|
||||
use libc::readdir as readdir64;
|
||||
#[cfg(target_os = "linux")]
|
||||
@ -69,7 +71,8 @@ use libc::readdir64_r;
|
||||
target_os = "illumos",
|
||||
target_os = "l4re",
|
||||
target_os = "fuchsia",
|
||||
target_os = "redox"
|
||||
target_os = "redox",
|
||||
target_os = "nto",
|
||||
)))]
|
||||
use libc::readdir_r as readdir64_r;
|
||||
#[cfg(target_os = "android")]
|
||||
@ -277,7 +280,8 @@ unsafe impl Sync for Dir {}
|
||||
target_os = "solaris",
|
||||
target_os = "illumos",
|
||||
target_os = "fuchsia",
|
||||
target_os = "redox"
|
||||
target_os = "redox",
|
||||
target_os = "nto",
|
||||
))]
|
||||
pub struct DirEntry {
|
||||
dir: Arc<InnerReadDir>,
|
||||
@ -297,11 +301,12 @@ pub struct DirEntry {
|
||||
target_os = "solaris",
|
||||
target_os = "illumos",
|
||||
target_os = "fuchsia",
|
||||
target_os = "redox"
|
||||
target_os = "redox",
|
||||
target_os = "nto",
|
||||
))]
|
||||
struct dirent64_min {
|
||||
d_ino: u64,
|
||||
#[cfg(not(any(target_os = "solaris", target_os = "illumos")))]
|
||||
#[cfg(not(any(target_os = "solaris", target_os = "illumos", target_os = "nto")))]
|
||||
d_type: u8,
|
||||
}
|
||||
|
||||
@ -311,7 +316,8 @@ struct dirent64_min {
|
||||
target_os = "solaris",
|
||||
target_os = "illumos",
|
||||
target_os = "fuchsia",
|
||||
target_os = "redox"
|
||||
target_os = "redox",
|
||||
target_os = "nto",
|
||||
)))]
|
||||
pub struct DirEntry {
|
||||
dir: Arc<InnerReadDir>,
|
||||
@ -438,7 +444,7 @@ impl FileAttr {
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(target_os = "netbsd"))]
|
||||
#[cfg(not(any(target_os = "netbsd", target_os = "nto")))]
|
||||
impl FileAttr {
|
||||
#[cfg(not(any(target_os = "vxworks", target_os = "espidf", target_os = "horizon")))]
|
||||
pub fn modified(&self) -> io::Result<SystemTime> {
|
||||
@ -524,6 +530,21 @@ impl FileAttr {
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(target_os = "nto")]
|
||||
impl FileAttr {
|
||||
pub fn modified(&self) -> io::Result<SystemTime> {
|
||||
Ok(SystemTime::new(self.stat.st_mtim.tv_sec, self.stat.st_mtim.tv_nsec))
|
||||
}
|
||||
|
||||
pub fn accessed(&self) -> io::Result<SystemTime> {
|
||||
Ok(SystemTime::new(self.stat.st_atim.tv_sec, self.stat.st_atim.tv_nsec))
|
||||
}
|
||||
|
||||
pub fn created(&self) -> io::Result<SystemTime> {
|
||||
Ok(SystemTime::new(self.stat.st_ctim.tv_sec, self.stat.st_ctim.tv_nsec))
|
||||
}
|
||||
}
|
||||
|
||||
impl AsInner<stat64> for FileAttr {
|
||||
fn as_inner(&self) -> &stat64 {
|
||||
&self.stat
|
||||
@ -603,7 +624,8 @@ impl Iterator for ReadDir {
|
||||
target_os = "solaris",
|
||||
target_os = "fuchsia",
|
||||
target_os = "redox",
|
||||
target_os = "illumos"
|
||||
target_os = "illumos",
|
||||
target_os = "nto",
|
||||
))]
|
||||
fn next(&mut self) -> Option<io::Result<DirEntry>> {
|
||||
if self.end_of_stream {
|
||||
@ -686,7 +708,11 @@ impl Iterator for ReadDir {
|
||||
|
||||
let entry = dirent64_min {
|
||||
d_ino: *offset_ptr!(entry_ptr, d_ino) as u64,
|
||||
#[cfg(not(any(target_os = "solaris", target_os = "illumos")))]
|
||||
#[cfg(not(any(
|
||||
target_os = "solaris",
|
||||
target_os = "illumos",
|
||||
target_os = "nto",
|
||||
)))]
|
||||
d_type: *offset_ptr!(entry_ptr, d_type) as u8,
|
||||
};
|
||||
|
||||
@ -705,7 +731,8 @@ impl Iterator for ReadDir {
|
||||
target_os = "solaris",
|
||||
target_os = "fuchsia",
|
||||
target_os = "redox",
|
||||
target_os = "illumos"
|
||||
target_os = "illumos",
|
||||
target_os = "nto",
|
||||
)))]
|
||||
fn next(&mut self) -> Option<io::Result<DirEntry>> {
|
||||
if self.end_of_stream {
|
||||
@ -794,7 +821,8 @@ impl DirEntry {
|
||||
target_os = "solaris",
|
||||
target_os = "illumos",
|
||||
target_os = "haiku",
|
||||
target_os = "vxworks"
|
||||
target_os = "vxworks",
|
||||
target_os = "nto",
|
||||
))]
|
||||
pub fn file_type(&self) -> io::Result<FileType> {
|
||||
self.metadata().map(|m| m.file_type())
|
||||
@ -804,7 +832,8 @@ impl DirEntry {
|
||||
target_os = "solaris",
|
||||
target_os = "illumos",
|
||||
target_os = "haiku",
|
||||
target_os = "vxworks"
|
||||
target_os = "vxworks",
|
||||
target_os = "nto",
|
||||
)))]
|
||||
pub fn file_type(&self) -> io::Result<FileType> {
|
||||
match self.entry.d_type {
|
||||
@ -834,7 +863,8 @@ impl DirEntry {
|
||||
target_os = "redox",
|
||||
target_os = "vxworks",
|
||||
target_os = "espidf",
|
||||
target_os = "horizon"
|
||||
target_os = "horizon",
|
||||
target_os = "nto",
|
||||
))]
|
||||
pub fn ino(&self) -> u64 {
|
||||
self.entry.d_ino as u64
|
||||
@ -887,7 +917,8 @@ impl DirEntry {
|
||||
target_os = "solaris",
|
||||
target_os = "illumos",
|
||||
target_os = "fuchsia",
|
||||
target_os = "redox"
|
||||
target_os = "redox",
|
||||
target_os = "nto",
|
||||
)))]
|
||||
fn name_cstr(&self) -> &CStr {
|
||||
unsafe { CStr::from_ptr(self.entry.d_name.as_ptr()) }
|
||||
@ -898,7 +929,8 @@ impl DirEntry {
|
||||
target_os = "solaris",
|
||||
target_os = "illumos",
|
||||
target_os = "fuchsia",
|
||||
target_os = "redox"
|
||||
target_os = "redox",
|
||||
target_os = "nto",
|
||||
))]
|
||||
fn name_cstr(&self) -> &CStr {
|
||||
&self.name
|
||||
@ -1051,7 +1083,8 @@ impl File {
|
||||
target_os = "linux",
|
||||
target_os = "android",
|
||||
target_os = "netbsd",
|
||||
target_os = "openbsd"
|
||||
target_os = "openbsd",
|
||||
target_os = "nto",
|
||||
))]
|
||||
unsafe fn os_datasync(fd: c_int) -> c_int {
|
||||
libc::fdatasync(fd)
|
||||
@ -1065,6 +1098,7 @@ impl File {
|
||||
target_os = "netbsd",
|
||||
target_os = "openbsd",
|
||||
target_os = "watchos",
|
||||
target_os = "nto",
|
||||
)))]
|
||||
unsafe fn os_datasync(fd: c_int) -> c_int {
|
||||
libc::fsync(fd)
|
||||
@ -1750,13 +1784,25 @@ pub fn chroot(dir: &Path) -> io::Result<()> {
|
||||
pub use remove_dir_impl::remove_dir_all;
|
||||
|
||||
// Fallback for REDOX, ESP-ID, Horizon, and Miri
|
||||
#[cfg(any(target_os = "redox", target_os = "espidf", target_os = "horizon", miri))]
|
||||
#[cfg(any(
|
||||
target_os = "redox",
|
||||
target_os = "espidf",
|
||||
target_os = "horizon",
|
||||
target_os = "nto",
|
||||
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", target_os = "horizon", miri)))]
|
||||
#[cfg(not(any(
|
||||
target_os = "redox",
|
||||
target_os = "espidf",
|
||||
target_os = "horizon",
|
||||
target_os = "nto",
|
||||
miri
|
||||
)))]
|
||||
mod remove_dir_impl {
|
||||
use super::{lstat, Dir, DirEntry, InnerReadDir, ReadDir};
|
||||
use crate::ffi::CStr;
|
||||
|
@ -2,7 +2,10 @@ use crate::cell::UnsafeCell;
|
||||
use crate::ptr;
|
||||
use crate::sync::atomic::{AtomicPtr, Ordering::Relaxed};
|
||||
use crate::sys::locks::{pthread_mutex, Mutex};
|
||||
#[cfg(not(target_os = "nto"))]
|
||||
use crate::sys::time::TIMESPEC_MAX;
|
||||
#[cfg(target_os = "nto")]
|
||||
use crate::sys::time::TIMESPEC_MAX_CAPPED;
|
||||
use crate::sys_common::lazy_box::{LazyBox, LazyInit};
|
||||
use crate::time::Duration;
|
||||
|
||||
@ -132,10 +135,18 @@ impl Condvar {
|
||||
let mutex = pthread_mutex::raw(mutex);
|
||||
self.verify(mutex);
|
||||
|
||||
#[cfg(not(target_os = "nto"))]
|
||||
let timeout = Timespec::now(libc::CLOCK_MONOTONIC)
|
||||
.checked_add_duration(&dur)
|
||||
.and_then(|t| t.to_timespec())
|
||||
.unwrap_or(TIMESPEC_MAX);
|
||||
|
||||
#[cfg(target_os = "nto")]
|
||||
let timeout = Timespec::now(libc::CLOCK_MONOTONIC)
|
||||
.checked_add_duration(&dur)
|
||||
.and_then(|t| t.to_timespec_capped())
|
||||
.unwrap_or(TIMESPEC_MAX_CAPPED);
|
||||
|
||||
let r = libc::pthread_cond_timedwait(raw(self), mutex, &timeout);
|
||||
assert!(r == libc::ETIMEDOUT || r == 0);
|
||||
r == 0
|
||||
|
@ -78,6 +78,7 @@ impl Socket {
|
||||
target_os = "linux",
|
||||
target_os = "netbsd",
|
||||
target_os = "openbsd",
|
||||
target_os = "nto",
|
||||
))] {
|
||||
// On platforms that support it we pass the SOCK_CLOEXEC
|
||||
// flag to atomically create the socket and set it as
|
||||
@ -115,6 +116,7 @@ impl Socket {
|
||||
target_os = "linux",
|
||||
target_os = "netbsd",
|
||||
target_os = "openbsd",
|
||||
target_os = "nto",
|
||||
))] {
|
||||
// Like above, set cloexec atomically
|
||||
cvt(libc::socketpair(fam, ty | libc::SOCK_CLOEXEC, 0, fds.as_mut_ptr()))?;
|
||||
|
@ -62,6 +62,7 @@ extern "C" {
|
||||
link_name = "__errno"
|
||||
)]
|
||||
#[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"),
|
||||
link_name = "__error"
|
||||
@ -361,6 +362,17 @@ pub fn current_exe() -> io::Result<PathBuf> {
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(target_os = "nto")]
|
||||
pub fn current_exe() -> io::Result<PathBuf> {
|
||||
let mut e = crate::fs::read("/proc/self/exefile")?;
|
||||
// Current versions of QNX Neutrino provide a null-terminated path.
|
||||
// Ensure the trailing null byte is not returned here.
|
||||
if let Some(0) = e.last() {
|
||||
e.pop();
|
||||
}
|
||||
Ok(PathBuf::from(OsString::from_vec(e)))
|
||||
}
|
||||
|
||||
#[cfg(any(target_os = "macos", target_os = "ios", target_os = "watchos"))]
|
||||
pub fn current_exe() -> io::Result<PathBuf> {
|
||||
unsafe {
|
||||
|
@ -18,6 +18,7 @@ use crate::sys::weak::raw_syscall;
|
||||
target_os = "freebsd",
|
||||
all(target_os = "linux", target_env = "gnu"),
|
||||
all(target_os = "linux", target_env = "musl"),
|
||||
target_os = "nto",
|
||||
))]
|
||||
use crate::sys::weak::weak;
|
||||
|
||||
@ -30,6 +31,15 @@ use libc::{c_int, pid_t};
|
||||
#[cfg(not(any(target_os = "vxworks", target_os = "l4re")))]
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Command
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
@ -140,11 +150,31 @@ impl Command {
|
||||
|
||||
// Attempts to fork the process. If successful, returns Ok((0, -1))
|
||||
// in the child, and Ok((child_pid, -1)) in the parent.
|
||||
#[cfg(not(target_os = "linux"))]
|
||||
#[cfg(not(any(target_os = "linux", 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))
|
||||
}
|
||||
|
||||
// On QNX Neutrino, fork can fail with EBADF in case "another thread might have opened
|
||||
// or closed a file descriptor while the fork() was occurring".
|
||||
// Documentation says "... or try calling fork() again". This is what we do here.
|
||||
// See also https://www.qnx.com/developers/docs/7.1/#com.qnx.doc.neutrino.lib_ref/topic/f/fork.html
|
||||
#[cfg(all(target_os = "nto", target_env = "nto71"))]
|
||||
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;
|
||||
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;
|
||||
} else {
|
||||
return cvt(r).map(|res| (res, -1));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Attempts to fork the process. If successful, returns Ok((0, -1))
|
||||
// in the child, and Ok((child_pid, child_pidfd)) in the parent.
|
||||
#[cfg(target_os = "linux")]
|
||||
@ -389,6 +419,7 @@ impl Command {
|
||||
target_os = "freebsd",
|
||||
all(target_os = "linux", target_env = "gnu"),
|
||||
all(target_os = "linux", target_env = "musl"),
|
||||
target_os = "nto",
|
||||
)))]
|
||||
fn posix_spawn(
|
||||
&mut self,
|
||||
@ -405,6 +436,7 @@ impl Command {
|
||||
target_os = "freebsd",
|
||||
all(target_os = "linux", target_env = "gnu"),
|
||||
all(target_os = "linux", target_env = "musl"),
|
||||
target_os = "nto",
|
||||
))]
|
||||
fn posix_spawn(
|
||||
&mut self,
|
||||
@ -436,6 +468,34 @@ impl Command {
|
||||
}
|
||||
}
|
||||
|
||||
// On QNX Neutrino, posix_spawnp can fail with EBADF in case "another thread might have opened
|
||||
// or closed a file descriptor while the posix_spawn() was occurring".
|
||||
// Documentation says "... or try calling posix_spawn() again". This is what we do here.
|
||||
// See also http://www.qnx.com/developers/docs/7.1/#com.qnx.doc.neutrino.lib_ref/topic/p/posix_spawn.html
|
||||
#[cfg(all(target_os = "nto", target_env = "nto71"))]
|
||||
unsafe fn retrying_libc_posix_spawnp(
|
||||
pid: *mut pid_t,
|
||||
file: *const c_char,
|
||||
file_actions: *const posix_spawn_file_actions_t,
|
||||
attrp: *const posix_spawnattr_t,
|
||||
argv: *const *mut c_char,
|
||||
envp: *const *mut c_char,
|
||||
) -> i32 {
|
||||
let mut tries_left = MAX_FORKSPAWN_TRIES;
|
||||
loop {
|
||||
match libc::posix_spawnp(pid, file, file_actions, attrp, argv, envp) {
|
||||
libc::EBADF if tries_left > 0 => {
|
||||
thread::yield_now();
|
||||
tries_left -= 1;
|
||||
continue;
|
||||
}
|
||||
r => {
|
||||
return r;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Solaris, glibc 2.29+, and musl 1.24+ can set a new working directory,
|
||||
// and maybe others will gain this non-POSIX function too. We'll check
|
||||
// for this weak symbol as soon as it's needed, so we can return early
|
||||
@ -555,7 +615,12 @@ impl Command {
|
||||
// Make sure we synchronize access to the global `environ` resource
|
||||
let _env_lock = sys::os::env_read_lock();
|
||||
let envp = envp.map(|c| c.as_ptr()).unwrap_or_else(|| *sys::os::environ() as *const _);
|
||||
cvt_nz(libc::posix_spawnp(
|
||||
|
||||
#[cfg(not(target_os = "nto"))]
|
||||
let spawn_fn = libc::posix_spawnp;
|
||||
#[cfg(target_os = "nto")]
|
||||
let spawn_fn = retrying_libc_posix_spawnp;
|
||||
cvt_nz(spawn_fn(
|
||||
&mut p.pid,
|
||||
self.get_program_cstr().as_ptr(),
|
||||
file_actions.0.as_ptr(),
|
||||
@ -760,7 +825,7 @@ fn signal_string(signal: i32) -> &'static str {
|
||||
)
|
||||
))]
|
||||
libc::SIGSTKFLT => " (SIGSTKFLT)",
|
||||
#[cfg(target_os = "linux")]
|
||||
#[cfg(any(target_os = "linux", target_os = "nto"))]
|
||||
libc::SIGPWR => " (SIGPWR)",
|
||||
#[cfg(any(
|
||||
target_os = "macos",
|
||||
@ -769,7 +834,8 @@ fn signal_string(signal: i32) -> &'static str {
|
||||
target_os = "freebsd",
|
||||
target_os = "netbsd",
|
||||
target_os = "openbsd",
|
||||
target_os = "dragonfly"
|
||||
target_os = "dragonfly",
|
||||
target_os = "nto",
|
||||
))]
|
||||
libc::SIGEMT => " (SIGEMT)",
|
||||
#[cfg(any(
|
||||
|
@ -9,7 +9,7 @@ use crate::time::Duration;
|
||||
|
||||
#[cfg(all(target_os = "linux", target_env = "gnu"))]
|
||||
use crate::sys::weak::dlsym;
|
||||
#[cfg(any(target_os = "solaris", target_os = "illumos"))]
|
||||
#[cfg(any(target_os = "solaris", target_os = "illumos", target_os = "nto"))]
|
||||
use crate::sys::weak::weak;
|
||||
#[cfg(not(any(target_os = "l4re", target_os = "vxworks", target_os = "espidf")))]
|
||||
pub const DEFAULT_MIN_STACK_SIZE: usize = 2 * 1024 * 1024;
|
||||
@ -173,7 +173,7 @@ impl Thread {
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(any(target_os = "solaris", target_os = "illumos"))]
|
||||
#[cfg(any(target_os = "solaris", target_os = "illumos", target_os = "nto"))]
|
||||
pub fn set_name(name: &CStr) {
|
||||
weak! {
|
||||
fn pthread_setname_np(
|
||||
@ -381,6 +381,17 @@ pub fn available_parallelism() -> io::Result<NonZeroUsize> {
|
||||
}
|
||||
|
||||
Ok(unsafe { NonZeroUsize::new_unchecked(cpus as usize) })
|
||||
} else if #[cfg(target_os = "nto")] {
|
||||
unsafe {
|
||||
use libc::_syspage_ptr;
|
||||
if _syspage_ptr.is_null() {
|
||||
Err(io::const_io_error!(io::ErrorKind::NotFound, "No syspage available"))
|
||||
} else {
|
||||
let cpus = (*_syspage_ptr).num_cpu;
|
||||
NonZeroUsize::new(cpus as usize)
|
||||
.ok_or(io::const_io_error!(io::ErrorKind::NotFound, "The number of hardware threads is not known for the target platform"))
|
||||
}
|
||||
}
|
||||
} else if #[cfg(target_os = "haiku")] {
|
||||
// system_info cpu_count field gets the static data set at boot time with `smp_set_num_cpus`
|
||||
// `get_system_info` calls then `smp_get_num_cpus`
|
||||
|
@ -6,7 +6,10 @@ use crate::pin::Pin;
|
||||
use crate::ptr::addr_of_mut;
|
||||
use crate::sync::atomic::AtomicUsize;
|
||||
use crate::sync::atomic::Ordering::SeqCst;
|
||||
#[cfg(not(target_os = "nto"))]
|
||||
use crate::sys::time::TIMESPEC_MAX;
|
||||
#[cfg(target_os = "nto")]
|
||||
use crate::sys::time::TIMESPEC_MAX_CAPPED;
|
||||
use crate::time::Duration;
|
||||
|
||||
const EMPTY: usize = 0;
|
||||
@ -80,8 +83,14 @@ unsafe fn wait_timeout(
|
||||
(Timespec::now(libc::CLOCK_MONOTONIC), dur)
|
||||
};
|
||||
|
||||
#[cfg(not(target_os = "nto"))]
|
||||
let timeout =
|
||||
now.checked_add_duration(&dur).and_then(|t| t.to_timespec()).unwrap_or(TIMESPEC_MAX);
|
||||
#[cfg(target_os = "nto")]
|
||||
let timeout = now
|
||||
.checked_add_duration(&dur)
|
||||
.and_then(|t| t.to_timespec_capped())
|
||||
.unwrap_or(TIMESPEC_MAX_CAPPED);
|
||||
let r = libc::pthread_cond_timedwait(cond, lock, &timeout);
|
||||
debug_assert!(r == libc::ETIMEDOUT || r == 0);
|
||||
}
|
||||
|
@ -9,6 +9,14 @@ pub const UNIX_EPOCH: SystemTime = SystemTime { t: Timespec::zero() };
|
||||
pub const TIMESPEC_MAX: libc::timespec =
|
||||
libc::timespec { tv_sec: <libc::time_t>::MAX, tv_nsec: 1_000_000_000 - 1 };
|
||||
|
||||
// This additional constant is only used when calling
|
||||
// `libc::pthread_cond_timedwait`.
|
||||
#[cfg(target_os = "nto")]
|
||||
pub(super) const TIMESPEC_MAX_CAPPED: libc::timespec = libc::timespec {
|
||||
tv_sec: (u64::MAX / NSEC_PER_SEC) as i64,
|
||||
tv_nsec: (u64::MAX % NSEC_PER_SEC) as i64,
|
||||
};
|
||||
|
||||
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||
#[repr(transparent)]
|
||||
#[rustc_layout_scalar_valid_range_start(0)]
|
||||
@ -144,6 +152,20 @@ impl Timespec {
|
||||
tv_nsec: self.tv_nsec.0.try_into().ok()?,
|
||||
})
|
||||
}
|
||||
|
||||
// On QNX Neutrino, the maximum timespec for e.g. pthread_cond_timedwait
|
||||
// is 2^64 nanoseconds
|
||||
#[cfg(target_os = "nto")]
|
||||
pub(super) fn to_timespec_capped(&self) -> Option<libc::timespec> {
|
||||
// Check if timeout in nanoseconds would fit into an u64
|
||||
if (self.tv_nsec.0 as u64)
|
||||
.checked_add((self.tv_sec as u64).checked_mul(NSEC_PER_SEC)?)
|
||||
.is_none()
|
||||
{
|
||||
return None;
|
||||
}
|
||||
self.to_timespec()
|
||||
}
|
||||
}
|
||||
|
||||
impl From<libc::timespec> for Timespec {
|
||||
|
@ -91,6 +91,19 @@ unsafe fn _print_fmt(fmt: &mut fmt::Formatter<'_>, print_fmt: PrintFmt) -> fmt::
|
||||
if stop {
|
||||
return false;
|
||||
}
|
||||
#[cfg(target_os = "nto")]
|
||||
if libc::__my_thread_exit as *mut libc::c_void == frame.ip() {
|
||||
if !hit && start {
|
||||
use crate::backtrace_rs::SymbolName;
|
||||
res = bt_fmt.frame().print_raw(
|
||||
frame.ip(),
|
||||
Some(SymbolName::new("__my_thread_exit".as_bytes())),
|
||||
None,
|
||||
None,
|
||||
);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
if !hit && start {
|
||||
res = bt_fmt.frame().print_raw(frame.ip(), None, None, None);
|
||||
}
|
||||
|
@ -21,7 +21,7 @@ cfg_if::cfg_if! {
|
||||
target_os = "dragonfly", target_os = "freebsd",
|
||||
target_os = "ios", target_os = "macos", target_os = "watchos",
|
||||
target_os = "openbsd", target_os = "netbsd", target_os = "illumos",
|
||||
target_os = "solaris", target_os = "haiku", target_os = "l4re"))] {
|
||||
target_os = "solaris", target_os = "haiku", target_os = "l4re", target_os = "nto"))] {
|
||||
use crate::sys::net::netc::IPV6_JOIN_GROUP as IPV6_ADD_MEMBERSHIP;
|
||||
use crate::sys::net::netc::IPV6_LEAVE_GROUP as IPV6_DROP_MEMBERSHIP;
|
||||
} else {
|
||||
@ -35,7 +35,7 @@ cfg_if::cfg_if! {
|
||||
target_os = "linux", target_os = "android",
|
||||
target_os = "dragonfly", target_os = "freebsd",
|
||||
target_os = "openbsd", target_os = "netbsd",
|
||||
target_os = "haiku"))] {
|
||||
target_os = "haiku", target_os = "nto"))] {
|
||||
use libc::MSG_NOSIGNAL;
|
||||
} else {
|
||||
const MSG_NOSIGNAL: c_int = 0x0;
|
||||
@ -46,7 +46,8 @@ cfg_if::cfg_if! {
|
||||
if #[cfg(any(
|
||||
target_os = "dragonfly", target_os = "freebsd",
|
||||
target_os = "openbsd", target_os = "netbsd",
|
||||
target_os = "solaris", target_os = "illumos"))] {
|
||||
target_os = "solaris", target_os = "illumos",
|
||||
target_os = "nto"))] {
|
||||
use crate::ffi::c_uchar;
|
||||
type IpV4MultiCastType = c_uchar;
|
||||
} else {
|
||||
|
@ -117,9 +117,15 @@ pub struct Key {
|
||||
/// This value specifies no destructor by default.
|
||||
pub const INIT: StaticKey = StaticKey::new(None);
|
||||
|
||||
// Define a sentinel value that is unlikely to be returned
|
||||
// as a TLS key (but it may be returned).
|
||||
// Define a sentinel value that is likely not to be returned
|
||||
// as a TLS key.
|
||||
#[cfg(not(target_os = "nto"))]
|
||||
const KEY_SENTVAL: usize = 0;
|
||||
// On QNX Neutrino, 0 is always returned when currently not in use.
|
||||
// Using 0 would mean to always create two keys and remote the first
|
||||
// one (with value of 0) immediately afterwards.
|
||||
#[cfg(target_os = "nto")]
|
||||
const KEY_SENTVAL: usize = libc::PTHREAD_KEYS_MAX + 1;
|
||||
|
||||
impl StaticKey {
|
||||
#[rustc_const_unstable(feature = "thread_local_internals", issue = "none")]
|
||||
|
@ -127,3 +127,7 @@ extern "C" {}
|
||||
#[cfg(target_os = "haiku")]
|
||||
#[link(name = "gcc_s")]
|
||||
extern "C" {}
|
||||
|
||||
#[cfg(target_os = "nto")]
|
||||
#[link(name = "gcc_s")]
|
||||
extern "C" {}
|
||||
|
@ -216,7 +216,7 @@ target | std | host | notes
|
||||
[`aarch64-kmc-solid_asp3`](platform-support/kmc-solid.md) | ✓ | | ARM64 SOLID with TOPPERS/ASP3
|
||||
[`aarch64-nintendo-switch-freestanding`](platform-support/aarch64-nintendo-switch-freestanding.md) | * | | ARM64 Nintendo Switch, Horizon
|
||||
[`aarch64-pc-windows-gnullvm`](platform-support/pc-windows-gnullvm.md) | ✓ | ✓ |
|
||||
[`aarch64-unknown-nto-qnx710`](platform-support/nto-qnx.md) | ? | | ARM64 QNX Neutrino 7.1 RTOS |
|
||||
[`aarch64-unknown-nto-qnx710`](platform-support/nto-qnx.md) | ✓ | | ARM64 QNX Neutrino 7.1 RTOS |
|
||||
`aarch64-unknown-freebsd` | ✓ | ✓ | ARM64 FreeBSD
|
||||
`aarch64-unknown-hermit` | ✓ | | ARM64 HermitCore
|
||||
`aarch64-unknown-linux-gnu_ilp32` | ✓ | ✓ | ARM64 Linux (ILP32 ABI)
|
||||
@ -308,7 +308,7 @@ target | std | host | notes
|
||||
`x86_64-apple-ios-macabi` | ✓ | | Apple Catalyst on x86_64
|
||||
`x86_64-apple-tvos` | * | | x86 64-bit tvOS
|
||||
[`x86_64-apple-watchos-sim`](platform-support/apple-watchos.md) | ✓ | | x86 64-bit Apple WatchOS simulator
|
||||
[`x86_64-pc-nto-qnx710`](platform-support/nto-qnx.md) | ? | | x86 64-bit QNX Neutrino 7.1 RTOS |
|
||||
[`x86_64-pc-nto-qnx710`](platform-support/nto-qnx.md) | ✓ | | x86 64-bit QNX Neutrino 7.1 RTOS |
|
||||
[`x86_64-pc-windows-gnullvm`](platform-support/pc-windows-gnullvm.md) | ✓ | ✓ |
|
||||
`x86_64-pc-windows-msvc` | * | | 64-bit Windows XP support
|
||||
`x86_64-sun-solaris` | ? | | Deprecated target for 64-bit Solaris 10/11, illumos
|
||||
|
@ -2,9 +2,9 @@
|
||||
|
||||
**Tier: 3**
|
||||
|
||||
[BlackBerry® QNX®][BlackBerry] Neutrino (nto) Real-time operating system.
|
||||
[QNX®][BlackBerry] Neutrino (nto) Real-time operating system.
|
||||
The support has been implemented jointly by [Elektrobit Automotive GmbH][Elektrobit]
|
||||
and [BlackBerry][BlackBerry].
|
||||
and [Blackberry QNX][BlackBerry].
|
||||
|
||||
[BlackBerry]: https://blackberry.qnx.com
|
||||
[Elektrobit]: https://www.elektrobit.com
|
||||
@ -19,19 +19,24 @@ and [BlackBerry][BlackBerry].
|
||||
Currently, only cross-compilation for QNX Neutrino on AArch64 and x86_64 are supported (little endian).
|
||||
Adding other architectures that are supported by QNX Neutrino is possible.
|
||||
|
||||
The standard library does not yet support QNX Neutrino. Therefore, only `no_std` code can
|
||||
be compiled.
|
||||
The standard library, including `core` and `alloc` (with default allocator) are supported.
|
||||
|
||||
`core` and `alloc` (with default allocator) are supported.
|
||||
For building or using the Rust toolchain for QNX Neutrino, the
|
||||
[QNX Software Development Platform (SDP)](https://blackberry.qnx.com/en/products/foundation-software/qnx-software-development-platform)
|
||||
must be installed and initialized.
|
||||
Initialization is usually done by sourcing `qnxsdp-env.sh` (this will be installed as part of the SDP, see also installation instruction provided with the SDP).
|
||||
Afterwards [`qcc`](https://www.qnx.com/developers/docs/7.1/#com.qnx.doc.neutrino.utilities/topic/q/qcc.html) (QNX C/C++ compiler)
|
||||
should be available (in the `$PATH` variable).
|
||||
`qcc` will be called e.g. for linking executables.
|
||||
|
||||
Applications must link against `libc.so` (see example). This is required because applications
|
||||
always link against the `crt` library and `crt` depends on `libc.so`.
|
||||
|
||||
The correct version of `qcc` must be available by setting the `$PATH` variable (e.g. by sourcing `qnxsdp-env.sh` of the
|
||||
QNX Neutrino toolchain).
|
||||
When linking `no_std` applications, they must link against `libc.so` (see example). This is
|
||||
required because applications always link against the `crt` library and `crt` depends on `libc.so`.
|
||||
This is done automatically when using the standard library.
|
||||
|
||||
### Small example application
|
||||
|
||||
Small `no_std` example is shown below. Applications using the standard library work as well.
|
||||
|
||||
```rust,ignore (platform-specific)
|
||||
#![no_std]
|
||||
#![no_main]
|
||||
@ -89,30 +94,150 @@ changelog-seen = 2
|
||||
|
||||
2. Compile the Rust toolchain for an `x86_64-unknown-linux-gnu` host (for both `aarch64` and `x86_64` targets)
|
||||
|
||||
Run the following:
|
||||
Compiling the Rust toolchain requires the same environment variables used for compiling C binaries.
|
||||
Refer to the [QNX developer manual](https://www.qnx.com/developers/docs/7.1/#com.qnx.doc.neutrino.prog/topic/devel_OS_version.html).
|
||||
|
||||
To compile for QNX Neutrino (aarch64 and x86_64) and Linux (x86_64):
|
||||
|
||||
```bash
|
||||
env \
|
||||
CC_aarch64-unknown-nto-qnx710="qcc" \
|
||||
CFLAGS_aarch64-unknown-nto-qnx710="-Vgcc_ntoaarch64le_cxx" \
|
||||
CXX_aarch64-unknown-nto-qnx710="qcc" \
|
||||
AR_aarch64_unknown_nto_qnx710="ntoaarch64-ar" \
|
||||
CC_x86_64-pc-nto-qnx710="qcc" \
|
||||
CFLAGS_x86_64-pc-nto-qnx710="-Vgcc_ntox86_64_cxx" \
|
||||
CXX_x86_64-pc-nto-qnx710="qcc" \
|
||||
AR_x86_64_pc_nto_qnx710="ntox86_64-ar" \
|
||||
./x.py build --target aarch64-unknown-nto-qnx710 --target x86_64-pc-nto-qnx710 --target x86_64-unknown-linux-gnu rustc library/core library/alloc/
|
||||
export build_env='
|
||||
CC_aarch64-unknown-nto-qnx710=qcc
|
||||
CFLAGS_aarch64-unknown-nto-qnx710=-Vgcc_ntoaarch64le_cxx
|
||||
CXX_aarch64-unknown-nto-qnx710=qcc
|
||||
AR_aarch64_unknown_nto_qnx710=ntoaarch64-ar
|
||||
CC_x86_64-pc-nto-qnx710=qcc
|
||||
CFLAGS_x86_64-pc-nto-qnx710=-Vgcc_ntox86_64_cxx
|
||||
CXX_x86_64-pc-nto-qnx710=qcc
|
||||
AR_x86_64_pc_nto_qnx710=ntox86_64-ar'
|
||||
|
||||
env $build_env \
|
||||
./x.py build \
|
||||
--target aarch64-unknown-nto-qnx710 \
|
||||
--target x86_64-pc-nto-qnx710 \
|
||||
--target x86_64-unknown-linux-gnu \
|
||||
rustc library/core library/alloc
|
||||
```
|
||||
|
||||
## Running the Rust test suite
|
||||
|
||||
The test suites of the Rust compiler and standard library can be executed much like other Rust targets.
|
||||
The environment for testing should match the one used during compiler compilation (refer to `build_env` and `qcc`/`PATH` above) with the
|
||||
addition of the TEST_DEVICE_ADDR environment variable.
|
||||
The TEST_DEVICE_ADDR variable controls the remote runner and should point to the target, despite localhost being shown in the following example.
|
||||
Note that some tests are failing which is why they are currently excluded by the target maintainers which can be seen in the following example.
|
||||
|
||||
To run all tests on a x86_64 QNX Neutrino target:
|
||||
|
||||
```bash
|
||||
export TEST_DEVICE_ADDR="localhost:12345" # must address the test target, can be a SSH tunnel
|
||||
export build_env='
|
||||
CC_aarch64-unknown-nto-qnx710=qcc
|
||||
CFLAGS_aarch64-unknown-nto-qnx710=-Vgcc_ntoaarch64le_cxx
|
||||
CXX_aarch64-unknown-nto-qnx710=qcc
|
||||
AR_aarch64_unknown_nto_qnx710=ntoaarch64-ar
|
||||
CC_x86_64-pc-nto-qnx710=qcc
|
||||
CFLAGS_x86_64-pc-nto-qnx710=-Vgcc_ntox86_64_cxx
|
||||
CXX_x86_64-pc-nto-qnx710=qcc
|
||||
AR_x86_64_pc_nto_qnx710=ntox86_64-ar'
|
||||
|
||||
# Disable tests that only work on the host or don't make sense for this target.
|
||||
# See also:
|
||||
# - src/ci/docker/host-x86_64/i686-gnu/Dockerfile
|
||||
# - https://rust-lang.zulipchat.com/#narrow/stream/182449-t-compiler.2Fhelp/topic/Running.20tests.20on.20remote.20target
|
||||
# - .github/workflows/ci.yml
|
||||
export exclude_tests='
|
||||
--exclude src/bootstrap
|
||||
--exclude src/tools/error_index_generator
|
||||
--exclude src/tools/linkchecker
|
||||
--exclude tests/ui-fulldeps
|
||||
--exclude rustc
|
||||
--exclude rustdoc
|
||||
--exclude tests/run-make-fulldeps'
|
||||
|
||||
env $build_env \
|
||||
./x.py test -j 1 \
|
||||
$exclude_tests \
|
||||
--stage 1 \
|
||||
--target x86_64-pc-nto-qnx710
|
||||
```
|
||||
|
||||
Currently, only one thread can be used when testing due to limitations in `libc::fork` and `libc::posix_spawnp`.
|
||||
See [fork documentation](https://www.qnx.com/developers/docs/7.1/#com.qnx.doc.neutrino.lib_ref/topic/f/fork.html)
|
||||
(error section) for more information.
|
||||
This can be achieved by using the `-j 1` parameter in the `x.py` call.
|
||||
This issue is being researched and we will try to allow parallelism in the future.
|
||||
|
||||
## Building Rust programs
|
||||
|
||||
Rust does not yet ship pre-compiled artifacts for this target. To compile for this target, you must either build Rust with the target enabled (see "Building the target" above), or build your own copy of `core` by using
|
||||
`build-std` or similar.
|
||||
Rust does not yet ship pre-compiled artifacts for this target.
|
||||
To compile for this target, you must either build Rust with the target enabled (see "Building the target" above),
|
||||
or build your own copy of `core` by using `build-std` or similar.
|
||||
|
||||
## Testing
|
||||
|
||||
Compiled executables can directly be run on QNX Neutrino.
|
||||
Compiled executables can run directly on QNX Neutrino.
|
||||
|
||||
### Rust std library test suite
|
||||
|
||||
The target needs sufficient resources to execute all tests. The commands below assume that a QEMU image
|
||||
is used.
|
||||
|
||||
* Ensure that the temporary directory used by `remote-test-server` has enough free space and inodes.
|
||||
5GB of free space and 40000 inodes are known to be sufficient (the test will create more than 32k files).
|
||||
To create a QEMU image in an empty directory, run this command inside the directory:
|
||||
|
||||
```bash
|
||||
mkqnximage --type=qemu --ssh-ident=$HOME/.ssh/id_ed25519.pub --data-size=5000 --data-inodes=40000
|
||||
```
|
||||
|
||||
`/data` should have enough free resources.
|
||||
Set the `TMPDIR` environment variable accordingly when running `remote-test-server`, e.g.:
|
||||
```bash
|
||||
TMPDIR=/data/tmp/rust remote-test-server --bind 0.0.0.0:12345
|
||||
```
|
||||
|
||||
* Ensure the TCP stack can handle enough parallel connections (default is 200, should be 300 or higher).
|
||||
After creating an image (see above), edit the file `output/build/startup.sh`:
|
||||
1. Search for `io-pkt-v6-hc`
|
||||
2. Add the parameter `-ptcpip threads_max=300`, e.g.:
|
||||
```text
|
||||
io-pkt-v6-hc -U 33:33 -d e1000 -ptcpip threads_max=300
|
||||
```
|
||||
3. Update the image by running `mkqnximage` again with the same parameters as above for creating it.
|
||||
|
||||
* Running and stopping the virtual machine
|
||||
|
||||
To start the virtual machine, run inside the directory of the VM:
|
||||
|
||||
```bash
|
||||
mkqnximage --run=-h
|
||||
```
|
||||
|
||||
To stop the virtual machine, run inside the directory of the VM:
|
||||
|
||||
```bash
|
||||
mkqnximage --stop
|
||||
```
|
||||
|
||||
* Ensure local networking
|
||||
|
||||
Ensure that 'localhost' is getting resolved to 127.0.0.1. If you can't ping the localhost, some tests may fail.
|
||||
Ensure it's appended to /etc/hosts (if first `ping` command fails).
|
||||
Commands have to be executed inside the virtual machine!
|
||||
|
||||
```bash
|
||||
$ ping localhost
|
||||
ping: Cannot resolve "localhost" (Host name lookup failure)
|
||||
|
||||
$ echo "127.0.0.1 localhost" >> /etc/hosts
|
||||
|
||||
$ ping localhost
|
||||
PING localhost (127.0.0.1): 56 data bytes
|
||||
64 bytes from 127.0.0.1: icmp_seq=0 ttl=255 time=1 ms
|
||||
```
|
||||
|
||||
## Cross-compilation toolchains and C code
|
||||
|
||||
Compiling C code requires the same environment variables to be set as compiling the Rust toolchain (see above), to ensure `qcc` is used with proper arguments. To ensure compatibility, do not specify any further arguments that for example change calling conventions or memory layout.
|
||||
Compiling C code requires the same environment variables to be set as compiling the Rust toolchain (see above),
|
||||
to ensure `qcc` is used with proper arguments.
|
||||
To ensure compatibility, do not specify any further arguments that for example change calling conventions or memory layout.
|
||||
|
@ -4,6 +4,7 @@
|
||||
// ignore-wasm globals are used instead of thread locals
|
||||
// ignore-emscripten globals are used instead of thread locals
|
||||
// ignore-android does not use #[thread_local]
|
||||
// ignore-nto does not use #[thread_local]
|
||||
|
||||
#![crate_type = "lib"]
|
||||
|
||||
|
@ -13,5 +13,6 @@
|
||||
// ignore-fuchsia no exception handler registered for segfault
|
||||
// compile-flags: -C lto
|
||||
// no-prefer-dynamic
|
||||
// ignore-nto Crash analysis impossible at SIGSEGV in QNX Neutrino
|
||||
|
||||
include!("stack-probes.rs");
|
||||
|
@ -9,6 +9,7 @@
|
||||
// ignore-emscripten no processes
|
||||
// ignore-sgx no processes
|
||||
// ignore-fuchsia no exception handler registered for segfault
|
||||
// ignore-nto Crash analysis impossible at SIGSEGV in QNX Neutrino
|
||||
|
||||
use std::env;
|
||||
use std::mem::MaybeUninit;
|
||||
|
@ -3,6 +3,7 @@
|
||||
// ignore-emscripten
|
||||
// ignore-sgx
|
||||
// ignore-musl - returns dummy result for _SC_NGROUPS_MAX
|
||||
// ignore-nto - does not have `/bin/id`, expects groups to be i32 (not u32)
|
||||
|
||||
#![feature(rustc_private)]
|
||||
#![feature(setgroups)]
|
||||
|
@ -22,7 +22,9 @@ mod rusti {
|
||||
target_os = "netbsd",
|
||||
target_os = "openbsd",
|
||||
target_os = "solaris",
|
||||
target_os = "vxworks"))]
|
||||
target_os = "vxworks",
|
||||
target_os = "nto",
|
||||
))]
|
||||
mod m {
|
||||
#[cfg(target_arch = "x86")]
|
||||
pub fn main() {
|
||||
|
@ -15,6 +15,7 @@
|
||||
// ignore-emscripten no threads support
|
||||
// ignore-vxworks no 'sh'
|
||||
// ignore-fuchsia no 'sh'
|
||||
// ignore-nto no 'yes'
|
||||
|
||||
use std::process;
|
||||
use std::thread;
|
||||
|
@ -6,6 +6,7 @@
|
||||
// ignore-emscripten no processes
|
||||
// ignore-sgx no processes
|
||||
// ignore-fuchsia must translate zircon signal to SIGABRT, FIXME (#58590)
|
||||
// ignore-nto no stack overflow handler used (no alternate stack available)
|
||||
|
||||
#![feature(core_intrinsics)]
|
||||
#![feature(rustc_private)]
|
||||
|
@ -7,6 +7,7 @@
|
||||
// ignore-windows
|
||||
// ignore-sgx no libc
|
||||
// ignore-vxworks no SIGWINCH in user space
|
||||
// ignore-nto no SA_ONSTACK
|
||||
|
||||
#![feature(rustc_private)]
|
||||
extern crate libc;
|
||||
|
@ -43,7 +43,9 @@ struct Outer {
|
||||
target_os = "netbsd",
|
||||
target_os = "openbsd",
|
||||
target_os = "solaris",
|
||||
target_os = "vxworks"))]
|
||||
target_os = "vxworks",
|
||||
target_os = "nto",
|
||||
))]
|
||||
mod m {
|
||||
#[cfg(target_arch = "x86")]
|
||||
pub mod m {
|
||||
|
@ -1,6 +1,7 @@
|
||||
// run-pass
|
||||
// ignore-emscripten no threads support
|
||||
// compile-flags: -O
|
||||
// ignore-nto Doesn't work without emulated TLS enabled (in LLVM)
|
||||
|
||||
#![feature(thread_local)]
|
||||
|
||||
|
@ -3,6 +3,7 @@
|
||||
// ignore-sgx no processes
|
||||
// ignore-vxworks no 'ps'
|
||||
// ignore-fuchsia no 'ps'
|
||||
// ignore-nto no 'ps'
|
||||
|
||||
#![feature(rustc_private)]
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user