-
Notifications
You must be signed in to change notification settings - Fork 346
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
Refactor fd read/write #3852
Refactor fd read/write #3852
Conversation
Thanks for the feedback, I will slowly address them. So currently Currently, I still need to:
|
Wow, the only difference between 7721683 and dc74101 is just one inlined variable, but dc74101 somehow failed EDIT: After a closer look, this should be caused by the variable I reverted the entire inline variable commit. |
You changed evaluation order: // Runs `bytes.to_vec()` after `Read::read.
let result = Read::read(&mut { self }, bytes);
ecx.read_byte_helper(ptr, bytes.to_vec(), result, dest)?; // Runs `bytes.to_vec()` before `Read::read.
ecx.read_byte_helper(ptr, bytes.to_vec(), Read::read(&mut { self }, bytes), dest)?; So maybe that explains the difference. |
Is there any nice way to deref Pointer type to a place? So for eventfd, I perhaps can directly write to the user supplied buffer using fn read_byte_helper_ev(
&mut self,
buf_place: &MPlaceTy<'tcx>,
read_val: u64,
result: io::Result<usize>,
dest: &MPlaceTy<'tcx>,
) -> InterpResult<'tcx> {
let this = self.eval_context_mut();
// `File::read` never returns a value larger than `count`, so this cannot fail.
match result.map(|c| i64::try_from(c).unwrap()) {
// try to pass this the write_ptr inside write
// Pass the pointer inside the write function.
Ok(read_bytes) => {
// Write to the user supplied buffer.
this.write_int(read_val, buf_place)?; // <-- Here!!
// Write to the function return value place.
this.write_int(read_bytes, dest)?;
return Ok(());
}
Err(e) => {
this.set_last_error_from_io_error(e)?;
this.write_int(-1, dest)?;
return Ok(());
}
}
} Unfortunately I can't just use |
71 | let buf_place = ecx.deref_pointer_as(&ptr, ecx.machine.layouts.u64);
| ---------------- ^^^^ the trait `rustc_const_eval::interpret::Readable<'_, machine::Provenance>` is not implemented for `rustc_const_eval::interpret::Pointer<std::option::Option<machine::Provenance>>`
| |
| required by a bound introduced by this call
|
= help: the following other types implement trait `rustc_const_eval::interpret::Readable<'tcx, Prov>`:
rustc_const_eval::interpret::ImmTy<'tcx, Prov>
rustc_const_eval::interpret::MPlaceTy<'tcx, Prov>
rustc_const_eval::interpret::OpTy<'tcx, Prov> We might also need to keep it as a Pointer type (instead of using // Check that the *entire* buffer is actually valid memory.
this.check_ptr_access(buf, Size::from_bytes(count), CheckInAllocMsg::MemoryAccessTest)?; |
Yes, Instead of passing it as a pointer, you could also try passing it as an |
Another idea here: These are all the file description that implements
So for the first three |
I think they should all just take a Pointer. We already have a helper function (I think) to write a bunch of bytes to a pointer, so it should not be hard for fs and socket to use that.
|
☔ The latest upstream changes (presumably #3867) made this pull request unmergeable. Please resolve the merge conflicts. |
This is partially blocked by rust-lang/rust#130215 as I'd need the |
@rustbot ready |
Please squash the commits, then r=me @bors delegate+ |
Refactor fd read/write This PR passed the responsibility of reading to user supplied buffer and dest place to each implementation of ``FileDescription::read/write/pread/pwrite``. This is part of #3665.
@bors r- |
src/shims/unix/linux/eventfd.rs
Outdated
// eventfd read at the size of u64. | ||
let buf_place = ecx.ptr_to_mplace_unaligned(ptr, ecx.machine.layouts.u64); |
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.
Please do this after the size check.
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.
Unfortunately inside the size check, return return_read_bytes_and_count_ev(&buf_place, None, result, dest, ecx);
is called, so we need buf_place
. I probably should separate these two code path in return_read_bytes_and_count
into different function.
match result {
Ok(read_bytes) => {
// If reading to `bytes` did not fail, we write those bytes to the buffer.
// Crucially, if fewer than `bytes.len()` bytes were read, only write
// that much into the output buffer!
this.write_bytes_ptr(buf, bytes[..read_bytes].iter().copied())?;
// The actual read size is always less than what got originally requested so this cannot fail.
this.write_int(u64::try_from(read_bytes).unwrap(), dest)?;
return Ok(());
}
Err(e) => {
this.set_last_error_from_io_error(e)?;
this.write_int(-1, dest)?;
return Ok(());
}
}
This is the same issue as #3852 (comment).
src/shims/unix/linux/eventfd.rs
Outdated
@@ -150,7 +157,8 @@ impl FileDescription for Event { | |||
// types for current file description. | |||
ecx.check_and_update_readiness(self_ref)?; | |||
|
|||
Ok(Ok(U64_ARRAY_SIZE)) | |||
let result = Ok(U64_ARRAY_SIZE); | |||
ecx.return_written_byte_count_or_error(result, dest) |
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.
Why is return_written_byte_count_or_error
a helper function? Every single caller fixes either Err
or Ok
so this is funneling through a Result
without a good reason, it just makes the code harder to follow.
If there is any helper we want here, it is a new very generic helper that sets the last errors and also writes -1
to dest
. But that's probably better done in a future PR, for now you can just copy those 2 lines here I would say, like we do everywhere else.
src/shims/unix/linux/eventfd.rs
Outdated
self.counter.set(0); | ||
// When any of the event happened, we check and update the status of all supported event | ||
// types for current file description. | ||
ecx.check_and_update_readiness(self_ref)?; | ||
|
||
return Ok(Ok(U64_ARRAY_SIZE)); | ||
return_read_bytes_and_count_ev(&buf_place, Some(counter), result, dest, ecx) |
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.
Why is return_read_bytes_and_count_ev
a helper function? Every single caller fixes either Err
or Ok
so this is funneling through a Result
without a good reason, it just makes the code harder to follow.
If there is any helper we want here, it is a new very generic helper that sets the last errors and also writes -1
to dest
. But that's probably better done in a future PR, for now you can just copy those 2 lines here I would say, like we do everywhere else.
☀️ Try build successful - checks-actions |
Instead of separating the helper with match result {
Ok(read_bytes) => {
// If reading to `bytes` did not fail, we write those bytes to the buffer.
// Crucially, if fewer than `bytes.len()` bytes were read, only write
// that much into the output buffer!
this.write_bytes_ptr(buf, bytes[..read_bytes].iter().copied())?;
// The actual read size is always less than what got originally requested so this cannot fail.
this.write_int(u64::try_from(read_bytes).unwrap(), dest)?;
return Ok(());
}
Err(e) => {
this.set_last_error_from_io_error(e)?;
this.write_int(-1, dest)?;
return Ok(());
}
} or use As this could be done in a new PR, @rustbot ready |
… len in read to usize
0d090f7
to
d7741a9
Compare
Thanks! I've done some further minor tweaks, mostly to remove a bunch of Also I re-did eventfd a bit, see the last commit. I didn't think that helper function was helpful so I removed it. Further improvements are possible I think (specifically some sort of helper for the quite common case of "set errno and return -1"), but that can be a separate PR. @bors r+ |
☀️ Test successful - checks-actions |
This PR passed the responsibility of reading to user supplied buffer and dest place to each implementation of
FileDescription::read/write/pread/pwrite
.This is part of #3665.