Skip to content

Commit 0464262

Browse files
authored
zephyr: Enable WASI support for file system and sockets on zephyr (#3633)
To address #3311. This work also implements the WASI support on Zephyr. Note that some comments haven't been addressed and will be fixed in the further patches.
1 parent e352f0a commit 0464262

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

48 files changed

+9673
-134
lines changed

core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/blocking_op.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -175,14 +175,14 @@ blocking_op_openat(wasm_exec_env_t exec_env, os_file_handle handle,
175175
#ifndef BH_PLATFORM_WINDOWS
176176
/* REVISIT: apply the os_file_handle style abstraction for pollfd? */
177177
__wasi_errno_t
178-
blocking_op_poll(wasm_exec_env_t exec_env, struct pollfd *pfds, nfds_t nfds,
179-
int timeout_ms, int *retp)
178+
blocking_op_poll(wasm_exec_env_t exec_env, os_poll_file_handle *pfds,
179+
os_nfds_t nfds, int timeout_ms, int *retp)
180180
{
181181
int ret;
182182
if (!wasm_runtime_begin_blocking_op(exec_env)) {
183183
return __WASI_EINTR;
184184
}
185-
ret = poll(pfds, nfds, timeout_ms);
185+
ret = os_poll(pfds, nfds, timeout_ms);
186186
wasm_runtime_end_blocking_op(exec_env);
187187
if (ret == -1) {
188188
return convert_errno(errno);

core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/blocking_op.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -57,8 +57,8 @@ blocking_op_openat(wasm_exec_env_t exec_env, os_file_handle handle,
5757

5858
#ifndef BH_PLATFORM_WINDOWS
5959
__wasi_errno_t
60-
blocking_op_poll(wasm_exec_env_t exec_env, struct pollfd *pfds, nfds_t nfds,
61-
int timeout, int *retp);
60+
blocking_op_poll(wasm_exec_env_t exec_env, os_poll_file_handle *pfds,
61+
os_nfds_t nfds, int timeout, int *retp);
6262
#endif
6363

6464
#endif /* end of _BLOCKING_OP_H_ */

core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/locking.h

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -196,8 +196,12 @@ static inline bool
196196
cond_timedwait(struct cond *cond, struct mutex *lock, uint64_t timeout,
197197
bool abstime) REQUIRES_EXCLUSIVE(*lock) NO_LOCK_ANALYSIS
198198
{
199+
#if defined(BH_PLATFORM_ZEPHYR)
200+
// TODO: Implement this for Zephyr
201+
return false;
202+
#else
199203
int ret;
200-
struct timespec ts = {
204+
os_timespec ts = {
201205
.tv_sec = (time_t)(timeout / 1000000000),
202206
.tv_nsec = (long)(timeout % 1000000000),
203207
};
@@ -210,8 +214,8 @@ cond_timedwait(struct cond *cond, struct mutex *lock, uint64_t timeout,
210214
* realtime clock.
211215
*/
212216
if (cond->clock != CLOCK_REALTIME) {
213-
struct timespec ts_monotonic;
214-
struct timespec ts_realtime;
217+
os_timespec ts_monotonic;
218+
os_timespec ts_realtime;
215219

216220
clock_gettime(cond->clock, &ts_monotonic);
217221
ts.tv_sec -= ts_monotonic.tv_sec;
@@ -229,7 +233,7 @@ cond_timedwait(struct cond *cond, struct mutex *lock, uint64_t timeout,
229233
++ts.tv_sec;
230234
}
231235
}
232-
#endif
236+
#endif /* !CONFIG_HAS_PTHREAD_CONDATTR_SETCLOCK */
233237
}
234238
else {
235239
#if CONFIG_HAS_PTHREAD_COND_TIMEDWAIT_RELATIVE_NP
@@ -241,7 +245,7 @@ cond_timedwait(struct cond *cond, struct mutex *lock, uint64_t timeout,
241245
return ret == ETIMEDOUT;
242246
#else
243247
/* Convert to absolute timeout. */
244-
struct timespec ts_now;
248+
os_timespec ts_now;
245249
#if CONFIG_HAS_PTHREAD_CONDATTR_SETCLOCK
246250
clock_gettime(cond->clock, &ts_now);
247251
#else
@@ -253,13 +257,14 @@ cond_timedwait(struct cond *cond, struct mutex *lock, uint64_t timeout,
253257
ts.tv_nsec -= 1000000000;
254258
++ts.tv_sec;
255259
}
256-
#endif
260+
#endif /* CONFIG_HAS_PTHREAD_COND_TIMEDWAIT_RELATIVE_NP */
257261
}
258262

259263
ret = pthread_cond_timedwait(&cond->object, &lock->object, &ts);
260264
bh_assert((ret == 0 || ret == ETIMEDOUT)
261265
&& "pthread_cond_timedwait() failed");
262266
return ret == ETIMEDOUT;
267+
#endif /* BH_PLATFORM_ZEPHYR */
263268
}
264269
#endif
265270

core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/posix.c

Lines changed: 42 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -356,16 +356,20 @@ fd_table_get_entry(struct fd_table *ft, __wasi_fd_t fd,
356356
REQUIRES_SHARED(ft->lock)
357357
{
358358
// Test for file descriptor existence.
359-
if (fd >= ft->size)
359+
if (fd >= ft->size) {
360360
return __WASI_EBADF;
361+
}
362+
361363
struct fd_entry *fe = &ft->entries[fd];
362-
if (fe->object == NULL)
364+
if (fe->object == NULL) {
363365
return __WASI_EBADF;
366+
}
364367

365368
// Validate rights.
366369
if ((~fe->rights_base & rights_base) != 0
367-
|| (~fe->rights_inheriting & rights_inheriting) != 0)
370+
|| (~fe->rights_inheriting & rights_inheriting) != 0) {
368371
return __WASI_ENOTCAPABLE;
372+
}
369373
*ret = fe;
370374
return 0;
371375
}
@@ -426,28 +430,28 @@ fd_table_attach(struct fd_table *ft, __wasi_fd_t fd, struct fd_object *fo,
426430
__wasi_rights_t rights_base, __wasi_rights_t rights_inheriting)
427431
REQUIRES_EXCLUSIVE(ft->lock) CONSUMES(fo->refcount)
428432
{
429-
assert(ft->size > fd && "File descriptor table too small");
433+
bh_assert(ft->size > fd && "File descriptor table too small");
430434
struct fd_entry *fe = &ft->entries[fd];
431-
assert(fe->object == NULL
432-
&& "Attempted to overwrite an existing descriptor");
435+
bh_assert(fe->object == NULL
436+
&& "Attempted to overwrite an existing descriptor");
433437
fe->object = fo;
434438
fe->rights_base = rights_base;
435439
fe->rights_inheriting = rights_inheriting;
436440
++ft->used;
437-
assert(ft->size >= ft->used * 2 && "File descriptor too full");
441+
bh_assert(ft->size >= ft->used * 2 && "File descriptor too full");
438442
}
439443

440444
// Detaches a file descriptor from the file descriptor table.
441445
static void
442446
fd_table_detach(struct fd_table *ft, __wasi_fd_t fd, struct fd_object **fo)
443447
REQUIRES_EXCLUSIVE(ft->lock) PRODUCES((*fo)->refcount)
444448
{
445-
assert(ft->size > fd && "File descriptor table too small");
449+
bh_assert(ft->size > fd && "File descriptor table too small");
446450
struct fd_entry *fe = &ft->entries[fd];
447451
*fo = fe->object;
448-
assert(*fo != NULL && "Attempted to detach nonexistent descriptor");
452+
bh_assert(*fo != NULL && "Attempted to detach nonexistent descriptor");
449453
fe->object = NULL;
450-
assert(ft->used > 0 && "Reference count mismatch");
454+
bh_assert(ft->used > 0 && "Reference count mismatch");
451455
--ft->used;
452456
}
453457

@@ -636,7 +640,7 @@ fd_table_insert_existing(struct fd_table *ft, __wasi_fd_t in,
636640
static __wasi_errno_t
637641
fd_table_unused(struct fd_table *ft, __wasi_fd_t *out) REQUIRES_SHARED(ft->lock)
638642
{
639-
assert(ft->size > ft->used && "File descriptor table has no free slots");
643+
bh_assert(ft->size > ft->used && "File descriptor table has no free slots");
640644
for (;;) {
641645
uintmax_t random_fd = 0;
642646
__wasi_errno_t error = random_uniform(ft->size, &random_fd);
@@ -1537,7 +1541,8 @@ path_put(struct path_access *pa) UNLOCKS(pa->fd_object->refcount)
15371541
{
15381542
if (pa->path_start)
15391543
wasm_runtime_free(pa->path_start);
1540-
if (pa->fd_object->file_handle != pa->fd)
1544+
/* Can't use `!=` operator when `os_file_handle` is a struct */
1545+
if (!os_compare_file_handle(pa->fd_object->file_handle, pa->fd))
15411546
os_close(pa->fd, false);
15421547
fd_object_release(NULL, pa->fd_object);
15431548
}
@@ -1878,7 +1883,7 @@ wasmtime_ssp_fd_filestat_get(wasm_exec_env_t exec_env, struct fd_table *curfds,
18781883
}
18791884

18801885
static void
1881-
convert_timestamp(__wasi_timestamp_t in, struct timespec *out)
1886+
convert_timestamp(__wasi_timestamp_t in, os_timespec *out)
18821887
{
18831888
// Store sub-second remainder.
18841889
#if defined(__SYSCALL_SLONG_TYPE)
@@ -2076,7 +2081,7 @@ wasmtime_ssp_poll_oneoff(wasm_exec_env_t exec_env, struct fd_table *curfds,
20762081
size_t nsubscriptions,
20772082
size_t *nevents) NO_LOCK_ANALYSIS
20782083
{
2079-
#ifdef BH_PLATFORM_WINDOWS
2084+
#if defined(BH_PLATFORM_WINDOWS) || defined(BH_PLATFORM_ZEPHYR)
20802085
return __WASI_ENOSYS;
20812086
#else
20822087
// Sleeping.
@@ -2088,7 +2093,7 @@ wasmtime_ssp_poll_oneoff(wasm_exec_env_t exec_env, struct fd_table *curfds,
20882093
#if CONFIG_HAS_CLOCK_NANOSLEEP
20892094
clockid_t clock_id;
20902095
if (wasi_clockid_to_clockid(in[0].u.u.clock.clock_id, &clock_id)) {
2091-
struct timespec ts;
2096+
os_timespec ts;
20922097
convert_timestamp(in[0].u.u.clock.timeout, &ts);
20932098
int ret = clock_nanosleep(
20942099
clock_id,
@@ -2115,7 +2120,7 @@ wasmtime_ssp_poll_oneoff(wasm_exec_env_t exec_env, struct fd_table *curfds,
21152120
else {
21162121
// Perform relative sleeps on the monotonic clock also using
21172122
// nanosleep(). This is incorrect, but good enough for now.
2118-
struct timespec ts;
2123+
os_timespec ts;
21192124
convert_timestamp(in[0].u.u.clock.timeout, &ts);
21202125
nanosleep(&ts, NULL);
21212126
}
@@ -2143,7 +2148,7 @@ wasmtime_ssp_poll_oneoff(wasm_exec_env_t exec_env, struct fd_table *curfds,
21432148
}
21442149
else {
21452150
// Relative sleeps can be done using nanosleep().
2146-
struct timespec ts;
2151+
os_timespec ts;
21472152
convert_timestamp(in[0].u.u.clock.timeout, &ts);
21482153
nanosleep(&ts, NULL);
21492154
}
@@ -2168,7 +2173,7 @@ wasmtime_ssp_poll_oneoff(wasm_exec_env_t exec_env, struct fd_table *curfds,
21682173
wasm_runtime_malloc((uint32)(nsubscriptions * sizeof(*fos)));
21692174
if (fos == NULL)
21702175
return __WASI_ENOMEM;
2171-
struct pollfd *pfds =
2176+
os_poll_file_handle *pfds =
21722177
wasm_runtime_malloc((uint32)(nsubscriptions * sizeof(*pfds)));
21732178
if (pfds == NULL) {
21742179
wasm_runtime_free(fos);
@@ -2193,7 +2198,7 @@ wasmtime_ssp_poll_oneoff(wasm_exec_env_t exec_env, struct fd_table *curfds,
21932198
__WASI_RIGHT_POLL_FD_READWRITE, 0);
21942199
if (error == 0) {
21952200
// Proper file descriptor on which we can poll().
2196-
pfds[i] = (struct pollfd){
2201+
pfds[i] = (os_poll_file_handle){
21972202
.fd = fos[i]->file_handle,
21982203
.events = s->u.type == __WASI_EVENTTYPE_FD_READ
21992204
? POLLIN
@@ -2203,7 +2208,7 @@ wasmtime_ssp_poll_oneoff(wasm_exec_env_t exec_env, struct fd_table *curfds,
22032208
else {
22042209
// Invalid file descriptor or rights missing.
22052210
fos[i] = NULL;
2206-
pfds[i] = (struct pollfd){ .fd = -1 };
2211+
pfds[i] = (os_poll_file_handle){ .fd = -1 };
22072212
out[(*nevents)++] = (__wasi_event_t){
22082213
.userdata = s->userdata,
22092214
.error = error,
@@ -2218,15 +2223,15 @@ wasmtime_ssp_poll_oneoff(wasm_exec_env_t exec_env, struct fd_table *curfds,
22182223
== 0) {
22192224
// Relative timeout.
22202225
fos[i] = NULL;
2221-
pfds[i] = (struct pollfd){ .fd = -1 };
2226+
pfds[i] = (os_poll_file_handle){ .fd = -1 };
22222227
clock_subscription = s;
22232228
break;
22242229
}
22252230
// Fallthrough.
22262231
default:
22272232
// Unsupported event.
22282233
fos[i] = NULL;
2229-
pfds[i] = (struct pollfd){ .fd = -1 };
2234+
pfds[i] = (os_poll_file_handle){ .fd = -1 };
22302235
out[(*nevents)++] = (__wasi_event_t){
22312236
.userdata = s->userdata,
22322237
.error = __WASI_ENOSYS,
@@ -2270,7 +2275,7 @@ wasmtime_ssp_poll_oneoff(wasm_exec_env_t exec_env, struct fd_table *curfds,
22702275
__wasi_filesize_t nbytes = 0;
22712276
if (in[i].u.type == __WASI_EVENTTYPE_FD_READ) {
22722277
int l;
2273-
if (ioctl(fos[i]->file_handle, FIONREAD, &l) == 0)
2278+
if (os_ioctl(fos[i]->file_handle, FIONREAD, &l) == 0)
22742279
nbytes = (__wasi_filesize_t)l;
22752280
}
22762281
if ((pfds[i].revents & POLLNVAL) != 0) {
@@ -2436,7 +2441,7 @@ wasi_addr_to_string(const __wasi_addr_t *addr, char *buf, size_t buflen)
24362441
if (addr->kind == IPv4) {
24372442
const char *format = "%u.%u.%u.%u";
24382443

2439-
assert(buflen >= 16);
2444+
bh_assert(buflen >= 16);
24402445

24412446
snprintf(buf, buflen, format, addr->addr.ip4.addr.n0,
24422447
addr->addr.ip4.addr.n1, addr->addr.ip4.addr.n2,
@@ -2448,14 +2453,13 @@ wasi_addr_to_string(const __wasi_addr_t *addr, char *buf, size_t buflen)
24482453
const char *format = "%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x";
24492454
__wasi_addr_ip6_t ipv6 = addr->addr.ip6.addr;
24502455

2451-
assert(buflen >= 40);
2456+
bh_assert(buflen >= 40);
24522457

24532458
snprintf(buf, buflen, format, ipv6.n0, ipv6.n1, ipv6.n2, ipv6.n3,
24542459
ipv6.h0, ipv6.h1, ipv6.h2, ipv6.h3);
24552460

24562461
return true;
24572462
}
2458-
24592463
return false;
24602464
}
24612465

@@ -2562,9 +2566,11 @@ wasi_ssp_sock_connect(wasm_exec_env_t exec_env, struct fd_table *curfds,
25622566
}
25632567

25642568
error = fd_object_get(curfds, &fo, fd, __WASI_RIGHT_SOCK_BIND, 0);
2565-
if (error != __WASI_ESUCCESS)
2569+
if (error != __WASI_ESUCCESS) {
25662570
return error;
2571+
}
25672572

2573+
/* Consume __wasi_addr_t */
25682574
ret = blocking_op_socket_connect(exec_env, fo->file_handle, buf,
25692575
addr->kind == IPv4 ? addr->addr.ip4.port
25702576
: addr->addr.ip6.port);
@@ -2713,10 +2719,10 @@ wasi_ssp_sock_open(wasm_exec_env_t exec_env, struct fd_table *curfds,
27132719
}
27142720

27152721
if (SOCKET_DGRAM == socktype) {
2716-
assert(wasi_type == __WASI_FILETYPE_SOCKET_DGRAM);
2722+
bh_assert(wasi_type == __WASI_FILETYPE_SOCKET_DGRAM);
27172723
}
27182724
else {
2719-
assert(wasi_type == __WASI_FILETYPE_SOCKET_STREAM);
2725+
bh_assert(wasi_type == __WASI_FILETYPE_SOCKET_STREAM);
27202726
}
27212727

27222728
// TODO: base rights and inheriting rights ?
@@ -2834,6 +2840,9 @@ wasmtime_ssp_sock_recv_from(wasm_exec_env_t exec_env, struct fd_table *curfds,
28342840
return error;
28352841
}
28362842

2843+
wasi_addr_to_bh_sockaddr(src_addr, &sockaddr);
2844+
2845+
/* Consume bh_sockaddr_t instead of __wasi_addr_t */
28372846
ret = blocking_op_socket_recv_from(exec_env, fo->file_handle, buf, buf_len,
28382847
0, &sockaddr);
28392848
fd_object_release(exec_env, fo);
@@ -2899,6 +2908,7 @@ wasmtime_ssp_sock_send_to(wasm_exec_env_t exec_env, struct fd_table *curfds,
28992908

29002909
wasi_addr_to_bh_sockaddr(dest_addr, &sockaddr);
29012910

2911+
/* Consume bh_sockaddr instead of __wasi_addr_t */
29022912
ret = blocking_op_socket_send_to(exec_env, fo->file_handle, buf, buf_len, 0,
29032913
&sockaddr);
29042914
fd_object_release(exec_env, fo);
@@ -2930,8 +2940,10 @@ wasmtime_ssp_sock_shutdown(wasm_exec_env_t exec_env, struct fd_table *curfds,
29302940
__wasi_errno_t
29312941
wasmtime_ssp_sched_yield(void)
29322942
{
2933-
#ifdef BH_PLATFORM_WINDOWS
2943+
#if defined(BH_PLATFORM_WINDOWS)
29342944
SwitchToThread();
2945+
#elif defined(BH_PLATFORM_ZEPHYR)
2946+
k_yield();
29352947
#else
29362948
if (sched_yield() < 0)
29372949
return convert_errno(errno);

core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/random.c

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,20 @@ random_buf(void *buf, size_t len)
6666
return ret ? __WASI_EINVAL : __WASI_ESUCCESS;
6767
}
6868

69+
#elif defined(BH_PLATFORM_ZEPHYR)
70+
#include <zephyr/random/random.h>
71+
// Maybe having an OS abstraction api would be a good idea
72+
// because every platform is implementing this function.
73+
// we could have a function like `os_random_buf`
74+
// and call `os_random_buf.` in the SSP wrapper `random_buf`.
75+
76+
__wasi_errno_t
77+
random_buf(void *buf, size_t len)
78+
{
79+
sys_rand_get(buf, len);
80+
return __WASI_ESUCCESS;
81+
}
82+
6983
#else
7084

7185
static int urandom = -1;

core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/ssp_config.h

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -42,15 +42,16 @@
4242
#define CONFIG_HAS_GETRANDOM 0
4343
#endif
4444

45-
#if defined(__CloudABI__) || defined(BH_PLATFORM_FREERTOS)
45+
#if defined(__CloudABI__) || defined(BH_PLATFORM_FREERTOS) \
46+
|| defined(BH_PLATFORM_ZEPHYR)
4647
#define CONFIG_HAS_CAP_ENTER 1
4748
#else
4849
#define CONFIG_HAS_CAP_ENTER 0
4950
#endif
5051

5152
#if !defined(__APPLE__) && !defined(__FreeBSD__) && !defined(__EMSCRIPTEN__) \
5253
&& !defined(ESP_PLATFORM) && !defined(DISABLE_CLOCK_NANOSLEEP) \
53-
&& !defined(BH_PLATFORM_FREERTOS)
54+
&& !defined(BH_PLATFORM_FREERTOS) && !defined(BH_PLATFORM_ZEPHYR)
5455
#define CONFIG_HAS_CLOCK_NANOSLEEP 1
5556
#else
5657
#define CONFIG_HAS_CLOCK_NANOSLEEP 0
@@ -63,7 +64,8 @@
6364
#endif
6465

6566
#if !defined(__APPLE__) && !defined(BH_PLATFORM_LINUX_SGX) && !defined(_WIN32) \
66-
&& !defined(__COSMOPOLITAN__) && !defined(BH_PLATFORM_FREERTOS)
67+
&& !defined(__COSMOPOLITAN__) && !defined(BH_PLATFORM_FREERTOS) \
68+
&& !defined(BH_PLATFORM_ZEPHYR)
6769
#define CONFIG_HAS_PTHREAD_CONDATTR_SETCLOCK 1
6870
#else
6971
#define CONFIG_HAS_PTHREAD_CONDATTR_SETCLOCK 0

0 commit comments

Comments
 (0)