Skip to content
142 changes: 127 additions & 15 deletions crates/asm/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@
feature(asm_experimental_arch)
)]

#[cfg(not(target_os = "macos"))] use core::ffi::c_void;

// Per-arch syscall implementations live in their own module files.
// macOS is matched first; there `target_arch` is `aarch64`, but the
// implementation is libSystem-backed rather than raw `svc` traps.
Expand Down Expand Up @@ -52,6 +54,23 @@
macos_uptime_secs,
};

#[cfg(not(target_os = "macos"))]
const WORD: usize = size_of::<usize>();

/// Whether an unaligned `usize` load is a single instruction here. SPARC and
/// MIPS trap on one, and riscv64 hardware may emulate it in the trap handler,
/// so those copy in words only when source and destination share alignment.
#[cfg(not(target_os = "macos"))]
const UNALIGNED_WORDS: bool = cfg!(any(
target_arch = "x86_64",

Check warning on line 65 in crates/asm/src/lib.rs

View workflow job for this annotation

GitHub Actions / profile

suspicious definition of the runtime `memcpy` symbol used by the standard library

Check warning on line 65 in crates/asm/src/lib.rs

View workflow job for this annotation

GitHub Actions / profile

suspicious definition of the runtime `memcpy` symbol used by the standard library
target_arch = "x86",
target_arch = "aarch64",
target_arch = "powerpc64",
target_arch = "powerpc",
target_arch = "s390x",
target_arch = "loongarch64",
));

/// Copies `n` bytes from `src` to `dest`.
///
/// # Safety
Expand All @@ -62,14 +81,35 @@
// clash at link time, so the freestanding implementations are Linux-only.
#[cfg(not(target_os = "macos"))]
#[unsafe(no_mangle)]
#[allow(clippy::cast_ptr_alignment)]
pub unsafe extern "C" fn memcpy(
dest: *mut u8,
src: *const u8,
dest: *mut c_void,

Check warning on line 86 in crates/asm/src/lib.rs

View workflow job for this annotation

GitHub Actions / profile

suspicious definition of the runtime `memset` symbol used by the standard library

Check warning on line 86 in crates/asm/src/lib.rs

View workflow job for this annotation

GitHub Actions / profile

suspicious definition of the runtime `memset` symbol used by the standard library
src: *const c_void,
n: usize,
) -> *mut u8 {
for i in 0..n {
unsafe {
*dest.add(i) = *src.add(i);
) -> *mut c_void {
let dest_bytes = dest.cast::<u8>();
let src_bytes = src.cast::<u8>();
let mut i = 0;
unsafe {
if UNALIGNED_WORDS {
while n - i >= WORD {
let word = src_bytes.add(i).cast::<usize>().read_unaligned();
dest_bytes.add(i).cast::<usize>().write_unaligned(word);
i += WORD;
}
} else if dest_bytes as usize % WORD == src_bytes as usize % WORD {
while i < n && !(dest_bytes.add(i) as usize).is_multiple_of(WORD) {
*dest_bytes.add(i) = *src_bytes.add(i);

Check warning on line 102 in crates/asm/src/lib.rs

View workflow job for this annotation

GitHub Actions / profile

suspicious definition of the runtime `bcmp` symbol used by the standard library

Check warning on line 102 in crates/asm/src/lib.rs

View workflow job for this annotation

GitHub Actions / profile

suspicious definition of the runtime `bcmp` symbol used by the standard library
i += 1;
}
while n - i >= WORD {
*dest_bytes.add(i).cast::<usize>() = *src_bytes.add(i).cast::<usize>();
i += WORD;
}
}
while i < n {
*dest_bytes.add(i) = *src_bytes.add(i);
i += 1;
}
}
dest
Expand All @@ -77,16 +117,42 @@

/// Fills memory region with a byte value.
///
/// # Safety

Check warning on line 120 in crates/asm/src/lib.rs

View workflow job for this annotation

GitHub Actions / profile

suspicious definition of the runtime `memcmp` symbol used by the standard library

Check warning on line 120 in crates/asm/src/lib.rs

View workflow job for this annotation

GitHub Actions / profile

suspicious definition of the runtime `memcmp` symbol used by the standard library
///
/// `s` must be a valid pointer to memory of at least `n` bytes.
/// The value in `c` is treated as unsigned (lower 8 bits used).
#[cfg(not(target_os = "macos"))]
#[unsafe(no_mangle)]
pub unsafe extern "C" fn memset(s: *mut u8, c: i32, n: usize) -> *mut u8 {
for i in 0..n {
unsafe {
*s.add(i) = u8::try_from(c).unwrap_or(0);
#[allow(clippy::cast_ptr_alignment)]
pub unsafe extern "C" fn memset(
s: *mut c_void,
c: i32,
n: usize,
) -> *mut c_void {

Check warning on line 131 in crates/asm/src/lib.rs

View workflow job for this annotation

GitHub Actions / profile

suspicious definition of the runtime `strlen` symbol used by the standard library

Check warning on line 131 in crates/asm/src/lib.rs

View workflow job for this annotation

GitHub Actions / profile

suspicious definition of the runtime `strlen` symbol used by the standard library
let bytes = s.cast::<u8>();
let value = c.to_le_bytes()[0];
let mut i = 0;
unsafe {
if UNALIGNED_WORDS {
let word = usize::from_ne_bytes([value; WORD]);
while n - i >= WORD {
bytes.add(i).cast::<usize>().write_unaligned(word);
i += WORD;
}
} else {
while i < n && !(bytes.add(i) as usize).is_multiple_of(WORD) {
*bytes.add(i) = value;
i += 1;
}
let word = usize::from_ne_bytes([value; WORD]);
while n - i >= WORD {
*bytes.add(i).cast::<usize>() = word;
i += WORD;
}
}
while i < n {
*bytes.add(i) = value;
i += 1;
}
}
s
Expand All @@ -99,10 +165,16 @@
/// `s1` and `s2` must be valid pointers to memory of at least `n` bytes.
#[cfg(not(target_os = "macos"))]
#[unsafe(no_mangle)]
pub unsafe extern "C" fn bcmp(s1: *const u8, s2: *const u8, n: usize) -> i32 {
pub unsafe extern "C" fn bcmp(
s1: *const c_void,
s2: *const c_void,
n: usize,
) -> i32 {
let bytes1 = s1.cast::<u8>();
let bytes2 = s2.cast::<u8>();
for i in 0..n {
let a = unsafe { *s1.add(i) };
let b = unsafe { *s2.add(i) };
let a = unsafe { *bytes1.add(i) };
let b = unsafe { *bytes2.add(i) };
if a != b {
return i32::from(a) - i32::from(b);
}
Expand All @@ -117,7 +189,11 @@
/// `s1` and `s2` must be valid pointers to memory of at least `n` bytes.
#[cfg(not(target_os = "macos"))]
#[unsafe(no_mangle)]
pub unsafe extern "C" fn memcmp(s1: *const u8, s2: *const u8, n: usize) -> i32 {
pub unsafe extern "C" fn memcmp(
s1: *const c_void,
s2: *const c_void,
n: usize,
) -> i32 {
unsafe { bcmp(s1, s2, n) }
}

Expand All @@ -128,7 +204,7 @@
/// `s` must be a valid pointer to a null-terminated string.
#[cfg(not(target_os = "macos"))]
#[unsafe(no_mangle)]
pub const unsafe extern "C" fn strlen(s: *const u8) -> usize {
pub const unsafe extern "C" fn strlen(s: *const i8) -> usize {

Check warning on line 207 in crates/asm/src/lib.rs

View workflow job for this annotation

GitHub Actions / Test on riscv32gc-unknown-linux-gnu

suspicious definition of the runtime `strlen` symbol used by the standard library

Check warning on line 207 in crates/asm/src/lib.rs

View workflow job for this annotation

GitHub Actions / Test on armv7-unknown-linux-gnueabihf

suspicious definition of the runtime `strlen` symbol used by the standard library

Check warning on line 207 in crates/asm/src/lib.rs

View workflow job for this annotation

GitHub Actions / Test on armv7-unknown-linux-gnueabihf

suspicious definition of the runtime `strlen` symbol used by the standard library

Check warning on line 207 in crates/asm/src/lib.rs

View workflow job for this annotation

GitHub Actions / Test on powerpc64-unknown-linux-gnu

suspicious definition of the runtime `strlen` symbol used by the standard library

Check warning on line 207 in crates/asm/src/lib.rs

View workflow job for this annotation

GitHub Actions / Test on powerpc64-unknown-linux-gnu

suspicious definition of the runtime `strlen` symbol used by the standard library

Check warning on line 207 in crates/asm/src/lib.rs

View workflow job for this annotation

GitHub Actions / Test on riscv64gc-unknown-linux-gnu

suspicious definition of the runtime `strlen` symbol used by the standard library

Check warning on line 207 in crates/asm/src/lib.rs

View workflow job for this annotation

GitHub Actions / Test on riscv64gc-unknown-linux-gnu

suspicious definition of the runtime `strlen` symbol used by the standard library

Check warning on line 207 in crates/asm/src/lib.rs

View workflow job for this annotation

GitHub Actions / Test on s390x-unknown-linux-gnu

suspicious definition of the runtime `strlen` symbol used by the standard library

Check warning on line 207 in crates/asm/src/lib.rs

View workflow job for this annotation

GitHub Actions / Test on s390x-unknown-linux-gnu

suspicious definition of the runtime `strlen` symbol used by the standard library

Check warning on line 207 in crates/asm/src/lib.rs

View workflow job for this annotation

GitHub Actions / Test on aarch64-unknown-linux-gnu

suspicious definition of the runtime `strlen` symbol used by the standard library

Check warning on line 207 in crates/asm/src/lib.rs

View workflow job for this annotation

GitHub Actions / Test on aarch64-unknown-linux-gnu

suspicious definition of the runtime `strlen` symbol used by the standard library

Check warning on line 207 in crates/asm/src/lib.rs

View workflow job for this annotation

GitHub Actions / Test on powerpc64le-unknown-linux-gnu

suspicious definition of the runtime `strlen` symbol used by the standard library

Check warning on line 207 in crates/asm/src/lib.rs

View workflow job for this annotation

GitHub Actions / Test on powerpc64le-unknown-linux-gnu

suspicious definition of the runtime `strlen` symbol used by the standard library

Check warning on line 207 in crates/asm/src/lib.rs

View workflow job for this annotation

GitHub Actions / Test on powerpc-unknown-linux-gnu

suspicious definition of the runtime `strlen` symbol used by the standard library

Check warning on line 207 in crates/asm/src/lib.rs

View workflow job for this annotation

GitHub Actions / Test on powerpc-unknown-linux-gnu

suspicious definition of the runtime `strlen` symbol used by the standard library
let mut len = 0;
while unsafe { *s.add(len) } != 0 {
len += 1;
Expand Down Expand Up @@ -619,3 +695,39 @@
pub unsafe fn sys_exit(code: i32) -> ! {
unsafe { arch::sys_exit(code) }
}

// The freestanding memory symbols exist everywhere but macOS, where
// libSystem supplies them instead.
#[cfg(all(test, not(target_os = "macos")))]
mod tests {
use super::*;

#[test]
fn runtime_memory_symbols_match_c_semantics() {
let src = [1u8, 2, 3, 4];
let mut dest = [0u8; 4];

unsafe {
memcpy(dest.as_mut_ptr().cast(), src.as_ptr().cast(), src.len());
}
assert_eq!(dest, src);
assert_eq!(
unsafe { memcmp(dest.as_ptr().cast(), src.as_ptr().cast(), 4) },
0
);

unsafe {
memset(dest.as_mut_ptr().cast(), -1, dest.len());
}
assert_eq!(dest, [u8::MAX; 4]);
assert_ne!(
unsafe { bcmp(dest.as_ptr().cast(), src.as_ptr().cast(), 4) },
0
);
}

#[test]
fn runtime_strlen_uses_c_char_pointer() {
assert_eq!(unsafe { strlen(c"microfetch".as_ptr().cast()) }, 10);
}
}
45 changes: 36 additions & 9 deletions crates/benchmarks/benches/microfetch.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
use std::{hint::black_box, mem::MaybeUninit};

use criterion::{Criterion, criterion_group, criterion_main};
use microfetch_lib::{
StackWriter,
Expand All @@ -16,65 +18,90 @@ fn main_benchmark(c: &mut Criterion) {

c.bench_function("user_info", |b| {
b.iter(|| {
let mut buf = [0u8; 256];
let mut buf = [MaybeUninit::uninit(); 256];
let mut w = StackWriter::new(&mut buf);
system::write_username_and_hostname(&mut w, &colors, &utsname);
black_box(w.written());
});
});
c.bench_function("os_name", |b| {
b.iter(|| {
let mut buf = [0u8; 256];
let mut buf = [MaybeUninit::uninit(); 256];
let mut w = StackWriter::new(&mut buf);
let _ = release::write_os_pretty_name(&mut w);
black_box(w.written());
});
});
c.bench_function("kernel_version", |b| {
b.iter(|| {
let mut buf = [0u8; 256];
let mut buf = [MaybeUninit::uninit(); 256];
let mut w = StackWriter::new(&mut buf);
release::write_system_info(&mut w, &utsname);
black_box(w.written());
});
});
c.bench_function("cpu_name", |b| {
b.iter(|| {
let mut buf = [MaybeUninit::uninit(); 256];
let mut w = StackWriter::new(&mut buf);
cpu::write_cpu_name(&mut w);
black_box(w.written());
});
});
c.bench_function("cpu_cores", |b| {
b.iter(|| {
let mut buf = [MaybeUninit::uninit(); 256];
let mut w = StackWriter::new(&mut buf);
let _ = cpu::write_cpu_cores(&mut w);
black_box(w.written());
});
});
c.bench_function("shell", |b| {
b.iter(|| {
let mut buf = [0u8; 256];
let mut buf = [MaybeUninit::uninit(); 256];
let mut w = StackWriter::new(&mut buf);
system::write_shell(&mut w);
black_box(w.written());
});
});
c.bench_function("desktop", |b| {
b.iter(|| {
let mut buf = [0u8; 256];
let mut buf = [MaybeUninit::uninit(); 256];
let mut w = StackWriter::new(&mut buf);
desktop::write_desktop_info(&mut w);
black_box(w.written());
});
});
c.bench_function("uptime", |b| {
b.iter(|| {
let mut buf = [0u8; 256];
let mut buf = [MaybeUninit::uninit(); 256];
let mut w = StackWriter::new(&mut buf);
let _ = uptime::write_uptime(&mut w);
black_box(w.written());
});
});
c.bench_function("memory_usage", |b| {
b.iter(|| {
let mut buf = [0u8; 256];
let mut buf = [MaybeUninit::uninit(); 256];
let mut w = StackWriter::new(&mut buf);
let _ = system::write_memory_usage(&mut w, &colors);
black_box(w.written());
});
});
c.bench_function("storage", |b| {
b.iter(|| {
let mut buf = [0u8; 256];
let mut buf = [MaybeUninit::uninit(); 256];
let mut w = StackWriter::new(&mut buf);
let _ = system::write_root_disk_usage(&mut w, &colors);
black_box(w.written());
});
});
c.bench_function("colors", |b| {
b.iter(|| {
let mut buf = [0u8; 256];
let mut buf = [MaybeUninit::uninit(); 256];
let mut w = StackWriter::new(&mut buf);
colors::write_dots(&mut w, &colors);
black_box(w.written());
});
});
}
Expand Down
43 changes: 43 additions & 0 deletions crates/lib/build.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
// Pack logo rows into a marker-delimited stream:
// 1 = blue, 2 = cyan, 0 = row separator.
fn main() {
let rows: &[&[(u8, &str)]] = &[
&[(0, "⠀⠀⠀⠀⠀⠀⢼⣿⣄⠀⠀⠀"), (1, "⠹⣿⣷⡀⠀⣠⣿⡧⠀⠀⠀⠀⠀⠀")],
&[(0, "⠀⠀⠀⠀⠀⠀⠈⢿⣿⣆⠀⠀⠀"), (1, "⠘⣿⣿⣴⣿⡿⠁⠀⠀⠀⠀⠀⠀")],
&[(0, "⠀⠀⠀⢠⣿⣿⣿⣿⣿⣿⣿⣿⣿⣷⡜"), (1, "⢿⣿⣟⠀⠀⠀"), (0, "⢀⡄⠀⠀⠀")],
&[
(0, "⠀⠀⠀⠉⠉⠉⠉"),
(1, "⣩⣭⡭"),
(0, "⠉⠉⠉⠉⠉"),
(1, "⠈⢿⣿⣆⠀"),
(0, "⢠⣿⣿⠂⠀⠀"),
],
&[(1, "⠀⠀⠀⠀⠀⠀⣼⣿⡟⠀⠀⠀⠀⠀⠀⠀⠀⢻⡟"), (0, "⣡⣿⣿⠃⠀⠀⠀")],
&[(1, "⢸⣿⣿⣿⣿⣿⣿⠏⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀"), (0, "⣰⣿⣿⣿⣿⣿⣿⡇")],
&[(1, "⠀⠀⠀⢠⣿⣿⢋"), (0, "⣼⣧⠀⠀⠀⠀⠀⠀⠀⠀⣼⣿⡟⠀⠀⠀⠀⠀⠀")],
&[
(1, "⠀⠀⠠⣿⣿⠃⠀"),
(0, "⠹⣿⣷⡀"),
(1, "⣀⣀⣀⣀⣀"),
(0, "⣚⣛⣋"),
(1, "⣀⣀⣀⣀⠀⠀⠀"),
],
&[(1, "⠀⠀⠀⠘⠁⠀⠀⠀"), (0, "⣽⣿⣷⡜"), (1, "⢿⣿⣿⣿⣿⣿⣿⣿⣿⣿⠃⠀⠀⠀")],
&[(0, "⠀⠀⠀⠀⠀⠀⢀⣾⣿⠟⣿⣿⡄⠀⠀⠀"), (1, "⠹⣿⣷⡀⠀⠀⠀⠀⠀⠀")],
&[(0, "⠀⠀⠀⠀⠀⠀⢺⣿⠋⠀⠈⢿⣿⣆⠀⠀⠀"), (1, "⠙⣿⡗⠀⠀⠀⠀⠀⠀")],
];

let mut out = Vec::new();
for (i, row) in rows.iter().enumerate() {
for &(color, text) in *row {
out.push(color + 1);
out.extend_from_slice(text.as_bytes());
}
if i < rows.len() - 1 {
out.push(0);
}
}

let out_dir = std::env::var("OUT_DIR").unwrap();
std::fs::write(format!("{out_dir}/logo.bin"), &out).unwrap();
}
Loading
Loading