Skip to content

Commit 7c6c6fc

Browse files
authored
fix: support MemoryArena allocations up to 4GB (#62)
A MemoryArena should support allocations up to 4GB and #60 broke this by not accounting for the "max page id" when pages are now 50% the size of what the originally were. This cleans up the code so things stay in sync if we change NUM_BITS_PAGE_ADDR again and adds a unit test
1 parent 5b5ea75 commit 7c6c6fc

1 file changed

Lines changed: 40 additions & 6 deletions

File tree

stacker/src/memory_arena.rs

Lines changed: 40 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,12 @@ use parking_lot::Mutex;
3535
const NUM_BITS_PAGE_ADDR: usize = 19;
3636
const PAGE_SIZE: usize = 1 << NUM_BITS_PAGE_ADDR; // pages are 512k large
3737

38+
// We use 32-bits addresses.
39+
// - 19 bits for the in-page addressing
40+
// - 13 bits for the page id.
41+
// This limits us to 2^13 - 1=8191 for the page id.
42+
const MAX_PAGES: usize = 1 << (32 - NUM_BITS_PAGE_ADDR);
43+
3844
/// Represents a pointer into the `MemoryArena`
3945
/// .
4046
/// Pointer are 32-bits and are split into
@@ -248,11 +254,7 @@ struct Page {
248254

249255
impl Page {
250256
fn new(page_id: usize) -> Page {
251-
// We use 32-bits addresses.
252-
// - 20 bits for the in-page addressing
253-
// - 12 bits for the page id.
254-
// This limits us to 2^12 - 1=4095 for the page id.
255-
assert!(page_id < 4096);
257+
assert!(page_id < MAX_PAGES);
256258
Page {
257259
page_id,
258260
len: 0,
@@ -301,7 +303,7 @@ impl Page {
301303
#[cfg(test)]
302304
mod tests {
303305

304-
use super::MemoryArena;
306+
use super::{MemoryArena, MAX_PAGES};
305307
use crate::memory_arena::PAGE_SIZE;
306308

307309
#[test]
@@ -376,4 +378,36 @@ mod tests {
376378
assert_eq!(arena.read::<MyTest>(addr_a), a);
377379
assert_eq!(arena.read::<MyTest>(addr_b), b);
378380
}
381+
382+
#[test]
383+
fn test_can_allocate_4GB() {
384+
use super::NUM_BITS_PAGE_ADDR;
385+
386+
let mut arena = MemoryArena::default();
387+
for i in 0..MAX_PAGES {
388+
let addr = arena.allocate_space(PAGE_SIZE - 1); // -1 to ensure we don't cross page boundary
389+
assert_eq!(addr.page_id(), i);
390+
}
391+
assert_eq!(arena.pages.len(), 1 << (32 - NUM_BITS_PAGE_ADDR));
392+
assert_eq!(
393+
arena.mem_usage(),
394+
PAGE_SIZE * (1 << (32 - NUM_BITS_PAGE_ADDR))
395+
);
396+
}
397+
#[test]
398+
#[should_panic]
399+
fn test_cannot_allocate_more_than_4GB() {
400+
use super::NUM_BITS_PAGE_ADDR;
401+
402+
let mut arena = MemoryArena::default();
403+
for i in 0..MAX_PAGES + 1 {
404+
let addr = arena.allocate_space(PAGE_SIZE - 1); // -1 to ensure we don't cross page boundary
405+
assert_eq!(addr.page_id(), i);
406+
}
407+
assert_eq!(arena.pages.len(), 1 << (32 - NUM_BITS_PAGE_ADDR));
408+
assert_eq!(
409+
arena.mem_usage(),
410+
PAGE_SIZE * (1 << (32 - NUM_BITS_PAGE_ADDR))
411+
);
412+
}
379413
}

0 commit comments

Comments
 (0)