Skip to content

Commit 7460f65

Browse files
committed
Rewrite allocate
1 parent ab8343b commit 7460f65

File tree

1 file changed

+85
-49
lines changed

1 file changed

+85
-49
lines changed

src/hole.rs

Lines changed: 85 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -44,15 +44,15 @@ impl HoleList {
4444
println!("allocate {} bytes (align {})", size, align);
4545
assert!(size >= Self::min_size());
4646

47-
if let Some((start_addr, front_padding, back_padding)) =
48-
allocate_first_fit(&mut self.first, size, align) {
49-
if let Some((padding_addr, padding_size)) = front_padding {
50-
self.deallocate(padding_addr as *mut u8, padding_size)
47+
if let Some(result) = allocate_first_fit(&mut self.first, size, align) {
48+
println!("allocated address: {:#x}", result.hole.addr);
49+
if let Some(HoleInfo{addr: padding_addr, size: padding_size}) = result.front_padding {
50+
self.deallocate(padding_addr as *mut u8, padding_size);
5151
}
52-
if let Some((padding_addr, padding_size)) = back_padding {
53-
self.deallocate(padding_addr as *mut u8, padding_size)
52+
if let Some(HoleInfo{addr: padding_addr, size: padding_size}) = result.back_padding {
53+
self.deallocate(padding_addr as *mut u8, padding_size);
5454
}
55-
Some(start_addr as *mut u8)
55+
Some(result.hole.addr as *mut u8)
5656
} else {
5757
None
5858
}
@@ -84,56 +84,92 @@ pub struct Hole {
8484
pub next: Option<Unique<Hole>>,
8585
}
8686

87-
fn allocate_first_fit(previous: &mut Hole,
88-
size: usize,
89-
align: usize)
90-
-> Option<(usize, Option<(usize, usize)>, Option<(usize, usize)>)> {
91-
let mut front_padding = None;
92-
let mut back_padding = None;
93-
94-
if previous.next.is_some() {
95-
let hole_addr = **previous.next.as_ref().unwrap() as usize;
96-
let aligned_hole_addr = align_up(hole_addr, align);
97-
98-
if aligned_hole_addr > hole_addr {
99-
if aligned_hole_addr < hole_addr + HoleList::min_size() {
100-
// hole would cause a new, too small hole. try next hole
101-
return allocate_first_fit(unsafe { previous.next.as_mut().unwrap().get_mut() },
102-
size,
103-
align);
104-
} else {
105-
let padding_hole_size = aligned_hole_addr - hole_addr;
106-
front_padding = Some((hole_addr, padding_hole_size));
107-
}
87+
impl Hole {
88+
fn info(&self) -> HoleInfo {
89+
HoleInfo {
90+
addr: self as *const _ as usize,
91+
size: self.size,
10892
}
93+
}
94+
}
10995

110-
let aligned_hole_size = unsafe { previous.next.as_ref().unwrap().get().size } -
111-
(aligned_hole_addr - hole_addr);
112-
113-
if aligned_hole_size > size {
114-
if aligned_hole_size - size < HoleList::min_size() {
115-
// hole would cause a new, too small hole. try next hole
116-
return allocate_first_fit(unsafe { previous.next.as_mut().unwrap().get_mut() },
117-
size,
118-
align);
119-
} else {
120-
let padding_hole_size = aligned_hole_size - size;
121-
back_padding = Some((aligned_hole_addr + size, padding_hole_size));
122-
}
96+
struct HoleInfo {
97+
addr: usize,
98+
size: usize,
99+
}
100+
101+
struct HoleResult {
102+
hole: HoleInfo,
103+
front_padding: Option<HoleInfo>,
104+
back_padding: Option<HoleInfo>,
105+
}
106+
107+
fn split_hole(hole: HoleInfo, required_size: usize, required_align: usize) -> Option<HoleResult> {
108+
let aligned_hole = {
109+
let aligned_hole_addr = align_up(hole.addr, required_align);
110+
if aligned_hole_addr + required_size > hole.addr + hole.size {
111+
// hole is too small
112+
return None;
113+
}
114+
HoleInfo {
115+
addr: aligned_hole_addr,
116+
size: hole.size - (aligned_hole_addr - hole.addr),
123117
}
118+
};
124119

125-
if aligned_hole_size >= size {
126-
previous.next = unsafe { previous.next.as_mut().unwrap().get_mut().next.take() };
127-
Some((aligned_hole_addr, front_padding, back_padding))
120+
let front_padding = if aligned_hole.addr > hole.addr {
121+
if aligned_hole.addr < hole.addr + HoleList::min_size() {
122+
// hole would cause a new, too small hole
123+
return None;
128124
} else {
129-
// hole is too small, try next hole
130-
return allocate_first_fit(unsafe { previous.next.as_mut().unwrap().get_mut() },
131-
size,
132-
align);
125+
Some(HoleInfo {
126+
addr: hole.addr,
127+
size: aligned_hole.addr - hole.addr,
128+
})
133129
}
134130
} else {
135131
None
136-
}
132+
};
133+
134+
let back_padding = if aligned_hole.size > required_size {
135+
if aligned_hole.size - required_size < HoleList::min_size() {
136+
// hole would cause a new, too small hole
137+
return None;
138+
} else {
139+
Some(HoleInfo {
140+
addr: aligned_hole.addr + required_size,
141+
size: aligned_hole.size - required_size,
142+
})
143+
}
144+
} else {
145+
None
146+
};
147+
148+
Some(HoleResult {
149+
hole: HoleInfo {
150+
addr: aligned_hole.addr,
151+
size: required_size,
152+
},
153+
front_padding: front_padding,
154+
back_padding: back_padding,
155+
})
156+
}
157+
158+
fn allocate_first_fit(previous: &mut Hole, size: usize, align: usize) -> Option<HoleResult> {
159+
160+
previous.next
161+
.as_mut()
162+
.and_then(|current| split_hole(unsafe { current.get() }.info(), size, align))
163+
.map(|result| {
164+
previous.next = unsafe { previous.next.as_mut().unwrap().get_mut().next.take() };
165+
result
166+
})
167+
.or_else(|| {
168+
// hole is too small, try next hole
169+
allocate_first_fit(unsafe { previous.next.as_mut().unwrap().get_mut() },
170+
size,
171+
align)
172+
})
137173
}
138174

139175
fn deallocate(hole: &mut Hole, addr: usize, size: usize) {

0 commit comments

Comments
 (0)