-
Notifications
You must be signed in to change notification settings - Fork 138
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
Add checked arithmetic operations traits #298
Add checked arithmetic operations traits #298
Conversation
137cdef
to
76ca2e9
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.
Thanks for this PR. My comments are mostly doc/implementation nits.
Note that while #299 makes some of the implementation tricky. I don't think we have to wait on that bug to be fixed before submitting these changes.
I've made all requested changes and have mostly stuck to your requests directly, the only difference would be retention of the chain in the |
@ncatelli I've resolved all the comments that you've fixed (I think there are still a few more comment nits to fixed). Can you add implementations for the other address types ( |
Also @ncatelli per #293 (comment) can you remove the |
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.
Sorry about that. I had over looked the other changes you'd requested, these are now fixed.
I've implemented the trait for the additional types you requested for the types laid out in #293. I've left a few comments regarding preference questions on a few of the check calls. Since most of these questions apply to the implementations of both Page
and PhysFrame
, I've only left discussion comments on PhysFrame
.
Again, thanks again for all the time, I know this PR and attached issue have been fairly high-touch.
@@ -16,7 +17,7 @@ pub struct PhysFrame<S: PageSize = Size4KiB> { | |||
} | |||
|
|||
impl<S: PageSize> PhysFrame<S> { | |||
/// Returns the frame that starts at the given virtual address. | |||
/// Returns the frame that starts at the given physical address. |
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.
Small typo that I'd noticed and corrected. I just wanted to call it out explicitly since this was beyond the scope of the PR and just to spot-check my change
@@ -28,7 +29,7 @@ impl<S: PageSize> PhysFrame<S> { | |||
} | |||
|
|||
const_fn! { | |||
/// Returns the frame that starts at the given virtual address. | |||
/// Returns the frame that starts at the given physical address. |
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.
Same as above, additional doc change.
src/structures/paging/frame.rs
Outdated
fn checked_sub(self, rhs: PhysFrame<S>) -> Option<Self::Output> { | ||
self.start_address() | ||
.checked_sub(rhs.start_address()) | ||
.map(PhysAddr::new) |
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 opted for new
, which can panic over try_new
as the sub should prevent ever falling into panic inducing address space unless someone is doing something really bananas. I can happily change this to try_new
if you would prefer since new
just calls try_new
under the hood. This would guarantee we entirely avoid a panic that I think won't ever even happen, but at the expense of denser code.
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.
Nevermind. The more i thought about this I opted to change it. The guarantee of no panic for a checked_*
method should probably be the default.
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.
What is the point of converting the offset to a PhysAddr
and PhysFrame
? Couldn't you just write this?
self.start_address()
.checked_sub(rhs.start_address())
.map(|offset| offset / S::SIZE)
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.
Hello, I opted for the case of safely validating of the address and the alignment as there are a few cases where an unaligned frame start address could be returned. This would necessitate the caller broke the contract of from_start_address_unchecked. I'm happy to change this method if you feel strongly about it.
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.
Because from_start_unchecked
is marked as unsafe, we can always assume that the caller did not violate the safety requirements and we don't need to check for them again.
Even if the caller did violate the requirements, this would cause the function to fail as if an underflow occurred even when that's not the case, which seems a bit unexpected.
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.
Fair, the change you've requested has been made.
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 noticed that you also used this pattern in a few other places, those probably need to be changed too.
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.
Applied the same change to Page::checked_sub
to match the same. By other's i assume you mean something like https://github.com/rust-osdev/x86_64/pull/298/files#diff-d2a15219d98ad66c2aeac0ee03d682034bc619fe5905e63960599aa58b7a63cfR332-R342, in which this was done for the sake of checking valid addresses of the multiple and I think there is no reason to change that.
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.
You don't need to check if the offset is a valid address, in fact it is wrong to do so. For addition it's perfectly fine to jump from the lower half of the address space to the upper half. In that case the offset is not necessarily a valid virtual address. Offsets just aren't the same as virtual (or physical) addresses.
I'm aware that there has been some discussion on whether we should allow jumping from the lower half to the upper half and I'm open to change in that direction. However for now we should make sure that the checked and non-checked implementations behave in the same way.
fn checked_add(self, rhs: u64) -> Option<Self::Output> { | ||
let phys_addr_rhs = rhs | ||
.checked_mul(S::SIZE) | ||
.and_then(|addr| PhysAddr::try_new(addr).ok())?; |
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.
Let me know if this is overkill and you'd like me to opt for a lighter weight checked op by removing the PhysAddr validity check.
Alright, that should be the last of my changes until the next review cycle. I wanted to make sure intent was either clear or documented with examples (that hopefully make it clear). |
One additional note, while I'm aware of the discussion in #293 about removing the |
Triage: This PR has been waiting for some time. @josephlr Do you have time for a new review, or should I try to take over? |
4d95a3a
to
ad70df8
Compare
General
This is an initial attempt to define a
CheckedAdd
andCheckedSub
set of traits per the traits discussed in the linked issue below. I've applied these traits to theaddressing types listed in the issue to check address, page and frame arithmetic.VirtAddr
Related Issues
#293