diff --git a/src/header/ifaddrs/mod.rs b/src/header/ifaddrs/mod.rs index 0f9d490a9c..efea1194e5 100644 --- a/src/header/ifaddrs/mod.rs +++ b/src/header/ifaddrs/mod.rs @@ -5,8 +5,9 @@ use crate::{ header::{ errno, stdlib, - netinet_in::{sockaddr_in, sockaddr_in6, AF_INET}, - sys_socket::{sa_family_t, sockaddr, AF_PACKET}, + bits_safamily_t::sa_family_t, + netinet_in::{sockaddr_in, sockaddr_in6}, + sys_socket::{sockaddr}, }, platform::{ self, @@ -14,6 +15,7 @@ use crate::{ }, }; +use alloc::vec::Vec; use core::ptr; #[cfg(target_os = "redox")] @@ -21,6 +23,9 @@ const O_RDONLY: usize = 0; #[cfg(target_os = "redox")] const O_DIRECTORY: usize = 0x10000; +const AF_INET: sa_family_t = 2; +const AF_INET6: sa_family_t = 10; + #[cfg(target_os = "redox")] #[repr(C)] struct Dirent { @@ -94,7 +99,7 @@ pub unsafe extern "C" fn getifaddrs(ifap: *mut *mut ifaddrs) -> c_int { let mut head: *mut ifaddrs = ptr::null_mut(); let mut tail: *mut *mut ifaddrs = &mut head; let Ok(interfaces) = enumerate_interfaces() else { - *ifap = ptr::null_mut(); + unsafe { *ifap = ptr::null_mut() }; platform::ERRNO.set(errno::ENOSYS); return -1; }; @@ -103,17 +108,17 @@ pub unsafe extern "C" fn getifaddrs(ifap: *mut *mut ifaddrs) -> c_int { let node = match build_ifa_node(&iface) { Ok(n) => n, Err(_) => { - *ifap = head; - freeifaddrs(head); + unsafe { *ifap = head }; + unsafe { freeifaddrs(head) }; platform::ERRNO.set(errno::ENOMEM); return -1; } }; - *tail = node; + unsafe { *tail = node }; tail = unsafe { &mut (*node).ifa_next }; } - *ifap = head; + unsafe { *ifap = head }; platform::ERRNO.set(0); 0 } @@ -153,10 +158,13 @@ fn parse_addr_string(s: &[u8]) -> Option<([u8; 16], u8, sa_family_t)> { let ip_part = split.next()?; let prefix_part = split.next(); let prefix: u8 = match prefix_part { - Some(p) => match core::str::from_utf8(p).ok()?.parse().ok()? { - 0..=128 => return None, - v => v, - }, + Some(p) => { + let v: u8 = core::str::from_utf8(p).ok()?.parse().ok()?; + if v > 128 { + return None; + } + v + } None => 64, }; let mut out = [0u8; 16]; @@ -203,7 +211,7 @@ fn parse_addr_string(s: &[u8]) -> Option<([u8; 16], u8, sa_family_t)> { if prefix > (len as u8) * 8 { return None; } - Some((out, prefix, if len == 4 { AF_INET } else { AF_PACKET })) + Some((out, prefix, if len == 4 { AF_INET } else { AF_INET6 })) } #[cfg(target_os = "redox")] @@ -420,17 +428,29 @@ fn build_ifa_node(iface: &InterfaceInfo) -> Result<*mut ifaddrs, ()> { unsafe { (*addr).sin_family = AF_INET; (*addr).sin_port = 0; - let addr_bytes = (*addr).sin_addr.s_addr.to_ne_bytes(); - core::ptr::copy_nonoverlapping( - addr_bytes.as_ptr(), - iface.addr.as_ptr(), - 4, - ); + (*addr).sin_addr.s_addr = u32::from_ne_bytes([ + iface.addr[0], + iface.addr[1], + iface.addr[2], + iface.addr[3], + ]); (*node).ifa_addr = addr_ptr; } } else { + let addr6 = addr_ptr as *mut sockaddr_in6; unsafe { - (*(addr_ptr as *mut sockaddr_in6)).sin6_family = iface.addr_family; + (*addr6).sin6_family = iface.addr_family; + let sin6_addr_bytes = + core::slice::from_raw_parts_mut( + &mut (*addr6).sin6_addr as *mut _ as *mut u8, + 16, + ); + let copy_len = iface.addr_len.min(16) as usize; + core::ptr::copy_nonoverlapping( + iface.addr.as_ptr(), + sin6_addr_bytes.as_mut_ptr(), + copy_len, + ); (*node).ifa_addr = addr_ptr; } } @@ -445,17 +465,29 @@ fn build_ifa_node(iface: &InterfaceInfo) -> Result<*mut ifaddrs, ()> { let addr = netmask_ptr as *mut sockaddr_in; unsafe { (*addr).sin_family = AF_INET; - let nm_bytes = (*addr).sin_addr.s_addr.to_ne_bytes(); - core::ptr::copy_nonoverlapping( - nm_bytes.as_ptr(), - iface.netmask.as_ptr(), - 4, - ); + (*addr).sin_addr.s_addr = u32::from_ne_bytes([ + iface.netmask[0], + iface.netmask[1], + iface.netmask[2], + iface.netmask[3], + ]); (*node).ifa_netmask = netmask_ptr; } } else { unsafe { - (*(netmask_ptr as *mut sockaddr_in6)).sin6_family = AF_INET as sa_family_t; + let addr6 = netmask_ptr as *mut sockaddr_in6; + (*addr6).sin6_family = AF_INET6; + let sin6_addr_bytes = + core::slice::from_raw_parts_mut( + &mut (*addr6).sin6_addr as *mut _ as *mut u8, + 16, + ); + let copy_len = iface.netmask_len.min(16) as usize; + core::ptr::copy_nonoverlapping( + iface.netmask.as_ptr(), + sin6_addr_bytes.as_mut_ptr(), + copy_len, + ); (*node).ifa_netmask = netmask_ptr; } } diff --git a/src/header/pthread/cond.rs b/src/header/pthread/cond.rs index 44eb19f3ee..ae2e3b056c 100644 --- a/src/header/pthread/cond.rs +++ b/src/header/pthread/cond.rs @@ -4,7 +4,7 @@ use crate::{ header::{ errno::EINVAL, pthread::{PTHREAD_PROCESS_PRIVATE, PTHREAD_PROCESS_SHARED, RlctMutex, e}, - time::{CLOCK_MONOTONIC, CLOCK_REALTIME, timespec}, + time::{CLOCK_MONOTONIC, CLOCK_REALTIME, CLOCK_PROCESS_CPUTIME_ID, timespec}, }, platform::types::{c_int, clockid_t, pthread_cond_t, pthread_condattr_t, pthread_mutex_t}, }; @@ -293,7 +293,7 @@ pub unsafe extern "C" fn pthread_condattr_setclock( // POSIX: only CLOCK_REALTIME and CLOCK_MONOTONIC are portable clocks for // condition variable timeouts. Any other clock_id must fail with EINVAL. match clock_id { - CLOCK_REALTIME | CLOCK_MONOTONIC => { + CLOCK_REALTIME | CLOCK_MONOTONIC | CLOCK_PROCESS_CPUTIME_ID => { (unsafe { *attr.cast::() }).clock = clock_id; 0 } diff --git a/src/platform/redox/mod.rs b/src/platform/redox/mod.rs index e25fbc936c..f3be46c3b1 100644 --- a/src/platform/redox/mod.rs +++ b/src/platform/redox/mod.rs @@ -109,12 +109,17 @@ const fn default_rlimits() -> [rlimit; RLIM_COUNT] { /// Fields parsed from the kernel proc scheme's Linux-compatible stat line, /// used by `getrusage`. The kernel reports `utime`/`stime` in whole seconds -/// and `rss` in pages. Per-process fault and context-switch counters are -/// currently hardwired to zero by the kernel proc scheme. +/// and `rss` in pages. The kernel currently hardwires fault counters +/// (`minflt`/`majflt`) to zero, but relibc parses them so they will be +/// reported automatically once the kernel starts tracking real values. +/// Context-switch and I/O counters (`inblock`, `oublock`, `nvcsw`, +/// `nivcsw`) are not present in the proc stat line at all. struct ProcStatFields { utime_sec: u64, stime_sec: u64, rss_pages: u64, + minflt: u64, + majflt: u64, } /// Read and parse `/scheme/proc//stat` from the kernel proc scheme. @@ -156,6 +161,8 @@ fn read_proc_stat_fields(pid: usize) -> Option { utime_sec: parse(11)?, stime_sec: parse(12)?, rss_pages: parse(21).unwrap_or(0), + minflt: parse(7).unwrap_or(0), + majflt: parse(9).unwrap_or(0), }) } @@ -324,8 +331,20 @@ impl Pal for Sys { } unsafe fn clock_settime(clk_id: clockid_t, tp: *const timespec) -> Result<()> { - todo_skip!(0, "clock_settime({}, {:p}): not implemented", clk_id, tp); - Err(Errno(ENOSYS)) + if tp.is_null() { + return Err(Errno(EINVAL)); + } + let relibc_ts = unsafe { &*tp }; + let redox_tp = syscall::TimeSpec { + tv_sec: relibc_ts.tv_sec as i64, + tv_nsec: relibc_ts.tv_nsec as i64, + }; + syscall::syscall2( + syscall::SYS_CLOCK_SETTIME, + clk_id as usize, + &redox_tp as *const _ as usize, + )?; + Ok(()) } fn close(fd: c_int) -> Result<()> { @@ -886,6 +905,8 @@ impl Pal for Sys { utime_sec: 0, stime_sec: 0, rss_pages: 0, + minflt: 0, + majflt: 0, }); // ru_maxrss is in kilobytes (Linux convention); rss from the stat @@ -905,10 +926,12 @@ impl Pal for Sys { ru_ixrss: 0, ru_idrss: 0, ru_isrss: 0, - // The kernel proc scheme hardwires fault counters to zero today. - ru_minflt: 0, - ru_majflt: 0, + ru_minflt: stat.minflt as c_long, + ru_majflt: stat.majflt as c_long, ru_nswap: 0, + // The proc stat line does not include I/O or context-switch + // counters; these require /proc//io or /proc//status + // interfaces that the Redox proc scheme does not expose today. ru_inblock: 0, ru_oublock: 0, ru_msgsnd: 0,