mirror of
https://github.com/RustPython/RustPython.git
synced 2026-10-28 18:59:04 +08:00
host_env: Use close_range syscall (FreeBSD/Linux) (#9016)
FreeBSD and Linux implement a syscall for close_range. It's faster than looping through the file descriptors to close which would cause a context switch per descriptor. CPython also uses the syscall where available. See: * https://man.freebsd.org/cgi/man.cgi?close_range(2) * https://man7.org/linux/man-pages/man2/close_range.2.html * https://github.com/python/cpython/blob/5a22a62b96a68c2dd31784c5e3427ad7b365388a/Python/fileutils.c#L3193-L3231
This commit is contained in:
1 parent
f5b6526c49
commit
5c40bb25af
1 file changed
+34
-1
@@ -348,8 +348,41 @@ pub fn close(fd: Owned) -> io::Result<()> {
|
||||
_close(fd.into_raw())
|
||||
}
|
||||
|
||||
#[cfg(not(any(target_os = "freebsd", target_os = "linux")))]
|
||||
pub fn closerange(fd_low: Raw, fd_high: Raw) {
|
||||
for fd in fd_low..fd_high {
|
||||
close_range_slow(fd_low, fd_high);
|
||||
}
|
||||
|
||||
// _Py_closerange
|
||||
#[cfg(any(target_os = "freebsd", target_os = "linux"))]
|
||||
pub fn closerange(fd_low: Raw, fd_high: Raw) {
|
||||
// CPython clamps low to 0.
|
||||
let fd_low = fd_low.max(0);
|
||||
// close_range(2) is [low, high] whereas CPython's is [low, high).
|
||||
if fd_high < fd_low {
|
||||
return;
|
||||
}
|
||||
let high = fd_high - 1;
|
||||
|
||||
if close_range(fd_low as _, high as _) == -1
|
||||
&& io::Error::last_os_error().raw_os_error() == Some(libc::ENOSYS)
|
||||
{
|
||||
close_range_slow(fd_low, fd_high);
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(target_os = "freebsd")]
|
||||
fn close_range(low: ffi::c_uint, high: ffi::c_uint) -> ffi::c_int {
|
||||
unsafe { libc::close_range(low, high, 0) as ffi::c_int }
|
||||
}
|
||||
|
||||
#[cfg(target_os = "linux")]
|
||||
fn close_range(low: ffi::c_uint, high: ffi::c_uint) -> ffi::c_int {
|
||||
unsafe { libc::syscall(libc::SYS_close_range, low, high, 0) as ffi::c_int }
|
||||
}
|
||||
|
||||
fn close_range_slow(low: Raw, high: Raw) {
|
||||
for fd in low..high {
|
||||
// The range can contain closed descriptors, so it cannot use Owned.
|
||||
let _ = _close(fd);
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user