Skip to content

Commit fbad771

Browse files
authored
Merge pull request #15 from fortanix/raoul/interface
Refactoring system interface
2 parents dc184e2 + 4786050 commit fbad771

File tree

11 files changed

+319
-310
lines changed

11 files changed

+319
-310
lines changed

.github/workflows/main.yml

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -38,13 +38,3 @@ jobs:
3838
run: rustup update stable && rustup default stable && rustup target add wasm32-unknown-unknown
3939
- run: cargo build --target wasm32-unknown-unknown
4040
- run: cargo build --target wasm32-unknown-unknown --release
41-
42-
alloc_api:
43-
name: Allocator API
44-
runs-on: ubuntu-latest
45-
steps:
46-
- uses: actions/checkout@master
47-
- name: Install Rust
48-
run: rustup update nightly && rustup default nightly
49-
- run: cargo test --features 'allocator-api global'
50-

Cargo.toml

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "dlmalloc"
3-
version = "0.1.4"
3+
version = "0.2.0"
44
authors = ["Alex Crichton <[email protected]>"]
55
license = "MIT/Apache-2.0"
66
readme = "README.md"
@@ -40,6 +40,4 @@ global = []
4040
# Enable very expensive debug checks in this crate
4141
debug = []
4242

43-
# Enable experimental support for the standard library's unstable allocator API.
44-
allocator-api = []
4543
rustc-dep-of-std = ['core', 'compiler_builtins/rustc-dep-of-std']

src/dlmalloc.rs

Lines changed: 59 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,9 @@ use core::cmp;
77
use core::mem;
88
use core::ptr;
99

10-
use sys;
10+
use Allocator;
1111

12-
pub struct Dlmalloc {
12+
pub struct Dlmalloc<A> {
1313
smallmap: u32,
1414
treemap: u32,
1515
smallbins: [*mut Chunk; (NSMALLBINS + 1) * 2],
@@ -24,31 +24,9 @@ pub struct Dlmalloc {
2424
trim_check: usize,
2525
least_addr: *mut u8,
2626
release_checks: usize,
27+
system_allocator: A,
2728
}
28-
29-
unsafe impl Send for Dlmalloc {}
30-
31-
pub const DLMALLOC_INIT: Dlmalloc = Dlmalloc {
32-
smallmap: 0,
33-
treemap: 0,
34-
smallbins: [0 as *mut _; (NSMALLBINS + 1) * 2],
35-
treebins: [0 as *mut _; NTREEBINS],
36-
dvsize: 0,
37-
topsize: 0,
38-
dv: 0 as *mut _,
39-
top: 0 as *mut _,
40-
footprint: 0,
41-
max_footprint: 0,
42-
seg: Segment {
43-
base: 0 as *mut _,
44-
size: 0,
45-
next: 0 as *mut _,
46-
flags: 0,
47-
},
48-
trim_check: 0,
49-
least_addr: 0 as *mut _,
50-
release_checks: 0,
51-
};
29+
unsafe impl<A: Send> Send for Dlmalloc<A> {}
5230

5331
// TODO: document this
5432
const NSMALLBINS: usize = 32;
@@ -108,7 +86,34 @@ fn leftshift_for_tree_index(x: u32) -> u32 {
10886
}
10987
}
11088

111-
impl Dlmalloc {
89+
impl<A> Dlmalloc<A> {
90+
pub const fn new(system_allocator: A) -> Dlmalloc<A> {
91+
Dlmalloc {
92+
smallmap: 0,
93+
treemap: 0,
94+
smallbins: [0 as *mut _; (NSMALLBINS + 1) * 2],
95+
treebins: [0 as *mut _; NTREEBINS],
96+
dvsize: 0,
97+
topsize: 0,
98+
dv: 0 as *mut _,
99+
top: 0 as *mut _,
100+
footprint: 0,
101+
max_footprint: 0,
102+
seg: Segment {
103+
base: 0 as *mut _,
104+
size: 0,
105+
next: 0 as *mut _,
106+
flags: 0,
107+
},
108+
trim_check: 0,
109+
least_addr: 0 as *mut _,
110+
release_checks: 0,
111+
system_allocator,
112+
}
113+
}
114+
}
115+
116+
impl<A: Allocator> Dlmalloc<A> {
112117
// TODO: can we get rid of this?
113118
pub fn malloc_alignment(&self) -> usize {
114119
mem::size_of::<usize>() * 2
@@ -225,7 +230,7 @@ impl Dlmalloc {
225230
}
226231

227232
pub unsafe fn calloc_must_clear(&self, ptr: *mut u8) -> bool {
228-
!sys::allocates_zeros() || !Chunk::mmapped(Chunk::from_mem(ptr))
233+
!self.system_allocator.allocates_zeros() || !Chunk::mmapped(Chunk::from_mem(ptr))
229234
}
230235

231236
pub unsafe fn malloc(&mut self, size: usize) -> *mut u8 {
@@ -344,6 +349,7 @@ impl Dlmalloc {
344349
self.sys_alloc(nb)
345350
}
346351

352+
/// allocates system resources
347353
unsafe fn sys_alloc(&mut self, size: usize) -> *mut u8 {
348354
self.check_malloc_state();
349355
// keep in sync with max_request
@@ -352,7 +358,7 @@ impl Dlmalloc {
352358
DEFAULT_GRANULARITY,
353359
);
354360

355-
let (tbase, tsize, flags) = sys::alloc(asize);
361+
let (tbase, tsize, flags) = self.system_allocator.alloc(asize);
356362
if tbase.is_null() {
357363
return tbase;
358364
}
@@ -533,7 +539,7 @@ impl Dlmalloc {
533539
let oldmmsize = oldsize + offset + self.mmap_foot_pad();
534540
let newmmsize =
535541
self.mmap_align(nb + 6 * mem::size_of::<usize>() + self.malloc_alignment() - 1);
536-
let ptr = sys::remap(
542+
let ptr = self.system_allocator.remap(
537543
(oldp as *mut u8).offset(-(offset as isize)),
538544
oldmmsize,
539545
newmmsize,
@@ -555,7 +561,7 @@ impl Dlmalloc {
555561
}
556562

557563
fn mmap_align(&self, a: usize) -> usize {
558-
align_up(a, sys::page_size())
564+
align_up(a, self.system_allocator.page_size())
559565
}
560566

561567
// Only call this with power-of-two alignment and alignment >
@@ -631,7 +637,10 @@ impl Dlmalloc {
631637
let prevsize = (*p).prev_foot;
632638
if Chunk::mmapped(p) {
633639
psize += prevsize + self.mmap_foot_pad();
634-
if sys::free((p as *mut u8).offset(-(prevsize as isize)), psize) {
640+
if self
641+
.system_allocator
642+
.free((p as *mut u8).offset(-(prevsize as isize)), psize)
643+
{
635644
self.footprint -= psize;
636645
}
637646
return;
@@ -1161,7 +1170,10 @@ impl Dlmalloc {
11611170

11621171
if Chunk::mmapped(p) {
11631172
psize += prevsize + self.mmap_foot_pad();
1164-
if sys::free((p as *mut u8).offset(-(prevsize as isize)), psize) {
1173+
if self
1174+
.system_allocator
1175+
.free((p as *mut u8).offset(-(prevsize as isize)), psize)
1176+
{
11651177
self.footprint -= psize;
11661178
}
11671179
return;
@@ -1242,10 +1254,13 @@ impl Dlmalloc {
12421254
debug_assert!(!sp.is_null());
12431255

12441256
if !Segment::is_extern(sp) {
1245-
if Segment::can_release_part(sp) {
1257+
if Segment::can_release_part(&self.system_allocator, sp) {
12461258
if (*sp).size >= extra && !self.has_segment_link(sp) {
12471259
let newsize = (*sp).size - extra;
1248-
if sys::free_part((*sp).base, (*sp).size, newsize) {
1260+
if self
1261+
.system_allocator
1262+
.free_part((*sp).base, (*sp).size, newsize)
1263+
{
12491264
released = extra;
12501265
}
12511266
}
@@ -1295,7 +1310,7 @@ impl Dlmalloc {
12951310
let next = (*sp).next;
12961311
nsegs += 1;
12971312

1298-
if Segment::can_release_part(sp) && !Segment::is_extern(sp) {
1313+
if Segment::can_release_part(&self.system_allocator, sp) && !Segment::is_extern(sp) {
12991314
let p = self.align_as_chunk(base);
13001315
let psize = Chunk::size(p);
13011316
// We can unmap if the first chunk holds the entire segment and
@@ -1311,7 +1326,7 @@ impl Dlmalloc {
13111326
} else {
13121327
self.unlink_large_chunk(tp);
13131328
}
1314-
if sys::free(base, size) {
1329+
if self.system_allocator.free(base, size) {
13151330
released += size;
13161331
self.footprint -= size;
13171332
// unlink our obsolete record
@@ -1405,7 +1420,7 @@ impl Dlmalloc {
14051420
);
14061421
debug_assert!(p as *mut u8 >= self.least_addr);
14071422
debug_assert!(!self.is_small(sz));
1408-
debug_assert_eq!(align_up(len, sys::page_size()), len);
1423+
debug_assert_eq!(align_up(len, self.system_allocator.page_size()), len);
14091424
debug_assert_eq!((*Chunk::plus_offset(p, sz)).head, Chunk::fencepost_head());
14101425
debug_assert_eq!(
14111426
(*Chunk::plus_offset(p, sz + mem::size_of::<usize>())).head,
@@ -1746,8 +1761,8 @@ impl Segment {
17461761
(*seg).flags & EXTERN != 0
17471762
}
17481763

1749-
unsafe fn can_release_part(seg: *mut Segment) -> bool {
1750-
sys::can_release_part((*seg).flags >> 1)
1764+
unsafe fn can_release_part<A: Allocator>(system_allocator: &A, seg: *mut Segment) -> bool {
1765+
system_allocator.can_release_part((*seg).flags >> 1)
17511766
}
17521767

17531768
unsafe fn sys_flags(seg: *mut Segment) -> u32 {
@@ -1766,10 +1781,11 @@ impl Segment {
17661781
#[cfg(test)]
17671782
mod tests {
17681783
use super::*;
1784+
use System;
17691785

17701786
// Prime the allocator with some allocations such that there will be free
17711787
// chunks in the treemap
1772-
unsafe fn setup_treemap(a: &mut Dlmalloc) {
1788+
unsafe fn setup_treemap<A: Allocator>(a: &mut Dlmalloc<A>) {
17731789
let large_request_size = NSMALLBINS * (1 << SMALLBIN_SHIFT);
17741790
assert!(!a.is_small(large_request_size));
17751791
let large_request1 = a.malloc(large_request_size);
@@ -1784,7 +1800,7 @@ mod tests {
17841800
// Test allocating, with a non-empty treemap, a specific size that used to
17851801
// trigger an integer overflow bug
17861802
fn treemap_alloc_overflow_minimal() {
1787-
let mut a = DLMALLOC_INIT;
1803+
let mut a = Dlmalloc::new(System::new());
17881804
unsafe {
17891805
setup_treemap(&mut a);
17901806
let min_idx31_size = (0xc000 << TREEBIN_SHIFT) - a.chunk_overhead() + 1;
@@ -1795,7 +1811,7 @@ mod tests {
17951811
#[test]
17961812
// Test allocating the maximum request size with a non-empty treemap
17971813
fn treemap_alloc_max() {
1798-
let mut a = DLMALLOC_INIT;
1814+
let mut a = Dlmalloc::new(System::new());
17991815
unsafe {
18001816
setup_treemap(&mut a);
18011817
let max_request_size = a.max_request() - 1;

src/dummy.rs

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
use core::ptr;
2+
use Allocator;
3+
4+
pub struct System {
5+
_priv: (),
6+
}
7+
8+
impl System {
9+
const fn new() -> System {
10+
System { _priv: () }
11+
}
12+
}
13+
14+
unsafe impl Allocator for System {
15+
fn alloc(&self, size: usize) -> (*mut u8, usize, u32) {
16+
(ptr::null_mut(), 0, 0)
17+
}
18+
19+
fn remap(&self, ptr: *mut u8, oldsize: usize, newsize: usize, can_move: bool) -> *mut u8 {
20+
ptr::null_mut()
21+
}
22+
23+
fn free_part(&self, ptr: *mut u8, oldsize: usize, newsize: usize) -> bool {
24+
false
25+
}
26+
27+
fn free(&self, ptr: *mut u8, size: usize) -> bool {
28+
false
29+
}
30+
31+
fn can_release_part(&self, flags: u32) -> bool {
32+
false
33+
}
34+
35+
fn allocates_zeros(&self) -> bool {
36+
false
37+
}
38+
39+
fn page_size(&self) -> usize {
40+
1
41+
}
42+
}

src/global.rs

Lines changed: 1 addition & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,5 @@
1-
#[cfg(feature = "allocator-api")]
2-
use core::alloc::{Alloc, AllocErr};
31
use core::alloc::{GlobalAlloc, Layout};
42
use core::ops::{Deref, DerefMut};
5-
#[cfg(feature = "allocator-api")]
6-
use core::ptr::NonNull;
73

84
use Dlmalloc;
95

@@ -35,35 +31,7 @@ unsafe impl GlobalAlloc for GlobalDlmalloc {
3531
}
3632
}
3733

38-
#[cfg(feature = "allocator-api")]
39-
unsafe impl Alloc for GlobalDlmalloc {
40-
#[inline]
41-
unsafe fn alloc(&mut self, layout: Layout) -> Result<NonNull<u8>, AllocErr> {
42-
get().alloc(layout)
43-
}
44-
45-
#[inline]
46-
unsafe fn dealloc(&mut self, ptr: NonNull<u8>, layout: Layout) {
47-
get().dealloc(ptr, layout)
48-
}
49-
50-
#[inline]
51-
unsafe fn realloc(
52-
&mut self,
53-
ptr: NonNull<u8>,
54-
layout: Layout,
55-
new_size: usize,
56-
) -> Result<NonNull<u8>, AllocErr> {
57-
Alloc::realloc(&mut *get(), ptr, layout, new_size)
58-
}
59-
60-
#[inline]
61-
unsafe fn alloc_zeroed(&mut self, layout: Layout) -> Result<NonNull<u8>, AllocErr> {
62-
get().alloc_zeroed(layout)
63-
}
64-
}
65-
66-
static mut DLMALLOC: Dlmalloc = Dlmalloc(::dlmalloc::DLMALLOC_INIT);
34+
static mut DLMALLOC: Dlmalloc = Dlmalloc::new();
6735

6836
struct Instance;
6937

0 commit comments

Comments
 (0)