1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374 |
- //! BRK abstractions.
- //!
- //! This module provides safe abstractions over SBRK.
- use prelude::*;
- use core::cmp;
- /// Canonicalize a BRK request.
- ///
- /// Syscalls can be expensive, which is why we would rather accquire more memory than necessary,
- /// than having many syscalls acquiring memory stubs. Memory stubs are small blocks of memory,
- /// which are essentially useless until merge with another block.
- ///
- /// To avoid many syscalls and accumulating memory stubs, we BRK a little more memory than
- /// necessary. This function calculate the memory to be BRK'd based on the necessary memory.
- ///
- /// The return value is always greater than or equals to the argument.
- #[inline]
- fn canonicalize_space(min: usize) -> usize {
- // TODO: Tweak this.
- /// The BRK multiplier.
- ///
- /// The factor determining the linear dependence between the minimum segment, and the acquired
- /// segment.
- const BRK_MULTIPLIER: usize = 2;
- /// The minimum size to be BRK'd.
- const BRK_MIN: usize = 1024;
- /// The maximal amount of _extra_ elements.
- const BRK_MAX_EXTRA: usize = 65536;
- let res = cmp::max(BRK_MIN, min + cmp::min(BRK_MULTIPLIER * min, BRK_MAX_EXTRA));
- // Make some handy assertions.
- debug_assert!(res >= min, "Canonicalized BRK space is smaller than the one requested.");
- res
- }
- /// BRK new space.
- ///
- /// The first block represents the aligner segment (that is the precursor aligning the middle
- /// block to `align`), the second one is the result and is of exactly size `size`. The last
- /// block is the excessive space.
- pub fn get(size: usize, align: usize) -> (Block, Block, Block) {
- // Calculate the canonical size (extra space is allocated to limit the number of system calls).
- let brk_size = canonicalize_space(size) + align;
- // Use SBRK to allocate extra data segment. The alignment is used as precursor for our
- // allocated block. This ensures that it is properly memory aligned to the requested value.
- let (alignment_block, rest) = Block::brk(brk_size).align(align).unwrap();
- // Split the block to leave the excessive space.
- let (res, excessive) = rest.split(size);
- // Make some assertions.
- debug_assert!(res.aligned_to(align), "Alignment failed.");
- debug_assert!(res.size() + alignment_block.size() + excessive.size() == brk_size, "BRK memory leak.");
- (alignment_block, res, excessive)
- }
- #[cfg(test)]
- mod test {
- use super::*;
- #[test]
- fn test_ordered() {
- let brk = get(20, 1);
- assert!(brk.0 <= brk.1);
- assert!(brk.1 <= brk.2);
- }
- }
|