From 8a525d41d675c852a8c205747c6afcfbadb89403 Mon Sep 17 00:00:00 2001 From: xjd Date: Tue, 4 Jun 2024 15:37:57 +0800 Subject: [PATCH 1/4] Dummy atomic implementation make some crates(like bytes, log) work on ckb-vm --- Cargo.toml | 1 + README.md | 2 +- contracts/Cargo.lock | 7 + contracts/ckb-std-tests/Cargo.toml | 3 +- contracts/ckb-std-tests/src/entry.rs | 16 + src/atomic.rs | 532 +++++++++++++++++++++++++++ src/lib.rs | 3 + test/Makefile | 3 +- test/simulator/Cargo.toml | 1 + 9 files changed, 565 insertions(+), 3 deletions(-) create mode 100644 src/atomic.rs diff --git a/Cargo.toml b/Cargo.toml index 292e083..fa9896f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -24,6 +24,7 @@ dlopen-c = ["libc"] build-with-clang = [] libc = [] ckb2023 = [] +atomic = [] [build-dependencies] cc = "1.0" diff --git a/README.md b/README.md index 739bd3e..9e9897e 100644 --- a/README.md +++ b/README.md @@ -15,7 +15,7 @@ This library contains several modules that help you write CKB contract with Rust * `debug!` macro: a `println!` like macro helps debugging * `entry!` macro: defines contract entry point * `default_alloc!` macro: defines global allocator for no-std rust - +* `atomic` module: atomic operations ### Memory allocator Default allocator uses a mixed allocation strategy: diff --git a/contracts/Cargo.lock b/contracts/Cargo.lock index c074620..aeb9f20 100644 --- a/contracts/Cargo.lock +++ b/contracts/Cargo.lock @@ -14,6 +14,12 @@ version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1f0d2da64a6a895d5a7e0724882825d50f83c13396b1b9f1878e19a024bab395" +[[package]] +name = "bytes" +version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "514de17de45fdb8dc022b1a7975556c53c86f9f0aa5f534b98977b171857c2c9" + [[package]] name = "cc" version = "1.0.83" @@ -64,6 +70,7 @@ name = "ckb-std-tests" version = "0.1.0" dependencies = [ "blake2b-ref", + "bytes", "ckb-std", ] diff --git a/contracts/ckb-std-tests/Cargo.toml b/contracts/ckb-std-tests/Cargo.toml index 073b376..b13175c 100644 --- a/contracts/ckb-std-tests/Cargo.toml +++ b/contracts/ckb-std-tests/Cargo.toml @@ -6,5 +6,6 @@ edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -ckb-std = { path = "../../", features = [ "dlopen-c" ] } +ckb-std = { path = "../../", features = [ "dlopen-c", "atomic" ] } blake2b-ref = { version = "0.3", default-features = false } +bytes = { version = "1.6.0", default-features = false } diff --git a/contracts/ckb-std-tests/src/entry.rs b/contracts/ckb-std-tests/src/entry.rs index ee74a68..44f360a 100644 --- a/contracts/ckb-std-tests/src/entry.rs +++ b/contracts/ckb-std-tests/src/entry.rs @@ -15,6 +15,7 @@ use ckb_std::since::{EpochNumberWithFraction, Since}; use ckb_std::{dynamic_loading, dynamic_loading_c_impl}; #[cfg(target_arch = "riscv64")] use core::mem::size_of_val; +use bytes; use crate::error::Error; @@ -402,6 +403,20 @@ fn test_since() { ); } +fn test_atomic() { + let b = bytes::Bytes::copy_from_slice(&[0, 1, 2, 3]); + + let b2 = b.slice(1..2); + assert_eq!(b2[0], 1); + assert_eq!(b2.len(), 1); + + let v : Vec = b.into(); + assert_eq!(v[1], 1); + assert_eq!(v.len(), 4); + debug!("test_atomic done"); +} + + pub fn main() -> Result<(), Error> { test_basic(); test_load_data(); @@ -424,5 +439,6 @@ pub fn main() -> Result<(), Error> { test_vm_version(); test_current_cycles(); test_since(); + test_atomic(); Ok(()) } diff --git a/src/atomic.rs b/src/atomic.rs new file mode 100644 index 0000000..78f9c8c --- /dev/null +++ b/src/atomic.rs @@ -0,0 +1,532 @@ +/// This library provides a Rust dummy atomic implementation inspired by +/// [xxuejie/lib-dummy-atomics](https://github.com/xxuejie/lib-dummy-atomics). +/// +/// When the RISC-V atomic extension is disabled by specifying the +/// `target-feature=-a` flag, LLVM will attempt to link the atomic operations to +/// functions prefixed with `__atomic`. For more details, refer to the [LLVM +/// Atomics Documentation](https://llvm.org/docs/Atomics.html). +/// +/// On the CKB-VM, only a single thread is present, making dummy atomic +/// operations sufficient for its purposes. +/// +use core::cmp::PartialEq; +use core::ffi::c_void; +use core::ops::{Add, BitAnd, BitOr, BitXor, Not, Sub}; + +fn atomic_exchange(ptr: *mut c_void, val: T) -> T { + unsafe { + let p = ptr as *mut T; + p.replace(val) + } +} + +fn atomic_compare_exchange( + ptr: *mut c_void, + expected: *mut c_void, + desired: T, +) -> bool { + unsafe { + let dst = ptr as *mut T; + let old = expected as *mut T; + let dst_val: T = dst.read_unaligned(); + if dst_val == old.read_unaligned() { + dst.write_unaligned(desired); + true + } else { + old.write_unaligned(dst_val); + false + } + } +} + +fn atomic_fetch_add + Copy>(ptr: *mut c_void, val: T) -> T { + unsafe { + let dst = ptr as *mut T; + let old: T = dst.read_unaligned(); + dst.write_unaligned(old + val); + old + } +} + +fn atomic_fetch_sub + Copy>(ptr: *mut c_void, val: T) -> T { + unsafe { + let dst = ptr as *mut T; + let old: T = dst.read_unaligned(); + dst.write_unaligned(old - val); + old + } +} + +fn atomic_fetch_xor + Copy>(ptr: *mut c_void, val: T) -> T { + unsafe { + let dst = ptr as *mut T; + let old: T = dst.read_unaligned(); + dst.write_unaligned(old ^ val); + old + } +} + +fn atomic_fetch_and + Copy>(ptr: *mut c_void, val: T) -> T { + unsafe { + let dst = ptr as *mut T; + let old: T = dst.read_unaligned(); + dst.write_unaligned(old & val); + old + } +} + +fn atomic_fetch_or + Copy>(ptr: *mut c_void, val: T) -> T { + unsafe { + let dst = ptr as *mut T; + let old: T = dst.read_unaligned(); + dst.write_unaligned(old | val); + old + } +} + +fn atomic_fetch_nand + Not + Copy>( + ptr: *mut c_void, + val: T, +) -> T { + unsafe { + let dst = ptr as *mut T; + let old: T = dst.read_unaligned(); + dst.write_unaligned(!(old & val)); + old + } +} + +fn atomic_add_fetch + Copy>(ptr: *mut c_void, val: T) -> T { + unsafe { + let dst = ptr as *mut T; + let old: T = dst.read_unaligned(); + let val2 = old + val; + dst.write_unaligned(val2); + val2 + } +} + +fn atomic_sub_fetch + Copy>(ptr: *mut c_void, val: T) -> T { + unsafe { + let dst = ptr as *mut T; + let old: T = dst.read_unaligned(); + let val2 = old - val; + dst.write_unaligned(val2); + val2 + } +} + +fn atomic_xor_fetch + Copy>(ptr: *mut c_void, val: T) -> T { + unsafe { + let dst = ptr as *mut T; + let old: T = dst.read_unaligned(); + let val2 = old ^ val; + dst.write_unaligned(val2); + val2 + } +} + +fn atomic_and_fetch + Copy>(ptr: *mut c_void, val: T) -> T { + unsafe { + let dst = ptr as *mut T; + let old: T = dst.read_unaligned(); + let val2 = old & val; + dst.write_unaligned(val2); + val2 + } +} + +fn atomic_or_fetch + Copy>(ptr: *mut c_void, val: T) -> T { + unsafe { + let dst = ptr as *mut T; + let old: T = dst.read_unaligned(); + let val2 = old | val; + dst.write_unaligned(val2); + val2 + } +} + +fn atomic_nand_fetch + Not + Copy>( + ptr: *mut c_void, + val: T, +) -> T { + unsafe { + let dst = ptr as *mut T; + let old: T = dst.read_unaligned(); + let val2 = !(old & val); + dst.write_unaligned(val2); + val2 + } +} + +#[no_mangle] +pub extern "C" fn __atomic_exchange_1(ptr: *mut c_void, val: u8, _memorder: isize) -> u8 { + atomic_exchange(ptr, val) +} + +#[no_mangle] +pub extern "C" fn __atomic_exchange_2(ptr: *mut c_void, val: u16, _memorder: isize) -> u16 { + atomic_exchange(ptr, val) +} + +#[no_mangle] +pub extern "C" fn __atomic_exchange_4(ptr: *mut c_void, val: u32, _memorder: isize) -> u32 { + atomic_exchange(ptr, val) +} + +#[no_mangle] +pub extern "C" fn __atomic_exchange_8(ptr: *mut c_void, val: u64, _memorder: isize) -> u64 { + atomic_exchange(ptr, val) +} + +#[no_mangle] +pub extern "C" fn __atomic_compare_exchange_1( + ptr: *mut c_void, + expected: *mut c_void, + desired: u8, + _weak: bool, + _success_memorder: isize, + _failure_memorder: isize, +) -> bool { + atomic_compare_exchange(ptr, expected, desired) +} + +#[no_mangle] +pub extern "C" fn __atomic_compare_exchange_2( + ptr: *mut c_void, + expected: *mut c_void, + desired: u16, + _weak: bool, + _success_memorder: isize, + _failure_memorder: isize, +) -> bool { + atomic_compare_exchange(ptr, expected, desired) +} + +#[no_mangle] +pub extern "C" fn __atomic_compare_exchange_4( + ptr: *mut c_void, + expected: *mut c_void, + desired: u32, + _weak: bool, + _success_memorder: isize, + _failure_memorder: isize, +) -> bool { + atomic_compare_exchange(ptr, expected, desired) +} + +#[no_mangle] +pub extern "C" fn __atomic_compare_exchange_8( + ptr: *mut c_void, + expected: *mut c_void, + desired: u64, + _weak: bool, + _success_memorder: isize, + _failure_memorder: isize, +) -> bool { + atomic_compare_exchange(ptr, expected, desired) +} + +#[no_mangle] +pub extern "C" fn __atomic_load_1(ptr: *mut c_void, _memorder: isize) -> u8 { + unsafe { + let p = ptr as *mut u8; + p.read_unaligned() + } +} + +#[no_mangle] +pub extern "C" fn __atomic_load_2(ptr: *mut c_void, _memorder: isize) -> u16 { + unsafe { + let p = ptr as *mut u16; + p.read_unaligned() + } +} + +#[no_mangle] +pub extern "C" fn __atomic_load_4(ptr: *mut c_void, _memorder: isize) -> u32 { + unsafe { + let p = ptr as *mut u32; + p.read_unaligned() + } +} + +#[no_mangle] +pub extern "C" fn __atomic_load_8(ptr: *mut c_void, _memorder: isize) -> u64 { + unsafe { + let p = ptr as *mut u64; + p.read_unaligned() + } +} + +#[no_mangle] +pub extern "C" fn __atomic_store_1(ptr: *mut c_void, val: u8, _memorder: isize) { + unsafe { + let p = ptr as *mut u8; + p.write_unaligned(val); + } +} + +#[no_mangle] +pub extern "C" fn __atomic_store_2(ptr: *mut c_void, val: u16, _memorder: isize) { + unsafe { + let p = ptr as *mut u16; + p.write_unaligned(val); + } +} + +#[no_mangle] +pub extern "C" fn __atomic_store_4(ptr: *mut c_void, val: u32, _memorder: isize) { + unsafe { + let p = ptr as *mut u32; + p.write_unaligned(val); + } +} + +#[no_mangle] +pub extern "C" fn __atomic_store_8(ptr: *mut c_void, val: u64, _memorder: isize) { + unsafe { + let p = ptr as *mut u64; + p.write_unaligned(val); + } +} + +#[no_mangle] +pub extern "C" fn __atomic_fetch_add_1(ptr: *mut c_void, val: u8, _memorder: isize) -> u8 { + atomic_fetch_add(ptr, val) +} + +#[no_mangle] +pub extern "C" fn __atomic_fetch_add_2(ptr: *mut c_void, val: u16, _memorder: isize) -> u16 { + atomic_fetch_add(ptr, val) +} + +#[no_mangle] +pub extern "C" fn __atomic_fetch_add_4(ptr: *mut c_void, val: u32, _memorder: isize) -> u32 { + atomic_fetch_add(ptr, val) +} + +#[no_mangle] +pub extern "C" fn __atomic_fetch_add_8(ptr: *mut c_void, val: u64, _memorder: isize) -> u64 { + atomic_fetch_add(ptr, val) +} + +#[no_mangle] +pub extern "C" fn __atomic_fetch_sub_1(ptr: *mut c_void, val: u8, _memorder: isize) -> u8 { + atomic_fetch_sub(ptr, val) +} + +#[no_mangle] +pub extern "C" fn __atomic_fetch_sub_2(ptr: *mut c_void, val: u16, _memorder: isize) -> u16 { + atomic_fetch_sub(ptr, val) +} + +#[no_mangle] +pub extern "C" fn __atomic_fetch_sub_4(ptr: *mut c_void, val: u32, _memorder: isize) -> u32 { + atomic_fetch_sub(ptr, val) +} + +#[no_mangle] +pub extern "C" fn __atomic_fetch_sub_8(ptr: *mut c_void, val: u64, _memorder: isize) -> u64 { + atomic_fetch_sub(ptr, val) +} + +#[no_mangle] +pub extern "C" fn __atomic_fetch_and_1(ptr: *mut c_void, val: u8, _memorder: isize) -> u8 { + atomic_fetch_and(ptr, val) +} + +#[no_mangle] +pub extern "C" fn __atomic_fetch_and_2(ptr: *mut c_void, val: u16, _memorder: isize) -> u16 { + atomic_fetch_and(ptr, val) +} + +#[no_mangle] +pub extern "C" fn __atomic_fetch_and_4(ptr: *mut c_void, val: u32, _memorder: isize) -> u32 { + atomic_fetch_and(ptr, val) +} + +#[no_mangle] +pub extern "C" fn __atomic_fetch_and_8(ptr: *mut c_void, val: u64, _memorder: isize) -> u64 { + atomic_fetch_and(ptr, val) +} + +#[no_mangle] +pub extern "C" fn __atomic_fetch_xor_1(ptr: *mut c_void, val: u8, _memorder: isize) -> u8 { + atomic_fetch_xor(ptr, val) +} + +#[no_mangle] +pub extern "C" fn __atomic_fetch_xor_2(ptr: *mut c_void, val: u16, _memorder: isize) -> u16 { + atomic_fetch_xor(ptr, val) +} + +#[no_mangle] +pub extern "C" fn __atomic_fetch_xor_4(ptr: *mut c_void, val: u32, _memorder: isize) -> u32 { + atomic_fetch_xor(ptr, val) +} + +#[no_mangle] +pub extern "C" fn __atomic_fetch_xor_8(ptr: *mut c_void, val: u64, _memorder: isize) -> u64 { + atomic_fetch_xor(ptr, val) +} + +#[no_mangle] +pub extern "C" fn __atomic_fetch_or_1(ptr: *mut c_void, val: u8, _memorder: isize) -> u8 { + atomic_fetch_or(ptr, val) +} + +#[no_mangle] +pub extern "C" fn __atomic_fetch_or_2(ptr: *mut c_void, val: u16, _memorder: isize) -> u16 { + atomic_fetch_or(ptr, val) +} + +#[no_mangle] +pub extern "C" fn __atomic_fetch_or_4(ptr: *mut c_void, val: u32, _memorder: isize) -> u32 { + atomic_fetch_or(ptr, val) +} + +#[no_mangle] +pub extern "C" fn __atomic_fetch_or_8(ptr: *mut c_void, val: u64, _memorder: isize) -> u64 { + atomic_fetch_or(ptr, val) +} + +#[no_mangle] +pub extern "C" fn __atomic_fetch_nand_1(ptr: *mut c_void, val: u8, _memorder: isize) -> u8 { + atomic_fetch_nand(ptr, val) +} + +#[no_mangle] +pub extern "C" fn __atomic_fetch_nand_2(ptr: *mut c_void, val: u16, _memorder: isize) -> u16 { + atomic_fetch_nand(ptr, val) +} + +#[no_mangle] +pub extern "C" fn __atomic_fetch_nand_4(ptr: *mut c_void, val: u32, _memorder: isize) -> u32 { + atomic_fetch_nand(ptr, val) +} + +#[no_mangle] +pub extern "C" fn __atomic_fetch_nand_8(ptr: *mut c_void, val: u64, _memorder: isize) -> u64 { + atomic_fetch_nand(ptr, val) +} + +#[no_mangle] +pub extern "C" fn __atomic_add_fetch_1(ptr: *mut c_void, val: u8, _memorder: isize) -> u8 { + atomic_add_fetch(ptr, val) +} + +#[no_mangle] +pub extern "C" fn __atomic_add_fetch_2(ptr: *mut c_void, val: u16, _memorder: isize) -> u16 { + atomic_add_fetch(ptr, val) +} + +#[no_mangle] +pub extern "C" fn __atomic_add_fetch_4(ptr: *mut c_void, val: u32, _memorder: isize) -> u32 { + atomic_add_fetch(ptr, val) +} + +#[no_mangle] +pub extern "C" fn __atomic_add_fetch_8(ptr: *mut c_void, val: u64, _memorder: isize) -> u64 { + atomic_add_fetch(ptr, val) +} + +#[no_mangle] +pub extern "C" fn __atomic_sub_fetch_1(ptr: *mut c_void, val: u8, _memorder: isize) -> u8 { + atomic_sub_fetch(ptr, val) +} + +#[no_mangle] +pub extern "C" fn __atomic_sub_fetch_2(ptr: *mut c_void, val: u16, _memorder: isize) -> u16 { + atomic_sub_fetch(ptr, val) +} + +#[no_mangle] +pub extern "C" fn __atomic_sub_fetch_4(ptr: *mut c_void, val: u32, _memorder: isize) -> u32 { + atomic_sub_fetch(ptr, val) +} + +#[no_mangle] +pub extern "C" fn __atomic_sub_fetch_8(ptr: *mut c_void, val: u64, _memorder: isize) -> u64 { + atomic_sub_fetch(ptr, val) +} + +#[no_mangle] +pub extern "C" fn __atomic_and_fetch_1(ptr: *mut c_void, val: u8, _memorder: isize) -> u8 { + atomic_and_fetch(ptr, val) +} + +#[no_mangle] +pub extern "C" fn __atomic_and_fetch_2(ptr: *mut c_void, val: u16, _memorder: isize) -> u16 { + atomic_and_fetch(ptr, val) +} + +#[no_mangle] +pub extern "C" fn __atomic_and_fetch_4(ptr: *mut c_void, val: u32, _memorder: isize) -> u32 { + atomic_and_fetch(ptr, val) +} + +#[no_mangle] +pub extern "C" fn __atomic_and_fetch_8(ptr: *mut c_void, val: u64, _memorder: isize) -> u64 { + atomic_and_fetch(ptr, val) +} + +#[no_mangle] +pub extern "C" fn __atomic_xor_fetch_1(ptr: *mut c_void, val: u8, _memorder: isize) -> u8 { + atomic_xor_fetch(ptr, val) +} + +#[no_mangle] +pub extern "C" fn __atomic_xor_fetch_2(ptr: *mut c_void, val: u16, _memorder: isize) -> u16 { + atomic_xor_fetch(ptr, val) +} + +#[no_mangle] +pub extern "C" fn __atomic_xor_fetch_4(ptr: *mut c_void, val: u32, _memorder: isize) -> u32 { + atomic_xor_fetch(ptr, val) +} + +#[no_mangle] +pub extern "C" fn __atomic_xor_fetch_8(ptr: *mut c_void, val: u64, _memorder: isize) -> u64 { + atomic_xor_fetch(ptr, val) +} + +#[no_mangle] +pub extern "C" fn __atomic_or_fetch_1(ptr: *mut c_void, val: u8, _memorder: isize) -> u8 { + atomic_or_fetch(ptr, val) +} + +#[no_mangle] +pub extern "C" fn __atomic_or_fetch_2(ptr: *mut c_void, val: u16, _memorder: isize) -> u16 { + atomic_or_fetch(ptr, val) +} + +#[no_mangle] +pub extern "C" fn __atomic_or_fetch_4(ptr: *mut c_void, val: u32, _memorder: isize) -> u32 { + atomic_or_fetch(ptr, val) +} + +#[no_mangle] +pub extern "C" fn __atomic_or_fetch_8(ptr: *mut c_void, val: u64, _memorder: isize) -> u64 { + atomic_or_fetch(ptr, val) +} + +#[no_mangle] +pub extern "C" fn __atomic_nand_fetch_1(ptr: *mut c_void, val: u8, _memorder: isize) -> u8 { + atomic_nand_fetch(ptr, val) +} + +#[no_mangle] +pub extern "C" fn __atomic_nand_fetch_2(ptr: *mut c_void, val: u16, _memorder: isize) -> u16 { + atomic_nand_fetch(ptr, val) +} + +#[no_mangle] +pub extern "C" fn __atomic_nand_fetch_4(ptr: *mut c_void, val: u32, _memorder: isize) -> u32 { + atomic_nand_fetch(ptr, val) +} + +#[no_mangle] +pub extern "C" fn __atomic_nand_fetch_8(ptr: *mut c_void, val: u64, _memorder: isize) -> u64 { + atomic_nand_fetch(ptr, val) +} diff --git a/src/lib.rs b/src/lib.rs index 7f99ad3..1bc0cea 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -14,6 +14,8 @@ #[cfg(not(feature = "rustc-dep-of-std"))] extern crate alloc; +#[cfg(feature = "atomic")] +pub mod atomic; pub mod ckb_constants; #[doc(hidden)] pub mod debug; @@ -27,6 +29,7 @@ pub mod global_alloc_macro; pub mod high_level; pub mod since; pub mod syscalls; + #[cfg(feature = "ckb-types")] pub use ckb_types; #[cfg(feature = "ckb-types")] diff --git a/test/Makefile b/test/Makefile index ad55d82..c082011 100644 --- a/test/Makefile +++ b/test/Makefile @@ -1,4 +1,4 @@ -test: clean build +test: build RUST_LOG=debug cargo test -- --nocapture make -C simulator build make -C simulator run @@ -6,6 +6,7 @@ test: clean build build: make -C shared-lib all-via-docker cd .. && capsule build + cd .. && RUSTFLAGS="-C target-feature=-a" capsule build -n ckb-std-tests clean: rm -rf ../build diff --git a/test/simulator/Cargo.toml b/test/simulator/Cargo.toml index 0981945..4947073 100644 --- a/test/simulator/Cargo.toml +++ b/test/simulator/Cargo.toml @@ -18,3 +18,4 @@ path = "src/exec_callee.rs" [dependencies] ckb-std = { path = "../..", features = ["ckb-types", "simulator"] } blake2b-ref = { version = "0.3", default-features = false } +bytes = { version = "1.6.0", default-features = false } From 251caa584be53f831674f63f3e55426b66e9153b Mon Sep 17 00:00:00 2001 From: xjd Date: Wed, 5 Jun 2024 10:49:02 +0800 Subject: [PATCH 2/4] Add test cases --- Cargo.toml | 1 + contracts/Cargo.lock | 7 + contracts/ckb-std-tests/Cargo.toml | 1 + contracts/ckb-std-tests/src/entry.rs | 374 ++++++++++++++++++++++++++- src/atomic.rs | 17 +- src/lib.rs | 4 +- test/simulator/Cargo.toml | 3 +- 7 files changed, 392 insertions(+), 15 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index fa9896f..57d3496 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -24,6 +24,7 @@ dlopen-c = ["libc"] build-with-clang = [] libc = [] ckb2023 = [] +# work with `target-feature=-a` Cargo flag atomic = [] [build-dependencies] diff --git a/contracts/Cargo.lock b/contracts/Cargo.lock index aeb9f20..48d0f04 100644 --- a/contracts/Cargo.lock +++ b/contracts/Cargo.lock @@ -72,6 +72,7 @@ dependencies = [ "blake2b-ref", "bytes", "ckb-std", + "log", ] [[package]] @@ -107,6 +108,12 @@ version = "0.2.151" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "302d7ab3130588088d277783b1e2d2e10c9e9e4a16dd9050e6ec93fb3e7048f4" +[[package]] +name = "log" +version = "0.4.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "90ed8c1e510134f979dbc4f070f87d4313098b704861a105fe34231c70a3901c" + [[package]] name = "molecule" version = "0.7.5" diff --git a/contracts/ckb-std-tests/Cargo.toml b/contracts/ckb-std-tests/Cargo.toml index b13175c..c8e4659 100644 --- a/contracts/ckb-std-tests/Cargo.toml +++ b/contracts/ckb-std-tests/Cargo.toml @@ -9,3 +9,4 @@ edition = "2021" ckb-std = { path = "../../", features = [ "dlopen-c", "atomic" ] } blake2b-ref = { version = "0.3", default-features = false } bytes = { version = "1.6.0", default-features = false } +log = { version = "0.4.17", default-features = false } diff --git a/contracts/ckb-std-tests/src/entry.rs b/contracts/ckb-std-tests/src/entry.rs index 44f360a..9e950b8 100644 --- a/contracts/ckb-std-tests/src/entry.rs +++ b/contracts/ckb-std-tests/src/entry.rs @@ -10,14 +10,15 @@ use core::mem::size_of; #[cfg(target_arch = "riscv64")] use crate::code_hashes::CODE_HASH_SHARED_LIB; +use crate::error::Error; +use bytes; +use ckb_std::atomic; use ckb_std::since::{EpochNumberWithFraction, Since}; #[cfg(target_arch = "riscv64")] use ckb_std::{dynamic_loading, dynamic_loading_c_impl}; -#[cfg(target_arch = "riscv64")] +use core::ffi::c_void; use core::mem::size_of_val; -use bytes; - -use crate::error::Error; +use log::{info, warn}; fn new_blake2b() -> Blake2b { const CKB_HASH_PERSONALIZATION: &[u8] = b"ckb-default-hash"; @@ -404,18 +405,378 @@ fn test_since() { } fn test_atomic() { + // The bytes crate uses atomic operations. let b = bytes::Bytes::copy_from_slice(&[0, 1, 2, 3]); let b2 = b.slice(1..2); assert_eq!(b2[0], 1); assert_eq!(b2.len(), 1); - let v : Vec = b.into(); + let v: Vec = b.into(); assert_eq!(v[1], 1); assert_eq!(v.len(), 4); - debug!("test_atomic done"); + + // The log crate uses atomic operations. + info!("atomic info"); + warn!("atomic warn"); +} + +fn test_compare_exchange(data: &mut T, expected: &mut T, desired: u64, same: bool) { + let size = size_of_val(data); + let res = match size { + 1 => atomic::__atomic_compare_exchange_1( + data as *mut T as *mut c_void, + expected as *mut T as *mut c_void, + desired as u8, + false, + 0, + 0, + ), + 2 => atomic::__atomic_compare_exchange_2( + data as *mut T as *mut c_void, + expected as *mut T as *mut c_void, + desired as u16, + false, + 0, + 0, + ), + 4 => atomic::__atomic_compare_exchange_4( + data as *mut T as *mut c_void, + expected as *mut T as *mut c_void, + desired as u32, + false, + 0, + 0, + ), + 8 => atomic::__atomic_compare_exchange_8( + data as *mut T as *mut c_void, + expected as *mut T as *mut c_void, + desired as u64, + false, + 0, + 0, + ), + _ => { + panic!("Unknown size"); + } + }; + assert_eq!(res, same); } +fn test_atomic2() { + let mut data1: u8 = 42; + let old = atomic::__atomic_exchange_1(&mut data1 as *mut u8 as *mut c_void, 0, 0); + assert_eq!(old, 42); + let mut data2: u16 = 42; + let old = atomic::__atomic_exchange_2(&mut data2 as *mut u16 as *mut c_void, 0, 0); + assert_eq!(old, 42); + let mut data4: u32 = 42; + let old = atomic::__atomic_exchange_4(&mut data4 as *mut u32 as *mut c_void, 0, 0); + assert_eq!(old, 42); + let mut data8: u64 = 42; + let old = atomic::__atomic_exchange_8(&mut data8 as *mut u64 as *mut c_void, 0, 0); + assert_eq!(old, 42); + + let mut data: u8 = 42; + let mut expected: u8 = 42; + test_compare_exchange(&mut data, &mut expected, 0, true); + assert_eq!(data, 0); + test_compare_exchange(&mut data, &mut expected, 0, false); + assert_eq!(expected, 0); + + let mut data: u16 = 42; + let mut expected: u16 = 42; + test_compare_exchange(&mut data, &mut expected, 0, true); + assert_eq!(data, 0); + test_compare_exchange(&mut data, &mut expected, 0, false); + assert_eq!(expected, 0); + + let mut data: u32 = 42; + let mut expected: u32 = 42; + test_compare_exchange(&mut data, &mut expected, 0, true); + assert_eq!(data, 0); + test_compare_exchange(&mut data, &mut expected, 0, false); + assert_eq!(expected, 0); + + let mut data: u64 = 42; + let mut expected: u64 = 42; + test_compare_exchange(&mut data, &mut expected, 0, true); + assert_eq!(data, 0); + test_compare_exchange(&mut data, &mut expected, 0, false); + assert_eq!(expected, 0); + + let data: u8 = 42; + let expected = atomic::__atomic_load_1(&data as *const u8 as *const c_void, 0); + assert_eq!(expected, data); + + let data: u16 = 42; + let expected = atomic::__atomic_load_2(&data as *const u16 as *const c_void, 0); + assert_eq!(expected, data); + + let data: u32 = 42; + let expected = atomic::__atomic_load_4(&data as *const u32 as *const c_void, 0); + assert_eq!(expected, data); + + let data: u64 = 42; + let expected = atomic::__atomic_load_8(&data as *const u64 as *const c_void, 0); + assert_eq!(expected, data); + + let mut data: u8 = 42; + atomic::__atomic_store_1(&mut data as *mut u8 as *mut c_void, 0, 0); + assert_eq!(data, 0); + + let mut data: u16 = 42; + atomic::__atomic_store_2(&mut data as *mut u16 as *mut c_void, 0, 0); + assert_eq!(data, 0); + + let mut data: u32 = 42; + atomic::__atomic_store_4(&mut data as *mut u32 as *mut c_void, 0, 0); + assert_eq!(data, 0); + + let mut data: u64 = 42; + atomic::__atomic_store_8(&mut data as *mut u64 as *mut c_void, 0, 0); + assert_eq!(data, 0); + + let mut data: u8 = 42; + let res = atomic::__atomic_fetch_add_1(&mut data as *mut u8 as *mut c_void, 1, 0); + assert_eq!(res, 42); + assert_eq!(data, 43); + + let mut data: u16 = 42; + let res = atomic::__atomic_fetch_add_2(&mut data as *mut u16 as *mut c_void, 1, 0); + assert_eq!(res, 42); + assert_eq!(data, 43); + + let mut data: u32 = 42; + let res = atomic::__atomic_fetch_add_4(&mut data as *mut u32 as *mut c_void, 1, 0); + assert_eq!(res, 42); + assert_eq!(data, 43); + + let mut data: u64 = 42; + let res = atomic::__atomic_fetch_add_8(&mut data as *mut u64 as *mut c_void, 1, 0); + assert_eq!(res, 42); + assert_eq!(data, 43); + + let mut data: u8 = 42; + let res = atomic::__atomic_fetch_sub_1(&mut data as *mut u8 as *mut c_void, 1, 0); + assert_eq!(res, 42); + assert_eq!(data, 41); + + let mut data: u16 = 42; + let res = atomic::__atomic_fetch_sub_2(&mut data as *mut u16 as *mut c_void, 1, 0); + assert_eq!(res, 42); + assert_eq!(data, 41); + + let mut data: u32 = 42; + let res = atomic::__atomic_fetch_sub_4(&mut data as *mut u32 as *mut c_void, 1, 0); + assert_eq!(res, 42); + assert_eq!(data, 41); + + let mut data: u64 = 42; + let res = atomic::__atomic_fetch_sub_8(&mut data as *mut u64 as *mut c_void, 1, 0); + assert_eq!(res, 42); + assert_eq!(data, 41); + + let mut data: u8 = 43; + let res = atomic::__atomic_fetch_and_1(&mut data as *mut u8 as *mut c_void, 1, 0); + assert_eq!(res, 43); + assert_eq!(data, 1); + + let mut data: u16 = 43; + let res = atomic::__atomic_fetch_and_2(&mut data as *mut u16 as *mut c_void, 1, 0); + assert_eq!(res, 43); + assert_eq!(data, 1); + + let mut data: u32 = 43; + let res = atomic::__atomic_fetch_and_4(&mut data as *mut u32 as *mut c_void, 1, 0); + assert_eq!(res, 43); + assert_eq!(data, 1); + + let mut data: u64 = 43; + let res = atomic::__atomic_fetch_and_8(&mut data as *mut u64 as *mut c_void, 1, 0); + assert_eq!(res, 43); + assert_eq!(data, 1); + + let mut data: u8 = 43; + let res = atomic::__atomic_fetch_xor_1(&mut data as *mut u8 as *mut c_void, 1, 0); + assert_eq!(res, 43); + assert_eq!(data, 42); + + let mut data: u16 = 43; + let res = atomic::__atomic_fetch_xor_2(&mut data as *mut u16 as *mut c_void, 1, 0); + assert_eq!(res, 43); + assert_eq!(data, 42); + + let mut data: u32 = 43; + let res = atomic::__atomic_fetch_xor_4(&mut data as *mut u32 as *mut c_void, 1, 0); + assert_eq!(res, 43); + assert_eq!(data, 42); + + let mut data: u64 = 43; + let res = atomic::__atomic_fetch_xor_8(&mut data as *mut u64 as *mut c_void, 1, 0); + assert_eq!(res, 43); + assert_eq!(data, 42); + + let mut data: u8 = 42; + let res = atomic::__atomic_fetch_or_1(&mut data as *mut u8 as *mut c_void, 1, 0); + assert_eq!(res, 42); + assert_eq!(data, 43); + + let mut data: u16 = 42; + let res = atomic::__atomic_fetch_or_2(&mut data as *mut u16 as *mut c_void, 1, 0); + assert_eq!(res, 42); + assert_eq!(data, 43); + + let mut data: u32 = 42; + let res = atomic::__atomic_fetch_or_4(&mut data as *mut u32 as *mut c_void, 1, 0); + assert_eq!(res, 42); + assert_eq!(data, 43); + + let mut data: u64 = 42; + let res = atomic::__atomic_fetch_or_8(&mut data as *mut u64 as *mut c_void, 1, 0); + assert_eq!(res, 42); + assert_eq!(data, 43); + + let mut data: u8 = 1; + let res = atomic::__atomic_fetch_nand_1(&mut data as *mut u8 as *mut c_void, 1, 0); + assert_eq!(res, 1); + assert_eq!(data, 0xFE); + + let mut data: u16 = 1; + let res = atomic::__atomic_fetch_nand_2(&mut data as *mut u16 as *mut c_void, 1, 0); + assert_eq!(res, 1); + assert_eq!(data, 0xFFFE); + + let mut data: u32 = 1; + let res = atomic::__atomic_fetch_nand_4(&mut data as *mut u32 as *mut c_void, 1, 0); + assert_eq!(res, 1); + assert_eq!(data, 0xFFFFFFFE); + + let mut data: u64 = 1; + let res = atomic::__atomic_fetch_nand_8(&mut data as *mut u64 as *mut c_void, 1, 0); + assert_eq!(res, 1); + assert_eq!(data, 0xFFFFFFFFFFFFFFFE); + + let mut data: u8 = 42; + let res = atomic::__atomic_add_fetch_1(&mut data as *mut u8 as *mut c_void, 1, 0); + assert_eq!(res, 43); + assert_eq!(data, 43); + + let mut data: u16 = 42; + let res = atomic::__atomic_add_fetch_2(&mut data as *mut u16 as *mut c_void, 1, 0); + assert_eq!(res, 43); + assert_eq!(data, 43); + + let mut data: u32 = 42; + let res = atomic::__atomic_add_fetch_4(&mut data as *mut u32 as *mut c_void, 1, 0); + assert_eq!(res, 43); + assert_eq!(data, 43); + + let mut data: u64 = 42; + let res = atomic::__atomic_add_fetch_8(&mut data as *mut u64 as *mut c_void, 1, 0); + assert_eq!(res, 43); + assert_eq!(data, 43); + + let mut data: u8 = 42; + let res = atomic::__atomic_sub_fetch_1(&mut data as *mut u8 as *mut c_void, 1, 0); + assert_eq!(res, 41); + assert_eq!(data, 41); + + let mut data: u16 = 42; + let res = atomic::__atomic_sub_fetch_2(&mut data as *mut u16 as *mut c_void, 1, 0); + assert_eq!(res, 41); + assert_eq!(data, 41); + + let mut data: u32 = 42; + let res = atomic::__atomic_sub_fetch_4(&mut data as *mut u32 as *mut c_void, 1, 0); + assert_eq!(res, 41); + assert_eq!(data, 41); + + let mut data: u64 = 42; + let res = atomic::__atomic_sub_fetch_8(&mut data as *mut u64 as *mut c_void, 1, 0); + assert_eq!(res, 41); + assert_eq!(data, 41); + + let mut data: u8 = 43; + let res = atomic::__atomic_and_fetch_1(&mut data as *mut u8 as *mut c_void, 1, 0); + assert_eq!(res, 1); + assert_eq!(data, 1); + + let mut data: u16 = 43; + let res = atomic::__atomic_and_fetch_2(&mut data as *mut u16 as *mut c_void, 1, 0); + assert_eq!(res, 1); + assert_eq!(data, 1); + + let mut data: u32 = 43; + let res = atomic::__atomic_and_fetch_4(&mut data as *mut u32 as *mut c_void, 1, 0); + assert_eq!(res, 1); + assert_eq!(data, 1); + + let mut data: u64 = 43; + let res = atomic::__atomic_and_fetch_8(&mut data as *mut u64 as *mut c_void, 1, 0); + assert_eq!(res, 1); + assert_eq!(data, 1); + + let mut data: u8 = 43; + let res = atomic::__atomic_xor_fetch_1(&mut data as *mut u8 as *mut c_void, 1, 0); + assert_eq!(res, 42); + assert_eq!(data, 42); + + let mut data: u16 = 43; + let res = atomic::__atomic_xor_fetch_2(&mut data as *mut u16 as *mut c_void, 1, 0); + assert_eq!(res, 42); + assert_eq!(data, 42); + + let mut data: u32 = 43; + let res = atomic::__atomic_xor_fetch_4(&mut data as *mut u32 as *mut c_void, 1, 0); + assert_eq!(res, 42); + assert_eq!(data, 42); + + let mut data: u64 = 43; + let res = atomic::__atomic_xor_fetch_8(&mut data as *mut u64 as *mut c_void, 1, 0); + assert_eq!(res, 42); + assert_eq!(data, 42); + + let mut data: u8 = 42; + let res = atomic::__atomic_or_fetch_1(&mut data as *mut u8 as *mut c_void, 1, 0); + assert_eq!(res, 43); + assert_eq!(data, 43); + + let mut data: u16 = 42; + let res = atomic::__atomic_or_fetch_2(&mut data as *mut u16 as *mut c_void, 1, 0); + assert_eq!(res, 43); + assert_eq!(data, 43); + + let mut data: u32 = 42; + let res = atomic::__atomic_or_fetch_4(&mut data as *mut u32 as *mut c_void, 1, 0); + assert_eq!(res, 43); + assert_eq!(data, 43); + + let mut data: u64 = 42; + let res = atomic::__atomic_or_fetch_8(&mut data as *mut u64 as *mut c_void, 1, 0); + assert_eq!(res, 43); + assert_eq!(data, 43); + + let mut data: u8 = 1; + let res = atomic::__atomic_nand_fetch_1(&mut data as *mut u8 as *mut c_void, 1, 0); + assert_eq!(res, 0xFE); + assert_eq!(data, 0xFE); + + let mut data: u16 = 1; + let res = atomic::__atomic_nand_fetch_2(&mut data as *mut u16 as *mut c_void, 1, 0); + assert_eq!(res, 0xFFFE); + assert_eq!(data, 0xFFFE); + + let mut data: u32 = 1; + let res = atomic::__atomic_nand_fetch_4(&mut data as *mut u32 as *mut c_void, 1, 0); + assert_eq!(res, 0xFFFFFFFE); + assert_eq!(data, 0xFFFFFFFE); + + let mut data: u64 = 1; + let res = atomic::__atomic_nand_fetch_8(&mut data as *mut u64 as *mut c_void, 1, 0); + assert_eq!(res, 0xFFFFFFFFFFFFFFFE); + assert_eq!(data, 0xFFFFFFFFFFFFFFFE); +} pub fn main() -> Result<(), Error> { test_basic(); @@ -440,5 +801,6 @@ pub fn main() -> Result<(), Error> { test_current_cycles(); test_since(); test_atomic(); + test_atomic2(); Ok(()) } diff --git a/src/atomic.rs b/src/atomic.rs index 78f9c8c..a3a5fe1 100644 --- a/src/atomic.rs +++ b/src/atomic.rs @@ -1,10 +1,15 @@ +/// +/// Some Rust code can be compiled into atomic instructions for the RISC-V +/// target. However, these atomic instructions are not supported on ckb-vm. To +/// address this issue, this module has been introduced. +/// /// This library provides a Rust dummy atomic implementation inspired by /// [xxuejie/lib-dummy-atomics](https://github.com/xxuejie/lib-dummy-atomics). /// /// When the RISC-V atomic extension is disabled by specifying the /// `target-feature=-a` flag, LLVM will attempt to link the atomic operations to -/// functions prefixed with `__atomic`. For more details, refer to the [LLVM -/// Atomics Documentation](https://llvm.org/docs/Atomics.html). +/// functions prefixed with `__atomic` in this module. For more details, refer +/// to the [LLVM Atomics Documentation](https://llvm.org/docs/Atomics.html). /// /// On the CKB-VM, only a single thread is present, making dummy atomic /// operations sufficient for its purposes. @@ -228,7 +233,7 @@ pub extern "C" fn __atomic_compare_exchange_8( } #[no_mangle] -pub extern "C" fn __atomic_load_1(ptr: *mut c_void, _memorder: isize) -> u8 { +pub extern "C" fn __atomic_load_1(ptr: *const c_void, _memorder: isize) -> u8 { unsafe { let p = ptr as *mut u8; p.read_unaligned() @@ -236,7 +241,7 @@ pub extern "C" fn __atomic_load_1(ptr: *mut c_void, _memorder: isize) -> u8 { } #[no_mangle] -pub extern "C" fn __atomic_load_2(ptr: *mut c_void, _memorder: isize) -> u16 { +pub extern "C" fn __atomic_load_2(ptr: *const c_void, _memorder: isize) -> u16 { unsafe { let p = ptr as *mut u16; p.read_unaligned() @@ -244,7 +249,7 @@ pub extern "C" fn __atomic_load_2(ptr: *mut c_void, _memorder: isize) -> u16 { } #[no_mangle] -pub extern "C" fn __atomic_load_4(ptr: *mut c_void, _memorder: isize) -> u32 { +pub extern "C" fn __atomic_load_4(ptr: *const c_void, _memorder: isize) -> u32 { unsafe { let p = ptr as *mut u32; p.read_unaligned() @@ -252,7 +257,7 @@ pub extern "C" fn __atomic_load_4(ptr: *mut c_void, _memorder: isize) -> u32 { } #[no_mangle] -pub extern "C" fn __atomic_load_8(ptr: *mut c_void, _memorder: isize) -> u64 { +pub extern "C" fn __atomic_load_8(ptr: *const c_void, _memorder: isize) -> u64 { unsafe { let p = ptr as *mut u64; p.read_unaligned() diff --git a/src/lib.rs b/src/lib.rs index 1bc0cea..a4727d9 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -14,8 +14,6 @@ #[cfg(not(feature = "rustc-dep-of-std"))] extern crate alloc; -#[cfg(feature = "atomic")] -pub mod atomic; pub mod ckb_constants; #[doc(hidden)] pub mod debug; @@ -38,3 +36,5 @@ pub mod dynamic_loading; pub mod dynamic_loading_c_impl; #[cfg(feature = "allocator")] pub use buddy_alloc; +#[cfg(feature = "atomic")] +pub mod atomic; diff --git a/test/simulator/Cargo.toml b/test/simulator/Cargo.toml index 4947073..f040cac 100644 --- a/test/simulator/Cargo.toml +++ b/test/simulator/Cargo.toml @@ -16,6 +16,7 @@ name = "exec-callee" path = "src/exec_callee.rs" [dependencies] -ckb-std = { path = "../..", features = ["ckb-types", "simulator"] } +ckb-std = { path = "../..", features = ["ckb-types", "simulator", "atomic"] } blake2b-ref = { version = "0.3", default-features = false } bytes = { version = "1.6.0", default-features = false } +log = { version = "0.4.17", default-features = false } From da9b8f87bd6da46a0d1f64f08bdfe17fc089dc11 Mon Sep 17 00:00:00 2001 From: xjd Date: Thu, 6 Jun 2024 10:10:56 +0800 Subject: [PATCH 3/4] Fix by review * feature name changed to `dummy-atomic` * feature `dummy-atomic` can't be used on non risc-v target * use read/write instead of read_unaligned/write_unaligned --- Cargo.toml | 2 +- build.rs | 4 + contracts/ckb-std-tests/Cargo.toml | 2 +- contracts/ckb-std-tests/src/entry.rs | 145 ++++++++++++++------------- src/{atomic.rs => dummy_atomic.rs} | 72 ++++++------- src/lib.rs | 4 +- test/simulator/Cargo.toml | 2 +- 7 files changed, 123 insertions(+), 108 deletions(-) rename src/{atomic.rs => dummy_atomic.rs} (90%) diff --git a/Cargo.toml b/Cargo.toml index 57d3496..a4254e8 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -25,7 +25,7 @@ build-with-clang = [] libc = [] ckb2023 = [] # work with `target-feature=-a` Cargo flag -atomic = [] +dummy-atomic = [] [build-dependencies] cc = "1.0" diff --git a/build.rs b/build.rs index 5c79316..28a8bb4 100644 --- a/build.rs +++ b/build.rs @@ -24,6 +24,10 @@ fn main() { setup_compiler_flags(&mut build); build.compile("libc"); } + if target_arch != "riscv64" && cfg!(feature = "dummy-atomic") { + println!("cargo:warning=This build script intentionally failed: feature `dummy-atomic` can't be used in non risc-v target"); + std::process::exit(1); + } } fn setup_compiler_flags(build: &mut cc::Build) { diff --git a/contracts/ckb-std-tests/Cargo.toml b/contracts/ckb-std-tests/Cargo.toml index c8e4659..6765686 100644 --- a/contracts/ckb-std-tests/Cargo.toml +++ b/contracts/ckb-std-tests/Cargo.toml @@ -6,7 +6,7 @@ edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -ckb-std = { path = "../../", features = [ "dlopen-c", "atomic" ] } +ckb-std = { path = "../../", features = [ "dlopen-c", "dummy-atomic" ] } blake2b-ref = { version = "0.3", default-features = false } bytes = { version = "1.6.0", default-features = false } log = { version = "0.4.17", default-features = false } diff --git a/contracts/ckb-std-tests/src/entry.rs b/contracts/ckb-std-tests/src/entry.rs index 9e950b8..7b3901f 100644 --- a/contracts/ckb-std-tests/src/entry.rs +++ b/contracts/ckb-std-tests/src/entry.rs @@ -11,13 +11,18 @@ use core::mem::size_of; #[cfg(target_arch = "riscv64")] use crate::code_hashes::CODE_HASH_SHARED_LIB; use crate::error::Error; +#[cfg(target_arch = "riscv64")] use bytes; -use ckb_std::atomic; +#[cfg(target_arch = "riscv64")] +use ckb_std::dummy_atomic; use ckb_std::since::{EpochNumberWithFraction, Since}; #[cfg(target_arch = "riscv64")] use ckb_std::{dynamic_loading, dynamic_loading_c_impl}; +#[cfg(target_arch = "riscv64")] use core::ffi::c_void; +#[cfg(target_arch = "riscv64")] use core::mem::size_of_val; +#[cfg(target_arch = "riscv64")] use log::{info, warn}; fn new_blake2b() -> Blake2b { @@ -404,6 +409,7 @@ fn test_since() { ); } +#[cfg(target_arch = "riscv64")] fn test_atomic() { // The bytes crate uses atomic operations. let b = bytes::Bytes::copy_from_slice(&[0, 1, 2, 3]); @@ -421,10 +427,11 @@ fn test_atomic() { warn!("atomic warn"); } +#[cfg(target_arch = "riscv64")] fn test_compare_exchange(data: &mut T, expected: &mut T, desired: u64, same: bool) { let size = size_of_val(data); let res = match size { - 1 => atomic::__atomic_compare_exchange_1( + 1 => dummy_atomic::__atomic_compare_exchange_1( data as *mut T as *mut c_void, expected as *mut T as *mut c_void, desired as u8, @@ -432,7 +439,7 @@ fn test_compare_exchange(data: &mut T, expected: &mut T, desired: u64, same: 0, 0, ), - 2 => atomic::__atomic_compare_exchange_2( + 2 => dummy_atomic::__atomic_compare_exchange_2( data as *mut T as *mut c_void, expected as *mut T as *mut c_void, desired as u16, @@ -440,7 +447,7 @@ fn test_compare_exchange(data: &mut T, expected: &mut T, desired: u64, same: 0, 0, ), - 4 => atomic::__atomic_compare_exchange_4( + 4 => dummy_atomic::__atomic_compare_exchange_4( data as *mut T as *mut c_void, expected as *mut T as *mut c_void, desired as u32, @@ -448,7 +455,7 @@ fn test_compare_exchange(data: &mut T, expected: &mut T, desired: u64, same: 0, 0, ), - 8 => atomic::__atomic_compare_exchange_8( + 8 => dummy_atomic::__atomic_compare_exchange_8( data as *mut T as *mut c_void, expected as *mut T as *mut c_void, desired as u64, @@ -463,18 +470,19 @@ fn test_compare_exchange(data: &mut T, expected: &mut T, desired: u64, same: assert_eq!(res, same); } +#[cfg(target_arch = "riscv64")] fn test_atomic2() { let mut data1: u8 = 42; - let old = atomic::__atomic_exchange_1(&mut data1 as *mut u8 as *mut c_void, 0, 0); + let old = dummy_atomic::__atomic_exchange_1(&mut data1 as *mut u8 as *mut c_void, 0, 0); assert_eq!(old, 42); let mut data2: u16 = 42; - let old = atomic::__atomic_exchange_2(&mut data2 as *mut u16 as *mut c_void, 0, 0); + let old = dummy_atomic::__atomic_exchange_2(&mut data2 as *mut u16 as *mut c_void, 0, 0); assert_eq!(old, 42); let mut data4: u32 = 42; - let old = atomic::__atomic_exchange_4(&mut data4 as *mut u32 as *mut c_void, 0, 0); + let old = dummy_atomic::__atomic_exchange_4(&mut data4 as *mut u32 as *mut c_void, 0, 0); assert_eq!(old, 42); let mut data8: u64 = 42; - let old = atomic::__atomic_exchange_8(&mut data8 as *mut u64 as *mut c_void, 0, 0); + let old = dummy_atomic::__atomic_exchange_8(&mut data8 as *mut u64 as *mut c_void, 0, 0); assert_eq!(old, 42); let mut data: u8 = 42; @@ -506,274 +514,274 @@ fn test_atomic2() { assert_eq!(expected, 0); let data: u8 = 42; - let expected = atomic::__atomic_load_1(&data as *const u8 as *const c_void, 0); + let expected = dummy_atomic::__atomic_load_1(&data as *const u8 as *const c_void, 0); assert_eq!(expected, data); let data: u16 = 42; - let expected = atomic::__atomic_load_2(&data as *const u16 as *const c_void, 0); + let expected = dummy_atomic::__atomic_load_2(&data as *const u16 as *const c_void, 0); assert_eq!(expected, data); let data: u32 = 42; - let expected = atomic::__atomic_load_4(&data as *const u32 as *const c_void, 0); + let expected = dummy_atomic::__atomic_load_4(&data as *const u32 as *const c_void, 0); assert_eq!(expected, data); let data: u64 = 42; - let expected = atomic::__atomic_load_8(&data as *const u64 as *const c_void, 0); + let expected = dummy_atomic::__atomic_load_8(&data as *const u64 as *const c_void, 0); assert_eq!(expected, data); let mut data: u8 = 42; - atomic::__atomic_store_1(&mut data as *mut u8 as *mut c_void, 0, 0); + dummy_atomic::__atomic_store_1(&mut data as *mut u8 as *mut c_void, 0, 0); assert_eq!(data, 0); let mut data: u16 = 42; - atomic::__atomic_store_2(&mut data as *mut u16 as *mut c_void, 0, 0); + dummy_atomic::__atomic_store_2(&mut data as *mut u16 as *mut c_void, 0, 0); assert_eq!(data, 0); let mut data: u32 = 42; - atomic::__atomic_store_4(&mut data as *mut u32 as *mut c_void, 0, 0); + dummy_atomic::__atomic_store_4(&mut data as *mut u32 as *mut c_void, 0, 0); assert_eq!(data, 0); let mut data: u64 = 42; - atomic::__atomic_store_8(&mut data as *mut u64 as *mut c_void, 0, 0); + dummy_atomic::__atomic_store_8(&mut data as *mut u64 as *mut c_void, 0, 0); assert_eq!(data, 0); let mut data: u8 = 42; - let res = atomic::__atomic_fetch_add_1(&mut data as *mut u8 as *mut c_void, 1, 0); + let res = dummy_atomic::__atomic_fetch_add_1(&mut data as *mut u8 as *mut c_void, 1, 0); assert_eq!(res, 42); assert_eq!(data, 43); let mut data: u16 = 42; - let res = atomic::__atomic_fetch_add_2(&mut data as *mut u16 as *mut c_void, 1, 0); + let res = dummy_atomic::__atomic_fetch_add_2(&mut data as *mut u16 as *mut c_void, 1, 0); assert_eq!(res, 42); assert_eq!(data, 43); let mut data: u32 = 42; - let res = atomic::__atomic_fetch_add_4(&mut data as *mut u32 as *mut c_void, 1, 0); + let res = dummy_atomic::__atomic_fetch_add_4(&mut data as *mut u32 as *mut c_void, 1, 0); assert_eq!(res, 42); assert_eq!(data, 43); let mut data: u64 = 42; - let res = atomic::__atomic_fetch_add_8(&mut data as *mut u64 as *mut c_void, 1, 0); + let res = dummy_atomic::__atomic_fetch_add_8(&mut data as *mut u64 as *mut c_void, 1, 0); assert_eq!(res, 42); assert_eq!(data, 43); let mut data: u8 = 42; - let res = atomic::__atomic_fetch_sub_1(&mut data as *mut u8 as *mut c_void, 1, 0); + let res = dummy_atomic::__atomic_fetch_sub_1(&mut data as *mut u8 as *mut c_void, 1, 0); assert_eq!(res, 42); assert_eq!(data, 41); let mut data: u16 = 42; - let res = atomic::__atomic_fetch_sub_2(&mut data as *mut u16 as *mut c_void, 1, 0); + let res = dummy_atomic::__atomic_fetch_sub_2(&mut data as *mut u16 as *mut c_void, 1, 0); assert_eq!(res, 42); assert_eq!(data, 41); let mut data: u32 = 42; - let res = atomic::__atomic_fetch_sub_4(&mut data as *mut u32 as *mut c_void, 1, 0); + let res = dummy_atomic::__atomic_fetch_sub_4(&mut data as *mut u32 as *mut c_void, 1, 0); assert_eq!(res, 42); assert_eq!(data, 41); let mut data: u64 = 42; - let res = atomic::__atomic_fetch_sub_8(&mut data as *mut u64 as *mut c_void, 1, 0); + let res = dummy_atomic::__atomic_fetch_sub_8(&mut data as *mut u64 as *mut c_void, 1, 0); assert_eq!(res, 42); assert_eq!(data, 41); let mut data: u8 = 43; - let res = atomic::__atomic_fetch_and_1(&mut data as *mut u8 as *mut c_void, 1, 0); + let res = dummy_atomic::__atomic_fetch_and_1(&mut data as *mut u8 as *mut c_void, 1, 0); assert_eq!(res, 43); assert_eq!(data, 1); let mut data: u16 = 43; - let res = atomic::__atomic_fetch_and_2(&mut data as *mut u16 as *mut c_void, 1, 0); + let res = dummy_atomic::__atomic_fetch_and_2(&mut data as *mut u16 as *mut c_void, 1, 0); assert_eq!(res, 43); assert_eq!(data, 1); let mut data: u32 = 43; - let res = atomic::__atomic_fetch_and_4(&mut data as *mut u32 as *mut c_void, 1, 0); + let res = dummy_atomic::__atomic_fetch_and_4(&mut data as *mut u32 as *mut c_void, 1, 0); assert_eq!(res, 43); assert_eq!(data, 1); let mut data: u64 = 43; - let res = atomic::__atomic_fetch_and_8(&mut data as *mut u64 as *mut c_void, 1, 0); + let res = dummy_atomic::__atomic_fetch_and_8(&mut data as *mut u64 as *mut c_void, 1, 0); assert_eq!(res, 43); assert_eq!(data, 1); let mut data: u8 = 43; - let res = atomic::__atomic_fetch_xor_1(&mut data as *mut u8 as *mut c_void, 1, 0); + let res = dummy_atomic::__atomic_fetch_xor_1(&mut data as *mut u8 as *mut c_void, 1, 0); assert_eq!(res, 43); assert_eq!(data, 42); let mut data: u16 = 43; - let res = atomic::__atomic_fetch_xor_2(&mut data as *mut u16 as *mut c_void, 1, 0); + let res = dummy_atomic::__atomic_fetch_xor_2(&mut data as *mut u16 as *mut c_void, 1, 0); assert_eq!(res, 43); assert_eq!(data, 42); let mut data: u32 = 43; - let res = atomic::__atomic_fetch_xor_4(&mut data as *mut u32 as *mut c_void, 1, 0); + let res = dummy_atomic::__atomic_fetch_xor_4(&mut data as *mut u32 as *mut c_void, 1, 0); assert_eq!(res, 43); assert_eq!(data, 42); let mut data: u64 = 43; - let res = atomic::__atomic_fetch_xor_8(&mut data as *mut u64 as *mut c_void, 1, 0); + let res = dummy_atomic::__atomic_fetch_xor_8(&mut data as *mut u64 as *mut c_void, 1, 0); assert_eq!(res, 43); assert_eq!(data, 42); let mut data: u8 = 42; - let res = atomic::__atomic_fetch_or_1(&mut data as *mut u8 as *mut c_void, 1, 0); + let res = dummy_atomic::__atomic_fetch_or_1(&mut data as *mut u8 as *mut c_void, 1, 0); assert_eq!(res, 42); assert_eq!(data, 43); let mut data: u16 = 42; - let res = atomic::__atomic_fetch_or_2(&mut data as *mut u16 as *mut c_void, 1, 0); + let res = dummy_atomic::__atomic_fetch_or_2(&mut data as *mut u16 as *mut c_void, 1, 0); assert_eq!(res, 42); assert_eq!(data, 43); let mut data: u32 = 42; - let res = atomic::__atomic_fetch_or_4(&mut data as *mut u32 as *mut c_void, 1, 0); + let res = dummy_atomic::__atomic_fetch_or_4(&mut data as *mut u32 as *mut c_void, 1, 0); assert_eq!(res, 42); assert_eq!(data, 43); let mut data: u64 = 42; - let res = atomic::__atomic_fetch_or_8(&mut data as *mut u64 as *mut c_void, 1, 0); + let res = dummy_atomic::__atomic_fetch_or_8(&mut data as *mut u64 as *mut c_void, 1, 0); assert_eq!(res, 42); assert_eq!(data, 43); let mut data: u8 = 1; - let res = atomic::__atomic_fetch_nand_1(&mut data as *mut u8 as *mut c_void, 1, 0); + let res = dummy_atomic::__atomic_fetch_nand_1(&mut data as *mut u8 as *mut c_void, 1, 0); assert_eq!(res, 1); assert_eq!(data, 0xFE); let mut data: u16 = 1; - let res = atomic::__atomic_fetch_nand_2(&mut data as *mut u16 as *mut c_void, 1, 0); + let res = dummy_atomic::__atomic_fetch_nand_2(&mut data as *mut u16 as *mut c_void, 1, 0); assert_eq!(res, 1); assert_eq!(data, 0xFFFE); let mut data: u32 = 1; - let res = atomic::__atomic_fetch_nand_4(&mut data as *mut u32 as *mut c_void, 1, 0); + let res = dummy_atomic::__atomic_fetch_nand_4(&mut data as *mut u32 as *mut c_void, 1, 0); assert_eq!(res, 1); assert_eq!(data, 0xFFFFFFFE); let mut data: u64 = 1; - let res = atomic::__atomic_fetch_nand_8(&mut data as *mut u64 as *mut c_void, 1, 0); + let res = dummy_atomic::__atomic_fetch_nand_8(&mut data as *mut u64 as *mut c_void, 1, 0); assert_eq!(res, 1); assert_eq!(data, 0xFFFFFFFFFFFFFFFE); let mut data: u8 = 42; - let res = atomic::__atomic_add_fetch_1(&mut data as *mut u8 as *mut c_void, 1, 0); + let res = dummy_atomic::__atomic_add_fetch_1(&mut data as *mut u8 as *mut c_void, 1, 0); assert_eq!(res, 43); assert_eq!(data, 43); let mut data: u16 = 42; - let res = atomic::__atomic_add_fetch_2(&mut data as *mut u16 as *mut c_void, 1, 0); + let res = dummy_atomic::__atomic_add_fetch_2(&mut data as *mut u16 as *mut c_void, 1, 0); assert_eq!(res, 43); assert_eq!(data, 43); let mut data: u32 = 42; - let res = atomic::__atomic_add_fetch_4(&mut data as *mut u32 as *mut c_void, 1, 0); + let res = dummy_atomic::__atomic_add_fetch_4(&mut data as *mut u32 as *mut c_void, 1, 0); assert_eq!(res, 43); assert_eq!(data, 43); let mut data: u64 = 42; - let res = atomic::__atomic_add_fetch_8(&mut data as *mut u64 as *mut c_void, 1, 0); + let res = dummy_atomic::__atomic_add_fetch_8(&mut data as *mut u64 as *mut c_void, 1, 0); assert_eq!(res, 43); assert_eq!(data, 43); let mut data: u8 = 42; - let res = atomic::__atomic_sub_fetch_1(&mut data as *mut u8 as *mut c_void, 1, 0); + let res = dummy_atomic::__atomic_sub_fetch_1(&mut data as *mut u8 as *mut c_void, 1, 0); assert_eq!(res, 41); assert_eq!(data, 41); let mut data: u16 = 42; - let res = atomic::__atomic_sub_fetch_2(&mut data as *mut u16 as *mut c_void, 1, 0); + let res = dummy_atomic::__atomic_sub_fetch_2(&mut data as *mut u16 as *mut c_void, 1, 0); assert_eq!(res, 41); assert_eq!(data, 41); let mut data: u32 = 42; - let res = atomic::__atomic_sub_fetch_4(&mut data as *mut u32 as *mut c_void, 1, 0); + let res = dummy_atomic::__atomic_sub_fetch_4(&mut data as *mut u32 as *mut c_void, 1, 0); assert_eq!(res, 41); assert_eq!(data, 41); let mut data: u64 = 42; - let res = atomic::__atomic_sub_fetch_8(&mut data as *mut u64 as *mut c_void, 1, 0); + let res = dummy_atomic::__atomic_sub_fetch_8(&mut data as *mut u64 as *mut c_void, 1, 0); assert_eq!(res, 41); assert_eq!(data, 41); let mut data: u8 = 43; - let res = atomic::__atomic_and_fetch_1(&mut data as *mut u8 as *mut c_void, 1, 0); + let res = dummy_atomic::__atomic_and_fetch_1(&mut data as *mut u8 as *mut c_void, 1, 0); assert_eq!(res, 1); assert_eq!(data, 1); let mut data: u16 = 43; - let res = atomic::__atomic_and_fetch_2(&mut data as *mut u16 as *mut c_void, 1, 0); + let res = dummy_atomic::__atomic_and_fetch_2(&mut data as *mut u16 as *mut c_void, 1, 0); assert_eq!(res, 1); assert_eq!(data, 1); let mut data: u32 = 43; - let res = atomic::__atomic_and_fetch_4(&mut data as *mut u32 as *mut c_void, 1, 0); + let res = dummy_atomic::__atomic_and_fetch_4(&mut data as *mut u32 as *mut c_void, 1, 0); assert_eq!(res, 1); assert_eq!(data, 1); let mut data: u64 = 43; - let res = atomic::__atomic_and_fetch_8(&mut data as *mut u64 as *mut c_void, 1, 0); + let res = dummy_atomic::__atomic_and_fetch_8(&mut data as *mut u64 as *mut c_void, 1, 0); assert_eq!(res, 1); assert_eq!(data, 1); let mut data: u8 = 43; - let res = atomic::__atomic_xor_fetch_1(&mut data as *mut u8 as *mut c_void, 1, 0); + let res = dummy_atomic::__atomic_xor_fetch_1(&mut data as *mut u8 as *mut c_void, 1, 0); assert_eq!(res, 42); assert_eq!(data, 42); let mut data: u16 = 43; - let res = atomic::__atomic_xor_fetch_2(&mut data as *mut u16 as *mut c_void, 1, 0); + let res = dummy_atomic::__atomic_xor_fetch_2(&mut data as *mut u16 as *mut c_void, 1, 0); assert_eq!(res, 42); assert_eq!(data, 42); let mut data: u32 = 43; - let res = atomic::__atomic_xor_fetch_4(&mut data as *mut u32 as *mut c_void, 1, 0); + let res = dummy_atomic::__atomic_xor_fetch_4(&mut data as *mut u32 as *mut c_void, 1, 0); assert_eq!(res, 42); assert_eq!(data, 42); let mut data: u64 = 43; - let res = atomic::__atomic_xor_fetch_8(&mut data as *mut u64 as *mut c_void, 1, 0); + let res = dummy_atomic::__atomic_xor_fetch_8(&mut data as *mut u64 as *mut c_void, 1, 0); assert_eq!(res, 42); assert_eq!(data, 42); let mut data: u8 = 42; - let res = atomic::__atomic_or_fetch_1(&mut data as *mut u8 as *mut c_void, 1, 0); + let res = dummy_atomic::__atomic_or_fetch_1(&mut data as *mut u8 as *mut c_void, 1, 0); assert_eq!(res, 43); assert_eq!(data, 43); let mut data: u16 = 42; - let res = atomic::__atomic_or_fetch_2(&mut data as *mut u16 as *mut c_void, 1, 0); + let res = dummy_atomic::__atomic_or_fetch_2(&mut data as *mut u16 as *mut c_void, 1, 0); assert_eq!(res, 43); assert_eq!(data, 43); let mut data: u32 = 42; - let res = atomic::__atomic_or_fetch_4(&mut data as *mut u32 as *mut c_void, 1, 0); + let res = dummy_atomic::__atomic_or_fetch_4(&mut data as *mut u32 as *mut c_void, 1, 0); assert_eq!(res, 43); assert_eq!(data, 43); let mut data: u64 = 42; - let res = atomic::__atomic_or_fetch_8(&mut data as *mut u64 as *mut c_void, 1, 0); + let res = dummy_atomic::__atomic_or_fetch_8(&mut data as *mut u64 as *mut c_void, 1, 0); assert_eq!(res, 43); assert_eq!(data, 43); let mut data: u8 = 1; - let res = atomic::__atomic_nand_fetch_1(&mut data as *mut u8 as *mut c_void, 1, 0); + let res = dummy_atomic::__atomic_nand_fetch_1(&mut data as *mut u8 as *mut c_void, 1, 0); assert_eq!(res, 0xFE); assert_eq!(data, 0xFE); let mut data: u16 = 1; - let res = atomic::__atomic_nand_fetch_2(&mut data as *mut u16 as *mut c_void, 1, 0); + let res = dummy_atomic::__atomic_nand_fetch_2(&mut data as *mut u16 as *mut c_void, 1, 0); assert_eq!(res, 0xFFFE); assert_eq!(data, 0xFFFE); let mut data: u32 = 1; - let res = atomic::__atomic_nand_fetch_4(&mut data as *mut u32 as *mut c_void, 1, 0); + let res = dummy_atomic::__atomic_nand_fetch_4(&mut data as *mut u32 as *mut c_void, 1, 0); assert_eq!(res, 0xFFFFFFFE); assert_eq!(data, 0xFFFFFFFE); let mut data: u64 = 1; - let res = atomic::__atomic_nand_fetch_8(&mut data as *mut u64 as *mut c_void, 1, 0); + let res = dummy_atomic::__atomic_nand_fetch_8(&mut data as *mut u64 as *mut c_void, 1, 0); assert_eq!(res, 0xFFFFFFFFFFFFFFFE); assert_eq!(data, 0xFFFFFFFFFFFFFFFE); } @@ -800,7 +808,10 @@ pub fn main() -> Result<(), Error> { test_vm_version(); test_current_cycles(); test_since(); - test_atomic(); - test_atomic2(); + #[cfg(target_arch = "riscv64")] + { + test_atomic(); + test_atomic2(); + } Ok(()) } diff --git a/src/atomic.rs b/src/dummy_atomic.rs similarity index 90% rename from src/atomic.rs rename to src/dummy_atomic.rs index a3a5fe1..2be4429 100644 --- a/src/atomic.rs +++ b/src/dummy_atomic.rs @@ -33,12 +33,12 @@ fn atomic_compare_exchange( unsafe { let dst = ptr as *mut T; let old = expected as *mut T; - let dst_val: T = dst.read_unaligned(); - if dst_val == old.read_unaligned() { - dst.write_unaligned(desired); + let dst_val: T = dst.read(); + if dst_val == old.read() { + dst.write(desired); true } else { - old.write_unaligned(dst_val); + old.write(dst_val); false } } @@ -47,8 +47,8 @@ fn atomic_compare_exchange( fn atomic_fetch_add + Copy>(ptr: *mut c_void, val: T) -> T { unsafe { let dst = ptr as *mut T; - let old: T = dst.read_unaligned(); - dst.write_unaligned(old + val); + let old: T = dst.read(); + dst.write(old + val); old } } @@ -56,8 +56,8 @@ fn atomic_fetch_add + Copy>(ptr: *mut c_void, val: T) -> T { fn atomic_fetch_sub + Copy>(ptr: *mut c_void, val: T) -> T { unsafe { let dst = ptr as *mut T; - let old: T = dst.read_unaligned(); - dst.write_unaligned(old - val); + let old: T = dst.read(); + dst.write(old - val); old } } @@ -65,8 +65,8 @@ fn atomic_fetch_sub + Copy>(ptr: *mut c_void, val: T) -> T { fn atomic_fetch_xor + Copy>(ptr: *mut c_void, val: T) -> T { unsafe { let dst = ptr as *mut T; - let old: T = dst.read_unaligned(); - dst.write_unaligned(old ^ val); + let old: T = dst.read(); + dst.write(old ^ val); old } } @@ -74,8 +74,8 @@ fn atomic_fetch_xor + Copy>(ptr: *mut c_void, val: T) -> T fn atomic_fetch_and + Copy>(ptr: *mut c_void, val: T) -> T { unsafe { let dst = ptr as *mut T; - let old: T = dst.read_unaligned(); - dst.write_unaligned(old & val); + let old: T = dst.read(); + dst.write(old & val); old } } @@ -83,8 +83,8 @@ fn atomic_fetch_and + Copy>(ptr: *mut c_void, val: T) -> T fn atomic_fetch_or + Copy>(ptr: *mut c_void, val: T) -> T { unsafe { let dst = ptr as *mut T; - let old: T = dst.read_unaligned(); - dst.write_unaligned(old | val); + let old: T = dst.read(); + dst.write(old | val); old } } @@ -95,8 +95,8 @@ fn atomic_fetch_nand + Not + Copy>( ) -> T { unsafe { let dst = ptr as *mut T; - let old: T = dst.read_unaligned(); - dst.write_unaligned(!(old & val)); + let old: T = dst.read(); + dst.write(!(old & val)); old } } @@ -104,9 +104,9 @@ fn atomic_fetch_nand + Not + Copy>( fn atomic_add_fetch + Copy>(ptr: *mut c_void, val: T) -> T { unsafe { let dst = ptr as *mut T; - let old: T = dst.read_unaligned(); + let old: T = dst.read(); let val2 = old + val; - dst.write_unaligned(val2); + dst.write(val2); val2 } } @@ -114,9 +114,9 @@ fn atomic_add_fetch + Copy>(ptr: *mut c_void, val: T) -> T { fn atomic_sub_fetch + Copy>(ptr: *mut c_void, val: T) -> T { unsafe { let dst = ptr as *mut T; - let old: T = dst.read_unaligned(); + let old: T = dst.read(); let val2 = old - val; - dst.write_unaligned(val2); + dst.write(val2); val2 } } @@ -124,9 +124,9 @@ fn atomic_sub_fetch + Copy>(ptr: *mut c_void, val: T) -> T { fn atomic_xor_fetch + Copy>(ptr: *mut c_void, val: T) -> T { unsafe { let dst = ptr as *mut T; - let old: T = dst.read_unaligned(); + let old: T = dst.read(); let val2 = old ^ val; - dst.write_unaligned(val2); + dst.write(val2); val2 } } @@ -134,9 +134,9 @@ fn atomic_xor_fetch + Copy>(ptr: *mut c_void, val: T) -> T fn atomic_and_fetch + Copy>(ptr: *mut c_void, val: T) -> T { unsafe { let dst = ptr as *mut T; - let old: T = dst.read_unaligned(); + let old: T = dst.read(); let val2 = old & val; - dst.write_unaligned(val2); + dst.write(val2); val2 } } @@ -144,9 +144,9 @@ fn atomic_and_fetch + Copy>(ptr: *mut c_void, val: T) -> T fn atomic_or_fetch + Copy>(ptr: *mut c_void, val: T) -> T { unsafe { let dst = ptr as *mut T; - let old: T = dst.read_unaligned(); + let old: T = dst.read(); let val2 = old | val; - dst.write_unaligned(val2); + dst.write(val2); val2 } } @@ -157,9 +157,9 @@ fn atomic_nand_fetch + Not + Copy>( ) -> T { unsafe { let dst = ptr as *mut T; - let old: T = dst.read_unaligned(); + let old: T = dst.read(); let val2 = !(old & val); - dst.write_unaligned(val2); + dst.write(val2); val2 } } @@ -236,7 +236,7 @@ pub extern "C" fn __atomic_compare_exchange_8( pub extern "C" fn __atomic_load_1(ptr: *const c_void, _memorder: isize) -> u8 { unsafe { let p = ptr as *mut u8; - p.read_unaligned() + p.read() } } @@ -244,7 +244,7 @@ pub extern "C" fn __atomic_load_1(ptr: *const c_void, _memorder: isize) -> u8 { pub extern "C" fn __atomic_load_2(ptr: *const c_void, _memorder: isize) -> u16 { unsafe { let p = ptr as *mut u16; - p.read_unaligned() + p.read() } } @@ -252,7 +252,7 @@ pub extern "C" fn __atomic_load_2(ptr: *const c_void, _memorder: isize) -> u16 { pub extern "C" fn __atomic_load_4(ptr: *const c_void, _memorder: isize) -> u32 { unsafe { let p = ptr as *mut u32; - p.read_unaligned() + p.read() } } @@ -260,7 +260,7 @@ pub extern "C" fn __atomic_load_4(ptr: *const c_void, _memorder: isize) -> u32 { pub extern "C" fn __atomic_load_8(ptr: *const c_void, _memorder: isize) -> u64 { unsafe { let p = ptr as *mut u64; - p.read_unaligned() + p.read() } } @@ -268,7 +268,7 @@ pub extern "C" fn __atomic_load_8(ptr: *const c_void, _memorder: isize) -> u64 { pub extern "C" fn __atomic_store_1(ptr: *mut c_void, val: u8, _memorder: isize) { unsafe { let p = ptr as *mut u8; - p.write_unaligned(val); + p.write(val); } } @@ -276,7 +276,7 @@ pub extern "C" fn __atomic_store_1(ptr: *mut c_void, val: u8, _memorder: isize) pub extern "C" fn __atomic_store_2(ptr: *mut c_void, val: u16, _memorder: isize) { unsafe { let p = ptr as *mut u16; - p.write_unaligned(val); + p.write(val); } } @@ -284,7 +284,7 @@ pub extern "C" fn __atomic_store_2(ptr: *mut c_void, val: u16, _memorder: isize) pub extern "C" fn __atomic_store_4(ptr: *mut c_void, val: u32, _memorder: isize) { unsafe { let p = ptr as *mut u32; - p.write_unaligned(val); + p.write(val); } } @@ -292,7 +292,7 @@ pub extern "C" fn __atomic_store_4(ptr: *mut c_void, val: u32, _memorder: isize) pub extern "C" fn __atomic_store_8(ptr: *mut c_void, val: u64, _memorder: isize) { unsafe { let p = ptr as *mut u64; - p.write_unaligned(val); + p.write(val); } } diff --git a/src/lib.rs b/src/lib.rs index a4727d9..f3ec82b 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -36,5 +36,5 @@ pub mod dynamic_loading; pub mod dynamic_loading_c_impl; #[cfg(feature = "allocator")] pub use buddy_alloc; -#[cfg(feature = "atomic")] -pub mod atomic; +#[cfg(feature = "dummy-atomic")] +pub mod dummy_atomic; diff --git a/test/simulator/Cargo.toml b/test/simulator/Cargo.toml index f040cac..5a768ab 100644 --- a/test/simulator/Cargo.toml +++ b/test/simulator/Cargo.toml @@ -16,7 +16,7 @@ name = "exec-callee" path = "src/exec_callee.rs" [dependencies] -ckb-std = { path = "../..", features = ["ckb-types", "simulator", "atomic"] } +ckb-std = { path = "../..", features = ["ckb-types", "simulator"] } blake2b-ref = { version = "0.3", default-features = false } bytes = { version = "1.6.0", default-features = false } log = { version = "0.4.17", default-features = false } From c4557bf32c9bd55eea4273bccd451c95c706618a Mon Sep 17 00:00:00 2001 From: xjd Date: Fri, 7 Jun 2024 09:26:31 +0800 Subject: [PATCH 4/4] Update README --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 9e9897e..0161fbe 100644 --- a/README.md +++ b/README.md @@ -15,7 +15,7 @@ This library contains several modules that help you write CKB contract with Rust * `debug!` macro: a `println!` like macro helps debugging * `entry!` macro: defines contract entry point * `default_alloc!` macro: defines global allocator for no-std rust -* `atomic` module: atomic operations +* `dummy_atomic` module: dummy atomic operations ### Memory allocator Default allocator uses a mixed allocation strategy: