1use std::{io, mem::MaybeUninit};
2
3#[inline]
5fn itoa(mut n: u64, buf: &mut [u8]) -> &str {
6 if n == 0 {
7 return "0";
8 }
9
10 let mut i = buf.len();
11 while n > 0 {
12 i -= 1;
13 buf[i] = b'0' + (n % 10) as u8;
14 n /= 10;
15 }
16
17 unsafe { std::str::from_utf8_unchecked(&buf[i..]) }
18}
19
20#[inline]
27unsafe fn sys_sysinfo(info: *mut libc::sysinfo) -> i64 {
28 #[cfg(target_arch = "x86_64")]
29 {
30 let ret: i64;
31 unsafe {
32 std::arch::asm!(
33 "syscall",
34 in("rax") 99_i64, in("rdi") info,
36 out("rcx") _,
37 out("r11") _,
38 lateout("rax") ret,
39 options(nostack)
40 );
41 }
42 ret
43 }
44
45 #[cfg(target_arch = "aarch64")]
46 {
47 let ret: i64;
48 unsafe {
49 std::arch::asm!(
50 "svc #0",
51 in("x8") 179_i64, in("x0") info,
53 lateout("x0") ret,
54 options(nostack)
55 );
56 }
57 ret
58 }
59
60 #[cfg(not(any(target_arch = "x86_64", target_arch = "aarch64")))]
61 {
62 unsafe { libc::sysinfo(info) as i64 }
63 }
64}
65
66#[cfg_attr(feature = "hotpath", hotpath::measure)]
72pub fn get_current() -> Result<String, io::Error> {
73 let uptime_seconds = {
74 let mut info = MaybeUninit::uninit();
75 if unsafe { sys_sysinfo(info.as_mut_ptr()) } != 0 {
76 return Err(io::Error::last_os_error());
77 }
78 #[allow(clippy::cast_sign_loss)]
79 unsafe {
80 info.assume_init().uptime as u64
81 }
82 };
83
84 let days = uptime_seconds / 86400;
85 let hours = (uptime_seconds / 3600) % 24;
86 let minutes = (uptime_seconds / 60) % 60;
87
88 let mut result = String::with_capacity(32);
89 let mut buf = [0u8; 20]; if days > 0 {
92 result.push_str(itoa(days, &mut buf));
93 result.push_str(if days == 1 { " day" } else { " days" });
94 }
95 if hours > 0 {
96 if !result.is_empty() {
97 result.push_str(", ");
98 }
99 result.push_str(itoa(hours, &mut buf));
100 result.push_str(if hours == 1 { " hour" } else { " hours" });
101 }
102 if minutes > 0 {
103 if !result.is_empty() {
104 result.push_str(", ");
105 }
106 result.push_str(itoa(minutes, &mut buf));
107 result.push_str(if minutes == 1 { " minute" } else { " minutes" });
108 }
109 if result.is_empty() {
110 result.push_str("less than a minute");
111 }
112
113 Ok(result)
114}