Commit ecf4a191 authored by qinsoon's avatar qinsoon

[wip] treadmill large object space

parent 12515743
Pipeline #224 failed with stage
in 25 minutes and 28 seconds
use utils::Address;
use heap::immix;
use heap::gc;
use aligned_alloc;
use std::collections::LinkedList;
use std::sync::Arc;
use std::sync::RwLock;
pub struct FreeListSpace {
current_nodes : LinkedList<Box<FreeListNode>>,
node_id: usize,
size : usize,
used_bytes : usize
}
impl FreeListSpace {
pub fn new(size: usize) -> FreeListSpace {
FreeListSpace {
current_nodes: LinkedList::new(),
node_id: 0,
size: size,
used_bytes: 0
}
}
#[allow(unused_variables)]
pub fn mark(&mut self, obj: Address) {
}
pub fn alloc(&mut self, size: usize, align: usize) -> Option<Address> {
if self.used_bytes + size > self.size {
None
} else {
let ret = aligned_alloc::aligned_alloc(size, align);
let addr = Address::from_ptr::<()>(ret);
self.current_nodes.push_front(Box::new(FreeListNode{id: self.node_id, start: addr, size: size, mark: NodeMark::FreshAlloc}));
self.node_id += 1;
self.used_bytes += size;
Some(addr)
}
}
pub fn sweep(&mut self) {
let (new_nodes, new_used_bytes) = {
let mut ret = LinkedList::new();
let nodes = &mut self.current_nodes;
let mut used_bytes = 0;
while !nodes.is_empty() {
let mut node = nodes.pop_front().unwrap();
match node.mark {
NodeMark::Live => {
node.set_mark(NodeMark::PrevLive);
used_bytes += node.size;
ret.push_back(node);
},
NodeMark::PrevLive | NodeMark::FreshAlloc => {
let ptr = node.start.to_ptr::<()>() as *mut ();
// free the memory
unsafe {aligned_alloc::aligned_free(ptr);}
// do not add this node into new linked list
}
}
}
(ret, used_bytes)
};
self.current_nodes = new_nodes;
self.used_bytes = new_used_bytes;
}
pub fn current_nodes(&self) -> &LinkedList<Box<FreeListNode>> {
&self.current_nodes
}
pub fn current_nodes_mut(&mut self) -> &mut LinkedList<Box<FreeListNode>> {
&mut self.current_nodes
}
}
pub struct FreeListNode {
id: usize,
start : Address,
size : usize,
mark : NodeMark
}
impl FreeListNode {
pub fn set_mark(&mut self, mark: NodeMark) {
self.mark = mark;
}
}
#[derive(PartialEq, Eq, Copy, Clone, Debug)]
pub enum NodeMark {
FreshAlloc,
PrevLive,
Live,
}
unsafe impl Sync for NodeMark {}
#[inline(never)]
pub fn alloc_large(size: usize, align: usize, mutator: &mut immix::ImmixMutatorLocal, space: Arc<RwLock<FreeListSpace>>) -> Address {
loop {
mutator.yieldpoint();
let ret_addr = {
let mut lo_space_lock = space.write().unwrap();
lo_space_lock.alloc(size, align)
};
match ret_addr {
Some(addr) => {
return addr;
},
None => {
gc::trigger_gc();
}
}
}
}
use std::fmt;
impl fmt::Display for FreeListSpace {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "FreeListSpace\n").unwrap();
write!(f, "{} used, {} total\n", self.used_bytes, self.size).unwrap();
write!(f, "nodes:\n").unwrap();
for node in self.current_nodes() {
write!(f, " {}\n", node).unwrap();
}
write!(f, "done\n")
}
}
impl fmt::Display for FreeListNode {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "FreeListNode#{}(start={:#X}, size={}, state={:?})", self.id, self.start, self.size, self.mark)
}
}
\ No newline at end of file
use utils::Address;
use heap::immix;
use heap::gc;
use aligned_alloc;
mod malloc_list;
mod treadmill;
use std::collections::LinkedList;
use std::sync::Arc;
use std::sync::RwLock;
pub struct FreeListSpace {
current_nodes : LinkedList<Box<FreeListNode>>,
node_id: usize,
size : usize,
used_bytes : usize
}
impl FreeListSpace {
pub fn new(size: usize) -> FreeListSpace {
FreeListSpace {
current_nodes: LinkedList::new(),
node_id: 0,
size: size,
used_bytes: 0
}
}
#[allow(unused_variables)]
pub fn mark(&mut self, obj: Address) {
}
pub fn alloc(&mut self, size: usize, align: usize) -> Option<Address> {
if self.used_bytes + size > self.size {
None
} else {
let ret = aligned_alloc::aligned_alloc(size, align);
let addr = Address::from_ptr::<()>(ret);
self.current_nodes.push_front(Box::new(FreeListNode{id: self.node_id, start: addr, size: size, mark: NodeMark::FreshAlloc}));
self.node_id += 1;
self.used_bytes += size;
Some(addr)
}
}
pub fn sweep(&mut self) {
let (new_nodes, new_used_bytes) = {
let mut ret = LinkedList::new();
let nodes = &mut self.current_nodes;
let mut used_bytes = 0;
while !nodes.is_empty() {
let mut node = nodes.pop_front().unwrap();
match node.mark {
NodeMark::Live => {
node.set_mark(NodeMark::PrevLive);
used_bytes += node.size;
ret.push_back(node);
},
NodeMark::PrevLive | NodeMark::FreshAlloc => {
let ptr = node.start.to_ptr::<()>() as *mut ();
// free the memory
unsafe {aligned_alloc::aligned_free(ptr);}
// do not add this node into new linked list
}
}
}
(ret, used_bytes)
};
self.current_nodes = new_nodes;
self.used_bytes = new_used_bytes;
}
pub fn current_nodes(&self) -> &LinkedList<Box<FreeListNode>> {
&self.current_nodes
}
pub fn current_nodes_mut(&mut self) -> &mut LinkedList<Box<FreeListNode>> {
&mut self.current_nodes
}
}
pub struct FreeListNode {
id: usize,
start : Address,
size : usize,
mark : NodeMark
}
impl FreeListNode {
pub fn set_mark(&mut self, mark: NodeMark) {
self.mark = mark;
}
}
#[derive(PartialEq, Eq, Copy, Clone, Debug)]
pub enum NodeMark {
FreshAlloc,
PrevLive,
Live,
}
unsafe impl Sync for NodeMark {}
#[inline(never)]
pub fn alloc_large(size: usize, align: usize, mutator: &mut immix::ImmixMutatorLocal, space: Arc<RwLock<FreeListSpace>>) -> Address {
loop {
mutator.yieldpoint();
let ret_addr = {
let mut lo_space_lock = space.write().unwrap();
lo_space_lock.alloc(size, align)
};
match ret_addr {
Some(addr) => {
return addr;
},
None => {
gc::trigger_gc();
}
}
}
}
use std::fmt;
impl fmt::Display for FreeListSpace {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "FreeListSpace\n").unwrap();
write!(f, "{} used, {} total\n", self.used_bytes, self.size).unwrap();
write!(f, "nodes:\n").unwrap();
for node in self.current_nodes() {
write!(f, " {}\n", node).unwrap();
}
write!(f, "done\n")
}
}
impl fmt::Display for FreeListNode {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "FreeListNode#{}(start={:#X}, size={}, state={:?})", self.id, self.start, self.size, self.mark)
}
}
\ No newline at end of file
pub use heap::freelist::malloc_list::FreeListSpace;
pub use heap::freelist::malloc_list::alloc_large;
\ No newline at end of file
#![allow(dead_code)]
use utils::Address;
use utils::mem::memmap;
use std::ptr;
use std::sync::Arc;
use common::AddressMap;
const SPACE_ALIGN : usize = 1 << 19;
const BLOCK_SIZE : usize = 1 << 12; // 4kb
#[repr(C)]
pub struct FreeListSpace {
start : Address,
end : Address,
pub alloc_map : Arc<AddressMap<u8>>,
pub trace_map : Arc<AddressMap<u8>>,
#[allow(dead_code)]
mmap : memmap::Mmap,
treadmill: TreadMill
}
impl FreeListSpace {
pub fn new(space_size: usize) -> FreeListSpace {
let anon_mmap : memmap::Mmap = match memmap::Mmap::anonymous(space_size + SPACE_ALIGN, memmap::Protection::ReadWrite) {
Ok(m) => m,
Err(_) => panic!("failed to call mmap")
};
let start : Address = Address::from_ptr::<u8>(anon_mmap.ptr()).align_up(SPACE_ALIGN);
let end : Address = start.plus(space_size);
unimplemented!()
}
}
struct TreadMill{
free: *mut TreadMillNode,
scan: *mut TreadMillNode,
t : *mut TreadMillNode,
b : *mut TreadMillNode
}
impl TreadMill {
fn new(start: Address, end: Address) -> TreadMill {
let mut addr = start;
let free = TreadMillNode::singleton(addr);
let mut tail = free;
while addr < end {
tail = TreadMillNode::insert_after(tail, addr);
}
unimplemented!()
}
}
struct TreadMillNode {
payload: Address,
prev: *mut TreadMillNode,
next: *mut TreadMillNode
}
impl TreadMillNode {
fn singleton(addr: Address) -> *mut TreadMillNode {
let mut ptr = Box::into_raw(Box::new(TreadMillNode {
payload: addr,
prev: ptr::null_mut(),
next: ptr::null_mut(),
}));
// first node in the cyclic doubly linked list
unsafe {
(*ptr).prev = ptr;
(*ptr).next = ptr;
}
ptr
}
/// returns the inserted node
fn insert_after(node: *mut TreadMillNode, addr: Address) -> *mut TreadMillNode {
unsafe {
// node <- ptr -> node.next
let mut ptr = Box::into_raw(Box::new(TreadMillNode {
payload: addr,
// inserted between node and node.next
prev: node,
next: (*node).next
}));
// ptr <- node.next
(*(*node).next).prev = ptr;
// node -> ptr
(*node).next = ptr;
ptr
}
}
}
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment