From 45889fecafffec8c964c5159896b0080c21851a6 Mon Sep 17 00:00:00 2001 From: Philipp Oppermann Date: Fri, 6 Mar 2020 11:27:57 +0100 Subject: [PATCH 1/3] Make AllocRef implementation optional behind new `alloc_ref` feature --- Cargo.toml | 1 + src/hole.rs | 8 ++++---- src/lib.rs | 14 ++++++++++---- 3 files changed, 15 insertions(+), 8 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 8d7cfad..412ddf5 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -14,6 +14,7 @@ homepage = "http://os.phil-opp.com/kernel-heap.html#a-better-allocator" [features] default = ["use_spin"] use_spin = ["spinning_top"] +alloc_ref = [] [dependencies.spinning_top] version = "0.1.0" diff --git a/src/hole.rs b/src/hole.rs index e2e0bfc..c95d0e4 100644 --- a/src/hole.rs +++ b/src/hole.rs @@ -1,4 +1,4 @@ -use alloc::alloc::{AllocErr, Layout}; +use alloc::alloc::Layout; use core::mem::{align_of, size_of}; use core::ptr::NonNull; @@ -49,7 +49,7 @@ impl HoleList { /// block is returned. /// This function uses the “first fit” strategy, so it uses the first hole that is big /// enough. Thus the runtime is in O(n) but it should be reasonably fast for small allocations. - pub fn allocate_first_fit(&mut self, layout: Layout) -> Result, AllocErr> { + pub fn allocate_first_fit(&mut self, layout: Layout) -> Result, ()> { assert!(layout.size() >= Self::min_size()); allocate_first_fit(&mut self.first, layout).map(|allocation| { @@ -192,7 +192,7 @@ fn split_hole(hole: HoleInfo, required_layout: Layout) -> Option { /// care of freeing it again. /// This function uses the “first fit” strategy, so it breaks as soon as a big enough hole is /// found (and returns it). -fn allocate_first_fit(mut previous: &mut Hole, layout: Layout) -> Result { +fn allocate_first_fit(mut previous: &mut Hole, layout: Layout) -> Result { loop { let allocation: Option = previous .next @@ -210,7 +210,7 @@ fn allocate_first_fit(mut previous: &mut Hole, layout: Layout) -> Result { // this was the last hole, so no hole is big enough -> allocation not possible - return Err(AllocErr); + return Err(()); } } } diff --git a/src/lib.rs b/src/lib.rs index 7b2177a..c61e25e 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,5 +1,5 @@ #![feature(const_fn)] -#![feature(allocator_api)] +#![cfg_attr(feature = "alloc_ref", feature(allocator_api))] #![no_std] #[cfg(test)] @@ -11,7 +11,9 @@ extern crate spinning_top; extern crate alloc; -use alloc::alloc::{AllocErr, AllocRef, Layout}; +use alloc::alloc::Layout; +#[cfg(feature = "alloc_ref")] +use alloc::alloc::{AllocErr, AllocRef}; use core::alloc::GlobalAlloc; use core::mem; #[cfg(feature = "use_spin")] @@ -71,7 +73,7 @@ impl Heap { /// This function scans the list of free memory blocks and uses the first block that is big /// enough. The runtime is in O(n) where n is the number of free blocks, but it should be /// reasonably fast for small allocations. - pub fn allocate_first_fit(&mut self, layout: Layout) -> Result, AllocErr> { + pub fn allocate_first_fit(&mut self, layout: Layout) -> Result, ()> { let mut size = layout.size(); if size < HoleList::min_size() { size = HoleList::min_size(); @@ -129,9 +131,13 @@ impl Heap { } } +#[cfg(feature = "alloc_ref")] unsafe impl AllocRef for Heap { unsafe fn alloc(&mut self, layout: Layout) -> Result<(NonNull, usize), AllocErr> { - Ok((self.allocate_first_fit(layout)?, layout.size())) + match self.allocate_first_fit(layout) { + Ok(ptr) => Ok((ptr, layout.size())), + Err(()) => Err(AllocErr), + } } unsafe fn dealloc(&mut self, ptr: NonNull, layout: Layout) { From 1c00a974ccea50b806f39725a8bd29dbd0a3bb83 Mon Sep 17 00:00:00 2001 From: Philipp Oppermann Date: Fri, 6 Mar 2020 11:29:28 +0100 Subject: [PATCH 2/3] Document crate features in Readme --- README.md | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/README.md b/README.md index e379de6..220c011 100644 --- a/README.md +++ b/README.md @@ -28,5 +28,14 @@ pub fn init_heap() { } ``` +## Features + +- **`use_spin`** (default): Provide a `LockedHeap` type that implements the [`GlobalAlloc`] trait by using a spinlock. +- **`alloc_ref`**: Provide an implementation of the unstable [`AllocRef`] trait. + - Warning: The `AllocRef` trait is still regularly changed on the Rust side, so expect some regular breakage when using this feature. + +[`GlobalAlloc`]: https://doc.rust-lang.org/nightly/core/alloc/trait.GlobalAlloc.html +[`AllocRef`]: https://doc.rust-lang.org/nightly/core/alloc/trait.AllocRef.html + ## License This crate is dual-licensed under MIT or the Apache License (Version 2.0). See LICENSE-APACHE and LICENSE-MIT for details. From 4a0f8ddee943a41321c041f6c1a0ca9f034af920 Mon Sep 17 00:00:00 2001 From: Philipp Oppermann Date: Fri, 6 Mar 2020 11:29:44 +0100 Subject: [PATCH 3/3] Add GitHub actions workflow --- .github/workflows/build.yml | 65 +++++++++++++++++++++++++++++++++++++ 1 file changed, 65 insertions(+) create mode 100644 .github/workflows/build.yml diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml new file mode 100644 index 0000000..37250cf --- /dev/null +++ b/.github/workflows/build.yml @@ -0,0 +1,65 @@ +name: Build + +on: + push: + branches: + - 'master' + tags: + - '*' + schedule: + - cron: '40 5 * * *' # every day at 5:40 + pull_request: + +jobs: + test: + name: "Test" + + strategy: + matrix: + platform: [ + ubuntu-latest, + macos-latest, + windows-latest + ] + + runs-on: ${{ matrix.platform }} + timeout-minutes: 15 + + steps: + - name: "Checkout Repository" + uses: actions/checkout@v1 + + - name: Install Rustup + run: | + curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y --default-toolchain nightly + echo ::add-path::$HOME/.cargo/bin + if: runner.os == 'macOS' + + - name: Set Rustup profile to minimal + run: rustup set profile minimal + + - name: "Print Rust Version" + run: | + rustc -Vv + cargo -Vv + + - name: "Run cargo build" + run: cargo build + + - name: "Build with `alloc_ref` feature" + run: cargo build --features alloc_ref + + - name: "Run cargo test" + run: cargo test + + - name: 'Deny Warnings' + run: cargo rustc -- -D warnings + + check_formatting: + name: "Check Formatting" + runs-on: ubuntu-latest + timeout-minutes: 2 + steps: + - uses: actions/checkout@v1 + - run: rustup install nightly + - run: cargo +nightly fmt -- --check