diff --git a/Makefile b/Makefile index 1c07efd..2db7c33 100644 --- a/Makefile +++ b/Makefile @@ -150,6 +150,7 @@ UPROGS=\ $U/_wc\ $U/_zombie\ $U/_trace\ + $U/_sysinfotest diff --git a/kernel/defs.h b/kernel/defs.h index 4b9bbc0..fa86032 100644 --- a/kernel/defs.h +++ b/kernel/defs.h @@ -63,6 +63,7 @@ void ramdiskrw(struct buf*); void* kalloc(void); void kfree(void *); void kinit(void); +uint64 getfreemem(void); // log.c void initlog(int, struct superblock*); @@ -104,6 +105,7 @@ void yield(void); int either_copyout(int user_dst, uint64 dst, void *src, uint64 len); int either_copyin(void *dst, int user_src, uint64 src, uint64 len); void procdump(void); +uint64 getnproc(void); // swtch.S void swtch(struct context*, struct context*); diff --git a/kernel/kalloc.c b/kernel/kalloc.c index fa6a0ac..9d7565a 100644 --- a/kernel/kalloc.c +++ b/kernel/kalloc.c @@ -80,3 +80,20 @@ kalloc(void) memset((char*)r, 5, PGSIZE); // fill with junk return (void*)r; } + +uint64 +getfreemem(void) +{ + struct run *r; + uint64 n = 0; + + acquire(&kmem.lock); + r = kmem.freelist; + while (r) { + ++n; + r = r->next; + } + release(&kmem.lock); + + return n * PGSIZE; +} diff --git a/kernel/proc.c b/kernel/proc.c index 3de92aa..222e664 100644 --- a/kernel/proc.c +++ b/kernel/proc.c @@ -694,3 +694,14 @@ procdump(void) printf("\n"); } } + +uint64 +getnproc(void) +{ + uint64 n = 0; + struct proc *p; + for (p = proc; p < &proc[NPROC]; ++p) { + if (p->state != UNUSED) ++n; + } + return n; +} diff --git a/kernel/syscall.c b/kernel/syscall.c index d554c45..be48ab7 100644 --- a/kernel/syscall.c +++ b/kernel/syscall.c @@ -105,6 +105,7 @@ extern uint64 sys_wait(void); extern uint64 sys_write(void); extern uint64 sys_uptime(void); extern uint64 sys_trace(void); +extern uint64 sys_sysinfo(void); static uint64 (*syscalls[])(void) = { [SYS_fork] sys_fork, @@ -129,6 +130,7 @@ static uint64 (*syscalls[])(void) = { [SYS_mkdir] sys_mkdir, [SYS_close] sys_close, [SYS_trace] sys_trace, +[SYS_sysinfo] sys_sysinfo, }; static char *syscall_list[23] = { diff --git a/kernel/syscall.h b/kernel/syscall.h index cc112b9..0dfedc7 100644 --- a/kernel/syscall.h +++ b/kernel/syscall.h @@ -21,3 +21,4 @@ #define SYS_mkdir 20 #define SYS_close 21 #define SYS_trace 22 +#define SYS_sysinfo 23 diff --git a/kernel/sysproc.c b/kernel/sysproc.c index 8de6712..2b3eb3a 100644 --- a/kernel/sysproc.c +++ b/kernel/sysproc.c @@ -6,6 +6,7 @@ #include "memlayout.h" #include "spinlock.h" #include "proc.h" +#include "sysinfo.h" uint64 sys_exit(void) @@ -108,3 +109,23 @@ sys_trace(void) return 0; } + +uint64 +sys_sysinfo(void) +{ + uint64 addr; // user virtual address, pointing to a struct sysinfo. + + if (argaddr(0, &addr) < 0) + return -1; + + struct proc *p = myproc(); + struct sysinfo si; + + si.freemem = getfreemem(); + si.nproc = getnproc(); + + if (copyout(p->pagetable, addr, (char *)&si, sizeof(si)) < 0) + return -1; + + return 0; +} diff --git a/user/user.h b/user/user.h index fdeeefc..83fe38a 100644 --- a/user/user.h +++ b/user/user.h @@ -1,5 +1,6 @@ struct stat; struct rtcdate; +struct sysinfo; // system calls int fork(void); @@ -24,6 +25,7 @@ char* sbrk(int); int sleep(int); int uptime(void); int trace(int); +int sysinfo(struct sysinfo *); // ulib.c int stat(const char*, struct stat*); diff --git a/user/usys.pl b/user/usys.pl index 9c97b05..bc109fd 100755 --- a/user/usys.pl +++ b/user/usys.pl @@ -37,3 +37,4 @@ sub entry { entry("sleep"); entry("uptime"); entry("trace"); +entry("sysinfo");