Skip to content

Commit

Permalink
Merge pull request #27 from phil-opp/optional-alloc-ref
Browse files Browse the repository at this point in the history
Make AllocRef implementation optional behind new `alloc_ref` feature
  • Loading branch information
phil-opp authored Mar 6, 2020
2 parents a1d398c + 4a0f8dd commit bea8cfc
Show file tree
Hide file tree
Showing 5 changed files with 89 additions and 8 deletions.
65 changes: 65 additions & 0 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
@@ -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
1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down
9 changes: 9 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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.
8 changes: 4 additions & 4 deletions src/hole.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use alloc::alloc::{AllocErr, Layout};
use alloc::alloc::Layout;
use core::mem::{align_of, size_of};
use core::ptr::NonNull;

Expand Down Expand Up @@ -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<NonNull<u8>, AllocErr> {
pub fn allocate_first_fit(&mut self, layout: Layout) -> Result<NonNull<u8>, ()> {
assert!(layout.size() >= Self::min_size());

allocate_first_fit(&mut self.first, layout).map(|allocation| {
Expand Down Expand Up @@ -192,7 +192,7 @@ fn split_hole(hole: HoleInfo, required_layout: Layout) -> Option<Allocation> {
/// 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<Allocation, AllocErr> {
fn allocate_first_fit(mut previous: &mut Hole, layout: Layout) -> Result<Allocation, ()> {
loop {
let allocation: Option<Allocation> = previous
.next
Expand All @@ -210,7 +210,7 @@ fn allocate_first_fit(mut previous: &mut Hole, layout: Layout) -> Result<Allocat
}
None => {
// this was the last hole, so no hole is big enough -> allocation not possible
return Err(AllocErr);
return Err(());
}
}
}
Expand Down
14 changes: 10 additions & 4 deletions src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
#![feature(const_fn)]
#![feature(allocator_api)]
#![cfg_attr(feature = "alloc_ref", feature(allocator_api))]
#![no_std]

#[cfg(test)]
Expand All @@ -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")]
Expand Down Expand Up @@ -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<NonNull<u8>, AllocErr> {
pub fn allocate_first_fit(&mut self, layout: Layout) -> Result<NonNull<u8>, ()> {
let mut size = layout.size();
if size < HoleList::min_size() {
size = HoleList::min_size();
Expand Down Expand Up @@ -129,9 +131,13 @@ impl Heap {
}
}

#[cfg(feature = "alloc_ref")]
unsafe impl AllocRef for Heap {
unsafe fn alloc(&mut self, layout: Layout) -> Result<(NonNull<u8>, 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<u8>, layout: Layout) {
Expand Down

0 comments on commit bea8cfc

Please sign in to comment.