Просмотр исходного кода

Support more features for rt-thread (#3661)

1, enable thread mgr
2, enable libc wasi
3, enable libc wasi threads
4, specify a function name of the module to run rather main
dongsheng28849455 1 год назад
Родитель
Сommit
6e727dc18d

+ 2 - 1
.gitignore

@@ -12,6 +12,7 @@
 *.so
 .clangd
 .DS_Store
+*.o
 
 core/deps/**
 core/shared/mem-alloc/tlsf
@@ -37,4 +38,4 @@ tests/benchmarks/coremark/coremark*
 samples/workload/include/**
 !samples/workload/include/.gitkeep
 
-# core/iwasm/libraries/wasi-threads
+# core/iwasm/libraries/wasi-threads

+ 6 - 1
build-scripts/SConscript

@@ -31,9 +31,11 @@ if GetDepend(['WAMR_BUILD_LIBC_BUILTIN']):
 
 if GetDepend(['WAMR_BUILD_LIBC_WASI']):
     objs += SConscript(os.path.join(IWASM_DIR, 'libraries', 'libc-wasi', 'SConscript'))
+    objs += SConscript(os.path.join(SHARED_DIR, 'platform', 'common', 'posix', 'SConscript'))
+    objs += SConscript(os.path.join(SHARED_DIR, 'platform', 'common', 'libc-util', 'SConscript'))
 
 if GetDepend(['WAMR_BUILD_LIB_PTHREAD']):
-    objs += SConscript(os.path.join(IWASM_DIR, 'libraries', 'libc-pthread', 'SConscript'))
+    objs += SConscript(os.path.join(IWASM_DIR, 'libraries', 'lib-pthread', 'SConscript'))
 
 if GetDepend(['WAMR_BUILD_THREAD_MGR']):
     objs += SConscript(os.path.join(IWASM_DIR, 'libraries', 'thread-mgr', 'SConscript'))
@@ -41,6 +43,9 @@ if GetDepend(['WAMR_BUILD_THREAD_MGR']):
 if GetDepend(['WAMR_BUILD_LIBC_EMCC']):
     objs += SConscript(os.path.join(IWASM_DIR, 'libraries', 'libc-emmc', 'SConscript'))
 
+if GetDepend(['WAMR_BUILD_LIB_WASI_THREADS']):
+    objs += SConscript(os.path.join(IWASM_DIR, 'libraries', 'lib-wasi-threads', 'SConscript'))
+
 objs += SConscript(os.path.join(cwd, 'SConscript_config'));
 
 objs += SConscript(os.path.join(SHARED_DIR, 'platform', 'rt-thread', 'SConscript'))

+ 21 - 1
build-scripts/SConscript_config

@@ -109,7 +109,27 @@ if GetDepend(['WAMR_BUILD_CUSTOM_NAME_SECTION']):
 
 if GetDepend(['WAMR_BUILD_TAIL_CALL']):
     CPPDEFINES += ['WASM_ENABLE_TAIL_CALL=1']
-    print('[WAMR] Tail call enabledd')
+    print('[WAMR] Tail call enabled')
+
+if GetDepend(['WAMR_BUILD_THREAD_MGR']):
+    CPPDEFINES += ['WASM_ENABLE_THREAD_MGR=1']
+    print('[WAMR] Thread manager enabled')
+
+if GetDepend(['WAMR_BUILD_LIBC_WASI']):
+    CPPDEFINES += ['WASM_ENABLE_LIBC_WASI=1']
+    CPPDEFINES += ['WASM_ENABLE_MODULE_INST_CONTEXT=1']
+    print('[WAMR] Libc wasi enabled')
+
+if GetDepend(['WAMR_BUILD_LIB_WASI_THREADS']):
+    CPPDEFINES += ['WASM_ENABLE_LIB_WASI_THREADS=1']
+    print('[WAMR] Lib wasi threads enabled')
+
+if GetDepend(['WAMR_BUILD_REF_TYPES']):
+    CPPDEFINES += ['WASM_ENABLE_REF_TYPES=1']
+    print('[WAMR] enable ref types')
+
+CPPDEFINES += ['BH_MALLOC=wasm_runtime_malloc']
+CPPDEFINES += ['BH_FREE=wasm_runtime_free']
 
 LIBS = ['m']
 

+ 2 - 2
core/iwasm/libraries/lib-pthread/SConscript

@@ -9,12 +9,12 @@ from building import *
 cwd     = GetCurrentDir()
 
 src = Split('''
-libc_pthread_wrapper.c
+lib_pthread_wrapper.c
 ''')
 
 CPPPATH = [cwd]
 
 
-group = DefineGroup('iwasm_libc_pthread', src, depend = [''], CPPPATH = CPPPATH)
+group = DefineGroup('iwasm_lib_pthread', src, depend = [''], CPPPATH = CPPPATH)
 
 Return('group')

+ 15 - 0
core/iwasm/libraries/lib-wasi-threads/SConscript

@@ -0,0 +1,15 @@
+#
+# Copyright 2024 Sony Semiconductor Solutions Corporation.
+#
+# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+#
+
+from building import *
+
+cwd     = GetCurrentDir()
+src     = Glob('*.c')
+CPPPATH = [cwd]
+
+group = DefineGroup('iwasm_lib_wasi_threads', src, depend = [''], CPPPATH = CPPPATH)
+
+Return('group')

+ 20 - 0
core/shared/platform/common/libc-util/SConscript

@@ -0,0 +1,20 @@
+#
+# Copyright 2024 Sony Semiconductor Solutions Corporation.
+#
+# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+#
+
+from building import *
+import re
+
+Import('rtconfig')
+
+cwd     = GetCurrentDir()
+src     = Split('''
+libc_errno.c
+''')
+CPPPATH = [cwd]
+
+group = DefineGroup('iwasm_libc_util', src, depend = [''], CPPPATH = CPPPATH)
+
+Return('group')

+ 20 - 0
core/shared/platform/common/posix/SConscript

@@ -0,0 +1,20 @@
+#
+# Copyright 2024 Sony Semiconductor Solutions Corporation.
+#
+# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+#
+
+from building import *
+import re
+
+Import('rtconfig')
+
+cwd     = GetCurrentDir()
+src     = Split('''
+posix_file.c
+''')
+CPPPATH = [cwd]
+
+group = DefineGroup('iwasm_common_posix', src, depend = [''], CPPPATH = CPPPATH)
+
+Return('group')

+ 1 - 1
core/shared/platform/common/posix/posix_file.c

@@ -26,7 +26,7 @@
  * (platform_internal.h)
  */
 #if !defined(CONFIG_HAS_D_INO)
-#if !defined(__NuttX__)
+#if !defined(__NuttX__) && !defined(__RTTHREAD__)
 #define CONFIG_HAS_D_INO 1
 #define CONFIG_HAS_ISATTY 1
 #else

+ 3 - 1
core/shared/platform/common/posix/posix_thread.c

@@ -4,8 +4,10 @@
  */
 
 #ifndef _GNU_SOURCE
+#if !defined(__RTTHREAD__)
 #define _GNU_SOURCE
 #endif
+#endif
 #include "platform_api_vmcore.h"
 #include "platform_api_extension.h"
 
@@ -448,7 +450,7 @@ os_thread_get_stack_boundary()
         addr += guard_size;
     }
     (void)stack_size;
-#elif defined(__APPLE__) || defined(__NuttX__)
+#elif defined(__APPLE__) || defined(__NuttX__) || defined(__RTTHREAD__)
     if ((addr = (uint8 *)pthread_get_stackaddr_np(self))) {
         stack_size = pthread_get_stacksize_np(self);
 

+ 66 - 0
core/shared/platform/rt-thread/platform_internal.h

@@ -7,7 +7,16 @@
 #ifndef RTTHREAD_PLATFORM_INTERNAL_H
 #define RTTHREAD_PLATFORM_INTERNAL_H
 
+#include <sys/ioctl.h>
+#include <fcntl.h>
+#include <limits.h>
+#include <errno.h>
+#include <poll.h>
+#if defined(RT_USING_PTHREADS)
+#include <pthread.h>
+#else
 #include <rtthread.h>
+#endif
 #include <stdbool.h>
 #include <string.h>
 #include <stdio.h>
@@ -15,6 +24,8 @@
 #include <math.h>
 #include <stdint.h>
 #include <ctype.h>
+#include <dirent.h>
+#include <assert.h>
 
 #if defined(WASM_ENABLE_AOT)
 #if defined(RTT_WAMR_BUILD_TARGET_THUMB)
@@ -32,12 +43,67 @@
 #endif
 #endif /* WASM_ENABLE_AOT */
 
+/* Use rt-thread's definition as default */
+#if 0 // defined(RT_USING_PTHREADS)
+typedef pthread_t korp_tid;
+typedef pthread_mutex_t korp_mutex;
+typedef pthread_cond_t korp_cond;
+typedef pthread_t korp_thread;
+#else
 typedef rt_thread_t korp_tid;
 typedef struct rt_mutex korp_mutex;
 typedef struct rt_thread korp_cond;
 typedef struct rt_thread korp_thread;
+#endif
 typedef unsigned int korp_sem;
 
+#if !defined(socklen_t) && !defined(SOCKLEN_T_DEFINED)
+typedef uint32_t socklen_t;
+#endif
+
+#if !defined(SOL_SOCKET)
+#define SOL_SOCKET 1
+#endif
+
+#if !defined(SO_TYPE)
+#define SO_TYPE 3
+#endif
+
+#if !defined(SOCK_DGRAM)
+#define SOCK_DGRAM 2
+#endif
+
+#if !defined(SOCK_STREAM)
+#define SOCK_STREAM 1
+#endif
+
+#if !defined(UTIME_NOW)
+#define UTIME_NOW -2L
+#endif
+
+#if !defined(UTIME_OMIT)
+#define UTIME_OMIT -1L
+#endif
+
+#if !defined(AT_SYMLINK_NOFOLLOW)
+#define AT_SYMLINK_NOFOLLOW 2
+#endif
+
+#if !defined(AT_SYMLINK_FOLLOW)
+#define AT_SYMLINK_FOLLOW 4
+#endif
+
+#if !defined(AT_REMOVEDIR)
+#define AT_REMOVEDIR 8
+#endif
+
+#define DT_BLK 0x06
+#define DT_CHR 0x02
+#define DT_LNK 0x0A
+
+#define PTHREAD_STACK_MIN 1024
+#define BH_THREAD_DEFAULT_PRIORITY 30
+
 /* korp_rwlock is used in platform_api_extension.h,
    we just define the type to make the compiler happy */
 typedef struct {

+ 194 - 0
core/shared/platform/rt-thread/rtt_file.c

@@ -0,0 +1,194 @@
+/*
+ * Copyright 2024 Sony Semiconductor Solutions Corporation.
+ *
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#include "platform_api_vmcore.h"
+#include "platform_api_extension.h"
+
+#include <errno.h>
+#include <stdio.h>
+#include <stddef.h>
+#include <fcntl.h>
+#include <stdint.h>
+
+struct iovec {
+    void *iov_base;
+    size_t iov_len;
+};
+
+ssize_t
+readv(int fd, const struct iovec *iov, int iovcnt)
+{
+    ssize_t ntotal;
+    ssize_t nread;
+    size_t remaining;
+    uint8_t *buffer;
+    int i;
+
+    /* Process each entry in the struct iovec array */
+
+    for (i = 0, ntotal = 0; i < iovcnt; i++) {
+        /* Ignore zero-length reads */
+
+        if (iov[i].iov_len > 0) {
+            buffer = iov[i].iov_base;
+            remaining = iov[i].iov_len;
+
+            /* Read repeatedly as necessary to fill buffer */
+
+            do {
+                /* NOTE:  read() is a cancellation point */
+
+                nread = read(fd, buffer, remaining);
+
+                /* Check for a read error */
+
+                if (nread < 0) {
+                    return nread;
+                }
+
+                /* Check for an end-of-file condition */
+
+                else if (nread == 0) {
+                    return ntotal;
+                }
+
+                /* Update pointers and counts in order to handle partial
+                 * buffer reads.
+                 */
+
+                buffer += nread;
+                remaining -= nread;
+                ntotal += nread;
+            } while (remaining > 0);
+        }
+    }
+
+    return ntotal;
+}
+
+ssize_t
+writev(int fd, const struct iovec *iov, int iovcnt)
+{
+    uint16_t i, num;
+    int length;
+
+    num = 0;
+    for (i = 0; i < iovcnt; i++) {
+        if (iov[i].iov_len > 0) {
+            length = write(fd, iov[i].iov_base, iov[i].iov_len);
+            if (length != iov[i].iov_len)
+                return errno;
+
+            num += iov[i].iov_len;
+        }
+    }
+    return num;
+}
+
+int
+fstatat(int fd, const char *path, struct stat *buf, int flag)
+{
+    errno = ENOSYS;
+    return -1;
+}
+
+int
+mkdirat(int fd, const char *path, mode_t mode)
+{
+    errno = ENOSYS;
+    return -1;
+}
+
+ssize_t
+readlinkat(int fd, const char *path, char *buf, size_t bufsize)
+{
+    errno = EINVAL;
+    return -1;
+}
+
+int
+linkat(int fd1, const char *path1, int fd2, const char *path2, int flag)
+{
+    errno = ENOSYS;
+    return -1;
+}
+
+int
+renameat(int fromfd, const char *from, int tofd, const char *to)
+{
+    errno = ENOSYS;
+    return -1;
+}
+
+int
+symlinkat(const char *target, int fd, const char *path)
+{
+    errno = ENOSYS;
+    return -1;
+}
+
+int
+unlinkat(int fd, const char *path, int flag)
+{
+    errno = ENOSYS;
+    return -1;
+}
+
+int
+utimensat(int fd, const char *path, const struct timespec *ts, int flag)
+{
+    errno = ENOSYS;
+    return -1;
+}
+
+DIR *
+fdopendir(int fd)
+{
+    errno = ENOSYS;
+    return NULL;
+}
+
+int
+fdatasync(int fd)
+{
+    errno = ENOSYS;
+    return -1;
+}
+
+ssize_t
+preadv(int fd, const struct iovec *iov, int iovcnt, off_t offset)
+{
+    errno = ENOSYS;
+    return 0;
+}
+
+ssize_t
+pwritev(int fd, const struct iovec *iov, int iovcnt, off_t offset)
+{
+    errno = ENOSYS;
+    return 0;
+}
+
+char *
+realpath(char *path, char *resolved_path)
+{
+    errno = ENOSYS;
+    return NULL;
+}
+
+int
+futimens(int fd, const struct timespec *times)
+{
+    errno = ENOSYS;
+    return -1;
+}
+
+int
+posix_fallocate(int __fd, off_t __offset, off_t __length)
+{
+    errno = ENOSYS;
+    return -1;
+}

+ 45 - 62
core/shared/platform/rt-thread/rtt_platform.c

@@ -134,96 +134,79 @@ os_time_thread_cputime_us(void)
     return os_time_get_boot_us();
 }
 
-korp_tid
-os_self_thread(void)
-{
-    return rt_thread_self();
-}
-
-uint8 *
-os_thread_get_stack_boundary(void)
+void *
+os_mmap(void *hint, size_t size, int prot, int flags, os_file_handle file)
 {
-    rt_thread_t tid = rt_thread_self();
-    return tid->stack_addr;
-}
+    void *buf_origin;
+    void *buf_fixed;
+    rt_ubase_t *addr_field;
 
-void
-os_thread_jit_write_protect_np(bool enabled)
-{}
+    buf_origin = rt_malloc(size + 8 + sizeof(rt_ubase_t));
+    if (!buf_origin)
+        return NULL;
 
-int
-os_mutex_init(korp_mutex *mutex)
-{
-    return rt_mutex_init(mutex, "wamr0", RT_IPC_FLAG_FIFO);
-}
+    buf_fixed = buf_origin + sizeof(void *);
+    if ((rt_ubase_t)buf_fixed & 0x7) {
+        buf_fixed = (void *)((rt_ubase_t)(buf_fixed + 8) & (~7));
+    }
 
-int
-os_mutex_destroy(korp_mutex *mutex)
-{
-    return rt_mutex_detach(mutex);
-}
+    addr_field = buf_fixed - sizeof(rt_ubase_t);
+    *addr_field = (rt_ubase_t)buf_origin;
 
-int
-os_mutex_lock(korp_mutex *mutex)
-{
-    return rt_mutex_take(mutex, RT_WAITING_FOREVER);
+    memset(buf_origin, 0, size + 8 + sizeof(rt_ubase_t));
+    return buf_fixed;
 }
 
-int
-os_mutex_unlock(korp_mutex *mutex)
+void
+os_munmap(void *addr, size_t size)
 {
-    return rt_mutex_release(mutex);
-}
+    void *mem_origin;
+    rt_ubase_t *addr_field;
 
-/*
- * functions below was not implement
- */
+    if (addr) {
+        addr_field = addr - sizeof(rt_ubase_t);
+        mem_origin = (void *)(*addr_field);
 
-int
-os_cond_init(korp_cond *cond)
-{
-    return 0;
+        rt_free(mem_origin);
+    }
 }
 
 int
-os_cond_destroy(korp_cond *cond)
+os_mprotect(void *addr, size_t size, int prot)
 {
     return 0;
 }
 
+void
+os_dcache_flush(void)
+{}
+
+void
+os_icache_flush(void *start, size_t len)
+{}
+
 int
-os_cond_wait(korp_cond *cond, korp_mutex *mutex)
+os_getpagesize(void)
 {
-    return 0;
+    return 4096;
 }
 
 void *
-os_mmap(void *hint, size_t size, int prot, int flags, os_file_handle file)
+os_mremap(void *in, size_t old_size, size_t new_size)
 {
-    void *addr;
-
-    if ((addr = rt_malloc(size)))
-        memset(addr, 0, size);
-
-    return addr;
+    return os_realloc(in, new_size);
 }
 
-void
-os_munmap(void *addr, size_t size)
+__wasi_errno_t
+os_clock_time_get(__wasi_clockid_t clock_id, __wasi_timestamp_t precision,
+                  __wasi_timestamp_t *time)
 {
-    rt_free(addr);
+    *time = rt_tick_get() * 1000ll * 1000ll;
+    return 0;
 }
 
-int
-os_mprotect(void *addr, size_t size, int prot)
+__wasi_errno_t
+os_clock_res_get(__wasi_clockid_t clock_id, __wasi_timestamp_t *resolution)
 {
     return 0;
 }
-
-void
-os_dcache_flush(void)
-{}
-
-void
-os_icache_flush(void *start, size_t len)
-{}

+ 385 - 0
core/shared/platform/rt-thread/rtt_socket.c

@@ -0,0 +1,385 @@
+/*
+ * Copyright 2024 Sony Semiconductor Solutions Corporation.
+ *
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#include "platform_api_vmcore.h"
+#include "platform_api_extension.h"
+
+int
+os_socket_accept(bh_socket_t server_sock, bh_socket_t *sock, void *addr,
+                 unsigned int *addrlen)
+{
+    return BHT_ERROR;
+}
+
+int
+os_socket_connect(bh_socket_t socket, const char *addr, int port)
+{
+    return BHT_ERROR;
+}
+
+int
+os_socket_recv_from(bh_socket_t socket, void *buf, unsigned int len, int flags,
+                    bh_sockaddr_t *src_addr)
+{
+    return BHT_ERROR;
+}
+
+int
+os_socket_send_to(bh_socket_t socket, const void *buf, unsigned int len,
+                  int flags, const bh_sockaddr_t *dest_addr)
+{
+    return BHT_ERROR;
+}
+
+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)
+{
+    return BHT_ERROR;
+}
+
+int
+os_socket_close(bh_socket_t socket)
+{
+    return BHT_ERROR;
+}
+
+int
+os_socket_addr_local(bh_socket_t socket, bh_sockaddr_t *sockaddr)
+{
+    return BHT_ERROR;
+}
+
+int
+os_socket_addr_remote(bh_socket_t socket, bh_sockaddr_t *sockaddr)
+{
+    return BHT_ERROR;
+}
+
+int
+os_socket_bind(bh_socket_t socket, const char *host, int *port)
+{
+    return BHT_ERROR;
+}
+
+int
+os_socket_listen(bh_socket_t socket, int max_client)
+{
+    return BHT_ERROR;
+}
+
+int
+os_socket_create(bh_socket_t *sock, bool is_ipv4, bool is_tcp)
+{
+    return BHT_ERROR;
+}
+
+int
+os_socket_send(bh_socket_t socket, const void *buf, unsigned int len)
+{
+    return BHT_ERROR;
+}
+
+__wasi_errno_t
+os_socket_shutdown(bh_socket_t socket)
+{
+    return __WASI_ENOSYS;
+}
+
+int
+os_socket_inet_network(bool is_ipv4, const char *cp, bh_ip_addr_buffer_t *out)
+{
+    return BHT_ERROR;
+}
+
+int
+os_socket_set_send_timeout(bh_socket_t socket, uint64 timeout_us)
+{
+    return BHT_ERROR;
+}
+
+int
+os_socket_get_recv_timeout(bh_socket_t socket, uint64 *timeout_us)
+{
+    return BHT_ERROR;
+}
+
+int
+os_socket_set_send_buf_size(bh_socket_t socket, size_t bufsiz)
+{
+    return BHT_ERROR;
+}
+
+int
+os_socket_get_send_buf_size(bh_socket_t socket, size_t *bufsiz)
+{
+    return BHT_ERROR;
+}
+
+int
+os_socket_set_recv_buf_size(bh_socket_t socket, size_t bufsiz)
+{
+    return BHT_ERROR;
+}
+
+int
+os_socket_get_recv_buf_size(bh_socket_t socket, size_t *bufsiz)
+{
+    return BHT_ERROR;
+}
+
+int
+os_socket_set_broadcast(bh_socket_t socket, bool is_enabled)
+{
+    return BHT_ERROR;
+}
+
+int
+os_socket_get_broadcast(bh_socket_t socket, bool *is_enabled)
+{
+    return BHT_ERROR;
+}
+
+int
+os_socket_get_send_timeout(bh_socket_t socket, uint64 *timeout_us)
+{
+    return BHT_ERROR;
+}
+
+int
+os_socket_set_recv_timeout(bh_socket_t socket, uint64 timeout_us)
+{
+    return BHT_ERROR;
+}
+
+int
+os_socket_set_keep_alive(bh_socket_t socket, bool is_enabled)
+{
+    return BHT_ERROR;
+}
+
+int
+os_socket_get_keep_alive(bh_socket_t socket, bool *is_enabled)
+{
+    return BHT_ERROR;
+}
+
+int
+os_socket_set_reuse_addr(bh_socket_t socket, bool is_enabled)
+{
+    return BHT_ERROR;
+}
+
+int
+os_socket_get_reuse_addr(bh_socket_t socket, bool *is_enabled)
+{
+    return BHT_ERROR;
+}
+
+int
+os_socket_set_reuse_port(bh_socket_t socket, bool is_enabled)
+{
+    return BHT_ERROR;
+}
+
+int
+os_socket_get_reuse_port(bh_socket_t socket, bool *is_enabled)
+{
+    return BHT_ERROR;
+}
+
+int
+os_socket_set_linger(bh_socket_t socket, bool is_enabled, int linger_s)
+{
+    return BHT_ERROR;
+}
+
+int
+os_socket_get_linger(bh_socket_t socket, bool *is_enabled, int *linger_s)
+{
+    return BHT_ERROR;
+}
+
+int
+os_socket_set_tcp_no_delay(bh_socket_t socket, bool is_enabled)
+{
+    return BHT_ERROR;
+}
+
+int
+os_socket_get_tcp_no_delay(bh_socket_t socket, bool *is_enabled)
+{
+    return BHT_ERROR;
+}
+
+int
+os_socket_set_tcp_quick_ack(bh_socket_t socket, bool is_enabled)
+{
+    return BHT_ERROR;
+}
+
+int
+os_socket_get_tcp_quick_ack(bh_socket_t socket, bool *is_enabled)
+{
+    return BHT_ERROR;
+}
+
+int
+os_socket_set_tcp_keep_idle(bh_socket_t socket, uint32 time_s)
+{
+    return BHT_ERROR;
+}
+
+int
+os_socket_get_tcp_keep_idle(bh_socket_t socket, uint32 *time_s)
+{
+    return BHT_ERROR;
+}
+
+int
+os_socket_set_tcp_keep_intvl(bh_socket_t socket, uint32 time_s)
+{
+    return BHT_ERROR;
+}
+
+int
+os_socket_get_tcp_keep_intvl(bh_socket_t socket, uint32 *time_s)
+{
+    return BHT_ERROR;
+}
+
+int
+os_socket_set_tcp_fastopen_connect(bh_socket_t socket, bool is_enabled)
+{
+    return BHT_ERROR;
+}
+
+int
+os_socket_get_tcp_fastopen_connect(bh_socket_t socket, bool *is_enabled)
+{
+    return BHT_ERROR;
+}
+
+int
+os_socket_set_ip_multicast_loop(bh_socket_t socket, bool ipv6, bool is_enabled)
+{
+    return BHT_ERROR;
+}
+
+int
+os_socket_get_ip_multicast_loop(bh_socket_t socket, bool ipv6, bool *is_enabled)
+{
+    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)
+{
+    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)
+{
+    return BHT_ERROR;
+}
+
+int
+os_socket_set_ip_ttl(bh_socket_t socket, uint8_t ttl_s)
+{
+    return BHT_ERROR;
+}
+
+int
+os_socket_get_ip_ttl(bh_socket_t socket, uint8_t *ttl_s)
+{
+    return BHT_ERROR;
+}
+
+int
+os_socket_set_ip_multicast_ttl(bh_socket_t socket, uint8_t ttl_s)
+{
+    return BHT_ERROR;
+}
+
+int
+os_socket_get_ip_multicast_ttl(bh_socket_t socket, uint8_t *ttl_s)
+{
+    return BHT_ERROR;
+}
+
+int
+os_socket_set_ipv6_only(bh_socket_t socket, bool is_enabled)
+{
+    return BHT_ERROR;
+}
+
+int
+os_socket_get_ipv6_only(bh_socket_t socket, bool *is_enabled)
+{
+    return BHT_ERROR;
+}
+
+static void
+swap16(uint8 *pData)
+{
+    uint8 value = *pData;
+    *(pData) = *(pData + 1);
+    *(pData + 1) = value;
+}
+
+static void
+swap32(uint8 *pData)
+{
+    uint8 value = *pData;
+    *pData = *(pData + 3);
+    *(pData + 3) = value;
+
+    value = *(pData + 1);
+    *(pData + 1) = *(pData + 2);
+    *(pData + 2) = value;
+}
+
+/** In-enclave implementation of POSIX functions **/
+static bool
+is_little_endian()
+{
+    long i = 0x01020304;
+    unsigned char *c = (unsigned char *)&i;
+    return (*c == 0x04) ? true : false;
+}
+
+uint16
+htons(uint16 value)
+{
+    uint16 ret;
+    if (is_little_endian()) {
+        ret = value;
+        swap16((uint8 *)&ret);
+        return ret;
+    }
+
+    return value;
+}
+
+uint32
+htonl(uint32 value)
+{
+    uint32 ret;
+    if (is_little_endian()) {
+        ret = value;
+        swap32((uint8 *)&ret);
+        return ret;
+    }
+
+    return value;
+}

+ 427 - 0
core/shared/platform/rt-thread/rtt_thread.c

@@ -0,0 +1,427 @@
+/*
+ * Copyright 2024 Sony Semiconductor Solutions Corporation.
+ *
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#include "platform_api_vmcore.h"
+#include "platform_api_extension.h"
+
+#include <errno.h>
+#include <stdio.h>
+#include <stddef.h>
+#include <fcntl.h>
+#include <stdint.h>
+
+struct os_thread_data;
+typedef struct os_thread_wait_node *os_thread_wait_list;
+typedef struct os_thread_wait_node {
+    /* Binary semaphore */
+    rt_sem_t sem;
+    os_thread_wait_list next;
+} os_thread_wait_node;
+
+typedef struct os_thread_data {
+    /* Next thread data */
+    struct os_thread_data *next;
+    /* Thread handle */
+    rt_thread_t handle;
+    /* 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;
+    /* Lock for waiting list */
+    rt_mutex_t wait_list_lock;
+    /* Waiting list of other threads who are joining this thread */
+    os_thread_wait_list thread_wait_list;
+} os_thread_data;
+
+/* Lock for thread data list */
+static rt_mutex_t thread_data_lock;
+
+static bool is_thread_sys_inited = false;
+
+/* Thread data list */
+static os_thread_data *thread_data_list = NULL;
+
+/* Thread data of supervisor thread */
+static os_thread_data supervisor_thread_data;
+
+/* Thread name index */
+static int thread_name_index = 0;
+
+static void
+thread_data_list_add(os_thread_data *thread_data)
+{
+    rt_mutex_take(thread_data_lock, RT_WAITING_FOREVER);
+    if (!thread_data_list)
+        thread_data_list = thread_data;
+    else {
+        /* If already in list, just return */
+        os_thread_data *p = thread_data_list;
+        while (p) {
+            if (p == thread_data) {
+                rt_mutex_release(thread_data_lock);
+                return;
+            }
+            p = p->next;
+        }
+
+        /* Set as head of list */
+        thread_data->next = thread_data_list;
+        thread_data_list = thread_data;
+    }
+    rt_mutex_release(thread_data_lock);
+}
+
+static void
+os_thread_wrapper(void *arg)
+{
+    os_thread_data *thread_data = arg;
+
+    thread_data->handle = rt_thread_self();
+    thread_data_list_add(thread_data);
+
+    thread_data->start_routine(thread_data->arg);
+    rt_kprintf("start_routine quit\n");
+    os_thread_exit(NULL);
+}
+
+static void
+thread_data_list_remove(os_thread_data *thread_data)
+{
+    rt_mutex_take(thread_data_lock, RT_WAITING_FOREVER);
+    if (thread_data_list) {
+        if (thread_data_list == thread_data)
+            thread_data_list = thread_data_list->next;
+        else {
+            /* Search and remove it from list */
+            os_thread_data *p = thread_data_list;
+            while (p && p->next != thread_data)
+                p = p->next;
+            if (p && p->next == thread_data)
+                p->next = p->next->next;
+        }
+    }
+    rt_mutex_release(thread_data_lock);
+}
+
+static os_thread_data *
+thread_data_list_lookup(rt_thread_t handle)
+{
+    rt_mutex_take(thread_data_lock, RT_WAITING_FOREVER);
+    if (thread_data_list) {
+        os_thread_data *p = thread_data_list;
+        while (p) {
+            if (p->handle == handle) {
+                /* Found */
+                rt_mutex_release(thread_data_lock);
+                return p;
+            }
+            p = p->next;
+        }
+    }
+    rt_mutex_release(thread_data_lock);
+    return NULL;
+}
+
+static os_thread_data *
+thread_data_current()
+{
+    rt_thread_t handle = rt_thread_self();
+    return thread_data_list_lookup(handle);
+}
+
+int
+os_thread_sys_init()
+{
+    if (is_thread_sys_inited)
+        return BHT_OK;
+
+    if (!(thread_data_lock =
+              rt_mutex_create("thread_data_lock_mutex", RT_IPC_FLAG_FIFO)))
+        return BHT_ERROR;
+
+    /* Initialize supervisor thread data */
+    memset(&supervisor_thread_data, 0, sizeof(supervisor_thread_data));
+
+    if (!(supervisor_thread_data.wait_node.sem =
+              rt_sem_create("spvr", 0, RT_IPC_FLAG_PRIO))) {
+        rt_mutex_delete(thread_data_lock);
+        return BHT_ERROR;
+    }
+
+    supervisor_thread_data.handle = rt_thread_self();
+    /* Set as head of thread data list */
+    thread_data_list = &supervisor_thread_data;
+
+    is_thread_sys_inited = true;
+    return BHT_OK;
+}
+
+void
+os_thread_sys_destroy()
+{
+    if (is_thread_sys_inited) {
+        rt_sem_release(supervisor_thread_data.wait_node.sem);
+        rt_mutex_delete(thread_data_lock);
+        is_thread_sys_inited = false;
+    }
+}
+
+korp_tid
+os_self_thread(void)
+{
+    return rt_thread_self();
+}
+
+uint8 *
+os_thread_get_stack_boundary(void)
+{
+    rt_thread_t tid = rt_thread_self();
+    return tid->stack_addr;
+}
+
+void
+os_thread_jit_write_protect_np(bool enabled)
+{}
+
+int
+os_mutex_init(korp_mutex *mutex)
+{
+    return rt_mutex_init(mutex, "wamr0", RT_IPC_FLAG_FIFO);
+}
+
+int
+os_mutex_destroy(korp_mutex *mutex)
+{
+    return rt_mutex_detach(mutex);
+}
+
+int
+os_mutex_lock(korp_mutex *mutex)
+{
+    return rt_mutex_take(mutex, RT_WAITING_FOREVER);
+}
+
+int
+os_mutex_unlock(korp_mutex *mutex)
+{
+    return rt_mutex_release(mutex);
+}
+
+/*
+ * functions below was not implement
+ */
+
+int
+os_cond_init(korp_cond *cond)
+{
+    return 0;
+}
+
+int
+os_cond_destroy(korp_cond *cond)
+{
+    return 0;
+}
+
+int
+os_cond_wait(korp_cond *cond, korp_mutex *mutex)
+{
+    return 0;
+}
+
+int
+os_cond_signal(korp_cond *cond)
+{
+    return 0;
+}
+
+int
+os_cond_reltimedwait(korp_cond *cond, korp_mutex *mutex, uint64 useconds)
+{
+    return 0;
+}
+
+int
+os_rwlock_init(korp_rwlock *lock)
+{
+    return BHT_OK;
+}
+
+int
+os_rwlock_rdlock(korp_rwlock *lock)
+{
+
+    return BHT_OK;
+}
+
+int
+os_rwlock_wrlock(korp_rwlock *lock)
+{
+
+    return BHT_OK;
+}
+
+int
+os_rwlock_unlock(korp_rwlock *lock)
+{
+    return BHT_OK;
+}
+
+int
+os_rwlock_destroy(korp_rwlock *lock)
+{
+    return BHT_OK;
+}
+
+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 *thread_data;
+    char thread_name[32];
+    void *stack;
+
+    if (!p_tid || !stack_size)
+        return BHT_ERROR;
+
+    /* Create and initialize thread data */
+    if (!(thread_data = rt_malloc(sizeof(os_thread_data))))
+        return BHT_ERROR;
+
+    memset(thread_data, 0, sizeof(os_thread_data));
+
+    thread_data->start_routine = start;
+    thread_data->arg = arg;
+
+    if (!(thread_data->wait_node.sem =
+              rt_sem_create("sem", 0, RT_IPC_FLAG_PRIO)))
+        goto fail1;
+
+    if (!(thread_data->wait_list_lock =
+              rt_mutex_create("wait_list_lock_mutex", RT_IPC_FLAG_FIFO)))
+        goto fail2;
+
+    snprintf(thread_name, sizeof(thread_name), "%s%d", "wasm-thread-",
+             ++thread_name_index);
+
+    thread_data->handle = rt_thread_create(thread_name, os_thread_wrapper,
+                                           thread_data, stack_size, 15, 5);
+    if (thread_data->handle == RT_NULL) {
+        rt_kprintf("os_thread_create_with_prio failed, tid=%d\n",
+                   thread_data->handle);
+        goto fail3;
+    }
+
+    thread_data_list_add(thread_data);
+    *p_tid = thread_data->handle;
+    rt_thread_startup(*p_tid);
+    return BHT_OK;
+
+fail3:
+    rt_mutex_delete(thread_data->wait_list_lock);
+fail2:
+    rt_sem_delete(thread_data->wait_node.sem);
+fail1:
+    rt_free(thread_data);
+    return BHT_ERROR;
+}
+
+int
+os_thread_create(korp_tid *p_tid, thread_start_routine_t start, void *arg,
+                 unsigned int stack_size)
+{
+    return os_thread_create_with_prio(p_tid, start, arg, stack_size,
+                                      BH_THREAD_DEFAULT_PRIORITY);
+}
+
+int
+os_thread_detach(korp_tid thread)
+{
+    /* Do nothing */
+    (void)thread;
+    return BHT_OK;
+}
+
+int
+os_thread_join(korp_tid thread, void **value_ptr)
+{
+    os_thread_data *thread_data, *curr_thread_data;
+    rt_thread_t handle = thread;
+
+    (void)value_ptr;
+
+    /* Get thread data of current thread */
+    curr_thread_data = thread_data_current();
+    curr_thread_data->wait_node.next = NULL;
+
+    /* Get thread data */
+    thread_data = thread_data_list_lookup(handle);
+
+    rt_mutex_take(thread_data->wait_list_lock, RT_WAITING_FOREVER);
+    if (!thread_data->thread_wait_list)
+        thread_data->thread_wait_list = &curr_thread_data->wait_node;
+    else {
+        /* Add to end of waiting list */
+        os_thread_wait_node *p = thread_data->thread_wait_list;
+        while (p->next)
+            p = p->next;
+        p->next = &curr_thread_data->wait_node;
+    }
+    rt_mutex_release(thread_data->wait_list_lock);
+
+    /* Wait the sem */
+    rt_sem_take(curr_thread_data->wait_node.sem, RT_WAITING_FOREVER);
+    return BHT_OK;
+}
+
+static void
+os_thread_cleanup(void)
+{
+    os_thread_data *thread_data = thread_data_current();
+    os_thread_wait_list thread_wait_list;
+    rt_mutex_t wait_list_lock;
+    rt_sem_t wait_node_sem;
+
+    // bh_assert(thread_data != NULL);
+    wait_list_lock = thread_data->wait_list_lock;
+    thread_wait_list = thread_data->thread_wait_list;
+    wait_node_sem = thread_data->wait_node.sem;
+
+    rt_mutex_take(wait_list_lock, RT_WAITING_FOREVER);
+    if (thread_wait_list) {
+        /* Signal each joining thread */
+        os_thread_wait_list head = thread_wait_list;
+        while (head) {
+            os_thread_wait_list next = head->next;
+            rt_sem_release(head->sem);
+            head = next;
+        }
+    }
+    rt_mutex_release(wait_list_lock);
+
+    /* Free sem and lock */
+    rt_sem_delete(wait_node_sem);
+    rt_mutex_delete(wait_list_lock);
+
+    thread_data_list_remove(thread_data);
+    rt_free(thread_data);
+}
+
+void
+os_thread_exit(void *retval)
+{
+    (void)retval;
+    os_thread_cleanup();
+    // vTaskDelete(NULL);
+}
+
+int
+os_thread_kill(korp_tid tid, int sig)
+{
+    return rt_thread_kill(tid, sig);
+}

+ 70 - 20
product-mini/platforms/rt-thread/iwasm.c

@@ -11,6 +11,10 @@
 #include <dfs_file.h>
 #include <dfs_fs.h>
 
+#if WASM_ENABLE_LIBC_WASI != 0
+#include "../common/libc_wasi.c"
+#endif
+
 #ifdef WAMR_ENABLE_RTT_EXPORT
 
 #ifdef WAMR_RTT_EXPORT_VPRINTF
@@ -160,6 +164,15 @@ static NativeSymbol native_export_symbols[] = {
 
 #endif /* WAMR_ENABLE_RTT_EXPORT */
 
+static void *
+app_instance_func(wasm_module_inst_t module_inst, const char *func_name,
+                  int app_argc, char **app_argv)
+{
+    wasm_application_execute_func(module_inst, func_name, app_argc - 1,
+                                  app_argv + 1);
+    return wasm_runtime_get_exception(module_inst);
+}
+
 /**
  * run WASM module instance.
  * @param module_inst instance of wasm module
@@ -170,12 +183,8 @@ static NativeSymbol native_export_symbols[] = {
 static void *
 app_instance_main(wasm_module_inst_t module_inst, int app_argc, char **app_argv)
 {
-    const char *exception;
-
     wasm_application_execute_main(module_inst, app_argc, app_argv);
-    if ((exception = wasm_runtime_get_exception(module_inst)))
-        rt_kprintf("%s\n", exception);
-    return NULL;
+    return wasm_runtime_get_exception(module_inst);
 }
 
 rt_uint8_t *
@@ -214,28 +223,36 @@ void
 iwasm_help(void)
 {
 #ifdef WAMR_ENABLE_IWASM_PARAMS
-    rt_kputs("wrong input: iwasm [-t] [-m] [-s] <*.wasm> <wasm_args ...>\n"
-             "             iwasm [-h]\n");
-    rt_kputs("\t -h: show this tips.\n");
-    rt_kputs("\t -t: show time taking to run this app.\n");
-    rt_kputs("\t -m: show memory taking to run this app\n");
-    rt_kputs("\t wasm file name and exec params must behind of all vm-param\n");
+    rt_kputs("Usage: iwasm [-options] wasm_file [args...]\n");
+    rt_kputs("options:\n");
+    rt_kputs("  -t                       Show time taking to run this app.\n");
+    rt_kputs("  -m                       Show memory taking to run this app\n");
+    rt_kputs("  -f|--function name       Specify a function name of the module "
+             "to run rather than main\n");
+    rt_kputs("  --max-threads=n          Set maximum thread number per "
+             "cluster, default is 4\n");
 #else
-    rt_kputs("wrong input: iwasm <*.wasm> <wasm_args ...>\n");
+    rt_kputs("Usage: iwasm wasm_file [args...]\n");
 #endif /* WAMR_ENABLE_PARAMS */
 }
 
 int
 iwasm(int argc, char **argv)
 {
+    const char *exception = NULL;
+    const char *func_name = NULL;
     rt_uint8_t *wasm_file_buf = NULL;
     rt_uint32_t wasm_file_size;
-    rt_uint32_t stack_size = 4 * 1024, heap_size = 4 * 1024;
+    rt_uint32_t stack_size = 64 * 1024, heap_size = 256 * 1024;
     wasm_module_t wasm_module = NULL;
     wasm_module_inst_t wasm_module_inst = NULL;
     RuntimeInitArgs init_args;
     static char error_buf[128] = { 0 };
     /* avoid stack overflow */
+#if WASM_ENABLE_LIBC_WASI != 0
+    libc_wasi_parse_context_t wasi_parse_ctx;
+    memset(&wasi_parse_ctx, 0, sizeof(wasi_parse_ctx));
+#endif
 
 #ifdef WAMR_ENABLE_IWASM_PARAMS
     int i_arg_begin;
@@ -260,6 +277,17 @@ iwasm(int argc, char **argv)
             iwasm_help();
             return 0;
         }
+        else if (argv[i_arg_begin][1] == 'f') {
+            func_name = argv[++i_arg_begin];
+        }
+        else if (!strncmp(argv[i_arg_begin], "--max-threads=", 14)) {
+            if (argv[0][14] != '\0')
+                wasm_runtime_set_max_thread_num(atoi(argv[0] + 14));
+            else {
+                iwasm_help();
+                return 0;
+            }
+        }
         else if (argv[i_arg_begin][1] == 0x00) {
             continue;
         }
@@ -303,8 +331,8 @@ iwasm(int argc, char **argv)
     rt_thread_t tid;
     if (show_stack) {
         tid = rt_thread_self();
-        printf("thread stack addr: %p, size: %u, sp: %p\n", tid->stack_addr,
-               tid->stack_size, tid->sp);
+        rt_kprintf("thread stack addr: %p, size: %u, sp: %p\n", tid->stack_addr,
+                   tid->stack_size, tid->sp);
     }
 #endif /* WAMR_ENABLE_PARAMS */
 
@@ -326,6 +354,10 @@ iwasm(int argc, char **argv)
         rt_kprintf("%s\n", error_buf);
         goto fail2;
     }
+#if WASM_ENABLE_LIBC_WASI != 0
+    libc_wasi_init(wasm_module, argc, argv, &wasi_parse_ctx);
+#endif
+
     rt_memset(error_buf, 0x00, sizeof(error_buf));
     wasm_module_inst = wasm_runtime_instantiate(
         wasm_module, stack_size, heap_size, error_buf, sizeof(error_buf));
@@ -341,13 +373,31 @@ iwasm(int argc, char **argv)
     }
 #endif /* WAMR_ENABLE_PARAMS */
 
-    app_instance_main(wasm_module_inst, argc - i_arg_begin, &argv[i_arg_begin]);
+    if (func_name) {
+        exception = app_instance_func(wasm_module_inst, func_name,
+                                      argc - i_arg_begin, &argv[i_arg_begin]);
+    }
+    else {
+        exception = app_instance_main(wasm_module_inst, argc - i_arg_begin,
+                                      &argv[i_arg_begin]);
+        rt_kprintf("finshed run app_instance_main\n");
+    }
+
+    if (exception)
+        rt_kprintf("%s\n", exception);
+
+#if WASM_ENABLE_LIBC_WASI != 0
+    if (!exception) {
+        /* propagate wasi exit code. */
+        wasm_runtime_get_wasi_exit_code(wasm_module_inst);
+    }
+#endif
 
 #ifdef WAMR_ENABLE_IWASM_PARAMS
     if (show_time_exec) {
         ticks_exec = rt_tick_get() - ticks_exec;
-        printf("[iwasm] execute ticks took: %u [ticks/s = %u]\n", ticks_exec,
-               RT_TICK_PER_SECOND);
+        rt_kprintf("[iwasm] execute ticks took: %u [ticks/s = %u]\n",
+                   ticks_exec, RT_TICK_PER_SECOND);
     }
 #if defined(RT_USING_HEAP) && defined(RT_USING_MEMHEAP_AS_HEAP)
     if (show_mem) {
@@ -361,8 +411,8 @@ iwasm(int argc, char **argv)
     }
 #endif
     if (show_stack) {
-        printf("[iwasm] thread stack addr: %p, size: %u, sp: %p\n",
-               tid->stack_addr, tid->stack_size, tid->sp);
+        rt_kprintf("[iwasm] thread stack addr: %p, size: %u, sp: %p\n",
+                   tid->stack_addr, tid->stack_size, tid->sp);
     }
 
 #endif /* WAMR_ENABLE_PARAMS */