Skip to content

Commit

Permalink
Implement std.sys in Inko
Browse files Browse the repository at this point in the history
This changes the implementation of std.sys and std.sys.Command in
particular to no longer depend on any Rust code, instead implementing
the necessary logic in Inko using the C FFI.

The implementation of Command uses posix_spawnp() to spawn processes,
instead of using e.g. vfork+execve. While this requires bumping the
macOS requirement to 10.15 due to posix_spawn_file_actions_addchdir_np()
not being available on earlier versions, this should be OK since macOS
users tend to not stay on old versions for too long. For example, per
https://formulae.brew.sh/analytics/os-version/365d/ it seems that at
least for Homebrew less than 2% uses a version _older_ than Big Sur.

Changelog: changed
  • Loading branch information
yorickpeterse committed Sep 5, 2024
1 parent 125a4a8 commit e65d1e7
Show file tree
Hide file tree
Showing 22 changed files with 768 additions and 651 deletions.
6 changes: 3 additions & 3 deletions docs/source/setup/installation.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,9 @@ choice.

## Supported platforms

Inko supports Linux, macOS, and FreeBSD (13.2 or newer). Inko might also work on
other platforms, but we only provide support for the listed platforms. Windows
isn't supported.
Inko supports Linux (4.11 or newer), macOS (10.15 or newer), and FreeBSD (13.2
or newer). Inko might also work on other platforms, but we only provide support
for the listed platforms. Windows isn't supported.

## Requirements

Expand Down
13 changes: 0 additions & 13 deletions rt/src/process.rs
Original file line number Diff line number Diff line change
Expand Up @@ -746,19 +746,6 @@ impl ProcessPointer {
self.as_ptr() as usize
}

// TODO: remove
pub(crate) fn blocking<R>(mut self, function: impl FnOnce() -> R) -> R {
// Safety: threads are stored in processes before running them.
let thread = unsafe { self.thread() };

thread.start_blocking();

let res = function();

thread.stop_blocking(self);
res
}

pub(crate) fn start_blocking(mut self) {
// Safety: threads are stored in processes before running them.
unsafe { self.thread() }.start_blocking();
Expand Down
15 changes: 0 additions & 15 deletions rt/src/runtime.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ mod random;
mod signal;
mod socket;
mod string;
mod sys;
mod time;
mod tls;

Expand All @@ -25,8 +24,6 @@ use crate::stack::Stack;
use crate::state::{MethodCounts, RcState, State};
use rustix::param::page_size;
use std::ffi::CStr;
use std::io::{stdout, Write as _};
use std::process::exit as rust_exit;
use std::slice;
use std::thread;

Expand Down Expand Up @@ -87,7 +84,6 @@ pub unsafe extern "system" fn inko_runtime_start(
method: NativeAsyncMethod,
) {
(*runtime).start(class, method);
flush_stdout();
}

#[no_mangle]
Expand All @@ -107,17 +103,6 @@ pub unsafe extern "system" fn inko_runtime_stack_mask(
!(total - 1)
}

fn flush_stdout() {
// STDOUT is buffered by default, and not flushing it upon exit may result
// in parent processes not observing the output.
let _ = stdout().lock().flush();
}

pub(crate) fn exit(status: i32) -> ! {
flush_stdout();
rust_exit(status);
}

/// An Inko runtime along with all its state.
#[repr(C)]
pub struct Runtime {
Expand Down
6 changes: 0 additions & 6 deletions rt/src/runtime/general.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
use crate::mem::{header_of, ClassPointer};
use crate::process::ProcessPointer;
use crate::runtime::exit;
use crate::runtime::process::panic;
use std::alloc::handle_alloc_error;
use std::io::Error;
Expand All @@ -26,11 +25,6 @@ extern "C" {
fn errno_location() -> *mut i32;
}

#[no_mangle]
pub unsafe extern "system" fn inko_exit(status: i64) {
exit(status as i32);
}

#[no_mangle]
pub unsafe extern "system" fn inko_reference_count_error(
process: ProcessPointer,
Expand Down
17 changes: 1 addition & 16 deletions rt/src/runtime/helpers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,22 +4,7 @@ use crate::process::ProcessPointer;
use crate::scheduler::timeouts::Timeout;
use crate::socket::Socket;
use crate::state::State;
use std::io::{self, Read};

/// Reads a number of bytes from a buffer into a Vec.
pub(crate) fn read_into<T: Read>(
stream: &mut T,
output: &mut Vec<u8>,
size: i64,
) -> Result<i64, io::Error> {
let read = if size > 0 {
stream.take(size as u64).read_to_end(output)?
} else {
stream.read_to_end(output)?
};

Ok(read as i64)
}
use std::io::{self};

pub(crate) fn poll(
state: &State,
Expand Down
2 changes: 1 addition & 1 deletion rt/src/runtime/process.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,12 @@ use crate::process::{
ReceiveResult, RescheduleRights, SendResult, StackFrame,
};
use crate::result::Result as InkoResult;
use crate::runtime::exit;
use crate::scheduler::process::Action;
use crate::scheduler::timeouts::Timeout;
use crate::state::State;
use std::cmp::max;
use std::fmt::Write as _;
use std::process::exit;
use std::str;
use std::time::Duration;

Expand Down
188 changes: 0 additions & 188 deletions rt/src/runtime/sys.rs

This file was deleted.

18 changes: 13 additions & 5 deletions rt/src/rustls_platform_verifier/verification/apple.rs
Original file line number Diff line number Diff line change
Expand Up @@ -123,11 +123,19 @@ impl Verifier {
// Safety: well, technically none, but due to the way the runtime uses
// the verifier this should never misbehave.
let process = unsafe { ProcessPointer::new(CURRENT_PROCESS.get()) };
let trust_error =
match process.blocking(|| trust_evaluation.evaluate_with_error()) {
Ok(()) => return Ok(()),
Err(e) => e,
};

process.start_blocking();

let trust_error = match trust_evaluation.evaluate_with_error() {
Ok(()) => {
process.stop_blocking();
return Ok(());
}
Err(e) => {
process.stop_blocking();
e
}
};

let err_code = trust_error.code();

Expand Down
34 changes: 34 additions & 0 deletions std/src/std/alloc.inko
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import std.io (Error)
import std.libc

# Allocates or resizes a chunk of raw memory such that it can fit `size`
# _elements_ (not bytes).
#
# This method is a thin wrapper around the `realloc(2)`.
#
# # Panics
#
# This method panics if `realloc()` returns `NULL` and the `size` argument
# _isn't_ zero.
fn resize[T](buffer: Pointer[T], size: Int) -> Pointer[T] {
let bytes = size * _INKO.size_of_type_parameter(T)
let ptr = libc.realloc(buffer as Pointer[UInt8], bytes)

# In this case there's nothing we can do but abort.
if ptr as Int == 0 and size != 0 {
panic('std.alloc.resize() failed: ${Error.last_os_error}')
}

ptr as Pointer[T]
}

fn free[T](pointer: Pointer[T]) {
libc.free(pointer as Pointer[UInt8])
}

# Copies `size` _elements_ from the pointer `from` to the pointer `to`.
fn copy[T](from: Pointer[T], to: Pointer[T], size: Int) {
let bytes = size * _INKO.size_of_type_parameter(T)

libc.memmove(to as Pointer[UInt8], from as Pointer[UInt8], bytes as UInt64)
}
Loading

0 comments on commit e65d1e7

Please sign in to comment.