summaryrefslogtreecommitdiffstats
path: root/libc-bottom-half/cloudlibc
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--libc-bottom-half/cloudlibc/src/libc/poll/poll.c47
-rw-r--r--libc-bottom-half/cloudlibc/src/libc/sys/ioctl/ioctl.c57
-rw-r--r--libc-bottom-half/cloudlibc/src/libc/sys/select/pselect.c102
3 files changed, 140 insertions, 66 deletions
diff --git a/libc-bottom-half/cloudlibc/src/libc/poll/poll.c b/libc-bottom-half/cloudlibc/src/libc/poll/poll.c
index cde4e81..0ee1479 100644
--- a/libc-bottom-half/cloudlibc/src/libc/poll/poll.c
+++ b/libc-bottom-half/cloudlibc/src/libc/poll/poll.c
@@ -7,7 +7,7 @@
#include <poll.h>
#include <stdbool.h>
-int poll(struct pollfd *fds, size_t nfds, int timeout) {
+static int poll_wasip1(struct pollfd *fds, size_t nfds, int timeout) {
// Construct events for poll().
size_t maxevents = 2 * nfds + 1;
__wasi_subscription_t subscriptions[maxevents];
@@ -127,3 +127,48 @@ int poll(struct pollfd *fds, size_t nfds, int timeout) {
}
return retval;
}
+
+#ifdef __wasilibc_use_wasip2
+#include <wasi/descriptor_table.h>
+
+int poll_wasip2(struct pollfd *fds, size_t nfds, int timeout);
+
+int poll(struct pollfd* fds, nfds_t nfds, int timeout)
+{
+ bool found_socket = false;
+ bool found_non_socket = false;
+ for (size_t i = 0; i < nfds; ++i) {
+ descriptor_table_entry_t* entry;
+ if (descriptor_table_get_ref(fds[i].fd, &entry)) {
+ found_socket = true;
+ } else {
+ found_non_socket = true;
+ }
+ }
+
+ if (found_socket) {
+ if (found_non_socket) {
+ // We currently don't support polling a mix of non-sockets and
+ // sockets here (though you can do it by using the host APIs
+ // directly), and we probably won't until we've migrated entirely to
+ // WASI 0.2.
+ errno = ENOTSUP;
+ return -1;
+ }
+
+ return poll_wasip2(fds, nfds, timeout);
+ } else if (found_non_socket) {
+ return poll_wasip1(fds, nfds, timeout);
+ } else if (timeout >= 0) {
+ return poll_wasip2(fds, nfds, timeout);
+ } else {
+ errno = ENOTSUP;
+ return -1;
+ }
+}
+#else // not __wasilibc_use_wasip2
+int poll(struct pollfd* fds, nfds_t nfds, int timeout)
+{
+ return poll_wasip1(fds, nfds, timeout);
+}
+#endif // not __wasilibc_use_wasip2
diff --git a/libc-bottom-half/cloudlibc/src/libc/sys/ioctl/ioctl.c b/libc-bottom-half/cloudlibc/src/libc/sys/ioctl/ioctl.c
index 7d03cc6..2c968b2 100644
--- a/libc-bottom-half/cloudlibc/src/libc/sys/ioctl/ioctl.c
+++ b/libc-bottom-half/cloudlibc/src/libc/sys/ioctl/ioctl.c
@@ -4,11 +4,66 @@
#include <sys/ioctl.h>
-#include <wasi/api.h>
#include <errno.h>
#include <stdarg.h>
+#include <wasi/api.h>
+#ifdef __wasilibc_use_wasip2
+#include <wasi/descriptor_table.h>
+#endif
+
int ioctl(int fildes, int request, ...) {
+#ifdef __wasilibc_use_wasip2
+ descriptor_table_entry_t *entry;
+ if (descriptor_table_get_ref(fildes, &entry)) {
+ switch (entry->tag) {
+ case DESCRIPTOR_TABLE_ENTRY_TCP_SOCKET: {
+ tcp_socket_t *socket = &entry->tcp_socket;
+ switch (request) {
+ case FIONBIO: {
+ va_list ap;
+ va_start(ap, request);
+ socket->blocking = *va_arg(ap, const int *) ==
+ 0;
+ va_end(ap);
+
+ return 0;
+ }
+
+ default:
+ // TODO wasi-sockets: anything else we should support?
+ errno = EINVAL;
+ return -1;
+ }
+ }
+
+ case DESCRIPTOR_TABLE_ENTRY_UDP_SOCKET: {
+ udp_socket_t *socket = &entry->udp_socket;
+ switch (request) {
+ case FIONBIO: {
+ va_list ap;
+ va_start(ap, request);
+ socket->blocking = *va_arg(ap, const int *) ==
+ 0;
+ va_end(ap);
+
+ return 0;
+ }
+
+ default:
+ // TODO wasi-sockets: anything else we should support?
+ errno = EINVAL;
+ return -1;
+ }
+ }
+
+ default:
+ errno = ENOPROTOOPT;
+ return -1;
+ }
+ }
+#endif // __wasilibc_use_wasip2
+
switch (request) {
case FIONREAD: {
// Poll the file descriptor to determine how many bytes can be read.
diff --git a/libc-bottom-half/cloudlibc/src/libc/sys/select/pselect.c b/libc-bottom-half/cloudlibc/src/libc/sys/select/pselect.c
index fdc470e..3b479ed 100644
--- a/libc-bottom-half/cloudlibc/src/libc/sys/select/pselect.c
+++ b/libc-bottom-half/cloudlibc/src/libc/sys/select/pselect.c
@@ -8,6 +8,7 @@
#include <wasi/api.h>
#include <errno.h>
+#include <poll.h>
int pselect(int nfds, fd_set *restrict readfds, fd_set *restrict writefds,
fd_set *restrict errorfds, const struct timespec *restrict timeout,
@@ -33,93 +34,66 @@ int pselect(int nfds, fd_set *restrict readfds, fd_set *restrict writefds,
if (writefds == NULL)
writefds = &empty;
- // Determine the maximum number of events.
- size_t maxevents = readfds->__nfds + writefds->__nfds + 1;
- __wasi_subscription_t subscriptions[maxevents];
- size_t nsubscriptions = 0;
-
- // Convert the readfds set.
+ struct pollfd poll_fds[readfds->__nfds + writefds->__nfds];
+ size_t poll_nfds = 0;
+
for (size_t i = 0; i < readfds->__nfds; ++i) {
int fd = readfds->__fds[i];
if (fd < nfds) {
- __wasi_subscription_t *subscription = &subscriptions[nsubscriptions++];
- *subscription = (__wasi_subscription_t){
- .userdata = fd,
- .u.tag = __WASI_EVENTTYPE_FD_READ,
- .u.u.fd_read.file_descriptor = fd,
- };
+ poll_fds[poll_nfds++] = (struct pollfd){
+ .fd = fd,
+ .events = POLLRDNORM,
+ .revents = 0
+ };
}
}
-
- // Convert the writefds set.
+
for (size_t i = 0; i < writefds->__nfds; ++i) {
int fd = writefds->__fds[i];
if (fd < nfds) {
- __wasi_subscription_t *subscription = &subscriptions[nsubscriptions++];
- *subscription = (__wasi_subscription_t){
- .userdata = fd,
- .u.tag = __WASI_EVENTTYPE_FD_WRITE,
- .u.u.fd_write.file_descriptor = fd,
+ poll_fds[poll_nfds++] = (struct pollfd){
+ .fd = fd,
+ .events = POLLWRNORM,
+ .revents = 0
};
}
}
- // Create extra event for the timeout.
- if (timeout != NULL) {
- __wasi_subscription_t *subscription = &subscriptions[nsubscriptions++];
- *subscription = (__wasi_subscription_t){
- .u.tag = __WASI_EVENTTYPE_CLOCK,
- .u.u.clock.id = __WASI_CLOCKID_REALTIME,
- };
- if (!timespec_to_timestamp_clamp(timeout, &subscription->u.u.clock.timeout)) {
+ int poll_timeout;
+ if (timeout) {
+ uint64_t timeout_u64;
+ if (!timespec_to_timestamp_clamp(timeout, &timeout_u64) ) {
errno = EINVAL;
return -1;
}
- }
- // Execute poll().
- size_t nevents;
- __wasi_event_t events[nsubscriptions];
- __wasi_errno_t error =
- __wasi_poll_oneoff(subscriptions, events, nsubscriptions, &nevents);
- if (error != 0) {
- // WASI's poll requires at least one subscription, or else it returns
- // `EINVAL`. Since a `pselect` with nothing to wait for is valid in POSIX,
- // return `ENOTSUP` to indicate that we don't support that case.
- //
- // Wasm has no signal handling, so if none of the user-provided `pollfd`
- // elements, nor the timeout, led us to producing even one subscription
- // to wait for, there would be no way for the poll to wake up. WASI
- // returns `EINVAL` in this case, but for users of `poll`, `ENOTSUP` is
- // more likely to be understood.
- if (nsubscriptions == 0)
- errno = ENOTSUP;
- else
- errno = error;
- return -1;
- }
+ // Convert nanoseconds to milliseconds:
+ timeout_u64 /= 1000000;
- // Test for EBADF.
- for (size_t i = 0; i < nevents; ++i) {
- const __wasi_event_t *event = &events[i];
- if ((event->type == __WASI_EVENTTYPE_FD_READ ||
- event->type == __WASI_EVENTTYPE_FD_WRITE) &&
- event->error == __WASI_ERRNO_BADF) {
- errno = EBADF;
- return -1;
+ if (timeout_u64 > INT_MAX) {
+ timeout_u64 = INT_MAX;
}
+
+ poll_timeout = (int) timeout_u64;
+ } else {
+ poll_timeout = -1;
+ };
+
+ if (poll(poll_fds, poll_nfds, poll_timeout) < 0) {
+ return -1;
}
- // Clear and set entries in the result sets.
FD_ZERO(readfds);
FD_ZERO(writefds);
- for (size_t i = 0; i < nevents; ++i) {
- const __wasi_event_t *event = &events[i];
- if (event->type == __WASI_EVENTTYPE_FD_READ) {
- readfds->__fds[readfds->__nfds++] = event->userdata;
- } else if (event->type == __WASI_EVENTTYPE_FD_WRITE) {
- writefds->__fds[writefds->__nfds++] = event->userdata;
+ for (size_t i = 0; i < poll_nfds; ++i) {
+ struct pollfd* pollfd = poll_fds + i;
+ if ((pollfd->revents & POLLRDNORM) != 0) {
+ readfds->__fds[readfds->__nfds++] = pollfd->fd;
+ }
+ if ((pollfd->revents & POLLWRNORM) != 0) {
+ writefds->__fds[writefds->__nfds++] = pollfd->fd;
}
}
+
return readfds->__nfds + writefds->__nfds;
}