Skip to content

Commit

Permalink
WIP: implement std.sys in Inko
Browse files Browse the repository at this point in the history
  • Loading branch information
yorickpeterse committed Sep 5, 2024
1 parent 125a4a8 commit 8f6c4af
Show file tree
Hide file tree
Showing 17 changed files with 708 additions and 436 deletions.
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
24 changes: 7 additions & 17 deletions rt/src/runtime/sys.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
use crate::mem::{ByteArray, String as InkoString};
use crate::process::ProcessPointer;
use crate::result::Result as InkoResult;
use crate::runtime::helpers::read_into;
use std::io::Write;
Expand All @@ -16,7 +15,6 @@ fn stdio_for(value: i64) -> Stdio {

#[no_mangle]
pub(crate) unsafe extern "system" fn inko_child_process_spawn(
process: ProcessPointer,
program: *const InkoString,
args: *const *const InkoString,
args_length: i64,
Expand Down Expand Up @@ -52,19 +50,15 @@ pub(crate) unsafe extern "system" fn inko_child_process_spawn(
cmd.current_dir(directory);
}

process
.blocking(|| cmd.spawn())
.map(InkoResult::ok_boxed)
.unwrap_or_else(InkoResult::io_error)
cmd.spawn().map(InkoResult::ok_boxed).unwrap_or_else(InkoResult::io_error)
}

#[no_mangle]
pub(crate) unsafe extern "system" fn inko_child_process_wait(
process: ProcessPointer,
child: *mut Child,
) -> InkoResult {
process
.blocking(|| (*child).wait())
(*child)
.wait()
.map(|status| status.code().unwrap_or(0) as i64)
.map(|status| InkoResult::ok(status as _))
.unwrap_or_else(InkoResult::io_error)
Expand All @@ -88,7 +82,6 @@ pub(crate) unsafe extern "system" fn inko_child_process_try_wait(

#[no_mangle]
pub(crate) unsafe extern "system" fn inko_child_process_stdout_read(
process: ProcessPointer,
child: *mut Child,
buffer: *mut ByteArray,
size: i64,
Expand All @@ -99,15 +92,14 @@ pub(crate) unsafe extern "system" fn inko_child_process_stdout_read(
child
.stdout
.as_mut()
.map(|stream| process.blocking(|| read_into(stream, buff, size)))
.map(|stream| read_into(stream, buff, size))
.unwrap_or(Ok(0))
.map(|size| InkoResult::ok(size as _))
.unwrap_or_else(InkoResult::io_error)
}

#[no_mangle]
pub(crate) unsafe extern "system" fn inko_child_process_stderr_read(
process: ProcessPointer,
child: *mut Child,
buffer: *mut ByteArray,
size: i64,
Expand All @@ -118,15 +110,14 @@ pub(crate) unsafe extern "system" fn inko_child_process_stderr_read(
child
.stderr
.as_mut()
.map(|stream| process.blocking(|| read_into(stream, buff, size)))
.map(|stream| read_into(stream, buff, size))
.unwrap_or(Ok(0))
.map(|size| InkoResult::ok(size as _))
.unwrap_or_else(InkoResult::io_error)
}

#[no_mangle]
pub(crate) unsafe extern "system" fn inko_child_process_stdin_write(
process: ProcessPointer,
child: *mut Child,
data: *mut u8,
size: i64,
Expand All @@ -137,23 +128,22 @@ pub(crate) unsafe extern "system" fn inko_child_process_stdin_write(
child
.stdin
.as_mut()
.map(|stream| process.blocking(|| stream.write(slice)))
.map(|stream| stream.write(slice))
.unwrap_or(Ok(0))
.map(|size| InkoResult::ok(size as _))
.unwrap_or_else(InkoResult::io_error)
}

#[no_mangle]
pub(crate) unsafe extern "system" fn inko_child_process_stdin_flush(
process: ProcessPointer,
child: *mut Child,
) -> InkoResult {
let child = &mut *child;

child
.stdin
.as_mut()
.map(|stream| process.blocking(|| stream.flush()))
.map(|stream| stream.flush())
.unwrap_or(Ok(()))
.map(|_| InkoResult::none())
.unwrap_or_else(InkoResult::io_error)
Expand Down
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)
}
24 changes: 7 additions & 17 deletions std/src/std/array.inko
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
# An ordered, integer-indexed generic collection of values.
import std.alloc
import std.clone (Clone)
import std.cmp (Compare, Contains, Equal, Ordering, max, min)
import std.drop (Drop)
import std.fmt (Format, Formatter)
import std.hash (Hash, Hasher)
import std.iter (Iter, Stream)
import std.libc
import std.option (Option)
import std.ptr
import std.rand (Shuffle)

# The capacity to use when resizing an array for the first time.
Expand Down Expand Up @@ -112,10 +113,7 @@ class builtin Array[T] {
fn pub static with_capacity(size: Int) -> Array[T] {
if size < 0 { panic('The capacity must be greater than or equal to zero') }

let vsize = _INKO.size_of_type_parameter(T)
let buffer = libc.resize(0x0 as Pointer[T], size: size * vsize)

Array(size: 0, capacity: size, buffer: buffer)
Array(size: 0, capacity: size, buffer: alloc.resize(0 as Pointer[T], size))
}

# Returns an array filled with a certain amount of values.
Expand Down Expand Up @@ -150,10 +148,8 @@ class builtin Array[T] {
fn pub mut reserve(size: Int) {
if @capacity - @size >= size { return }

let vsize = _INKO.size_of_type_parameter(T)

@capacity = max(@capacity * 2, @capacity + size)
@buffer = libc.resize(@buffer, @capacity * vsize)
@buffer = alloc.resize(@buffer, @capacity)
}

# Removes all values in the Array.
Expand Down Expand Up @@ -248,13 +244,8 @@ class builtin Array[T] {

let addr = address_of(index)
let val = addr.0
let vsize = _INKO.size_of_type_parameter(T)

libc.copy(
from: addr as Int + vsize as Pointer[T],
to: addr,
size: len - index - 1 * vsize,
)
alloc.copy(from: ptr.add(addr, 1), to: addr, size: len - index - 1)

@size = len - 1
val
Expand Down Expand Up @@ -596,9 +587,8 @@ class builtin Array[T] {
if index < @size {
let from = address_of(index)
let to = address_of(index + 1)
let vsize = _INKO.size_of_type_parameter(T)

libc.copy(from, to, size: @size - index * vsize)
alloc.copy(from, to, size: @size - index)
}

write_to(index, value)
Expand Down Expand Up @@ -733,7 +723,7 @@ impl Array if T: mut {
impl Drop for Array {
fn mut drop {
clear
libc.free(@buffer as Pointer[UInt8])
alloc.free(@buffer)
}
}

Expand Down
83 changes: 61 additions & 22 deletions std/src/std/libc.inko
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ let SO_REUSEADDR = sys.SO_REUSEADDR
let SO_REUSEPORT = sys.SO_REUSEPORT
let SO_SNDBUF = sys.SO_SNDBUF
let TCP_NODELAY = sys.TCP_NODELAY
let WNOHANG = sys.WNOHANG

fn opendir(path: Pointer[UInt8]) -> Pointer[UInt8] {
sys.opendir(path)
Expand Down Expand Up @@ -123,37 +124,71 @@ fn extern isatty(fd: Int32) -> Int32

fn extern strlen(pointer: Pointer[UInt8]) -> UInt64

fn extern posix_spawnp(
pid: Pointer[Int32],
file: Pointer[UInt8],
file_actions: Pointer[sys.PosixSpawnFileActions],
attrp: Pointer[sys.PosixSpawnAttrs],
argv: Pointer[UInt64],
envp: Pointer[UInt64],
) -> Int32

fn extern posix_spawn_file_actions_init(
actions: Pointer[sys.PosixSpawnFileActions],
) -> Int32

fn extern posix_spawn_file_actions_destroy(
actions: Pointer[sys.PosixSpawnFileActions],
) -> Int32

fn extern posix_spawn_file_actions_adddup2(
actions: Pointer[sys.PosixSpawnFileActions],
fd: Int32,
new_fd: Int32,
) -> Int32

fn extern posix_spawn_file_actions_addchdir_np(
actions: mut Pointer[sys.PosixSpawnFileActions],
path: Pointer[UInt8],
) -> Int32

fn extern posix_spawnattr_init(attr: mut Pointer[sys.PosixSpawnAttrs]) -> Int32

fn extern posix_spawnattr_destroy(
attr: mut Pointer[sys.PosixSpawnAttrs],
) -> Int32

fn extern posix_spawnattr_setflags(
attr: mut Pointer[sys.PosixSpawnAttrs],
flags: Int16,
) -> Int32

fn extern posix_spawnattr_setsigdefault(
attr: mut Pointer[sys.PosixSpawnAttrs],
mask: mut Pointer[sys.SigSet],
) -> Int32

fn extern posix_spawnattr_setsigmask(
attr: mut Pointer[sys.PosixSpawnAttrs],
mask: mut Pointer[sys.SigSet],
) -> Int32

fn extern sigemptyset(set: mut Pointer[sys.SigSet]) -> Int32

fn extern sigfillset(set: mut Pointer[sys.SigSet]) -> Int32

fn extern waitpid(pid: Int32, status: Pointer[Int32], options: Int32) -> Int32

fn extern realloc(pointer: Pointer[UInt8], size: Int) -> Pointer[UInt8]

fn extern memmove(
to: Pointer[UInt8],
from: Pointer[UInt8],
size: Int,
size: UInt64,
) -> Pointer[UInt8]

fn extern free(pointer: Pointer[UInt8])

# A thin wrapper around `realloc()`.
#
# # 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 ptr = realloc(buffer as Pointer[UInt8], size)

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

ptr as Pointer[T]
}

fn copy[T](from: Pointer[T], to: Pointer[T], size: Int) {
memmove(to as Pointer[UInt8], from as Pointer[UInt8], size)
}

# Returns the type of a directory entry.
fn dirent_type(pointer: Pointer[sys.Dirent]) -> Int {
sys.dirent_type(pointer)
Expand All @@ -163,3 +198,7 @@ fn dirent_type(pointer: Pointer[sys.Dirent]) -> Int {
fn dirent_name(pointer: Pointer[sys.Dirent]) -> Pointer[UInt8] {
sys.dirent_name(pointer)
}

fn pipes -> Result[(Int32, Int32), Error] {
sys.pipes
}
Loading

0 comments on commit 8f6c4af

Please sign in to comment.