Skip to content

Commit bea8cfc

Browse files
authored
Merge pull request #27 from phil-opp/optional-alloc-ref
Make AllocRef implementation optional behind new `alloc_ref` feature
2 parents a1d398c + 4a0f8dd commit bea8cfc

File tree

5 files changed

+89
-8
lines changed

5 files changed

+89
-8
lines changed

.github/workflows/build.yml

+65
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
name: Build
2+
3+
on:
4+
push:
5+
branches:
6+
- 'master'
7+
tags:
8+
- '*'
9+
schedule:
10+
- cron: '40 5 * * *' # every day at 5:40
11+
pull_request:
12+
13+
jobs:
14+
test:
15+
name: "Test"
16+
17+
strategy:
18+
matrix:
19+
platform: [
20+
ubuntu-latest,
21+
macos-latest,
22+
windows-latest
23+
]
24+
25+
runs-on: ${{ matrix.platform }}
26+
timeout-minutes: 15
27+
28+
steps:
29+
- name: "Checkout Repository"
30+
uses: actions/checkout@v1
31+
32+
- name: Install Rustup
33+
run: |
34+
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y --default-toolchain nightly
35+
echo ::add-path::$HOME/.cargo/bin
36+
if: runner.os == 'macOS'
37+
38+
- name: Set Rustup profile to minimal
39+
run: rustup set profile minimal
40+
41+
- name: "Print Rust Version"
42+
run: |
43+
rustc -Vv
44+
cargo -Vv
45+
46+
- name: "Run cargo build"
47+
run: cargo build
48+
49+
- name: "Build with `alloc_ref` feature"
50+
run: cargo build --features alloc_ref
51+
52+
- name: "Run cargo test"
53+
run: cargo test
54+
55+
- name: 'Deny Warnings'
56+
run: cargo rustc -- -D warnings
57+
58+
check_formatting:
59+
name: "Check Formatting"
60+
runs-on: ubuntu-latest
61+
timeout-minutes: 2
62+
steps:
63+
- uses: actions/checkout@v1
64+
- run: rustup install nightly
65+
- run: cargo +nightly fmt -- --check

Cargo.toml

+1
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ homepage = "http://os.phil-opp.com/kernel-heap.html#a-better-allocator"
1414
[features]
1515
default = ["use_spin"]
1616
use_spin = ["spinning_top"]
17+
alloc_ref = []
1718

1819
[dependencies.spinning_top]
1920
version = "0.1.0"

README.md

+9
Original file line numberDiff line numberDiff line change
@@ -28,5 +28,14 @@ pub fn init_heap() {
2828
}
2929
```
3030

31+
## Features
32+
33+
- **`use_spin`** (default): Provide a `LockedHeap` type that implements the [`GlobalAlloc`] trait by using a spinlock.
34+
- **`alloc_ref`**: Provide an implementation of the unstable [`AllocRef`] trait.
35+
- Warning: The `AllocRef` trait is still regularly changed on the Rust side, so expect some regular breakage when using this feature.
36+
37+
[`GlobalAlloc`]: https://doc.rust-lang.org/nightly/core/alloc/trait.GlobalAlloc.html
38+
[`AllocRef`]: https://doc.rust-lang.org/nightly/core/alloc/trait.AllocRef.html
39+
3140
## License
3241
This crate is dual-licensed under MIT or the Apache License (Version 2.0). See LICENSE-APACHE and LICENSE-MIT for details.

src/hole.rs

+4-4
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use alloc::alloc::{AllocErr, Layout};
1+
use alloc::alloc::Layout;
22
use core::mem::{align_of, size_of};
33
use core::ptr::NonNull;
44

@@ -49,7 +49,7 @@ impl HoleList {
4949
/// block is returned.
5050
/// This function uses the “first fit” strategy, so it uses the first hole that is big
5151
/// enough. Thus the runtime is in O(n) but it should be reasonably fast for small allocations.
52-
pub fn allocate_first_fit(&mut self, layout: Layout) -> Result<NonNull<u8>, AllocErr> {
52+
pub fn allocate_first_fit(&mut self, layout: Layout) -> Result<NonNull<u8>, ()> {
5353
assert!(layout.size() >= Self::min_size());
5454

5555
allocate_first_fit(&mut self.first, layout).map(|allocation| {
@@ -192,7 +192,7 @@ fn split_hole(hole: HoleInfo, required_layout: Layout) -> Option<Allocation> {
192192
/// care of freeing it again.
193193
/// This function uses the “first fit” strategy, so it breaks as soon as a big enough hole is
194194
/// found (and returns it).
195-
fn allocate_first_fit(mut previous: &mut Hole, layout: Layout) -> Result<Allocation, AllocErr> {
195+
fn allocate_first_fit(mut previous: &mut Hole, layout: Layout) -> Result<Allocation, ()> {
196196
loop {
197197
let allocation: Option<Allocation> = previous
198198
.next
@@ -210,7 +210,7 @@ fn allocate_first_fit(mut previous: &mut Hole, layout: Layout) -> Result<Allocat
210210
}
211211
None => {
212212
// this was the last hole, so no hole is big enough -> allocation not possible
213-
return Err(AllocErr);
213+
return Err(());
214214
}
215215
}
216216
}

src/lib.rs

+10-4
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
#![feature(const_fn)]
2-
#![feature(allocator_api)]
2+
#![cfg_attr(feature = "alloc_ref", feature(allocator_api))]
33
#![no_std]
44

55
#[cfg(test)]
@@ -11,7 +11,9 @@ extern crate spinning_top;
1111

1212
extern crate alloc;
1313

14-
use alloc::alloc::{AllocErr, AllocRef, Layout};
14+
use alloc::alloc::Layout;
15+
#[cfg(feature = "alloc_ref")]
16+
use alloc::alloc::{AllocErr, AllocRef};
1517
use core::alloc::GlobalAlloc;
1618
use core::mem;
1719
#[cfg(feature = "use_spin")]
@@ -71,7 +73,7 @@ impl Heap {
7173
/// This function scans the list of free memory blocks and uses the first block that is big
7274
/// enough. The runtime is in O(n) where n is the number of free blocks, but it should be
7375
/// reasonably fast for small allocations.
74-
pub fn allocate_first_fit(&mut self, layout: Layout) -> Result<NonNull<u8>, AllocErr> {
76+
pub fn allocate_first_fit(&mut self, layout: Layout) -> Result<NonNull<u8>, ()> {
7577
let mut size = layout.size();
7678
if size < HoleList::min_size() {
7779
size = HoleList::min_size();
@@ -129,9 +131,13 @@ impl Heap {
129131
}
130132
}
131133

134+
#[cfg(feature = "alloc_ref")]
132135
unsafe impl AllocRef for Heap {
133136
unsafe fn alloc(&mut self, layout: Layout) -> Result<(NonNull<u8>, usize), AllocErr> {
134-
Ok((self.allocate_first_fit(layout)?, layout.size()))
137+
match self.allocate_first_fit(layout) {
138+
Ok(ptr) => Ok((ptr, layout.size())),
139+
Err(()) => Err(AllocErr),
140+
}
135141
}
136142

137143
unsafe fn dealloc(&mut self, ptr: NonNull<u8>, layout: Layout) {

0 commit comments

Comments
 (0)