Add Rust impl of wasmtime_ssp_fd_prestat_get#130
Add Rust impl of wasmtime_ssp_fd_prestat_get#130sunfishcode merged 3 commits intobytecodealliance:masterfrom kubkon:master
Conversation
|
|
||
| // Looks up a preopened resource table entry by number. | ||
| static __wasi_errno_t fd_prestats_get_entry( | ||
| __wasi_errno_t fd_prestats_get_entry( |
There was a problem hiding this comment.
I reckon this function could easily be re-implemented in Rust, and should be done in this PR. Would you agree?
There was a problem hiding this comment.
Yeah, this is a relatively simple one.
There was a problem hiding this comment.
OK, I've implemented it as a safe fn in Rust. Have a look and let me know what you think.
wasmtime-wasi/src/host_impls.rs
Outdated
| fd: host::__wasi_fd_t, | ||
| buf: *mut host::__wasi_prestat_t, | ||
| ) -> host::__wasi_errno_t { | ||
| host::rwlock_rdlock(&mut (*prestats).lock as *mut host::rwlock); |
There was a problem hiding this comment.
This should ultimately be handled with ::std::sync::RwLock but I was really apprehensive of changing fd_prestats struct which ultimately would result in having to change loads more in wasmtime-wasi than just a few calls in syscalls.rs. I'm really keen to hear your opinion on it though. Perhaps you can find a nicer solution to this problem.
There was a problem hiding this comment.
I think in the long term we'll want to switch to Rust's RwLock, but we should probably wait on that until all the code that uses read-write locks is in Rust, so we can do it all at once.
wasmtime-wasi/src/host_impls.rs
Outdated
| let dir_name = ::std::ffi::CStr::from_ptr((*prestat).dir).to_str(); | ||
| if let Err(_) = dir_name { | ||
| host::rwlock_unlock(&mut (*prestats).lock as *mut host::rwlock); | ||
| return host::__WASI_EBADF; |
There was a problem hiding this comment.
Here, I have to admit that I have absolutely no clue which error code would be best to return, or if it is even reasonable to convert raw C ptr to &str in order to get its length. We could use libc::strlen but to me that sounds even worse.
There was a problem hiding this comment.
These prestat directory names are things we can validate at wasmtime startup, so this code can actually just panic if it somehow sees an invalid string here.
Concerning the CStr, one thing we could do instead here is replace the dir member of prestat with a pointer and a length so that we can compute it once up front rather than at runtime.
There was a problem hiding this comment.
That sounds good. I'll give it a spin then!
There was a problem hiding this comment.
OK, so I've modified fd_prestat to hold C-str together with its length, and both are populated once in fd_prestats_insert. Have a look and lemme know what you reckon!
wasmtime-wasi/src/host_impls.rs
Outdated
| return error; | ||
| } | ||
|
|
||
| (*buf).pr_type = host::__WASI_PREOPENTYPE_DIR as host::__wasi_preopentype_t; |
There was a problem hiding this comment.
It's the host::__wasi_errno_t nightmare again, that is, type mismatch: host::__WASI_PREOPENTYPE_DIR == u32 while it should be host::__wasi_preopentype_t == u8. It might be a good opportunity to manually define all __wasi_preopentype_t values. What do you think?
There was a problem hiding this comment.
I think you're right. And similar to the errno situation, bringing in these defines into host.rs is where we'll need to go eventually anyway.
There was a problem hiding this comment.
Coolios. I'll include it in this PR then :-)
sunfishcode
left a comment
There was a problem hiding this comment.
I think your approach of making things non-static makes sense. Once everything is in Rust, these will go away anyway :-).
|
|
||
| // Looks up a preopened resource table entry by number. | ||
| static __wasi_errno_t fd_prestats_get_entry( | ||
| __wasi_errno_t fd_prestats_get_entry( |
There was a problem hiding this comment.
Yeah, this is a relatively simple one.
wasmtime-wasi/src/host_impls.rs
Outdated
| fd: host::__wasi_fd_t, | ||
| buf: *mut host::__wasi_prestat_t, | ||
| ) -> host::__wasi_errno_t { | ||
| host::rwlock_rdlock(&mut (*prestats).lock as *mut host::rwlock); |
There was a problem hiding this comment.
I think in the long term we'll want to switch to Rust's RwLock, but we should probably wait on that until all the code that uses read-write locks is in Rust, so we can do it all at once.
wasmtime-wasi/src/host_impls.rs
Outdated
| } | ||
|
|
||
| pub unsafe fn wasmtime_ssp_fd_prestat_get( | ||
| prestats: *mut host::fd_prestats, |
There was a problem hiding this comment.
Can this be an &mut instead of *mut here?
There was a problem hiding this comment.
I've changed it &mut and made the fn safe 😎
wasmtime-wasi/src/host_impls.rs
Outdated
| pub unsafe fn wasmtime_ssp_fd_prestat_get( | ||
| prestats: *mut host::fd_prestats, | ||
| fd: host::__wasi_fd_t, | ||
| buf: *mut host::__wasi_prestat_t, |
There was a problem hiding this comment.
And can this be a &mut too? And if so, can we remove unsafe from this function (though it may still need unsafe inside its body)?
There was a problem hiding this comment.
I've changed it &mut and made the fn safe 😎
wasmtime-wasi/src/host_impls.rs
Outdated
| return error; | ||
| } | ||
|
|
||
| (*buf).pr_type = host::__WASI_PREOPENTYPE_DIR as host::__wasi_preopentype_t; |
There was a problem hiding this comment.
I think you're right. And similar to the errno situation, bringing in these defines into host.rs is where we'll need to go eventually anyway.
wasmtime-wasi/src/host_impls.rs
Outdated
| let dir_name = ::std::ffi::CStr::from_ptr((*prestat).dir).to_str(); | ||
| if let Err(_) = dir_name { | ||
| host::rwlock_unlock(&mut (*prestats).lock as *mut host::rwlock); | ||
| return host::__WASI_EBADF; |
There was a problem hiding this comment.
These prestat directory names are things we can validate at wasmtime startup, so this code can actually just panic if it somehow sees an invalid string here.
Concerning the CStr, one thing we could do instead here is replace the dir member of prestat with a pointer and a length so that we can compute it once up front rather than at runtime.
Exactly my thinking as well! :-) |
In more detail, this commit: * makes fd_prestat_get safe * rewrites fd_prestats_get_entry in (safe) Rust * creates helper macros for rwlock read lock and unlock
| Some(prestat) | ||
| } | ||
|
|
||
| macro_rules! rwlock_rdlock { |
There was a problem hiding this comment.
Given the fact that we'll be using host::rwlock_rdlock (and host::rwlock_unlock) in a couple more places before we port every single bit of code from C that is using it, I've decided to add these simple macros, just for convenience.
|
I reckon that looks good! |
Add sha256 benchmark
…#130) Currentlly, `wasmtime_continuations::Payloads` looks like this (after inlining some definitions): ```rust pub struct Payloads { pub length: usize, pub capacity: usize, pub data: *mut u128, } ``` This PR changes the type of the `capacity` and `length` fields from `usize` to `u32`. This is reasonable, as the maximum length/capacity values we will see are bounded by the maximum of the following: - Number of parameters/return values of any function used as a continuation - Number of parameters/return values of any tag Of course, it would be nice to somehow enforce the actual maximum of these values that we support, but that seems out of scope for this PR. Each `ContinuationObject` contains two such `Payloads` objects, so this change saves us 16 bytes per continuation. This is probably not a meaningful optimization by itself, but shrinking these values is useful for subsequent work where it may come in handy when I'm packing parts of this in an enum in a custom way. This PR also adds a `repr(C)` to `Payloads`, which should have been there the whole time, but wasn't.
Implement `Constraint::Variant` binding constraint. This implementation is not ideal: 1. Will not handle cases where we have decided to model an ISLE enum as some other type. The binding the constraint applies to is assumed to have enum value type. 2. Does not confirm that the enum type matches the enum type of the binding constraint. The prior layers should have confirmed this won't happen. Updates avanhatt#48
…ero-length-stream-reads-and-writes handle zero-length stream writes/reads per latest spec
This PR addresses #120. It ports
wasmtime_ssp_fd_prestat_getfrom C to Rust.I'd like to use this PR to discuss a few things regarding all manner of
prestat_related things inwasmtime. Firstly, please note that I've decided to try and go the least intrusive way possible when portingfd_prestate_getfunctionality; that is, my goal was to change as few things at Rust's side ofwasmtime-wasias possible.Summary of changes:
rwlock_functions inlocking.hnon-static and non-inlined to be able to link to them viabindgen. The main reason for this was to avoid having to mess around with re-implementing in Rustfd_prestatsstruct which requires read-write locking. Having said that, however, IMHO it should ultimately be rewritten in safe Rust.fd_prestats_get_entrynon-static and bindable bybindgen. However, since the functionality of this function is relatively simple, it shouldn't prove hard for it to be rewritten in Rust, and hence, should be done ASAP.fd_prestatfromposix.cintoposix.hin order forbindgento be able to properly bind it. Here, I was mainly after getting access to the only field that the struct features, namelyconst char* dir.wasmtime_ssp_fd_prestat_getis currently a direct translation of C version into unsafe Rust, so any suggestions in improving its safety are more than welcome.Please leave as many suggestions and comments as possible!