-
Notifications
You must be signed in to change notification settings - Fork 2
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
Multipage Deallocator #19
base: main
Are you sure you want to change the base?
Changes from 4 commits
c42d438
1ba7094
2988a1a
7e319f9
b330656
b60af97
4148bf8
d4d2ece
ef92b91
91eb603
23cbbc8
2cb4bff
29ae1d2
85a99f9
c10bb2d
b0bb029
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -260,19 +260,21 @@ impl PageAllocator for Option<PerCpuPageAllocator> { | |
|
||
fn dealloc_data_page_list(&self, pages: &DataPageListWrapper<Clean, Free>) -> Result<()> { | ||
if let Some(allocator) = self { | ||
let mut page_list = pages.get_page_list_cursor(); | ||
let mut page = page_list.current(); | ||
while page.is_some() { | ||
// janky syntax to deal with the fact that page_list.current() returns an Option | ||
if let Some(page) = page { | ||
// TODO: refactor to avoid acquiring lock on every iteration | ||
allocator.dealloc_page(page.get_page_no())?; | ||
page_list.move_next(); | ||
} else { | ||
unreachable!() | ||
} | ||
page = page_list.current(); | ||
} | ||
let page_list = pages.get_page_list_cursor(); | ||
// let mut page = page_list.current(); | ||
// while page.is_some() { | ||
// // janky syntax to deal with the fact that page_list.current() returns an Option | ||
// if let Some(page) = page { | ||
// // TODO: refactor to avoid acquiring lock on every iteration | ||
// allocator.dealloc_page(page.get_page_no())?; | ||
// page_list.move_next(); | ||
// } else { | ||
// unreachable!() | ||
// } | ||
// page = page_list.current(); | ||
// } | ||
// Ok(()) | ||
allocator.dealloc_multiple_page(page_list)?; | ||
Ok(()) | ||
} else { | ||
pr_info!("ERROR: page allocator is uninitialized\n"); | ||
|
@@ -292,6 +294,7 @@ impl PageAllocator for Option<PerCpuPageAllocator> { | |
|
||
fn dealloc_dir_page_list(&self, pages: &DirPageListWrapper<Clean, Free>) -> Result<()> { | ||
if let Some(allocator) = self { | ||
let page_list = pages.get_page_list_cursor(); | ||
let mut page_list = pages.get_page_list_cursor(); | ||
let mut page = page_list.current(); | ||
while page.is_some() { | ||
|
@@ -343,6 +346,83 @@ impl PerCpuPageAllocator { | |
Ok(()) | ||
} | ||
} | ||
|
||
|
||
fn dealloc_multiple_page(&self, mut page_list : Cursor<'_, Box<LinkedPage>>) -> Result<()> { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It would be cleaner to move this code into |
||
// hash map to store free list lock for every cpu | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm a little confused by this comment -- it stores the free list for each CPU, not the lock, right? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. You're absolutely right. I made sure to change the comment. |
||
let mut cpu_free_list_map : RBTree<usize, Vec<PageNum>> = RBTree::new(); | ||
|
||
|
||
let mut page = page_list.current(); // head of page list | ||
|
||
let mut num_pages = 0; | ||
|
||
// get a list of pages #s for each cpu | ||
while page.is_some() { | ||
if let Some(page) = page { | ||
pr_info!("Page: {}", page.get_page_no()); | ||
|
||
let cpu : usize = ((page.get_page_no() - self.start) / self.pages_per_cpu).try_into()?; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. There might be a function defined elsewhere to do this calculation (if not, we should make one). There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'll go ahead and make a helper function to do this calculation. |
||
|
||
if matches!(cpu_free_list_map.get(&cpu), None) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Since we are only matching against one pattern, and it's the |
||
cpu_free_list_map.try_insert(cpu, Vec::new())?; | ||
} | ||
|
||
// add cpu page to vector (vector is mutable) | ||
let cpu_page_vec : &mut Vec<PageNum> = cpu_free_list_map.get_mut(&cpu).unwrap(); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Use There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. When I change it to ?, I get the following compiler error: "cannot use the Update: I think I made the unwrap safe by calling is_some() on the option returned by the get_mut() function |
||
|
||
cpu_page_vec.try_push(page.get_page_no())?; | ||
|
||
page_list.move_next(); | ||
} | ||
page = page_list.current(); | ||
num_pages += 1; | ||
} | ||
|
||
pr_info!("Num Pages in List: {}", num_pages); | ||
|
||
// add pages to corresponding free list in ascending cpu # order | ||
for (cpu, page_nos) in cpu_free_list_map.iter() { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Just to be sure -- have you confirmed/checked that this always iterates over the CPU keys in ascending order? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I've confirmed through |
||
|
||
let free_list = Arc::clone(&self.free_lists[*cpu]); | ||
let mut free_list = free_list.lock(); | ||
let old_free_pages = free_list.free_pages; | ||
|
||
for page_no in page_nos.iter() { | ||
|
||
free_list.free_pages += 1; | ||
let res = free_list.list.try_insert(*page_no, ()); | ||
|
||
// unwrap the error so we can get at the option | ||
let res = match res { | ||
Ok(res) => res, | ||
Err(e) => { | ||
pr_info!( | ||
"ERROR: failed to insert {:?} into page allocator at CPU {:?}, error {:?}\n", | ||
page_no, | ||
cpu, | ||
e | ||
); | ||
return Err(e); | ||
} | ||
}; | ||
|
||
// check that the page was not already present in the tree. CAUSING ERRORS DUE TO TYPE ANNOTATION ISSUES | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What error is this running into? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I was able to resolve that error but forgot to delete the comment. I'll make sure to delete it. |
||
if res.is_some() { | ||
pr_info!( | ||
"ERROR: page {:?} was already in the allocator at CPU {:?}\n", | ||
page_no, | ||
cpu | ||
); | ||
return Err(EINVAL); | ||
} | ||
pr_info!("Cpu: {} Freed: {}", cpu, page_no); | ||
pr_info!("Pages Added: {}", free_list.free_pages - old_free_pages); | ||
} | ||
} | ||
|
||
return Ok(()); | ||
} | ||
} | ||
|
||
// placeholder page descriptor that can represent either a dir or data page descriptor | ||
|
@@ -2365,4 +2445,4 @@ impl<Op> DataPageListWrapper<InFlight, Op> { | |
pages: self.pages, | ||
} | ||
} | ||
} | ||
} |
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.
Remove this line, since we obtain the cursor for the list on the next line.