Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make AllocRef implementation optional behind new alloc_ref feature #27

Merged
merged 3 commits into from
Mar 6, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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