Skip to content

Commit

Permalink
WIP: threading support
Browse files Browse the repository at this point in the history
  • Loading branch information
tizoc committed Dec 26, 2023
1 parent f5e8777 commit 059824f
Show file tree
Hide file tree
Showing 11 changed files with 162 additions and 78 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ jobs:
- name: Add Opam switch to PATH
run: opam var bin >> $GITHUB_PATH
- name: Setup Rust
uses: actions-rs/toolchain@v1
uses: dtolnay/rust-toolchain@v1
with:
toolchain: stable
- name: Setttings for cargo in OSX
Expand Down
4 changes: 2 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,11 @@ exclude = [
]

[package.metadata.docs.rs]
features = [ "without-ocamlopt" ]
features = [ "without-ocamlopt", "caml-state" ]

[dependencies]
ocaml-sys = "0.23"
ocaml-boxroot-sys = "0.3.0"
ocaml-boxroot-sys = { git = "https://gitlab.com/ocaml-rust/ocaml-boxroot.git", rev="652d92b1" }
static_assertions = "1.1.0"

[features]
Expand Down
10 changes: 9 additions & 1 deletion src/boxroot.rs
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,15 @@ impl<T> BoxRoot<T> {
pub fn keep<'tmp>(&'tmp mut self, val: OCaml<T>) -> OCamlRef<'tmp, T> {
unsafe {
if !boxroot_modify(&mut self.boxroot, val.raw) {
panic!("boxrooot_modify failed");
let status = boxroot_status();
let reason = match status {
Status::NotSetup => "NotSetup",
Status::Running => "Running",
Status::ToreDown => "ToreDown",
Status::Invalid => "Invalid",
_ => "Unknown",
};
panic!("Failed to modify boxroot, boxroot_status() -> {}", reason,)
}
&*(boxroot_get_ref(self.boxroot) as *const OCamlCell<T>)
}
Expand Down
2 changes: 1 addition & 1 deletion src/conv/to_ocaml.rs
Original file line number Diff line number Diff line change
Expand Up @@ -198,7 +198,7 @@ where
A: ToOCaml<OCamlA>,
{
fn to_ocaml<'a>(&self, cr: &'a mut OCamlRuntime) -> OCaml<'a, OCamlList<OCamlA>> {
let mut result = BoxRoot::new(OCaml::nil());
let mut result = BoxRoot::new(OCaml::nil(cr));
for elt in self.iter().rev() {
let ov = elt.to_boxroot(cr);
let cons = alloc_cons(cr, &ov, &result);
Expand Down
2 changes: 1 addition & 1 deletion src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -302,7 +302,7 @@ pub use crate::memory::OCamlRef;
pub use crate::mlvalues::{
bigarray, DynBox, OCamlBytes, OCamlFloat, OCamlInt, OCamlInt32, OCamlInt64, OCamlList, RawOCaml,
};
pub use crate::runtime::OCamlRuntime;
pub use crate::runtime::{OCamlRuntime, OCamlDomainLock};
pub use crate::value::OCaml;

#[doc(hidden)]
Expand Down
70 changes: 68 additions & 2 deletions src/runtime.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,10 @@
// SPDX-License-Identifier: MIT

use ocaml_boxroot_sys::boxroot_teardown;
use std::marker::PhantomData;
use std::{
marker::PhantomData,
ops::{Deref, DerefMut},
};

use crate::{memory::OCamlRef, value::OCaml};

Expand Down Expand Up @@ -35,9 +38,10 @@ impl OCamlRuntime {

INIT.call_once(|| {
let arg0 = "ocaml\0".as_ptr() as *const ocaml_sys::Char;
let c_args = vec![arg0, core::ptr::null()];
let c_args = [arg0, core::ptr::null()];
unsafe {
ocaml_sys::caml_startup(c_args.as_ptr());
ocaml_boxroot_sys::boxroot_setup_systhreads();
}
})
}
Expand Down Expand Up @@ -75,6 +79,10 @@ impl OCamlRuntime {
raw: unsafe { reference.get_raw() },
}
}

pub fn acquire_lock() -> OCamlDomainLock {
OCamlDomainLock::new()
}
}

impl Drop for OCamlRuntime {
Expand Down Expand Up @@ -108,6 +116,64 @@ impl Drop for OCamlBlockingSection {
}
}

pub struct OCamlDomainLock {
_private: (),
}

extern "C" {
pub fn caml_c_thread_register() -> isize;
pub fn caml_c_thread_unregister() -> isize;
}

impl OCamlDomainLock {
#[inline(always)]
fn new() -> Self {
unsafe {
caml_c_thread_register();
ocaml_sys::caml_leave_blocking_section();
};
Self { _private: () }
}

#[inline(always)]
pub fn perform<T, F>(self, f: F) -> T
where
F: FnOnce(&mut OCamlRuntime) -> T,
{
let cr = unsafe { OCamlRuntime::recover_handle() };
f(cr)
}

// FIXME: immutable reference but gets mut runtime
#[inline(always)]
pub fn recover_handle<'a>(&self) -> &'a mut OCamlRuntime {
unsafe { OCamlRuntime::recover_handle() }
}
}

impl Drop for OCamlDomainLock {
fn drop(&mut self) {
unsafe {
ocaml_sys::caml_enter_blocking_section();
caml_c_thread_unregister();
};
}
}

impl Deref for OCamlDomainLock {
type Target = OCamlRuntime;

fn deref(&self) -> &OCamlRuntime {
self.recover_handle()
}
}

impl DerefMut for OCamlDomainLock {
fn deref_mut(&mut self) -> &mut OCamlRuntime {
self.recover_handle()
}
}

// For initializing from an OCaml-driven program

#[no_mangle]
Expand Down
2 changes: 1 addition & 1 deletion src/value.rs
Original file line number Diff line number Diff line change
Expand Up @@ -369,7 +369,7 @@ impl<'a, A, Err> OCaml<'a, Result<A, Err>> {

impl<'a, A> OCaml<'a, OCamlList<A>> {
/// Returns an OCaml nil (empty list) value.
pub fn nil() -> Self {
pub fn nil(_: &'a mut OCamlRuntime) -> Self {
OCaml {
_marker: PhantomData,
raw: EMPTY_LIST,
Expand Down
2 changes: 1 addition & 1 deletion testing/rust-caller/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,4 @@ ocaml-interop = { path = "../.." }
ocaml-sys = "*"

[dev-dependencies]
serial_test = "*"
once_cell = "*"
14 changes: 7 additions & 7 deletions testing/rust-caller/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,29 +8,29 @@ fn main() {
let ocaml_callable_dir = "./ocaml";
let dune_dir = "../../_build/default/testing/rust-caller/ocaml";
Command::new("opam")
.args(&["exec", "--", "dune", "build", &format!("{}/callable.exe.o", ocaml_callable_dir)])
.args(["exec", "--", "dune", "build", &format!("{}/callable.exe.o", ocaml_callable_dir)])
.status()
.expect("Dune failed");
Command::new("rm")
.args(&["-f", &format!("{}/libcallable.a", out_dir)])
.args(["-f", &format!("{}/libcallable.a", out_dir)])
.status()
.expect("rm failed");
Command::new("rm")
.args(&["-f", &format!("{}/libcallable.o", out_dir)])
.args(["-f", &format!("{}/libcallable.o", out_dir)])
.status()
.expect("rm failed");
Command::new("cp")
.args(&[
.args([
&format!("{}/callable.exe.o", dune_dir),
&format!("{}/libcallable.o", out_dir),
&format!("{}/callable.o", out_dir),
])
.status()
.expect("File copy failed.");
Command::new("ar")
.args(&[
.args([
"qs",
&format!("{}/libcallable.a", out_dir),
&format!("{}/libcallable.o", out_dir),
&format!("{}/callable.o", out_dir),
])
.status()
.expect("ar failed");
Expand Down
2 changes: 2 additions & 0 deletions testing/rust-caller/ocaml/dune
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
(executables
(names callable)
(libraries threads)
(flags (:standard -noautolink -cclib -lunix -cclib -lthreadsnat))
(modes object))
Loading

0 comments on commit 059824f

Please sign in to comment.