-
Notifications
You must be signed in to change notification settings - Fork 54
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 with Cursor-based API, and passing Miri tests #62
Conversation
This first set of changes fixes a couple issues. The primary issues addressed so far are:
To address the former, I added a To verify the former, I made a little helper type that forces the alignment to some large amount, which made some of the failures go away. This fixed a number of "size isn't as expected", which I think were mostly just not handling the "shrunk heap due to alignment" case (the CODE seems to, but the TESTS seemed not to). #[repr(align(128))]
struct Chonk<const N: usize> {
data: [MaybeUninit<u8>; N]
} This probably isn't the right fix, but it helped verify things. The right fix is to probably either exposing how much of the heap space was lost to alignment somehow. |
The second commit also applies the force-alignment trick to the max_stack tests, which now allows all tests to pass in a "standard" miri run:
However, taking it one (or a few?) steps further, the following configuration now fails:
Digging in further! |
So, in this latest commit, I'm now sort of stuck on this issue:
I had to rework a couple of pointer types to get here, but I think there is some kind of issue between When doing some print debugging, I see the following memory ranges: fn allocate_first_fit(mut previous: &mut Hole, layout: Layout) -> Result<HoleInfo, ()> {
loop {
let allocation: Option<Allocation> = previous
.next
.as_mut()
.and_then(|current| split_hole(current.info(), layout.clone()));
match allocation {
Some(allocation) => {
// link the front/back padding
// Note that there must be no hole between following pair:
// previous - front_padding
// front_padding - back_padding
// back_padding - previous.next
let prev = previous as *mut Hole as usize;
println!("prev: {:016X}..{:016X}", prev, prev + previous.size);
if let Some(padding) = allocation.back_padding {
let back = padding.addr as usize;
println!("back: {:016X}..{:016X}", back, back + padding.size);
}
if let Some(next) = previous.next.as_mut() {
let nxt = (*next) as *mut Hole as usize;
println!("next: {:016X}..{:016X}", nxt, nxt + next.size);
}
panic!();
I'm not certain, but it looks weird to me that |
Specifically, it looks like mutating let new_next = previous.next.as_mut().unwrap().next.take(); Is what triggers the miri failure (I think it's the call to |
Thanks a lot for investigating! If I remember correctly, the let new_next = previous.next.as_mut().unwrap().next.take();
previous.next = new_next; I guess miri is not happy because there is aliasing of We probably need to rework the |
Ok, this seems to be caused by your recent change to |
I started to rework |
Nice! I thought I caught all those, the goal of that was to fix the "tried to access something with align 8 via an align 1 pointer", which might have been fixed/masked by the It's probably worth adding forced-misalignment tests in the future, e.g. starting with |
Hey @phil-opp, I'll likely have a little time later this afternoon to work on this some more, let me know how you want to collab on this. Mostly let me know if you are "tagging out" of a branch, and I can pick up where you left off. |
I don't have time to continue working on this today, so feel free to continue on my branches. I also just send you an invite to the repo to give you write access, then we don't need to synchronize across forks. Thanks again for looking into this! |
So uh, @phil-opp, I sort of rewrote the As of this commit, all tests are now passing with tagged pointers and strict provenance rules:
I probably should take a crack at the dealloc API, since I think it could be made simpler with the new |
I know significant rewrites are bad form - so if you'd like me to walk this back or find a way to make this change more minimal, just let me know! Otherwise I'll try and move the If this ends up not being immediately (or ever) mergeable, no worries! |
Hey @phil-opp, I'm marking this as ready for review, as I've completed the work to switch I know this is a pretty substantial change, let me know if you have any questions, or want to chat about this sync somewhere. |
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.
Looks great, thanks so much @jamesmunns! The code was really easy to follow, also thanks to your great comments. The new assertions on dealloc are a very good idea, too!
As of this commit, all tests are now passing with tagged pointers and strict provenance rules
Wow, even with strict provenance, I did not expect that. 🎉
I know significant rewrites are bad form - so if you'd like me to walk this back or find a way to make this change more minimal, just let me know!
No worries, it's fine :). Most of the code in this crate was written in 2016, long before the stacked borrows and the strict provenance models, so it would probably be difficult to retrofit the old code to the new models.
@phil-opp this should be ready to merge, added Miri checks to CI! |
One quick note - while investigating whether this fixed #60, I realized that containing a |
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.
Looks good to me!
Published as v0.10.0 |
Thanks, thank you so much 🎉 |
The API was changed in rust-osdev/linked-list-allocator#62.
This is WIP PR to address miri issues. it builds on @phil-opp's existing
miri
branch.Fixes #61
Fixes #60