diff --git a/Makefile b/Makefile
index f80c57ebe..79d0c4a1b 100644
--- a/Makefile
+++ b/Makefile
@@ -390,6 +390,7 @@ coreutils: \
filesystem/bin/echo \
filesystem/bin/env \
filesystem/bin/false \
+ filesystem/bin/free \
filesystem/bin/head \
filesystem/bin/ls \
filesystem/bin/mkdir \
@@ -411,7 +412,7 @@ coreutils: \
filesystem/bin/true \
filesystem/bin/wc \
filesystem/bin/yes
- #filesystem/bin/free filesystem/bin/shutdown filesystem/bin/test
+ #filesystem/bin/shutdown filesystem/bin/test
extrautils: \
filesystem/bin/calc \
diff --git a/arch/x86_64/src/memory/area_frame_allocator.rs b/arch/x86_64/src/memory/area_frame_allocator.rs
index 6367d06e4..e25f22ac4 100644
--- a/arch/x86_64/src/memory/area_frame_allocator.rs
+++ b/arch/x86_64/src/memory/area_frame_allocator.rs
@@ -43,6 +43,48 @@ impl AreaFrameAllocator {
}
impl FrameAllocator for AreaFrameAllocator {
+ fn free_frames(&self) -> usize {
+ let mut count = 0;
+
+ for area in self.areas.clone() {
+ let start_frame = Frame::containing_address(PhysicalAddress::new(area.base_addr as usize));
+ let end_frame = Frame::containing_address(PhysicalAddress::new((area.base_addr + area.length - 1) as usize));
+ for frame in Frame::range_inclusive(start_frame, end_frame) {
+ if frame >= self.kernel_start && frame <= self.kernel_end {
+ // Inside of kernel range
+ } else if frame >= self.next_free_frame {
+ // Frame is in free range
+ count += 1;
+ } else {
+ // Inside of used range
+ }
+ }
+ }
+
+ count
+ }
+
+ fn used_frames(&self) -> usize {
+ let mut count = 0;
+
+ for area in self.areas.clone() {
+ let start_frame = Frame::containing_address(PhysicalAddress::new(area.base_addr as usize));
+ let end_frame = Frame::containing_address(PhysicalAddress::new((area.base_addr + area.length - 1) as usize));
+ for frame in Frame::range_inclusive(start_frame, end_frame) {
+ if frame >= self.kernel_start && frame <= self.kernel_end {
+ // Inside of kernel range
+ count += 1
+ } else if frame >= self.next_free_frame {
+ // Frame is in free range
+ } else {
+ count += 1;
+ }
+ }
+ }
+
+ count
+ }
+
fn allocate_frames(&mut self, count: usize) -> Option {
if count == 0 {
None
diff --git a/arch/x86_64/src/memory/mod.rs b/arch/x86_64/src/memory/mod.rs
index bffe9abef..17b220005 100644
--- a/arch/x86_64/src/memory/mod.rs
+++ b/arch/x86_64/src/memory/mod.rs
@@ -90,6 +90,24 @@ pub fn deallocate_frame(frame: Frame) {
deallocate_frames(frame, 1)
}
+/// Get the number of frames available
+pub fn free_frames() -> usize {
+ if let Some(ref allocator) = *ALLOCATOR.lock() {
+ allocator.free_frames()
+ } else {
+ panic!("frame allocator not initialized");
+ }
+}
+
+/// Get the number of frames used
+pub fn used_frames() -> usize {
+ if let Some(ref allocator) = *ALLOCATOR.lock() {
+ allocator.used_frames()
+ } else {
+ panic!("frame allocator not initialized");
+ }
+}
+
/// Allocate a range of frames
pub fn allocate_frames(count: usize) -> Option {
if let Some(ref mut allocator) = *ALLOCATOR.lock() {
@@ -164,6 +182,8 @@ impl Iterator for FrameIter {
}
pub trait FrameAllocator {
+ fn free_frames(&self) -> usize;
+ fn used_frames(&self) -> usize;
fn allocate_frames(&mut self, size: usize) -> Option;
fn deallocate_frames(&mut self, frame: Frame, size: usize);
}
diff --git a/kernel/scheme/sys/memory.rs b/kernel/scheme/sys/memory.rs
new file mode 100644
index 000000000..ba58ae0de
--- /dev/null
+++ b/kernel/scheme/sys/memory.rs
@@ -0,0 +1,10 @@
+use collections::Vec;
+
+use arch::memory::{free_frames, used_frames};
+use syscall::error::Result;
+
+pub fn resource() -> Result> {
+ let string = format!("Memory Used: {} KB\nMemory Free: {} KB\n", used_frames() * 4, free_frames() * 4);
+
+ Ok(string.into_bytes())
+}
diff --git a/kernel/scheme/sys/mod.rs b/kernel/scheme/sys/mod.rs
index 7d560d370..f5ed0bffe 100644
--- a/kernel/scheme/sys/mod.rs
+++ b/kernel/scheme/sys/mod.rs
@@ -10,10 +10,10 @@ use syscall::flag::{MODE_DIR, MODE_FILE, SEEK_CUR, SEEK_END, SEEK_SET};
use syscall::scheme::Scheme;
mod context;
+mod memory;
mod scheme;
//mod interrupt;
//mod log;
-//mod memory;
//mod test;
struct Handle {
@@ -37,10 +37,10 @@ impl SysScheme {
let mut files: BTreeMap<&'static [u8], Box> = BTreeMap::new();
files.insert(b"context", Box::new(move || context::resource()));
+ files.insert(b"memory", Box::new(move || memory::resource()));
files.insert(b"scheme", Box::new(move || scheme::resource()));
//files.insert(b"interrupt", Box::new(move || interrupt::resource()));
//files.insert(b"log", Box::new(move || log::resource()));
- //files.insert(b"memory", Box::new(move || memory::resource()));
//files.insert(b"test", Box::new(move || test::resource()));
SysScheme {