-
Notifications
You must be signed in to change notification settings - Fork 216
Port clocks and filesystems functions to use native wasip2 operations #606
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
Note: there's no automated way (that I know of) to check that there are no uses of the preview1 filesystems methods when |
6f9de1e
to
76e18ad
Compare
76e18ad
to
39e65a4
Compare
e51b64f
to
bf042e2
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So far reviewed clocks, this one will take time to go through piece by piece
At this point, there should be no further uses of the preview1 component adapter for clocks and filesystems methods when __wasilibc_use_wasip2 is defined. Also added a DEBUG option to the Makefile that enables -O0/g when DEBUG=true is passed in.
Co-authored-by: Pat Hickey <[email protected]>
Co-authored-by: Pat Hickey <[email protected]>
a1a9296
to
b3c729d
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Today I made it up to the end of the libc itself, and I skimmed the tests. I'll give the tests another read-through later.
It appears __wasilibc_fd_renumber isnt ported in this PR - that should be possible to implement just by manipulating libc's own descriptor table
} | ||
|
||
if (!dir_entry_optional.is_some) { | ||
// End-of-file |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Need to close the stream and remove it from the descriptor table - otherwise its effectively leaked. (And in the error case as well)
fs_flags |= FILESYSTEM_DESCRIPTOR_FLAGS_READ; | ||
} | ||
if ((oflag & O_WRONLY) != 0) { | ||
// Sync flags are not supported yet |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this a TODO, or an assertion about implementations? I think you'd want to take care of the presence or absence of O_SYNC and translating that to a descriptor flag below this switch
@@ -110,6 +111,11 @@ int ioctl(int fildes, int request, ...) { | |||
return 0; | |||
} | |||
case FIONBIO: { | |||
#ifdef __wasilibc_use_wasip2 | |||
// wasip2 doesn't support setting the non-blocking flag |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thats correct, and for files this doesn't matter, but if this was a socket, I think we'd want to emulate setting the nonblocking flag by switching the implementations of send/recv from blocking to nonblocking stream read/writes. But just googling around it seems like this particular ioctl has a checkered past so maybe it doesn't matter if we just say ENOTSUP? Genuinely not sure what the right thing is to do here.
@@ -61,14 +61,24 @@ int pselect(int nfds, fd_set *restrict readfds, fd_set *restrict writefds, | |||
|
|||
int poll_timeout; | |||
if (timeout) { | |||
#ifdef __wasilibc_use_wasip2 | |||
wall_clock_datetime_t timestamp; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we want to use the monotonic clock for timeouts instead of the wall clock, since its about measuring duration
|
||
#ifdef __wasilibc_use_wasip2 | ||
// Following the behavior of the preview1 component adapter, | ||
// only write the first non-empty iov |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't have super strong feelings about this, but I'm fine with trying to write as much as possible here by iterating through the iovs instead of following the component adapter's behavior, which has surprised some users.
if ((flags & ~TIMER_ABSTIME) != 0) | ||
return EINVAL; | ||
|
||
// Prepare polling subscription. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I guess this is fine for this PR but I do see its rewritten properly in #608 so all good.
return -1; | ||
} | ||
} | ||
return bytes_skipped; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
should this be total_bytes_skipped?
offset_to_use = offset + entry->stream.offset; | ||
break; | ||
case SEEK_END: { | ||
// Find the end of the stream (is there a better way to do this?) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For file streams, I think the efficient way to implement this is to get the filestat and use the len field.
|
||
// Get the output stream | ||
filesystem_own_output_stream_t stream_owned; | ||
ok = filesystem_method_descriptor_write_via_stream(entry->file.file_handle, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we cache a stream per file_handle to be used by write, rather than open a new one each write?
|
||
if (num_bytes_permitted < nbyte) { | ||
streams_own_pollable_t pollable = streams_method_output_stream_subscribe(output_stream); | ||
poll_method_pollable_block(poll_borrow_pollable(pollable)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This pollable gets leaked - it needs a drop call. But also, can we cache it for next time this output stream is used? Creating a new pollable and dropping it each time creates more churn than ideal.
if (fildes == 1) | ||
output_stream = streams_borrow_output_stream(stdout_get_stdout()); | ||
else if (fildes == 2) | ||
output_stream = streams_borrow_output_stream(stderr_get_stderr()); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we cache these streams, as well, so that libc only needs to call get_stdout and get_stderr once for the lifetime of the instance?
// This is a tagged union. When adding/removing/renaming cases, be sure to keep the tag and union definitions in sync. | ||
typedef struct { | ||
enum { | ||
DESCRIPTOR_TABLE_ENTRY_TCP_SOCKET, | ||
DESCRIPTOR_TABLE_ENTRY_UDP_SOCKET, | ||
DESCRIPTOR_TABLE_ENTRY_FILE_HANDLE, | ||
DESCRIPTOR_TABLE_ENTRY_DIRECTORY_STREAM, | ||
DESCRIPTOR_TABLE_ENTRY_FILE_STREAM |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Mix of tabs/spaces
At this point, there should be no further uses of the preview1 component adapter for clocks and filesystems methods when __wasilibc_use_wasip2 is defined.
Also added a DEBUG option to the Makefile that enables -O0/g when DEBUG=true is passed in.