llam 0.1.2

Safe, Go-style Rust bindings for the LLAM runtime
#![allow(non_camel_case_types)]
#![allow(non_snake_case)]
#![allow(non_upper_case_globals)]

use libc::{c_char, c_int, c_short, c_void, size_t, sockaddr, ssize_t};

#[cfg(windows)]
pub type socklen_t = c_int;
#[cfg(not(windows))]
pub type socklen_t = libc::socklen_t;

pub const LLAM_VERSION_MAJOR: u32 = 1;
pub const LLAM_VERSION_MINOR: u32 = 0;
pub const LLAM_VERSION_PATCH: u32 = 0;
pub const LLAM_ABI_VERSION_MAJOR: u32 = 1;
pub const LLAM_ABI_VERSION_MINOR: u32 = 0;
pub const LLAM_ABI_VERSION: u32 = (LLAM_ABI_VERSION_MAJOR << 16) | LLAM_ABI_VERSION_MINOR;

pub const LLAM_TASK_CLASS_LATENCY: u32 = 0;
pub const LLAM_TASK_CLASS_DEFAULT: u32 = 1;
pub const LLAM_TASK_CLASS_BATCH: u32 = 2;

pub const LLAM_STACK_CLASS_DEFAULT: u32 = 0;
pub const LLAM_STACK_CLASS_LARGE: u32 = 1;
pub const LLAM_STACK_CLASS_HUGE: u32 = 2;

pub const LLAM_RUNTIME_PROFILE_BALANCED: u32 = 0;
pub const LLAM_RUNTIME_PROFILE_RELEASE_FAST: u32 = 1;
pub const LLAM_RUNTIME_PROFILE_DEBUG_SAFE: u32 = 2;
pub const LLAM_RUNTIME_PROFILE_IO_LATENCY: u32 = 3;

pub const LLAM_SPAWN_F_PINNED: u32 = 1 << 0;
pub const LLAM_SPAWN_F_NO_PREEMPT: u32 = 1 << 1;
pub const LLAM_SPAWN_F_SYS_TASK: u32 = 1 << 2;
pub const LLAM_SPAWN_F_LATENCY_CRITICAL: u32 = 1 << 3;

pub const LLAM_RUNTIME_EXPERIMENTAL_F_WORKER_RINGS: u64 = 1;
pub const LLAM_RUNTIME_EXPERIMENTAL_F_WORKER_RINGS_MULTISHOT: u64 = 1 << 1;
pub const LLAM_RUNTIME_EXPERIMENTAL_F_DYNAMIC_WORKERS: u64 = 1 << 2;
pub const LLAM_RUNTIME_EXPERIMENTAL_F_LOCKFREE_NORMQ: u64 = 1 << 3;
pub const LLAM_RUNTIME_EXPERIMENTAL_F_HUGE_ALLOC: u64 = 1 << 4;
pub const LLAM_RUNTIME_EXPERIMENTAL_F_SQPOLL: u64 = 1 << 5;

pub const LLAM_SELECT_OP_RECV: u32 = 1;
pub const LLAM_SELECT_OP_SEND: u32 = 2;
pub const LLAM_TASK_LOCAL_INVALID_KEY: u32 = u32::MAX;

#[cfg(windows)]
pub type llam_fd_t = usize;
#[cfg(not(windows))]
pub type llam_fd_t = c_int;

#[cfg(windows)]
pub const LLAM_INVALID_FD: llam_fd_t = !0usize;
#[cfg(not(windows))]
pub const LLAM_INVALID_FD: llam_fd_t = -1;

#[repr(C)]
pub struct llam_task_t {
    _private: [u8; 0],
}
#[repr(C)]
pub struct llam_mutex_t {
    _private: [u8; 0],
}
#[repr(C)]
pub struct llam_cond_t {
    _private: [u8; 0],
}
#[repr(C)]
pub struct llam_channel_t {
    _private: [u8; 0],
}
#[repr(C)]
pub struct llam_cancel_token_t {
    _private: [u8; 0],
}
#[repr(C)]
pub struct llam_io_buffer_t {
    _private: [u8; 0],
}
#[repr(C)]
pub struct llam_runtime_t {
    _private: [u8; 0],
}
#[repr(C)]
pub struct llam_task_group_t {
    _private: [u8; 0],
}

pub type llam_task_local_key_t = u32;
pub type llam_task_fn = unsafe extern "C" fn(*mut c_void);
pub type llam_blocking_fn = unsafe extern "C" fn(*mut c_void) -> *mut c_void;

#[repr(C)]
#[derive(Clone, Copy, Debug)]
pub struct llam_abi_info_t {
    pub abi_major: u32,
    pub abi_minor: u32,
    pub version_major: u32,
    pub version_minor: u32,
    pub version_patch: u32,
    pub reserved0: u32,
    pub struct_size: size_t,
    pub runtime_opts_size: size_t,
    pub spawn_opts_size: size_t,
    pub runtime_stats_size: size_t,
    pub runtime_name: *const c_char,
    pub version_string: *const c_char,
    pub platform_name: *const c_char,
}

#[repr(C)]
#[derive(Clone, Copy, Debug)]
pub struct llam_spawn_opts_t {
    pub task_class: u32,
    pub stack_class: u32,
    pub flags: u32,
    pub deadline_ns: u64,
    pub cancel_token: *mut llam_cancel_token_t,
}

#[repr(C)]
#[derive(Clone, Copy, Debug)]
pub struct llam_runtime_opts_t {
    pub deterministic: u32,
    pub forced_yield_every: u32,
    pub experimental_flags: u64,
    pub idle_spin_ns: u64,
    pub idle_spin_max_iters: u32,
    pub sqpoll_cpu: i32,
    pub profile: u32,
    pub reserved0: u32,
}

#[repr(C)]
#[derive(Clone, Copy, Debug, Default)]
pub struct llam_runtime_stats_t {
    pub ctx_switches: u64,
    pub yields: u64,
    pub parks: u64,
    pub wakes: u64,
    pub steals: u64,
    pub migrations: u64,
    pub blocking_calls: u64,
    pub blocking_completions: u64,
    pub io_submits: u64,
    pub io_submit_calls: u64,
    pub io_submit_syscalls: u64,
    pub io_completions: u64,
    pub idle_polls: u64,
    pub idle_spin_loops: u64,
    pub idle_spin_hits: u64,
    pub idle_spin_fallbacks: u64,
    pub idle_spin_ns: u64,
    pub queue_overflows: u64,
    pub overflow_depth: u64,
    pub active_workers: u32,
    pub online_workers: u32,
    pub online_workers_floor: u32,
    pub online_workers_min: u32,
    pub online_workers_max: u32,
    pub active_nodes: u32,
    pub dynamic_workers: u32,
    pub worker_rings: u32,
    pub worker_rings_multishot: u32,
    pub lockfree_normq: u32,
    pub huge_alloc: u32,
    pub sqpoll: u32,
    pub opaque_block_ns: u64,
    pub opaque_block_samples: u64,
    pub opaque_block_max_ns: u64,
    pub opaque_enter_wait_ns: u64,
    pub opaque_enter_wait_samples: u64,
    pub opaque_enter_wait_max_ns: u64,
    pub opaque_leave_wait_ns: u64,
    pub opaque_leave_wait_samples: u64,
    pub opaque_leave_wait_max_ns: u64,
    pub yield_direct_attempts: u64,
    pub yield_direct_fast_hits: u64,
    pub yield_direct_locked_hits: u64,
    pub yield_direct_fail_context: u64,
    pub yield_direct_fail_policy: u64,
    pub yield_direct_fail_no_work: u64,
    pub yield_direct_fail_self: u64,
    pub yield_direct_fail_push: u64,
}

#[repr(C)]
#[derive(Clone, Copy, Debug)]
pub struct llam_select_op_t {
    pub kind: u32,
    pub reserved0: u32,
    pub channel: *mut llam_channel_t,
    pub send_value: *mut c_void,
    pub recv_out: *mut *mut c_void,
    pub result_errno: c_int,
}

extern "C" {
    pub fn llam_abi_version() -> u32;
    pub fn llam_version_string() -> *const c_char;
    pub fn llam_abi_get_info(info: *mut llam_abi_info_t, info_size: size_t) -> c_int;

    pub fn llam_runtime_opts_init(opts: *mut llam_runtime_opts_t, opts_size: size_t) -> c_int;
    pub fn llam_spawn_opts_init(opts: *mut llam_spawn_opts_t, opts_size: size_t) -> c_int;
    pub fn llam_runtime_init_ex(opts: *const llam_runtime_opts_t, opts_size: size_t) -> c_int;
    pub fn llam_runtime_init(opts: *const llam_runtime_opts_t) -> c_int;
    pub fn llam_runtime_request_stop() -> c_int;
    pub fn llam_runtime_shutdown();
    pub fn llam_runtime_collect_stats_ex(
        stats: *mut llam_runtime_stats_t,
        stats_size: size_t,
    ) -> c_int;
    pub fn llam_runtime_collect_stats(stats: *mut llam_runtime_stats_t) -> c_int;
    pub fn llam_runtime_default() -> *mut llam_runtime_t;
    pub fn llam_runtime_create(
        opts: *const llam_runtime_opts_t,
        opts_size: size_t,
        out: *mut *mut llam_runtime_t,
    ) -> c_int;
    pub fn llam_runtime_run_handle(runtime: *mut llam_runtime_t) -> c_int;
    pub fn llam_runtime_destroy(runtime: *mut llam_runtime_t);
    pub fn llam_runtime_write_stats_json(fd: c_int) -> c_int;

    pub fn llam_spawn_ex(
        f: llam_task_fn,
        arg: *mut c_void,
        opts: *const llam_spawn_opts_t,
        opts_size: size_t,
    ) -> *mut llam_task_t;
    pub fn llam_spawn(
        f: llam_task_fn,
        arg: *mut c_void,
        opts: *const llam_spawn_opts_t,
    ) -> *mut llam_task_t;
    pub fn llam_run() -> c_int;
    pub fn llam_yield();
    pub fn llam_task_safepoint();
    pub fn llam_join(task: *mut llam_task_t) -> c_int;
    pub fn llam_join_until(task: *mut llam_task_t, deadline_ns: u64) -> c_int;
    pub fn llam_detach(task: *mut llam_task_t) -> c_int;

    pub fn llam_task_group_create() -> *mut llam_task_group_t;
    pub fn llam_task_group_destroy(group: *mut llam_task_group_t) -> c_int;
    pub fn llam_task_group_spawn_ex(
        group: *mut llam_task_group_t,
        f: llam_task_fn,
        arg: *mut c_void,
        opts: *const llam_spawn_opts_t,
        opts_size: size_t,
    ) -> *mut llam_task_t;
    pub fn llam_task_group_spawn(
        group: *mut llam_task_group_t,
        f: llam_task_fn,
        arg: *mut c_void,
        opts: *const llam_spawn_opts_t,
    ) -> *mut llam_task_t;
    pub fn llam_task_group_cancel(group: *mut llam_task_group_t) -> c_int;
    pub fn llam_task_group_join(group: *mut llam_task_group_t) -> c_int;
    pub fn llam_task_group_join_until(group: *mut llam_task_group_t, deadline_ns: u64) -> c_int;

    pub fn llam_sleep_until(deadline_ns: u64) -> c_int;
    pub fn llam_sleep_ns(duration_ns: u64) -> c_int;
    pub fn llam_call_blocking_result(
        f: llam_blocking_fn,
        arg: *mut c_void,
        out: *mut *mut c_void,
    ) -> c_int;
    pub fn llam_call_blocking(f: llam_blocking_fn, arg: *mut c_void) -> *mut c_void;
    pub fn llam_enter_blocking() -> c_int;
    pub fn llam_leave_blocking() -> c_int;
    pub fn llam_task_set_class(task_class: u32) -> c_int;
    pub fn llam_dump_runtime_state(fd: c_int);
    pub fn llam_task_flags(task: *const llam_task_t) -> u32;

    pub fn llam_task_local_key_create(out_key: *mut llam_task_local_key_t) -> c_int;
    pub fn llam_task_local_key_delete(key: llam_task_local_key_t) -> c_int;
    pub fn llam_task_local_get(key: llam_task_local_key_t) -> *mut c_void;
    pub fn llam_task_local_set(key: llam_task_local_key_t, value: *mut c_void) -> c_int;

    pub fn llam_cancel_token_create() -> *mut llam_cancel_token_t;
    pub fn llam_cancel_token_destroy(token: *mut llam_cancel_token_t) -> c_int;
    pub fn llam_cancel_token_cancel(token: *mut llam_cancel_token_t) -> c_int;
    pub fn llam_cancel_token_is_cancelled(token: *const llam_cancel_token_t) -> c_int;

    pub fn llam_mutex_create() -> *mut llam_mutex_t;
    pub fn llam_mutex_destroy(mutex: *mut llam_mutex_t) -> c_int;
    pub fn llam_mutex_lock(mutex: *mut llam_mutex_t) -> c_int;
    pub fn llam_mutex_lock_until(mutex: *mut llam_mutex_t, deadline_ns: u64) -> c_int;
    pub fn llam_mutex_trylock(mutex: *mut llam_mutex_t) -> c_int;
    pub fn llam_mutex_unlock(mutex: *mut llam_mutex_t) -> c_int;

    pub fn llam_cond_create() -> *mut llam_cond_t;
    pub fn llam_cond_destroy(cond: *mut llam_cond_t) -> c_int;
    pub fn llam_cond_wait(cond: *mut llam_cond_t, mutex: *mut llam_mutex_t) -> c_int;
    pub fn llam_cond_wait_until(
        cond: *mut llam_cond_t,
        mutex: *mut llam_mutex_t,
        deadline_ns: u64,
    ) -> c_int;
    pub fn llam_cond_signal(cond: *mut llam_cond_t) -> c_int;
    pub fn llam_cond_broadcast(cond: *mut llam_cond_t) -> c_int;

    pub fn llam_channel_create(capacity: size_t) -> *mut llam_channel_t;
    pub fn llam_channel_destroy(channel: *mut llam_channel_t) -> c_int;
    pub fn llam_channel_send(channel: *mut llam_channel_t, value: *mut c_void) -> c_int;
    pub fn llam_channel_send_until(
        channel: *mut llam_channel_t,
        value: *mut c_void,
        deadline_ns: u64,
    ) -> c_int;
    pub fn llam_channel_recv_result(channel: *mut llam_channel_t, out: *mut *mut c_void) -> c_int;
    pub fn llam_channel_recv_until_result(
        channel: *mut llam_channel_t,
        deadline_ns: u64,
        out: *mut *mut c_void,
    ) -> c_int;
    pub fn llam_channel_recv(channel: *mut llam_channel_t) -> *mut c_void;
    pub fn llam_channel_recv_until(channel: *mut llam_channel_t, deadline_ns: u64) -> *mut c_void;
    pub fn llam_channel_close(channel: *mut llam_channel_t) -> c_int;
    pub fn llam_channel_select(
        ops: *mut llam_select_op_t,
        op_count: size_t,
        deadline_ns: u64,
        selected_index: *mut size_t,
    ) -> c_int;

    pub fn llam_read(fd: llam_fd_t, buf: *mut c_void, count: size_t) -> ssize_t;
    pub fn llam_read_when_ready(
        fd: llam_fd_t,
        buf: *mut c_void,
        count: size_t,
        timeout_ms: c_int,
    ) -> ssize_t;
    pub fn llam_write(fd: llam_fd_t, buf: *const c_void, count: size_t) -> ssize_t;
    pub fn llam_read_owned(
        fd: llam_fd_t,
        max_count: size_t,
        out: *mut *mut llam_io_buffer_t,
    ) -> ssize_t;
    pub fn llam_recv_owned(
        fd: llam_fd_t,
        max_count: size_t,
        flags: c_int,
        out: *mut *mut llam_io_buffer_t,
    ) -> ssize_t;
    pub fn llam_io_buffer_release(buffer: *mut llam_io_buffer_t);
    pub fn llam_io_buffer_data(buffer: *mut llam_io_buffer_t) -> *mut c_void;
    pub fn llam_io_buffer_size(buffer: *const llam_io_buffer_t) -> size_t;
    pub fn llam_io_buffer_capacity(buffer: *const llam_io_buffer_t) -> size_t;
    pub fn llam_accept(fd: llam_fd_t, addr: *mut sockaddr, addrlen: *mut socklen_t) -> llam_fd_t;
    pub fn llam_connect(fd: llam_fd_t, addr: *const sockaddr, addrlen: socklen_t) -> c_int;
    pub fn llam_poll_fd(
        fd: llam_fd_t,
        events: c_short,
        timeout_ms: c_int,
        revents: *mut c_short,
    ) -> c_int;

    pub fn llam_now_ns() -> u64;
    pub fn llam_task_id(task: *const llam_task_t) -> u64;
    pub fn llam_task_state_name(task: *const llam_task_t) -> *const c_char;
    pub fn llam_task_class(task: *const llam_task_t) -> u32;
    pub fn llam_current_task() -> *mut llam_task_t;
}

pub fn fd_is_invalid(fd: llam_fd_t) -> bool {
    fd == LLAM_INVALID_FD
}