#![cfg(not(target_os = "macos"))]
use percpu::*;
#[def_percpu]
static BOOL: bool = false;
#[def_percpu]
static U8: u8 = 0;
#[def_percpu]
static U16: u16 = 0;
#[def_percpu]
static U32: u32 = 0;
#[def_percpu]
static U64: u64 = 0;
#[def_percpu]
static USIZE: usize = 0;
struct Struct {
foo: usize,
bar: u8,
}
#[def_percpu]
static STRUCT: Struct = Struct { foo: 0, bar: 0 };
#[cfg(all(target_os = "linux", feature = "non-zero-vma"))]
#[test]
fn test_percpu() {
println!("feature = \"sp-naive\": {}", cfg!(feature = "sp-naive"));
#[cfg(feature = "sp-naive")]
let base = 0;
#[cfg(not(feature = "sp-naive"))]
let base = {
assert_eq!(init(), 4);
let area_base_0 = percpu_area_base(0);
unsafe { write_percpu_reg(area_base_0) };
let base = read_percpu_reg();
println!("per-CPU area base (calculated) = {:#x}", area_base_0);
println!("per-CPU area base (read) = {:#x}", base);
println!("per-CPU area size = {}", percpu_area_size());
base
};
println!("bool offset: {:#x}", BOOL.offset());
println!("u8 offset: {:#x}", U8.offset());
println!("u16 offset: {:#x}", U16.offset());
println!("u32 offset: {:#x}", U32.offset());
println!("u64 offset: {:#x}", U64.offset());
println!("usize offset: {:#x}", USIZE.offset());
println!("struct offset: {:#x}", STRUCT.offset());
println!();
unsafe {
assert_eq!(base + BOOL.offset(), BOOL.current_ptr() as usize);
assert_eq!(base + U8.offset(), U8.current_ptr() as usize);
assert_eq!(base + U16.offset(), U16.current_ptr() as usize);
assert_eq!(base + U32.offset(), U32.current_ptr() as usize);
assert_eq!(base + U64.offset(), U64.current_ptr() as usize);
assert_eq!(base + USIZE.offset(), USIZE.current_ptr() as usize);
assert_eq!(base + STRUCT.offset(), STRUCT.current_ptr() as usize);
}
BOOL.write_current(true);
U8.write_current(123);
U16.write_current(0xabcd);
U32.write_current(0xdead_beef);
U64.write_current(0xa2ce_a2ce_a2ce_a2ce);
USIZE.write_current(0xffff_0000);
STRUCT.with_current(|s| {
s.foo = 0x2333;
s.bar = 100;
});
println!("bool value: {}", BOOL.read_current());
println!("u8 value: {}", U8.read_current());
println!("u16 value: {:#x}", U16.read_current());
println!("u32 value: {:#x}", U32.read_current());
println!("u64 value: {:#x}", U64.read_current());
println!("usize value: {:#x}", USIZE.read_current());
assert_eq!(U8.read_current(), 123);
assert_eq!(U16.read_current(), 0xabcd);
assert_eq!(U32.read_current(), 0xdead_beef);
assert_eq!(U64.read_current(), 0xa2ce_a2ce_a2ce_a2ce);
assert_eq!(USIZE.read_current(), 0xffff_0000);
STRUCT.with_current(|s| {
println!("struct.foo value: {:#x}", s.foo);
println!("struct.bar value: {}", s.bar);
assert_eq!(s.foo, 0x2333);
assert_eq!(s.bar, 100);
});
#[cfg(not(feature = "sp-naive"))]
test_remote_access();
}
#[cfg(all(
target_os = "linux",
not(feature = "sp-naive"),
feature = "non-zero-vma"
))]
fn test_remote_access() {
unsafe {
*BOOL.remote_ref_mut_raw(1) = false;
*U8.remote_ref_mut_raw(1) = 222;
*U16.remote_ref_mut_raw(1) = 0x1234;
*U32.remote_ref_mut_raw(1) = 0xf00d_f00d;
*U64.remote_ref_mut_raw(1) = 0xfeed_feed_feed_feed;
*USIZE.remote_ref_mut_raw(1) = 0x0000_ffff;
*STRUCT.remote_ref_mut_raw(1) = Struct {
foo: 0x6666,
bar: 200,
};
}
unsafe {
assert!(!*BOOL.remote_ptr(1));
assert_eq!(*U8.remote_ptr(1), 222);
assert_eq!(*U16.remote_ptr(1), 0x1234);
assert_eq!(*U32.remote_ptr(1), 0xf00d_f00d);
assert_eq!(*U64.remote_ptr(1), 0xfeed_feed_feed_feed);
assert_eq!(*USIZE.remote_ptr(1), 0x0000_ffff);
let s = STRUCT.remote_ref_raw(1);
assert_eq!(s.foo, 0x6666);
assert_eq!(s.bar, 200);
}
unsafe { write_percpu_reg(percpu_area_base(1)) };
println!();
println!("bool value on CPU 1: {}", BOOL.read_current());
println!("u8 value on CPU 1: {}", U8.read_current());
println!("u16 value on CPU 1: {:#x}", U16.read_current());
println!("u32 value on CPU 1: {:#x}", U32.read_current());
println!("u64 value on CPU 1: {:#x}", U64.read_current());
println!("usize value on CPU 1: {:#x}", USIZE.read_current());
assert!(!BOOL.read_current());
assert_eq!(U8.read_current(), 222);
assert_eq!(U16.read_current(), 0x1234);
assert_eq!(U32.read_current(), 0xf00d_f00d);
assert_eq!(U64.read_current(), 0xfeed_feed_feed_feed);
assert_eq!(USIZE.read_current(), 0x0000_ffff);
STRUCT.with_current(|s| {
println!("struct.foo value on CPU 1: {:#x}", s.foo);
println!("struct.bar value on CPU 1: {}", s.bar);
assert_eq!(s.foo, 0x6666);
assert_eq!(s.bar, 200);
});
}