diff --git a/Makefile b/Makefile index f8c820e..f049217 100644 --- a/Makefile +++ b/Makefile @@ -28,7 +28,8 @@ OBJS = \ $K/sysfile.o \ $K/kernelvec.o \ $K/plic.o \ - $K/virtio_disk.o + $K/virtio_disk.o \ + $K/freeram.o # riscv64-unknown-elf- or riscv64-linux-gnu- # perhaps in /opt/riscv/bin @@ -132,6 +133,7 @@ UPROGS=\ $U/_ln\ $U/_ls\ $U/_mkdir\ + $U/_freeram\ $U/_rm\ $U/_sh\ $U/_stressfs\ diff --git a/kernel/defs.h b/kernel/defs.h index d1b6bb9..5290161 100644 --- a/kernel/defs.h +++ b/kernel/defs.h @@ -187,3 +187,6 @@ void virtio_disk_intr(void); // number of elements in fixed-size array #define NELEM(x) (sizeof(x)/sizeof((x)[0])) + +// freeram.c exercise 2.9.1 +uint64 freeram(void); diff --git a/kernel/freeram.c b/kernel/freeram.c new file mode 100644 index 0000000..73357ab --- /dev/null +++ b/kernel/freeram.c @@ -0,0 +1,34 @@ +#include "types.h" +#include "param.h" +#include "memlayout.h" +#include "spinlock.h" +#include "riscv.h" +#include "defs.h" + +struct run { + struct run *next; +}; + +extern struct { + struct spinlock lock; + struct run *freelist; +} kmem; + +uint64 +sys_freeram(void) +{ + struct run *r; + uint64 free_pages = 0; + + acquire(&kmem.lock); + + // loop over free pages' list + r = kmem.freelist; + while (r != 0) { + free_pages++; + r = r->next; + } + release(&kmem.lock); + + return free_pages * PGSIZE; +} diff --git a/kernel/syscall.c b/kernel/syscall.c index ed65409..9663fa8 100644 --- a/kernel/syscall.c +++ b/kernel/syscall.c @@ -101,6 +101,7 @@ extern uint64 sys_unlink(void); extern uint64 sys_link(void); extern uint64 sys_mkdir(void); extern uint64 sys_close(void); +extern uint64 sys_freeram(void); // exercise 2.9.1 // An array mapping syscall numbers from syscall.h // to the function that handles the system call. @@ -126,6 +127,7 @@ static uint64 (*syscalls[])(void) = { [SYS_link] sys_link, [SYS_mkdir] sys_mkdir, [SYS_close] sys_close, +[SYS_freeram] sys_freeram, // exercise 2.9.1 }; void diff --git a/kernel/syscall.h b/kernel/syscall.h index bc5f356..f4b89a6 100644 --- a/kernel/syscall.h +++ b/kernel/syscall.h @@ -20,3 +20,4 @@ #define SYS_link 19 #define SYS_mkdir 20 #define SYS_close 21 +#define SYS_freeram 22 // exercise 2.9.1 diff --git a/user/freeram.c b/user/freeram.c new file mode 100644 index 0000000..6d7fa2b --- /dev/null +++ b/user/freeram.c @@ -0,0 +1,36 @@ +#include "kernel/types.h" +#include "kernel/stat.h" +#include "kernel/riscv.h" // to get PGSIZE +#include "user/user.h" + +#define KIBIBYTES 1024 +#define MEBIBYTES (1024 * 1024) +void +display_memory(void) +{ + uint64 free_ram, npages, nm, nk; + free_ram = freeram(); + npages = free_ram / PGSIZE; + nm = free_ram / MEBIBYTES; + nk = free_ram / KIBIBYTES; + printf("%ld bytes (%ld MiB or %ld KiB), %ld pages ", free_ram, nm, nk, npages); +} + +int +main(int argc, char *argv[]) +{ + void *mem; + + display_memory(); + printf("free memory at the start\n"); + + mem = malloc(PGSIZE * 1000); + display_memory(); + printf("after 1000*PGSIZE mem alloc\n"); + + free(mem); + display_memory(); + printf("after dealloc\n"); + + exit(0); +} diff --git a/user/user.h b/user/user.h index f16fe27..d4d1186 100644 --- a/user/user.h +++ b/user/user.h @@ -22,6 +22,7 @@ int getpid(void); char* sbrk(int); int sleep(int); int uptime(void); +uint64 freeram(void); // exercise 2.9.1 // ulib.c int stat(const char*, struct stat*); diff --git a/user/usys.pl b/user/usys.pl index 01e426e..9cea900 100755 --- a/user/usys.pl +++ b/user/usys.pl @@ -36,3 +36,4 @@ entry("getpid"); entry("sbrk"); entry("sleep"); entry("uptime"); +entry("freeram");