Additions:
- Added ability to control the size of the tag type for tagged unions.
- `union #tag_type u8`
+- Infrastructure to have custom sub-commands.
+ - Any `*.wasm` file in `$ONYX_PATH/tools` is available to run with `onyx <cmd>`
+- Added `--skip-native` flag to `onyx pkg sync` to skip compiling native libraries.
Removals:
Supports_Type_Info :: true
Supports_Threads :: true
Supports_Env_Vars :: false
+Supports_Futexes :: true
__output_string :: (s: str) -> u32 #foreign "host" "print_str" ---
__output_error :: (s: str) -> u32 #foreign "host" "print_str" ---
__read_from_input :: (buf: [] u8) -> u32 do return 0;
}
+__futex_wait :: (addr: rawptr, expected: i32, timeout: i32) -> i32 {
+ use core.intrinsics.atomics {__atomic_wait}
+ if context.thread_id != 0 {
+ __atomic_wait(addr, expected, ~~timeout);
+ }
+}
+
+__futex_wake :: (addr: rawptr, maximum: i32) -> i32 {
+ use core.intrinsics.atomics {__atomic_notify}
+ __atomic_notify(addr, maximum);
+}
+
// Sets up everything needed for execution.
__start :: () {
__runtime_initialize();
Supports_Type_Info :: true
Supports_Threads :: true
Supports_Env_Vars :: true
+Supports_Futexes :: true
#library "onyx_runtime"
// OS
__exit :: (status: i32) -> void ---
__sleep :: (milliseconds: i32) -> void ---
+ __futex_wait :: (addr: rawptr, expected: i32, timeout: i32) -> i32 ---
+ __futex_wake :: (addr: rawptr, maximum: i32) -> i32 ---
// Time and sleep
__time :: () -> u64 ---
Supports_Type_Info :: true
Supports_Threads :: true
Supports_Env_Vars :: true
+Supports_Futexes :: false
__output_string :: (s: str) -> u32 {
while __atomic_cmpxchg(&m.lock, 0, 1) == 1 {
if m.owner == context.thread_id do return;
- #if runtime.Wait_Notify_Available {
- // @ThreadingCleanup // You cannot wait on the main thread in
- // a web browser, for kind of obvious reasons. However, this
- // makes waiting for a mutex expensive because the only option
- // is to do a spin-lock. Ugh.
- if context.thread_id != 0 {
- __atomic_wait(&m.lock, 1);
- }
+ #if runtime.platform.Supports_Futexes {
+ runtime.platform.__futex_wait(&m.lock, 1, -1);
} else {
while (m.lock == 1) ---
}
m.owner = -1;
__atomic_store(&m.lock, 0);
- #if runtime.Wait_Notify_Available {
- __atomic_notify(&m.lock, maximum = 1);
+ #if runtime.platform.Supports_Futexes {
+ runtime.platform.__futex_wake(&m.lock, 1);
}
}
// @Bug
// This is susceptible to starvation. Semaphores should have a queue
// or something like that.
- #if runtime.Wait_Notify_Available {
- __atomic_notify(&s.counter, maximum = count);
+ #if runtime.platform.Supports_Futexes {
+ runtime.platform.__futex_wake(&s.counter, count);
}
}
} else {
mutex_unlock(&s.mutex);
- #if runtime.Wait_Notify_Available {
- __atomic_wait(&s.counter, 0);
+ #if runtime.platform.Supports_Futexes {
+ runtime.platform.__futex_wait(&s.counter, 0, -1);
}
}
}
#include <netinet/in.h>
#include <sys/socket.h>
#include <sys/un.h>
+ #include <linux/futex.h>
+ #include <sys/syscall.h>
#include <poll.h>
#endif
ONYX_FUNC(__time)
ONYX_FUNC(__lookup_env)
ONYX_FUNC(__random_get)
+ ONYX_FUNC(__futex_wait)
+ ONYX_FUNC(__futex_wake)
ONYX_FUNC(__register_cleanup)
ONYX_FUNC(__net_create_socket)
}
+ONYX_DEF(__futex_wait, (WASM_PTR, WASM_I32, WASM_I32), (WASM_I32)) {
+ int *addr = ONYX_PTR(params->data[0].of.i32);
+
+ #ifdef _BH_LINUX
+ struct timespec delay;
+
+ struct timespec *t = NULL;
+ if (params->data[2].of.i32 >= 0) {
+ delay.tv_sec = params->data[2].of.i32 / 1000;
+ delay.tv_nsec = params->data[2].of.i32 * 1000000;
+ t = &delay;
+ }
+
+ int res = syscall(SYS_futex, addr, FUTEX_WAIT, params->data[1].of.i32, t, NULL, 0);
+
+ if (res == 0) {
+ if (*addr == params->data[1].of.i32) results->data[0] = WASM_I32_VAL(0);
+ else results->data[0] = WASM_I32_VAL(1);
+ }
+ if (res == -1) {
+ if (errno == EAGAIN) results->data[0] = WASM_I32_VAL(2);
+ else results->data[0] = WASM_I32_VAL(1);
+ }
+ #endif
+
+ #ifdef _BH_WINDOWS
+ results->data[0] = WaitOnAddress(addr, ¶ms->data[1].of.i32, 4, params->data[2].of.i32);
+ #endif
+
+ return NULL;
+}
+
+ONYX_DEF(__futex_wake, (WASM_PTR, WASM_I32), (WASM_I32)) {
+ int *addr = ONYX_PTR(params->data[0].of.i32);
+
+ #ifdef _BH_LINUX
+ int res = syscall(SYS_futex, addr, FUTEX_WAKE, params->data[1].of.i32, NULL, NULL, 0);
+
+ results->data[0] = WASM_I32_VAL(res);
+ #endif
+
+ #ifdef _BH_WINDOWS
+ for (int i=0; i<params->data[1].of.i32; i++) {
+ WakeByAddressSingle(addr);
+ }
+
+ results->data[0] = WASM_I32_VAL(params->data[1].of.i32);
+ #endif
+
+ return NULL;
+}
+
+
#ifdef _BH_LINUX
static wasm_func_t *wasm_cleanup_func;
BCRYPT_ALG_HANDLE hAlgorithm,
unsigned long dwFlags
);
+
+GB_DLL_IMPORT void WakeByAddressSingle(PVOID Address);
+GB_DLL_IMPORT BOOL WaitOnAddress(volatile PVOID Address, PVOID compareAddress, size_t addressSize, DWORD milliseconds);
+