Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support new spawn #13

Merged
merged 36 commits into from
Oct 25, 2024
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
Show all changes
36 commits
Select commit Hold shift + click to select a range
a857ffa
Support spawn
joii2020 Sep 14, 2024
cbf704d
Remove unused deps
joii2020 Sep 26, 2024
24e5295
Fix warning: cargo clippy
joii2020 Sep 29, 2024
6162144
Add Pin for Global data
joii2020 Sep 29, 2024
a5687b6
Fix with value naming
joii2020 Sep 30, 2024
ad3cd0f
Add testcase
joii2020 Sep 30, 2024
72a4f71
Add CI : testcase
joii2020 Sep 30, 2024
a68a701
Refactore: process rename to vm
joii2020 Sep 30, 2024
975fbbe
Refactore: Remove struct Spawn
joii2020 Sep 30, 2024
84e07fe
Check fd when spawn
joii2020 Sep 30, 2024
848ac9b
Fix bug: spawn multiple reads
joii2020 Sep 30, 2024
af004df
Add ckb-std-wrapper on tests
joii2020 Sep 30, 2024
fcb59f9
Clean global data when before ckb_main
joii2020 Sep 30, 2024
9c00d32
Update deps git:rev
joii2020 Sep 30, 2024
3fa8a38
SpawnCmd using num_derive
joii2020 Oct 8, 2024
00001a4
Add testcase: Check invaild fd when spawn
joii2020 Oct 8, 2024
27db927
Refactory spawn parent and child
joii2020 Oct 8, 2024
7422483
Add testcase: spawn return max vms
joii2020 Oct 8, 2024
f6236ec
Add testcase : spawn wait exit
joii2020 Oct 8, 2024
79b8dd9
Add testcase
joii2020 Oct 10, 2024
513f90e
Add test: r/w failed
joii2020 Oct 10, 2024
5e070fd
Add spawn_cases (from ckb), doing
joii2020 Oct 14, 2024
6946164
vm_info.rs renamt to simulator_context
joii2020 Oct 15, 2024
bf51d2c
VmID and TxID move to simulator_context
joii2020 Oct 15, 2024
a8f1419
TxID rename to SimID
joii2020 Oct 15, 2024
1129816
Refactory
joii2020 Oct 15, 2024
437c5b8
Rewrite the spawn scheduling related code
joii2020 Oct 16, 2024
63ef979
Add testcase
joii2020 Oct 16, 2024
f3255bf
Add test and fix bug (about spawn close)
joii2020 Oct 17, 2024
b623f11
Fix cargo clippy warngin
joii2020 Oct 17, 2024
a977a96
Add testcase check_pid
joii2020 Oct 17, 2024
6fa43e1
Remove debugging code and unused comments
joii2020 Oct 18, 2024
f41ea4a
Adjust spawn io return order
joii2020 Oct 18, 2024
4e77e89
LLVM update to 18
joii2020 Oct 21, 2024
6b206dd
Use define to replace magic numbers that return error
joii2020 Oct 21, 2024
2bcd67c
Improve assert_vm_version logic
joii2020 Oct 22, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .github/workflows/rust.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -16,3 +16,5 @@ jobs:
- uses: actions/checkout@v3
- name: Run Cargo Test
run: cargo test
- name: Run Cargo clippy
run: cargo clippy --all
136 changes: 136 additions & 0 deletions src/global_data.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,136 @@
use crate::process_info::TxContext;
use std::{
collections::HashMap,
ffi::c_void,
pin::Pin,
sync::{Mutex, MutexGuard},
};

lazy_static! {
static ref GLOBAL_DATA: Pin<Box<Mutex<GlobalData>>> = Pin::new(Box::default());
}
static mut GLOBAL_DATA_PTR: *mut Mutex<GlobalData> = std::ptr::null_mut();

#[derive(Default, PartialEq, Eq, Clone, Hash, Debug)]
pub struct TxID(u64);
impl From<u64> for TxID {
fn from(value: u64) -> Self {
Self(value)
}
}
impl From<TxID> for u64 {
fn from(value: TxID) -> Self {
value.0
}
}
impl TxID {
fn next(&mut self) -> Self {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do you modify the original data here, but clone a copy of the data as the return value at the same time?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In many places, the next step is HashMap::insert. This way, the return is more convenient to use.

self.0 += 1;
self.clone()
}
}

#[derive(Default, PartialEq, Eq, Clone, Hash, Debug)]
pub struct ProcID(u64);
impl From<u64> for ProcID {
fn from(value: u64) -> Self {
Self(value)
}
}
impl From<ProcID> for u64 {
fn from(value: ProcID) -> Self {
value.0
}
}
impl ProcID {
pub fn next(&mut self) -> Self {
let id = self.clone();
self.0 += 1;
id
}
}

pub struct GlobalData {
tx_ctx: HashMap<TxID, TxContext>,
tx_ctx_id_count: TxID,
}
impl Default for GlobalData {
fn default() -> Self {
TxContext::set_ctx_id(0.into());
Self {
tx_ctx: [(0.into(), TxContext::default())].into(),
tx_ctx_id_count: 1.into(),
}
}
}

impl GlobalData {
pub fn get() -> &'static Mutex<Self> {
if unsafe { GLOBAL_DATA_PTR.is_null() } {
&GLOBAL_DATA
} else {
unsafe { &mut *GLOBAL_DATA_PTR as &mut Mutex<Self> }
}
}
pub fn locked() -> MutexGuard<'static, Self> {
Self::get().lock().unwrap()
}
pub fn get_ptr() -> *const c_void {
if unsafe { GLOBAL_DATA_PTR.is_null() } {
let infos_ref: &Mutex<Self> = &GLOBAL_DATA;
infos_ref as *const Mutex<Self> as *const c_void
} else {
unsafe { GLOBAL_DATA_PTR as *const c_void }
}
}
pub fn set_ptr(ptr: *const c_void) {
unsafe {
GLOBAL_DATA_PTR = ptr as *mut Mutex<GlobalData>;
}
}

pub fn set_tx(&mut self, ctx: TxContext) -> TxID {
self.tx_ctx.insert(self.tx_ctx_id_count.next(), ctx);
self.tx_ctx_id_count.clone()
}
pub fn get_tx(&self, id: &TxID) -> &TxContext {
self.tx_ctx
.get(id)
.unwrap_or_else(|| panic!("unknow tx context: {:?}", id))
}
pub fn get_tx_mut(&mut self, id: &TxID) -> &mut TxContext {
self.tx_ctx
.get_mut(id)
.unwrap_or_else(|| panic!("unknow mut tx context: {:?}", id))
}
}

#[macro_export]
macro_rules! get_tx {
($txid:expr) => {
GlobalData::locked().get_tx(&$txid)
};
}

#[macro_export]
macro_rules! get_tx_mut {
($txid:expr) => {
GlobalData::locked().get_tx_mut(&$txid)
};
}

#[macro_export]
macro_rules! get_proc {
($txid: expr, $procid: expr) => {
GlobalData::locked().get_tx(&$txid).process(&$procid)
};
}

#[macro_export]
macro_rules! get_cur_proc {
() => {
GlobalData::locked()
.get_tx(&TxContext::ctx_id())
.process(&Process::ctx_id())
};
}
121 changes: 77 additions & 44 deletions src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,15 @@
pub mod constants;

pub mod spawn;
pub use spawn::*;

mod global_data;
mod process_info;
mod utils;

use global_data::GlobalData;
use process_info::{Process, TxContext};

#[macro_use]
extern crate lazy_static;

Expand All @@ -20,7 +30,7 @@ use constants::{
};
use serde_derive::{Deserialize, Serialize};
use std::collections::HashMap;
use std::ffi::{CStr, CString};
use std::ffi::CString;
use std::os::raw::{c_char, c_int, c_void};

#[derive(Clone, Serialize, Deserialize)]
Expand Down Expand Up @@ -56,7 +66,7 @@ lazy_static! {
}

fn assert_vm_version() {
if SETUP.vm_version != 1 {
if SETUP.vm_version != 1 && SETUP.vm_version != 2 {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There may be version 3 in the future, use if SETUP.vm_version == 0 instead

panic!(
"Currently running setup vm_version({}) not support this syscall",
SETUP.vm_version
Expand Down Expand Up @@ -94,45 +104,40 @@ pub extern "C" fn ckb_exec_cell(
) -> c_int {
assert_vm_version();

let mut filename = None;
for ht in [hash_type, 0xFF] {
let code_hash = unsafe { std::slice::from_raw_parts(code_hash, 32) };
let mut buffer = vec![];
buffer.extend_from_slice(code_hash);
buffer.push(ht);
buffer.extend_from_slice(&offset.to_be_bytes()[..]);
buffer.extend_from_slice(&length.to_be_bytes()[..]);
let key = format!("0x{}", faster_hex::hex_string(&buffer));
filename = SETUP.native_binaries.get(&key);
if filename.is_some() {
break;
}
}
let filename = filename.expect("cannot locate native binary for ckb_exec syscall!");
let sim_path =
utils::get_simulator_path(utils::to_array(code_hash, 32), hash_type, offset, length);
let sim_path = sim_path.expect("cannot locate native binary for ckb_exec syscall!");

match SETUP.run_type.as_ref().unwrap_or(&RunningType::Executable) {
RunningType::Executable => {
let filename_cstring = CString::new(filename.as_bytes().to_vec()).unwrap();
let filename_cstring = CString::new(sim_path.as_bytes().to_vec()).unwrap();
unsafe {
let args = argv as *const *const i8;
libc::execvp(filename_cstring.as_ptr(), args)
}
}
RunningType::DynamicLib => {
use core::ffi::c_int;
type CkbMainFunc<'a> = libloading::Symbol<
'a,
unsafe extern "C" fn(argc: c_int, argv: *const *const i8) -> i8,
>;
use utils::CkbNativeSimulator;

unsafe {
let lib = libloading::Library::new(filename).expect("Load library");
let func: CkbMainFunc = lib
.get(b"__ckb_std_main")
.expect("load function : __ckb_std_main");
let args = argv as *const *const i8;
std::process::exit(func(argc, args).into())
}
let tx_ctx_id = GlobalData::locked().set_tx(process_info::TxContext::default());
TxContext::set_ctx_id(tx_ctx_id.clone());

let sim = CkbNativeSimulator::new_by_hash(code_hash, hash_type, offset, length);
let args = utils::to_vec_args(argc, argv as *const *const i8);

let t = std::thread::spawn(move || {
let proc_id = get_tx_mut!(&tx_ctx_id).new_process(None, &[]);

Process::set_ctx_id(proc_id.clone());
TxContext::set_ctx_id(tx_ctx_id.clone());

sim.update_script_info(tx_ctx_id.clone(), proc_id.clone());

sim.ckb_std_main(args)
// get_cur_proc!().notify();
});

t.join().expect("exec dylib") as c_int
}
}
}
Expand Down Expand Up @@ -165,7 +170,7 @@ pub extern "C" fn ckb_load_script(ptr: *mut c_void, len: *mut u64, offset: u64)

#[no_mangle]
pub extern "C" fn ckb_debug(s: *const c_char) {
let message = unsafe { CStr::from_ptr(s) }.to_str().expect("UTF8 error!");
let message = utils::to_c_str(s).to_str().expect("UTF8 error!");
println!("Debug message: {}", message);
}

Expand Down Expand Up @@ -378,6 +383,29 @@ extern "C" {
) -> c_int;
}

// TO fix clippy error: clippy::not_unsafe_ptr_arg_deref
fn rs_simulator_internal_dlopen2(
native_library_path: *const u8,
code: *const u8,
length: u64,
aligned_addr: *mut u8,
aligned_size: u64,
handle: *mut *mut c_void,
consumed_size: *mut u64,
) -> c_int {
unsafe {
simulator_internal_dlopen2(
native_library_path,
code,
length,
aligned_addr,
aligned_size,
handle,
consumed_size,
)
}
}

#[no_mangle]
pub extern "C" fn ckb_dlopen2(
dep_cell_hash: *const u8,
Expand All @@ -387,7 +415,7 @@ pub extern "C" fn ckb_dlopen2(
handle: *mut *mut c_void,
consumed_size: *mut u64,
) -> c_int {
let dep_cell_hash = unsafe { std::slice::from_raw_parts(dep_cell_hash, 32) };
let dep_cell_hash = utils::to_array(dep_cell_hash, 32);
let mut buffer = vec![];
buffer.extend_from_slice(dep_cell_hash);
buffer.push(hash_type);
Expand All @@ -414,17 +442,22 @@ pub extern "C" fn ckb_dlopen2(
})
.expect("cannot locate cell dep");
let cell_data = cell_dep.data.as_ref();
unsafe {
simulator_internal_dlopen2(
filename.as_str().as_ptr(),
cell_data.as_ptr(),
cell_data.len() as u64,
aligned_addr,
aligned_size,
handle,
consumed_size,
)
}
rs_simulator_internal_dlopen2(
filename.as_str().as_ptr(),
cell_data.as_ptr(),
cell_data.len() as u64,
aligned_addr,
aligned_size,
handle,
consumed_size,
)
}

#[no_mangle]
pub extern "C" fn set_script_info(ptr: *const std::ffi::c_void, tx_ctx_id: u64, proc_ctx_id: u64) {
GlobalData::set_ptr(ptr);
TxContext::set_ctx_id(tx_ctx_id.into());
Process::set_ctx_id(proc_ctx_id.into());
}

fn fetch_cell(index: u64, source: u64) -> Result<(CellOutput, Bytes), c_int> {
Expand Down
Loading
Loading