diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-05-05 12:08:03 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-05-05 12:08:18 +0000 |
commit | 5da14042f70711ea5cf66e034699730335462f66 (patch) | |
tree | 0f6354ccac934ed87a2d555f45be4c831cf92f4a /src/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/windows | |
parent | Releasing debian version 1.44.3-2. (diff) | |
download | netdata-5da14042f70711ea5cf66e034699730335462f66.tar.xz netdata-5da14042f70711ea5cf66e034699730335462f66.zip |
Merging upstream version 1.45.3+dfsg.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'src/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/windows')
9 files changed, 1741 insertions, 0 deletions
diff --git a/src/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/windows/platform_init.c b/src/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/windows/platform_init.c new file mode 100644 index 000000000..db5885387 --- /dev/null +++ b/src/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/windows/platform_init.c @@ -0,0 +1,75 @@ +/* + * Copyright (C) 2019 Intel Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#include "platform_api_vmcore.h" + +int +os_thread_sys_init(); + +void +os_thread_sys_destroy(); + +int +init_winsock(); + +void +deinit_winsock(); + +int +bh_platform_init() +{ + if (init_winsock() != 0) { + return -1; + } + + return os_thread_sys_init(); +} + +void +bh_platform_destroy() +{ + deinit_winsock(); + + os_thread_sys_destroy(); +} + +int +os_printf(const char *format, ...) +{ + int ret = 0; + va_list ap; + + va_start(ap, format); +#ifndef BH_VPRINTF + ret += vprintf(format, ap); +#else + ret += BH_VPRINTF(format, ap); +#endif + va_end(ap); + + return ret; +} + +int +os_vprintf(const char *format, va_list ap) +{ +#ifndef BH_VPRINTF + return vprintf(format, ap); +#else + return BH_VPRINTF(format, ap); +#endif +} + +unsigned +os_getpagesize() +{ + SYSTEM_INFO sys_info; + GetNativeSystemInfo(&sys_info); + return (unsigned)sys_info.dwPageSize; +} + +void +os_dcache_flush(void) +{} diff --git a/src/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/windows/platform_internal.h b/src/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/windows/platform_internal.h new file mode 100644 index 000000000..500ab200c --- /dev/null +++ b/src/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/windows/platform_internal.h @@ -0,0 +1,138 @@ +/* + * Copyright (C) 2019 Intel Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#ifndef _PLATFORM_INTERNAL_H +#define _PLATFORM_INTERNAL_H + +#include <inttypes.h> +#include <stdbool.h> +#include <assert.h> +#include <time.h> +#include <sys/timeb.h> +#include <string.h> +#include <stdio.h> +#include <stdlib.h> +#include <math.h> +#include <stdarg.h> +#include <ctype.h> +#include <limits.h> +#include <fcntl.h> +#include <errno.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <stdint.h> +#include <malloc.h> +#include <process.h> +#include <winsock2.h> +#include <ws2tcpip.h> +#include <windows.h> +#include <basetsd.h> + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef BH_PLATFORM_WINDOWS +#define BH_PLATFORM_WINDOWS +#endif + +#ifdef _MSC_VER +#ifndef PATH_MAX +#define PATH_MAX MAX_PATH +#endif +#endif /* #ifdef _MSC_VER */ + +/* Stack size of applet threads's native part. */ +#define BH_APPLET_PRESERVED_STACK_SIZE (32 * 1024) + +/* Default thread priority */ +#define BH_THREAD_DEFAULT_PRIORITY 0 + +typedef SSIZE_T ssize_t; + +typedef void *korp_thread; +typedef void *korp_tid; +typedef void *korp_mutex; +typedef void *korp_sem; + +/** + * Create the mutex when os_mutex_lock is called, and no need to + * CloseHandle() for the static lock's lifetime, since + * "The system closes the handle automatically when the process + * terminates. The mutex object is destroyed when its last + * handle has been closed." + * Refer to: + * https://learn.microsoft.com/en-us/windows/win32/api/synchapi/nf-synchapi-createmutexa + */ +#define OS_THREAD_MUTEX_INITIALIZER NULL + +struct os_thread_wait_node; +typedef struct os_thread_wait_node *os_thread_wait_list; +typedef struct korp_cond { + korp_mutex wait_list_lock; + os_thread_wait_list thread_wait_list; + struct os_thread_wait_node *thread_wait_list_end; +} korp_cond; + +#define bh_socket_t SOCKET + +unsigned +os_getpagesize(); +void * +os_mem_commit(void *ptr, size_t size, int flags); +void +os_mem_decommit(void *ptr, size_t size); + +#define os_thread_local_attribute __declspec(thread) + +#define strncasecmp _strnicmp +#define strcasecmp _stricmp + +#if WASM_DISABLE_HW_BOUND_CHECK == 0 +#if defined(BUILD_TARGET_X86_64) || defined(BUILD_TARGET_AMD_64) + +#include <setjmp.h> + +#define OS_ENABLE_HW_BOUND_CHECK + +typedef jmp_buf korp_jmpbuf; + +#define os_setjmp setjmp +#define os_longjmp longjmp + +int +os_thread_signal_init(); + +void +os_thread_signal_destroy(); + +bool +os_thread_signal_inited(); + +#define os_signal_unmask() (void)0 +#define os_sigreturn() (void)0 + +#endif /* end of BUILD_TARGET_X86_64/AMD_64 */ +#endif /* end of WASM_DISABLE_HW_BOUND_CHECK */ + +typedef enum os_memory_order { + os_memory_order_relaxed, + os_memory_order_consume, + os_memory_order_acquire, + os_memory_order_release, + os_memory_order_acq_rel, + os_memory_order_seq_cst, +} os_memory_order; + +void +bh_atomic_thread_fence(int mem_order); + +#define os_atomic_thread_fence bh_atomic_thread_fence + +#ifdef __cplusplus +} +#endif + +#endif /* end of _PLATFORM_INTERNAL_H */ diff --git a/src/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/windows/shared_platform.cmake b/src/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/windows/shared_platform.cmake new file mode 100644 index 000000000..a68d63177 --- /dev/null +++ b/src/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/windows/shared_platform.cmake @@ -0,0 +1,19 @@ +# Copyright (C) 2019 Intel Corporation. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +set (PLATFORM_SHARED_DIR ${CMAKE_CURRENT_LIST_DIR}) + +add_definitions(-DBH_PLATFORM_WINDOWS) +add_definitions(-DHAVE_STRUCT_TIMESPEC) +add_definitions(-D_WINSOCK_DEPRECATED_NO_WARNINGS) + +include_directories(${PLATFORM_SHARED_DIR}) +include_directories(${PLATFORM_SHARED_DIR}/../include) + +file (GLOB_RECURSE source_all ${PLATFORM_SHARED_DIR}/*.c + ${PLATFORM_SHARED_DIR}/*.cpp) + +set (PLATFORM_SHARED_SOURCE ${source_all}) + +file (GLOB header ${PLATFORM_SHARED_DIR}/../include/*.h) +LIST (APPEND RUNTIME_LIB_HEADER_LIST ${header}) diff --git a/src/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/windows/win_atomic.cpp b/src/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/windows/win_atomic.cpp new file mode 100644 index 000000000..80e8ef518 --- /dev/null +++ b/src/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/windows/win_atomic.cpp @@ -0,0 +1,22 @@ +/* + * Copyright (C) 2023 Intel Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#include "platform_api_vmcore.h" +#include "platform_api_extension.h" + +#if WASM_ENABLE_SHARED_MEMORY != 0 + +#include <atomic> + +void +bh_atomic_thread_fence(int mem_order) +{ + std::memory_order order = + (std::memory_order)(std::memory_order::memory_order_relaxed + mem_order + - os_memory_order_relaxed); + std::atomic_thread_fence(order); +} + +#endif diff --git a/src/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/windows/win_malloc.c b/src/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/windows/win_malloc.c new file mode 100644 index 000000000..56aaf9c7b --- /dev/null +++ b/src/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/windows/win_malloc.c @@ -0,0 +1,30 @@ +/* + * Copyright (C) 2019 Intel Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#include "platform_api_vmcore.h" + +void * +os_malloc(unsigned size) +{ + return malloc(size); +} + +void * +os_realloc(void *ptr, unsigned size) +{ + return realloc(ptr, size); +} + +void +os_free(void *ptr) +{ + free(ptr); +} + +int +os_dumps_proc_mem_info(char *out, unsigned int size) +{ + return -1; +}
\ No newline at end of file diff --git a/src/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/windows/win_memmap.c b/src/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/windows/win_memmap.c new file mode 100644 index 000000000..c4a6b0756 --- /dev/null +++ b/src/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/windows/win_memmap.c @@ -0,0 +1,146 @@ +/* + * Copyright (C) 2019 Intel Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#include "platform_api_vmcore.h" + +#define TRACE_MEMMAP 0 + +static DWORD +access_to_win32_flags(int prot) +{ + DWORD protect = PAGE_NOACCESS; + + if (prot & MMAP_PROT_EXEC) { + if (prot & MMAP_PROT_WRITE) + protect = PAGE_EXECUTE_READWRITE; + else + protect = PAGE_EXECUTE_READ; + } + else if (prot & MMAP_PROT_WRITE) { + protect = PAGE_READWRITE; + } + else if (prot & MMAP_PROT_READ) { + protect = PAGE_READONLY; + } + + return protect; +} + +void * +os_mmap(void *hint, size_t size, int prot, int flags) +{ + DWORD alloc_type = MEM_RESERVE; + DWORD protect; + size_t request_size, page_size; + void *addr; + + page_size = os_getpagesize(); + request_size = (size + page_size - 1) & ~(page_size - 1); + + if (request_size < size) + /* integer overflow */ + return NULL; + +#if WASM_ENABLE_JIT != 0 + /** + * Allocate memory at the highest possible address if the + * request size is large, or LLVM JIT might report error: + * IMAGE_REL_AMD64_ADDR32NB relocation requires an ordered + * section layout. + */ + if (request_size > 10 * BH_MB) + alloc_type |= MEM_TOP_DOWN; +#endif + + protect = access_to_win32_flags(prot); + if (protect != PAGE_NOACCESS) { + alloc_type |= MEM_COMMIT; + } + + addr = VirtualAlloc((LPVOID)hint, request_size, alloc_type, protect); + +#if TRACE_MEMMAP != 0 + printf("Map memory, request_size: %zu, alloc_type: 0x%x, " + "protect: 0x%x, ret: %p\n", + request_size, alloc_type, protect, addr); +#endif + return addr; +} + +void +os_munmap(void *addr, size_t size) +{ + size_t page_size = os_getpagesize(); + size_t request_size = (size + page_size - 1) & ~(page_size - 1); + + if (addr) { + if (!VirtualFree(addr, request_size, MEM_DECOMMIT)) { + printf("warning: os_munmap decommit pages failed, " + "addr: %p, request_size: %zu, errno: %d\n", + addr, request_size, errno); + return; + } + + if (!VirtualFree(addr, 0, MEM_RELEASE)) { + printf("warning: os_munmap release pages failed, " + "addr: %p, size: %zu, errno:%d\n", + addr, request_size, errno); + } + } +#if TRACE_MEMMAP != 0 + printf("Unmap memory, addr: %p, request_size: %zu\n", addr, request_size); +#endif +} + +void * +os_mem_commit(void *addr, size_t size, int flags) +{ + DWORD protect = access_to_win32_flags(flags); + size_t page_size = os_getpagesize(); + size_t request_size = (size + page_size - 1) & ~(page_size - 1); + + if (!addr) + return NULL; + +#if TRACE_MEMMAP != 0 + printf("Commit memory, addr: %p, request_size: %zu, protect: 0x%x\n", addr, + request_size, protect); +#endif + return VirtualAlloc((LPVOID)addr, request_size, MEM_COMMIT, protect); +} + +void +os_mem_decommit(void *addr, size_t size) +{ + size_t page_size = os_getpagesize(); + size_t request_size = (size + page_size - 1) & ~(page_size - 1); + + if (!addr) + return; + +#if TRACE_MEMMAP != 0 + printf("Decommit memory, addr: %p, request_size: %zu\n", addr, + request_size); +#endif + VirtualFree((LPVOID)addr, request_size, MEM_DECOMMIT); +} + +int +os_mprotect(void *addr, size_t size, int prot) +{ + DWORD protect; + size_t page_size = os_getpagesize(); + size_t request_size = (size + page_size - 1) & ~(page_size - 1); + + if (!addr) + return 0; + + protect = access_to_win32_flags(prot); +#if TRACE_MEMMAP != 0 + printf("Mprotect memory, addr: %p, request_size: %zu, protect: 0x%x\n", + addr, request_size, protect); +#endif + return VirtualProtect((LPVOID)addr, request_size, protect, NULL); +} diff --git a/src/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/windows/win_socket.c b/src/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/windows/win_socket.c new file mode 100644 index 000000000..9a1c7a3c9 --- /dev/null +++ b/src/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/windows/win_socket.c @@ -0,0 +1,541 @@ +/* + * Copyright (C) 2021 Intel Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#include "platform_api_vmcore.h" +#include "platform_api_extension.h" + +/* link with Ws2_32.lib */ +#pragma comment(lib, "ws2_32.lib") + +static bool is_winsock_inited = false; + +int +init_winsock() +{ + WSADATA wsaData; + + if (!is_winsock_inited) { + if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0) { + os_printf("winsock init failed"); + return BHT_ERROR; + } + + is_winsock_inited = true; + } + + return BHT_OK; +} + +void +deinit_winsock() +{ + if (is_winsock_inited) { + WSACleanup(); + } +} + +int +os_socket_create(bh_socket_t *sock, bool is_ipv4, bool is_tcp) +{ + int af; + + if (!sock) { + return BHT_ERROR; + } + + if (is_ipv4) { + af = AF_INET; + } + else { + errno = ENOSYS; + return BHT_ERROR; + } + + if (is_tcp) { + *sock = socket(af, SOCK_STREAM, IPPROTO_TCP); + } + else { + *sock = socket(af, SOCK_DGRAM, 0); + } + + return (*sock == -1) ? BHT_ERROR : BHT_OK; +} + +int +os_socket_bind(bh_socket_t socket, const char *host, int *port) +{ + struct sockaddr_in addr; + int socklen, ret; + + assert(host); + assert(port); + + addr.sin_addr.s_addr = inet_addr(host); + addr.sin_port = htons(*port); + addr.sin_family = AF_INET; + + ret = bind(socket, (struct sockaddr *)&addr, sizeof(addr)); + if (ret < 0) { + goto fail; + } + + socklen = sizeof(addr); + if (getsockname(socket, (void *)&addr, &socklen) == -1) { + os_printf("getsockname failed with error %d\n", WSAGetLastError()); + goto fail; + } + + *port = ntohs(addr.sin_port); + + return BHT_OK; + +fail: + return BHT_ERROR; +} + +int +os_socket_settimeout(bh_socket_t socket, uint64 timeout_us) +{ + DWORD tv = (DWORD)(timeout_us / 1000UL); + + if (setsockopt(socket, SOL_SOCKET, SO_RCVTIMEO, (const char *)&tv, + sizeof(tv)) + != 0) { + return BHT_ERROR; + } + + return BHT_OK; +} + +int +os_socket_listen(bh_socket_t socket, int max_client) +{ + if (listen(socket, max_client) != 0) { + os_printf("socket listen failed with error %d\n", WSAGetLastError()); + return BHT_ERROR; + } + + return BHT_OK; +} + +int +os_socket_accept(bh_socket_t server_sock, bh_socket_t *sock, void *addr, + unsigned int *addrlen) +{ + struct sockaddr addr_tmp; + unsigned int len = sizeof(struct sockaddr); + + *sock = accept(server_sock, (struct sockaddr *)&addr_tmp, &len); + + if (*sock < 0) { + os_printf("socket accept failed with error %d\n", WSAGetLastError()); + return BHT_ERROR; + } + + return BHT_OK; +} + +int +os_socket_recv(bh_socket_t socket, void *buf, unsigned int len) +{ + return recv(socket, buf, len, 0); +} + +int +os_socket_recv_from(bh_socket_t socket, void *buf, unsigned int len, int flags, + bh_sockaddr_t *src_addr) +{ + errno = ENOSYS; + + return BHT_ERROR; +} + +int +os_socket_send(bh_socket_t socket, const void *buf, unsigned int len) +{ + return send(socket, buf, len, 0); +} + +int +os_socket_send_to(bh_socket_t socket, const void *buf, unsigned int len, + int flags, const bh_sockaddr_t *dest_addr) +{ + errno = ENOSYS; + + return BHT_ERROR; +} + +int +os_socket_close(bh_socket_t socket) +{ + closesocket(socket); + return BHT_OK; +} + +int +os_socket_shutdown(bh_socket_t socket) +{ + shutdown(socket, SD_BOTH); + return BHT_OK; +} + +int +os_socket_inet_network(bool is_ipv4, const char *cp, bh_ip_addr_buffer_t *out) +{ + if (!cp) + return BHT_ERROR; + + if (is_ipv4) { + if (inet_pton(AF_INET, cp, &out->ipv4) != 1) { + return BHT_ERROR; + } + /* Note: ntohl(INADDR_NONE) == INADDR_NONE */ + out->ipv4 = ntohl(out->ipv4); + } + else { + if (inet_pton(AF_INET6, cp, out->ipv6) != 1) { + return BHT_ERROR; + } + for (int i = 0; i < 8; i++) { + out->ipv6[i] = ntohs(out->ipv6[i]); + } + } + + return BHT_OK; +} + +int +os_socket_addr_resolve(const char *host, const char *service, + uint8_t *hint_is_tcp, uint8_t *hint_is_ipv4, + bh_addr_info_t *addr_info, size_t addr_info_size, + size_t *max_info_size) +{ + errno = ENOSYS; + + return BHT_ERROR; +} + +int +os_socket_addr_local(bh_socket_t socket, bh_sockaddr_t *sockaddr) +{ + errno = ENOSYS; + + return BHT_ERROR; +} + +int +os_socket_set_send_timeout(bh_socket_t socket, uint64 timeout_us) +{ + errno = ENOSYS; + + return BHT_ERROR; +} + +int +os_socket_get_send_timeout(bh_socket_t socket, uint64 *timeout_us) +{ + errno = ENOSYS; + + return BHT_ERROR; +} + +int +os_socket_set_recv_timeout(bh_socket_t socket, uint64 timeout_us) +{ + errno = ENOSYS; + + return BHT_ERROR; +} + +int +os_socket_get_recv_timeout(bh_socket_t socket, uint64 *timeout_us) +{ + errno = ENOSYS; + + return BHT_ERROR; +} + +int +os_socket_addr_remote(bh_socket_t socket, bh_sockaddr_t *sockaddr) +{ + errno = ENOSYS; + + return BHT_ERROR; +} + +int +os_socket_set_send_buf_size(bh_socket_t socket, size_t bufsiz) +{ + errno = ENOSYS; + + return BHT_ERROR; +} + +int +os_socket_get_send_buf_size(bh_socket_t socket, size_t *bufsiz) +{ + errno = ENOSYS; + + return BHT_ERROR; +} + +int +os_socket_set_recv_buf_size(bh_socket_t socket, size_t bufsiz) +{ + errno = ENOSYS; + + return BHT_ERROR; +} + +int +os_socket_get_recv_buf_size(bh_socket_t socket, size_t *bufsiz) +{ + errno = ENOSYS; + + return BHT_ERROR; +} + +int +os_socket_set_keep_alive(bh_socket_t socket, bool is_enabled) +{ + errno = ENOSYS; + + return BHT_ERROR; +} + +int +os_socket_get_keep_alive(bh_socket_t socket, bool *is_enabled) +{ + errno = ENOSYS; + + return BHT_ERROR; +} + +int +os_socket_set_reuse_addr(bh_socket_t socket, bool is_enabled) +{ + errno = ENOSYS; + + return BHT_ERROR; +} + +int +os_socket_get_reuse_addr(bh_socket_t socket, bool *is_enabled) +{ + errno = ENOSYS; + + return BHT_ERROR; +} + +int +os_socket_set_reuse_port(bh_socket_t socket, bool is_enabled) +{ + errno = ENOSYS; + + return BHT_ERROR; +} + +int +os_socket_get_reuse_port(bh_socket_t socket, bool *is_enabled) +{ + errno = ENOSYS; + + return BHT_ERROR; +} + +int +os_socket_set_linger(bh_socket_t socket, bool is_enabled, int linger_s) +{ + errno = ENOSYS; + + return BHT_ERROR; +} + +int +os_socket_get_linger(bh_socket_t socket, bool *is_enabled, int *linger_s) +{ + errno = ENOSYS; + + return BHT_ERROR; +} + +int +os_socket_set_tcp_no_delay(bh_socket_t socket, bool is_enabled) +{ + errno = ENOSYS; + + return BHT_ERROR; +} + +int +os_socket_get_tcp_no_delay(bh_socket_t socket, bool *is_enabled) +{ + errno = ENOSYS; + + return BHT_ERROR; +} + +int +os_socket_set_tcp_quick_ack(bh_socket_t socket, bool is_enabled) +{ + errno = ENOSYS; + + return BHT_ERROR; +} + +int +os_socket_get_tcp_quick_ack(bh_socket_t socket, bool *is_enabled) +{ + errno = ENOSYS; + + return BHT_ERROR; +} + +int +os_socket_set_tcp_keep_idle(bh_socket_t socket, uint32 time_s) +{ + errno = ENOSYS; + + return BHT_ERROR; +} + +int +os_socket_get_tcp_keep_idle(bh_socket_t socket, uint32 *time_s) +{ + errno = ENOSYS; + + return BHT_ERROR; +} + +int +os_socket_set_tcp_keep_intvl(bh_socket_t socket, uint32 time_s) +{ + errno = ENOSYS; + + return BHT_ERROR; +} + +int +os_socket_get_tcp_keep_intvl(bh_socket_t socket, uint32 *time_s) +{ + errno = ENOSYS; + + return BHT_ERROR; +} + +int +os_socket_set_tcp_fastopen_connect(bh_socket_t socket, bool is_enabled) +{ + errno = ENOSYS; + + return BHT_ERROR; +} + +int +os_socket_get_tcp_fastopen_connect(bh_socket_t socket, bool *is_enabled) +{ + errno = ENOSYS; + + return BHT_ERROR; +} + +int +os_socket_set_ip_multicast_loop(bh_socket_t socket, bool ipv6, bool is_enabled) +{ + errno = ENOSYS; + + return BHT_ERROR; +} + +int +os_socket_get_ip_multicast_loop(bh_socket_t socket, bool ipv6, bool *is_enabled) +{ + errno = ENOSYS; + + return BHT_ERROR; +} + +int +os_socket_set_ip_add_membership(bh_socket_t socket, + bh_ip_addr_buffer_t *imr_multiaddr, + uint32_t imr_interface, bool is_ipv6) +{ + errno = ENOSYS; + + return BHT_ERROR; +} + +int +os_socket_set_ip_drop_membership(bh_socket_t socket, + bh_ip_addr_buffer_t *imr_multiaddr, + uint32_t imr_interface, bool is_ipv6) +{ + errno = ENOSYS; + + return BHT_ERROR; +} + +int +os_socket_set_ip_ttl(bh_socket_t socket, uint8_t ttl_s) +{ + errno = ENOSYS; + + return BHT_ERROR; +} + +int +os_socket_get_ip_ttl(bh_socket_t socket, uint8_t *ttl_s) +{ + errno = ENOSYS; + + return BHT_ERROR; +} + +int +os_socket_set_ip_multicast_ttl(bh_socket_t socket, uint8_t ttl_s) +{ + errno = ENOSYS; + + return BHT_ERROR; +} + +int +os_socket_get_ip_multicast_ttl(bh_socket_t socket, uint8_t *ttl_s) +{ + errno = ENOSYS; + + return BHT_ERROR; +} + +int +os_socket_set_ipv6_only(bh_socket_t socket, bool option) +{ + errno = ENOSYS; + + return BHT_ERROR; +} + +int +os_socket_get_ipv6_only(bh_socket_t socket, bool *option) +{ + errno = ENOSYS; + + return BHT_ERROR; +} + +int +os_socket_set_broadcast(bh_socket_t socket, bool is_enabled) +{ + errno = ENOSYS; + + return BHT_ERROR; +} + +int +os_socket_get_broadcast(bh_socket_t socket, bool *is_enabled) +{ + errno = ENOSYS; + return BHT_ERROR; +} diff --git a/src/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/windows/win_thread.c b/src/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/windows/win_thread.c new file mode 100644 index 000000000..09cf0c63f --- /dev/null +++ b/src/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/windows/win_thread.c @@ -0,0 +1,750 @@ +/* + * Copyright (C) 2019 Intel Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#include "platform_api_vmcore.h" +#include "platform_api_extension.h" + +#define bh_assert(v) assert(v) + +#define BH_SEM_COUNT_MAX 0xFFFF + +struct os_thread_data; + +typedef struct os_thread_wait_node { + korp_sem sem; + void *retval; + os_thread_wait_list next; +} os_thread_wait_node; + +typedef struct os_thread_data { + /* Next thread data */ + struct os_thread_data *next; + /* Thread data of parent thread */ + struct os_thread_data *parent; + /* Thread Id */ + DWORD thread_id; + /* Thread start routine */ + thread_start_routine_t start_routine; + /* Thread start routine argument */ + void *arg; + /* Wait node of current thread */ + os_thread_wait_node wait_node; + /* Wait cond */ + korp_cond wait_cond; + /* Wait lock */ + korp_mutex wait_lock; + /* Waiting list of other threads who are joining this thread */ + os_thread_wait_list thread_wait_list; + /* End node of the waiting list */ + os_thread_wait_node *thread_wait_list_end; + /* Whether the thread has exited */ + bool thread_exited; + /* Thread return value */ + void *thread_retval; +} os_thread_data; + +static bool is_thread_sys_inited = false; + +/* Thread data of supervisor thread */ +static os_thread_data supervisor_thread_data; + +/* Thread data list lock */ +static korp_mutex thread_data_list_lock; + +/* Thread data key */ +static DWORD thread_data_key; + +/* The GetCurrentThreadStackLimits API from "kernel32" */ +static void(WINAPI *GetCurrentThreadStackLimits_Kernel32)(PULONG_PTR, + PULONG_PTR) = NULL; + +int +os_sem_init(korp_sem *sem); +int +os_sem_destroy(korp_sem *sem); +int +os_sem_wait(korp_sem *sem); +int +os_sem_reltimed_wait(korp_sem *sem, uint64 useconds); +int +os_sem_signal(korp_sem *sem); + +int +os_thread_sys_init() +{ + HMODULE module; + + if (is_thread_sys_inited) + return BHT_OK; + + if ((thread_data_key = TlsAlloc()) == TLS_OUT_OF_INDEXES) + return BHT_ERROR; + + /* Initialize supervisor thread data */ + memset(&supervisor_thread_data, 0, sizeof(os_thread_data)); + + supervisor_thread_data.thread_id = GetCurrentThreadId(); + + if (os_sem_init(&supervisor_thread_data.wait_node.sem) != BHT_OK) + goto fail1; + + if (os_mutex_init(&supervisor_thread_data.wait_lock) != BHT_OK) + goto fail2; + + if (os_cond_init(&supervisor_thread_data.wait_cond) != BHT_OK) + goto fail3; + + if (!TlsSetValue(thread_data_key, &supervisor_thread_data)) + goto fail4; + + if (os_mutex_init(&thread_data_list_lock) != BHT_OK) + goto fail5; + + if ((module = GetModuleHandle((LPCTSTR) "kernel32"))) { + *(void **)&GetCurrentThreadStackLimits_Kernel32 = + GetProcAddress(module, "GetCurrentThreadStackLimits"); + } + + is_thread_sys_inited = true; + return BHT_OK; + +fail5: + TlsSetValue(thread_data_key, NULL); +fail4: + os_cond_destroy(&supervisor_thread_data.wait_cond); +fail3: + os_mutex_destroy(&supervisor_thread_data.wait_lock); +fail2: + os_sem_destroy(&supervisor_thread_data.wait_node.sem); +fail1: + TlsFree(thread_data_key); + return BHT_ERROR; +} + +void +os_thread_sys_destroy() +{ + if (is_thread_sys_inited) { + os_thread_data *thread_data, *thread_data_next; + + thread_data = supervisor_thread_data.next; + while (thread_data) { + thread_data_next = thread_data->next; + + /* Destroy resources of thread data */ + os_cond_destroy(&thread_data->wait_cond); + os_sem_destroy(&thread_data->wait_node.sem); + os_mutex_destroy(&thread_data->wait_lock); + BH_FREE(thread_data); + + thread_data = thread_data_next; + } + + os_mutex_destroy(&thread_data_list_lock); + os_cond_destroy(&supervisor_thread_data.wait_cond); + os_mutex_destroy(&supervisor_thread_data.wait_lock); + os_sem_destroy(&supervisor_thread_data.wait_node.sem); + memset(&supervisor_thread_data, 0, sizeof(os_thread_data)); + TlsFree(thread_data_key); + thread_data_key = 0; + is_thread_sys_inited = false; + } +} + +static os_thread_data * +thread_data_current() +{ + return (os_thread_data *)TlsGetValue(thread_data_key); +} + +static void +os_thread_cleanup(void *retval) +{ + os_thread_data *thread_data = thread_data_current(); + + bh_assert(thread_data != NULL); + + os_mutex_lock(&thread_data->wait_lock); + if (thread_data->thread_wait_list) { + /* Signal each joining thread */ + os_thread_wait_list head = thread_data->thread_wait_list; + while (head) { + os_thread_wait_list next = head->next; + head->retval = retval; + os_sem_signal(&head->sem); + head = next; + } + thread_data->thread_wait_list = thread_data->thread_wait_list_end = + NULL; + } + /* Set thread status and thread return value */ + thread_data->thread_exited = true; + thread_data->thread_retval = retval; + os_mutex_unlock(&thread_data->wait_lock); +} + +static unsigned __stdcall os_thread_wrapper(void *arg) +{ + os_thread_data *thread_data = arg; + os_thread_data *parent = thread_data->parent; + void *retval; + bool result; + +#if 0 + os_printf("THREAD CREATED %p\n", thread_data); +#endif + + os_mutex_lock(&parent->wait_lock); + thread_data->thread_id = GetCurrentThreadId(); + result = TlsSetValue(thread_data_key, thread_data); +#ifdef OS_ENABLE_HW_BOUND_CHECK + if (result) + result = os_thread_signal_init() == 0 ? true : false; +#endif + /* Notify parent thread */ + os_cond_signal(&parent->wait_cond); + os_mutex_unlock(&parent->wait_lock); + + if (!result) + return -1; + + retval = thread_data->start_routine(thread_data->arg); + + os_thread_cleanup(retval); + return 0; +} + +int +os_thread_create_with_prio(korp_tid *p_tid, thread_start_routine_t start, + void *arg, unsigned int stack_size, int prio) +{ + os_thread_data *parent = thread_data_current(); + os_thread_data *thread_data; + + if (!p_tid || !start) + return BHT_ERROR; + + if (stack_size < BH_APPLET_PRESERVED_STACK_SIZE) + stack_size = BH_APPLET_PRESERVED_STACK_SIZE; + + if (!(thread_data = BH_MALLOC(sizeof(os_thread_data)))) + return BHT_ERROR; + + memset(thread_data, 0, sizeof(os_thread_data)); + thread_data->parent = parent; + thread_data->start_routine = start; + thread_data->arg = arg; + + if (os_sem_init(&thread_data->wait_node.sem) != BHT_OK) + goto fail1; + + if (os_mutex_init(&thread_data->wait_lock) != BHT_OK) + goto fail2; + + if (os_cond_init(&thread_data->wait_cond) != BHT_OK) + goto fail3; + + os_mutex_lock(&parent->wait_lock); + if (!_beginthreadex(NULL, stack_size, os_thread_wrapper, thread_data, 0, + NULL)) { + os_mutex_unlock(&parent->wait_lock); + goto fail4; + } + + /* Add thread data into thread data list */ + os_mutex_lock(&thread_data_list_lock); + thread_data->next = supervisor_thread_data.next; + supervisor_thread_data.next = thread_data; + os_mutex_unlock(&thread_data_list_lock); + + /* Wait for the thread routine to set thread_data's tid + and add thread_data to thread data list */ + os_cond_wait(&parent->wait_cond, &parent->wait_lock); + os_mutex_unlock(&parent->wait_lock); + + *p_tid = (korp_tid)thread_data; + return BHT_OK; + +fail4: + os_cond_destroy(&thread_data->wait_cond); +fail3: + os_mutex_destroy(&thread_data->wait_lock); +fail2: + os_sem_destroy(&thread_data->wait_node.sem); +fail1: + BH_FREE(thread_data); + return BHT_ERROR; +} + +int +os_thread_create(korp_tid *tid, thread_start_routine_t start, void *arg, + unsigned int stack_size) +{ + return os_thread_create_with_prio(tid, start, arg, stack_size, + BH_THREAD_DEFAULT_PRIORITY); +} + +korp_tid +os_self_thread() +{ + return (korp_tid)TlsGetValue(thread_data_key); +} + +int +os_thread_join(korp_tid thread, void **p_retval) +{ + os_thread_data *thread_data, *curr_thread_data; + + /* Get thread data of current thread */ + curr_thread_data = thread_data_current(); + curr_thread_data->wait_node.next = NULL; + + /* Get thread data of thread to join */ + thread_data = (os_thread_data *)thread; + bh_assert(thread_data); + + os_mutex_lock(&thread_data->wait_lock); + + if (thread_data->thread_exited) { + /* Thread has exited */ + if (p_retval) + *p_retval = thread_data->thread_retval; + os_mutex_unlock(&thread_data->wait_lock); + return BHT_OK; + } + + /* Thread is running */ + if (!thread_data->thread_wait_list) { /* Waiting list is empty */ + thread_data->thread_wait_list = thread_data->thread_wait_list_end = + &curr_thread_data->wait_node; + } + else { /* Waiting list isn't empty */ + /* Add to end of waiting list */ + thread_data->thread_wait_list_end->next = &curr_thread_data->wait_node; + thread_data->thread_wait_list_end = &curr_thread_data->wait_node; + } + + os_mutex_unlock(&thread_data->wait_lock); + + /* Wait the sem */ + os_sem_wait(&curr_thread_data->wait_node.sem); + if (p_retval) + *p_retval = curr_thread_data->wait_node.retval; + return BHT_OK; +} + +int +os_thread_detach(korp_tid thread) +{ + /* Do nothing */ + return BHT_OK; + (void)thread; +} + +void +os_thread_exit(void *retval) +{ + os_thread_cleanup(retval); + _endthreadex(0); +} + +int +os_thread_env_init() +{ + os_thread_data *thread_data = TlsGetValue(thread_data_key); + + if (thread_data) + /* Already created */ + return BHT_OK; + + if (!(thread_data = BH_MALLOC(sizeof(os_thread_data)))) + return BHT_ERROR; + + memset(thread_data, 0, sizeof(os_thread_data)); + thread_data->thread_id = GetCurrentThreadId(); + + if (os_sem_init(&thread_data->wait_node.sem) != BHT_OK) + goto fail1; + + if (os_mutex_init(&thread_data->wait_lock) != BHT_OK) + goto fail2; + + if (os_cond_init(&thread_data->wait_cond) != BHT_OK) + goto fail3; + + if (!TlsSetValue(thread_data_key, thread_data)) + goto fail4; + + return BHT_OK; + +fail4: + os_cond_destroy(&thread_data->wait_cond); +fail3: + os_mutex_destroy(&thread_data->wait_lock); +fail2: + os_sem_destroy(&thread_data->wait_node.sem); +fail1: + BH_FREE(thread_data); + return BHT_ERROR; +} + +void +os_thread_env_destroy() +{ + os_thread_data *thread_data = TlsGetValue(thread_data_key); + + /* Note that supervisor_thread_data's resources will be destroyed + by os_thread_sys_destroy() */ + if (thread_data && thread_data != &supervisor_thread_data) { + TlsSetValue(thread_data_key, NULL); + os_cond_destroy(&thread_data->wait_cond); + os_mutex_destroy(&thread_data->wait_lock); + os_sem_destroy(&thread_data->wait_node.sem); + BH_FREE(thread_data); + } +} + +bool +os_thread_env_inited() +{ + os_thread_data *thread_data = TlsGetValue(thread_data_key); + return thread_data ? true : false; +} + +int +os_sem_init(korp_sem *sem) +{ + bh_assert(sem); + *sem = CreateSemaphore(NULL, 0, BH_SEM_COUNT_MAX, NULL); + return (*sem != NULL) ? BHT_OK : BHT_ERROR; +} + +int +os_sem_destroy(korp_sem *sem) +{ + bh_assert(sem); + CloseHandle(*sem); + return BHT_OK; +} + +int +os_sem_wait(korp_sem *sem) +{ + DWORD ret; + + bh_assert(sem); + + ret = WaitForSingleObject(*sem, INFINITE); + + if (ret == WAIT_OBJECT_0) + return BHT_OK; + else if (ret == WAIT_TIMEOUT) + return (int)WAIT_TIMEOUT; + else /* WAIT_FAILED or others */ + return BHT_ERROR; +} + +int +os_sem_reltimed_wait(korp_sem *sem, uint64 useconds) +{ + uint64 mseconds_64; + DWORD ret, mseconds; + + bh_assert(sem); + + if (useconds == BHT_WAIT_FOREVER) + mseconds = INFINITE; + else { + mseconds_64 = useconds / 1000; + + if (mseconds_64 < (uint64)(UINT32_MAX - 1)) { + mseconds = (uint32)mseconds_64; + } + else { + mseconds = UINT32_MAX - 1; + os_printf("Warning: os_sem_reltimed_wait exceeds limit, " + "set to max timeout instead\n"); + } + } + + ret = WaitForSingleObject(*sem, mseconds); + + if (ret == WAIT_OBJECT_0) + return BHT_OK; + else if (ret == WAIT_TIMEOUT) + return (int)WAIT_TIMEOUT; + else /* WAIT_FAILED or others */ + return BHT_ERROR; +} + +int +os_sem_signal(korp_sem *sem) +{ + bh_assert(sem); + return ReleaseSemaphore(*sem, 1, NULL) != FALSE ? BHT_OK : BHT_ERROR; +} + +int +os_mutex_init(korp_mutex *mutex) +{ + bh_assert(mutex); + *mutex = CreateMutex(NULL, FALSE, NULL); + return (*mutex != NULL) ? BHT_OK : BHT_ERROR; +} + +int +os_recursive_mutex_init(korp_mutex *mutex) +{ + bh_assert(mutex); + *mutex = CreateMutex(NULL, FALSE, NULL); + return (*mutex != NULL) ? BHT_OK : BHT_ERROR; +} + +int +os_mutex_destroy(korp_mutex *mutex) +{ + assert(mutex); + return CloseHandle(*mutex) ? BHT_OK : BHT_ERROR; +} + +int +os_mutex_lock(korp_mutex *mutex) +{ + int ret; + + assert(mutex); + + if (*mutex == NULL) { /* static initializer? */ + HANDLE p = CreateMutex(NULL, FALSE, NULL); + + if (!p) { + return BHT_ERROR; + } + + if (InterlockedCompareExchangePointer((PVOID *)mutex, (PVOID)p, NULL) + != NULL) { + /* lock has been created by other threads */ + CloseHandle(p); + } + } + + ret = WaitForSingleObject(*mutex, INFINITE); + return ret != WAIT_FAILED ? BHT_OK : BHT_ERROR; +} + +int +os_mutex_unlock(korp_mutex *mutex) +{ + bh_assert(mutex); + return ReleaseMutex(*mutex) ? BHT_OK : BHT_ERROR; +} + +int +os_cond_init(korp_cond *cond) +{ + bh_assert(cond); + if (os_mutex_init(&cond->wait_list_lock) != BHT_OK) + return BHT_ERROR; + + cond->thread_wait_list = cond->thread_wait_list_end = NULL; + return BHT_OK; +} + +int +os_cond_destroy(korp_cond *cond) +{ + bh_assert(cond); + os_mutex_destroy(&cond->wait_list_lock); + return BHT_OK; +} + +static int +os_cond_wait_internal(korp_cond *cond, korp_mutex *mutex, bool timed, + uint64 useconds) +{ + os_thread_wait_node *node = &thread_data_current()->wait_node; + + node->next = NULL; + + bh_assert(cond); + bh_assert(mutex); + os_mutex_lock(&cond->wait_list_lock); + if (!cond->thread_wait_list) { /* Waiting list is empty */ + cond->thread_wait_list = cond->thread_wait_list_end = node; + } + else { /* Waiting list isn't empty */ + /* Add to end of wait list */ + cond->thread_wait_list_end->next = node; + cond->thread_wait_list_end = node; + } + os_mutex_unlock(&cond->wait_list_lock); + + /* Unlock mutex, wait sem and lock mutex again */ + os_mutex_unlock(mutex); + int wait_result; + if (timed) + wait_result = os_sem_reltimed_wait(&node->sem, useconds); + else + wait_result = os_sem_wait(&node->sem); + os_mutex_lock(mutex); + + /* Remove wait node from wait list */ + os_mutex_lock(&cond->wait_list_lock); + if (cond->thread_wait_list == node) { + cond->thread_wait_list = node->next; + + if (cond->thread_wait_list_end == node) { + bh_assert(node->next == NULL); + cond->thread_wait_list_end = NULL; + } + } + else { + /* Remove from the wait list */ + os_thread_wait_node *p = cond->thread_wait_list; + while (p->next != node) + p = p->next; + p->next = node->next; + + if (cond->thread_wait_list_end == node) { + cond->thread_wait_list_end = p; + } + } + os_mutex_unlock(&cond->wait_list_lock); + + return wait_result; +} + +int +os_cond_wait(korp_cond *cond, korp_mutex *mutex) +{ + return os_cond_wait_internal(cond, mutex, false, 0); +} + +int +os_cond_reltimedwait(korp_cond *cond, korp_mutex *mutex, uint64 useconds) +{ + if (useconds == BHT_WAIT_FOREVER) { + return os_cond_wait_internal(cond, mutex, false, 0); + } + else { + return os_cond_wait_internal(cond, mutex, true, useconds); + } +} + +int +os_cond_signal(korp_cond *cond) +{ + /* Signal the head wait node of wait list */ + os_mutex_lock(&cond->wait_list_lock); + if (cond->thread_wait_list) + os_sem_signal(&cond->thread_wait_list->sem); + os_mutex_unlock(&cond->wait_list_lock); + + return BHT_OK; +} + +int +os_cond_broadcast(korp_cond *cond) +{ + /* Signal all of the wait node of wait list */ + os_mutex_lock(&cond->wait_list_lock); + if (cond->thread_wait_list) { + os_thread_wait_node *p = cond->thread_wait_list; + while (p) { + os_sem_signal(&p->sem); + p = p->next; + } + } + + os_mutex_unlock(&cond->wait_list_lock); + + return BHT_OK; +} + +static os_thread_local_attribute uint8 *thread_stack_boundary = NULL; + +static ULONG +GetCurrentThreadStackLimits_Win7(PULONG_PTR p_low_limit, + PULONG_PTR p_high_limit) +{ + MEMORY_BASIC_INFORMATION mbi; + NT_TIB *tib = (NT_TIB *)NtCurrentTeb(); + + if (!tib) { + os_printf("warning: NtCurrentTeb() failed\n"); + return -1; + } + + *p_high_limit = (ULONG_PTR)tib->StackBase; + + if (VirtualQuery(tib->StackLimit, &mbi, sizeof(mbi))) { + *p_low_limit = (ULONG_PTR)mbi.AllocationBase; + return 0; + } + + os_printf("warning: VirtualQuery() failed\n"); + return GetLastError(); +} + +uint8 * +os_thread_get_stack_boundary() +{ + ULONG_PTR low_limit = 0, high_limit = 0; + uint32 page_size; + + if (thread_stack_boundary) + return thread_stack_boundary; + + page_size = os_getpagesize(); + if (GetCurrentThreadStackLimits_Kernel32) { + GetCurrentThreadStackLimits_Kernel32(&low_limit, &high_limit); + } + else { + if (0 != GetCurrentThreadStackLimits_Win7(&low_limit, &high_limit)) + return NULL; + } + + /* 4 pages are set unaccessible by system, we reserved + one more page at least for safety */ + thread_stack_boundary = (uint8 *)(uintptr_t)low_limit + page_size * 5; + return thread_stack_boundary; +} + +#ifdef OS_ENABLE_HW_BOUND_CHECK +static os_thread_local_attribute bool thread_signal_inited = false; + +int +os_thread_signal_init() +{ +#if WASM_DISABLE_STACK_HW_BOUND_CHECK == 0 + ULONG StackSizeInBytes = 16 * 1024; +#endif + bool ret; + + if (thread_signal_inited) + return 0; + +#if WASM_DISABLE_STACK_HW_BOUND_CHECK == 0 + ret = SetThreadStackGuarantee(&StackSizeInBytes); +#else + ret = true; +#endif + if (ret) + thread_signal_inited = true; + return ret ? 0 : -1; +} + +void +os_thread_signal_destroy() +{ + /* Do nothing */ +} + +bool +os_thread_signal_inited() +{ + return thread_signal_inited; +} +#endif diff --git a/src/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/windows/win_time.c b/src/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/windows/win_time.c new file mode 100644 index 000000000..20e90d5eb --- /dev/null +++ b/src/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/shared/platform/windows/win_time.c @@ -0,0 +1,20 @@ +/* + * Copyright (C) 2019 Intel Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#include "platform_api_vmcore.h" + +uint64 +os_time_get_boot_microsecond() +{ + struct timespec ts; +#if defined(__MINGW32__) + // https://www.mail-archive.com/mingw-w64-public@lists.sourceforge.net/msg18361.html + clock_gettime(CLOCK_REALTIME, &ts); +#else + timespec_get(&ts, TIME_UTC); +#endif + + return ((uint64)ts.tv_sec) * 1000 * 1000 + ((uint64)ts.tv_nsec) / 1000; +} |