Jelajahi Sumber

Merge branch 'master' of github.com:redox-os/ralloc

ticki 9 tahun lalu
induk
melakukan
413aaeb77b
1 mengubah file dengan 55 tambahan dan 8 penghapusan
  1. 55 8
      src/bookkeeper.rs

+ 55 - 8
src/bookkeeper.rs

@@ -1,4 +1,4 @@
-//! The memory bookkeeping module.
+//! Memory bookkeeping primitives.
 //!
 //! Blocks are the main unit for the memory bookkeeping. A block is a simple construct with a
 //! `Unique` pointer and a size. Occupied (non-free) blocks are represented by a zero-sized block.
@@ -138,6 +138,36 @@ impl BlockList {
         }
     }
 
+    /// Initialize the block list.
+    ///
+    /// This will do some basic initial allocation, and a bunch of other things as well. It is
+    /// necessary to avoid meta-circular dependency.
+    // TODO can this be done in a more elegant way?
+    fn init(&mut self) {
+        debug_assert!(self.cap == 0, "Capacity is non-zero on initialization.");
+
+        /// The initial capacity.
+        const INITIAL_CAPACITY: usize = 16;
+
+        let reserve = INITIAL_CAPACITY * size_of::<Block>();
+        let brk = unsafe {
+            sys::inc_brk(reserve + align_of::<Block>()).unwrap_or_else(|x| x.handle())
+        };
+        let aligner = aligner(*brk as *const _, align_of::<Block>());
+
+        self.cap = reserve;
+        self.ptr = unsafe {
+            Unique::new((*brk as usize + aligner) as *mut _)
+        };
+
+        self.push(Block {
+            size: aligner,
+            ptr: brk,
+        });
+
+        self.check();
+    }
+
     /// *[See `Bookkeeper`'s respective method.](./struct.Bookkeeper.html#method.alloc)*
     ///
     /// # Example
@@ -232,11 +262,17 @@ impl BlockList {
     /// This will append a block entry to the end of the block list. Make sure that this entry has
     /// a value higher than any of the elements in the list, to keep it sorted.
     fn push(&mut self, block: Block) {
-        let len = self.len;
-        // This is guaranteed not to overflow, since `len` is bounded by the address space, since
-        // each entry represent at minimum one byte, meaning that `len` is bounded by the address
-        // space.
-        self.reserve(len + 1);
+        // Some assertions.
+        debug_assert!(block.size != 0, "Pushing a zero sized block.");
+        debug_assert!(self.last().map_or(0, |x| *x.ptr as usize) <= *block.ptr as usize, "The previous last block is higher than the new.");
+
+        {
+            let len = self.len;
+            // This is guaranteed not to overflow, since `len` is bounded by the address space, since
+            // each entry represent at minimum one byte, meaning that `len` is bounded by the address
+            // space.
+            self.reserve(len + 1);
+        }
 
         unsafe {
             ptr::write((*self.ptr as usize + size_of::<Block>() * self.len) as *mut _, block);
@@ -276,8 +312,8 @@ impl BlockList {
             ptr: ptr,
         };
         let res = Block {
-            ptr: alignment_block.end(),
             size: size,
+            ptr: alignment_block.end(),
         };
 
         // Add it to the list. This will not change the order, since the pointer is higher than all
@@ -429,6 +465,10 @@ impl BlockList {
             self.check();
         }
         */
+
+        // Initialize if necessary.
+        if *self.ptr == EMPTY_HEAP as *mut _ { self.init() }
+
         if needed > self.cap {
             let block = Block {
                 ptr: unsafe { Unique::new(*self.ptr as *mut _) },
@@ -518,6 +558,7 @@ impl BlockList {
     ///
     /// See [`free`](#method.free) for more information.
     fn free_ind(&mut self, ind: usize, block: Block) {
+        // Make some handy assertions.
         debug_assert!(*self[ind].ptr != *block.ptr || !self[ind].is_free(), "Double free.");
 
         // Try to merge right.
@@ -591,6 +632,10 @@ impl BlockList {
     ///
     /// The insertion is now completed.
     fn insert(&mut self, ind: usize, block: Block) {
+        // Some assertions...
+        debug_assert!(block >= self[ind.saturating_sub(1)], "Inserting at {} will make the list unsorted.", ind);
+        debug_assert!(self.find(&block) == ind, "Block is not inserted at the appropriate index.");
+
         // TODO consider moving right before searching left.
 
         // Find the next gap, where a used block were.
@@ -634,10 +679,12 @@ impl BlockList {
     /// This will check for the following conditions:
     ///
     /// 1. The list is sorted.
-    /// 2. No entries are not overlapping.
+    /// 2. No entries are overlapping.
     /// 3. The length does not exceed the capacity.
     #[cfg(debug_assertions)]
     fn check(&self) {
+        if self.len == 0 { return; }
+
         // Check if sorted.
         let mut prev = *self[0].ptr;
         for (n, i) in self.iter().enumerate().skip(1) {