Skip to content

Commit

Permalink
Auto merge of rust-lang#115228 - saethlin:is-interrupted, r=thomcc
Browse files Browse the repository at this point in the history
Add a new helper to avoid calling io::Error::kind

On `cfg(unix)`, `Error::kind` emits an enormous jump table that LLVM seems unable to optimize out. I don't really understand why, but see for yourself: https://godbolt.org/z/17hY496KG

This change lets us check for `ErrorKind::Interrupted` without going through a big match. I've checked the codegen locally, and it has the desired effect on the codegen for `BufReader::read_exact`.
  • Loading branch information
bors committed Aug 26, 2023
2 parents c503527 + 1abaf40 commit 9334ec9
Show file tree
Hide file tree
Showing 12 changed files with 66 additions and 7 deletions.
3 changes: 3 additions & 0 deletions library/std/src/fs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -745,14 +745,17 @@ fn buffer_capacity_required(mut file: &File) -> Option<usize> {

#[stable(feature = "rust1", since = "1.0.0")]
impl Read for &File {
#[inline]
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
self.inner.read(buf)
}

#[inline]
fn read_vectored(&mut self, bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> {
self.inner.read_vectored(bufs)
}

#[inline]
fn read_buf(&mut self, cursor: BorrowedCursor<'_>) -> io::Result<()> {
self.inner.read_buf(cursor)
}
Expand Down
10 changes: 10 additions & 0 deletions library/std/src/io/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -916,6 +916,16 @@ impl Error {
ErrorData::SimpleMessage(m) => m.kind,
}
}

#[inline]
pub(crate) fn is_interrupted(&self) -> bool {
match self.repr.data() {
ErrorData::Os(code) => sys::is_interrupted(code),
ErrorData::Custom(c) => c.kind == ErrorKind::Interrupted,
ErrorData::Simple(kind) => kind == ErrorKind::Interrupted,
ErrorData::SimpleMessage(m) => m.kind == ErrorKind::Interrupted,
}
}
}

impl fmt::Debug for Repr {
Expand Down
14 changes: 7 additions & 7 deletions library/std/src/io/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -390,7 +390,7 @@ pub(crate) fn default_read_to_end<R: Read + ?Sized>(
let mut cursor = read_buf.unfilled();
match r.read_buf(cursor.reborrow()) {
Ok(()) => {}
Err(e) if e.kind() == ErrorKind::Interrupted => continue,
Err(e) if e.is_interrupted() => continue,
Err(e) => return Err(e),
}

Expand Down Expand Up @@ -421,7 +421,7 @@ pub(crate) fn default_read_to_end<R: Read + ?Sized>(
buf.extend_from_slice(&probe[..n]);
break;
}
Err(ref e) if e.kind() == ErrorKind::Interrupted => continue,
Err(ref e) if e.is_interrupted() => continue,
Err(e) => return Err(e),
}
}
Expand Down Expand Up @@ -470,7 +470,7 @@ pub(crate) fn default_read_exact<R: Read + ?Sized>(this: &mut R, mut buf: &mut [
let tmp = buf;
buf = &mut tmp[n..];
}
Err(ref e) if e.kind() == ErrorKind::Interrupted => {}
Err(ref e) if e.is_interrupted() => {}
Err(e) => return Err(e),
}
}
Expand Down Expand Up @@ -860,7 +860,7 @@ pub trait Read {
let prev_written = cursor.written();
match self.read_buf(cursor.reborrow()) {
Ok(()) => {}
Err(e) if e.kind() == ErrorKind::Interrupted => continue,
Err(e) if e.is_interrupted() => continue,
Err(e) => return Err(e),
}

Expand Down Expand Up @@ -1579,7 +1579,7 @@ pub trait Write {
));
}
Ok(n) => buf = &buf[n..],
Err(ref e) if e.kind() == ErrorKind::Interrupted => {}
Err(ref e) if e.is_interrupted() => {}
Err(e) => return Err(e),
}
}
Expand Down Expand Up @@ -1943,7 +1943,7 @@ fn read_until<R: BufRead + ?Sized>(r: &mut R, delim: u8, buf: &mut Vec<u8>) -> R
let (done, used) = {
let available = match r.fill_buf() {
Ok(n) => n,
Err(ref e) if e.kind() == ErrorKind::Interrupted => continue,
Err(ref e) if e.is_interrupted() => continue,
Err(e) => return Err(e),
};
match memchr::memchr(delim, available) {
Expand Down Expand Up @@ -2734,7 +2734,7 @@ impl<R: Read> Iterator for Bytes<R> {
return match self.inner.read(slice::from_mut(&mut byte)) {
Ok(0) => None,
Ok(..) => Some(Ok(byte)),
Err(ref e) if e.kind() == ErrorKind::Interrupted => continue,
Err(ref e) if e.is_interrupted() => continue,
Err(e) => Some(Err(e)),
};
}
Expand Down
5 changes: 5 additions & 0 deletions library/std/src/sys/itron/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,11 @@ pub fn error_name(er: abi::ER) -> Option<&'static str> {
}
}

#[inline]
pub fn is_interrupted(er: abi::ER) -> bool {
er == abi::E_RLWAI
}

pub fn decode_error_kind(er: abi::ER) -> ErrorKind {
match er {
// Success
Expand Down
6 changes: 6 additions & 0 deletions library/std/src/sys/sgx/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,12 @@ pub fn sgx_ineffective<T>(v: T) -> crate::io::Result<T> {
}
}

#[inline]
pub fn is_interrupted(code: i32) -> bool {
use fortanix_sgx_abi::Error;
code == Error::Interrupted as _
}

pub fn decode_error_kind(code: i32) -> ErrorKind {
use fortanix_sgx_abi::Error;

Expand Down
5 changes: 5 additions & 0 deletions library/std/src/sys/solid/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,11 @@ pub fn error_name(er: abi::ER) -> Option<&'static str> {
}
}

#[inline]
fn is_interrupted(er: abi::ER) -> bool {
false
}

pub fn decode_error_kind(er: abi::ER) -> ErrorKind {
match er {
// Success
Expand Down
5 changes: 5 additions & 0 deletions library/std/src/sys/solid/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,11 @@ pub fn unsupported_err() -> crate::io::Error {
)
}

#[inline]
pub fn is_interrupted(code: i32) -> bool {
error::is_interrupted(code)
}

pub fn decode_error_kind(code: i32) -> crate::io::ErrorKind {
error::decode_error_kind(code)
}
Expand Down
6 changes: 6 additions & 0 deletions library/std/src/sys/solid/net.rs
Original file line number Diff line number Diff line change
Expand Up @@ -181,6 +181,12 @@ pub(super) fn error_name(er: abi::ER) -> Option<&'static str> {
unsafe { CStr::from_ptr(netc::strerror(er)) }.to_str().ok()
}

#[inline]
pub fn is_interrupted(er: abi::ER) -> bool {
let errno = netc::SOLID_NET_ERR_BASE - er;
errno as libc::c_int == libc::EINTR
}

pub(super) fn decode_error_kind(er: abi::ER) -> ErrorKind {
let errno = netc::SOLID_NET_ERR_BASE - er;
match errno as libc::c_int {
Expand Down
5 changes: 5 additions & 0 deletions library/std/src/sys/unix/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -240,6 +240,11 @@ pub use crate::sys::android::signal;
#[cfg(not(target_os = "android"))]
pub use libc::signal;

#[inline]
pub(crate) fn is_interrupted(errno: i32) -> bool {
errno == libc::EINTR
}

pub fn decode_error_kind(errno: i32) -> ErrorKind {
use ErrorKind::*;
match errno as libc::c_int {
Expand Down
4 changes: 4 additions & 0 deletions library/std/src/sys/unsupported/common.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,10 @@ pub fn unsupported_err() -> std_io::Error {
)
}

pub fn is_interrupted(_code: i32) -> bool {
false
}

pub fn decode_error_kind(_code: i32) -> crate::io::ErrorKind {
crate::io::ErrorKind::Uncategorized
}
Expand Down
5 changes: 5 additions & 0 deletions library/std/src/sys/wasi/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,11 @@ cfg_if::cfg_if! {
mod common;
pub use common::*;

#[inline]
pub fn is_interrupted(errno: i32) -> bool {
errno == wasi::ERRNO_INTR.raw().into()
}

pub fn decode_error_kind(errno: i32) -> std_io::ErrorKind {
use std_io::ErrorKind::*;
if errno > u16::MAX as i32 || errno < 0 {
Expand Down
5 changes: 5 additions & 0 deletions library/std/src/sys/windows/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,11 @@ pub unsafe fn cleanup() {
net::cleanup();
}

#[inline]
pub fn is_interrupted(_errno: i32) -> bool {
false
}

pub fn decode_error_kind(errno: i32) -> ErrorKind {
use ErrorKind::*;

Expand Down

0 comments on commit 9334ec9

Please sign in to comment.