From 35eb823963b8c896f006e23a66bf16b1cd82e188 Mon Sep 17 00:00:00 2001 From: Xiaoguang Sun Date: Sun, 9 Jun 2013 15:15:39 +0000 Subject: [PATCH] Add vm_total, vm_total_max, vm_minor_page_fault and vm_major_page_fault Add vm_total, vm_total_max, vm_minor_page_fault and vm_major_page_fault to vm server to implement getrusage --- servers/vm/exit.c | 10 ++++++++++ servers/vm/mem_anon.c | 6 ++++-- servers/vm/mem_anon_contig.c | 6 ++++-- servers/vm/mem_cache.c | 8 +++++--- servers/vm/mem_directphys.c | 6 ++++-- servers/vm/mem_file.c | 7 ++++--- servers/vm/mem_shared.c | 7 ++++--- servers/vm/memtype.h | 3 ++- servers/vm/pagefaults.c | 9 +++++++-- servers/vm/proto.h | 3 ++- servers/vm/region.c | 15 ++++++++++++--- servers/vm/vmproc.h | 4 ++++ 12 files changed, 62 insertions(+), 22 deletions(-) diff --git a/servers/vm/exit.c b/servers/vm/exit.c index f287b327a..11cfcc94b 100644 --- a/servers/vm/exit.c +++ b/servers/vm/exit.c @@ -24,6 +24,14 @@ #include "util.h" #include "sanitycheck.h" +static void reset_vm_rusage(struct vmproc *vmp) +{ + vmp->vm_total = 0; + vmp->vm_total_max = 0; + vmp->vm_minor_page_fault = 0; + vmp->vm_major_page_fault = 0; +} + void free_proc(struct vmproc *vmp) { map_free_proc(vmp); @@ -33,6 +41,7 @@ void free_proc(struct vmproc *vmp) vmp->vm_bytecopies = 0; #endif vmp->vm_region_top = 0; + reset_vm_rusage(vmp); } void clear_proc(struct vmproc *vmp) @@ -43,6 +52,7 @@ void clear_proc(struct vmproc *vmp) vmp->vm_bytecopies = 0; #endif vmp->vm_region_top = 0; + reset_vm_rusage(vmp); } /*===========================================================================* diff --git a/servers/vm/mem_anon.c b/servers/vm/mem_anon.c index 9adc52419..5158f882d 100644 --- a/servers/vm/mem_anon.c +++ b/servers/vm/mem_anon.c @@ -22,7 +22,8 @@ static void anon_split(struct vmproc *vmp, struct vir_region *vr, static int anon_lowshrink(struct vir_region *vr, vir_bytes len); static int anon_unreference(struct phys_region *pr); static int anon_pagefault(struct vmproc *vmp, struct vir_region *region, - struct phys_region *ph, int write, vfs_callback_t cb, void *, int); + struct phys_region *ph, int write, vfs_callback_t cb, void *state, + int len, int *io); static int anon_sanitycheck(struct phys_region *pr, char *file, int line); static int anon_writable(struct phys_region *pr); static int anon_resize(struct vmproc *vmp, struct vir_region *vr, vir_bytes l); @@ -51,7 +52,8 @@ static int anon_unreference(struct phys_region *pr) } static int anon_pagefault(struct vmproc *vmp, struct vir_region *region, - struct phys_region *ph, int write, vfs_callback_t cb, void *st, int l) + struct phys_region *ph, int write, vfs_callback_t cb, void *state, + int len, int *io) { phys_bytes new_page, new_page_cl; u32_t allocflags; diff --git a/servers/vm/mem_anon_contig.c b/servers/vm/mem_anon_contig.c index 1f2750d18..127ee4cfa 100644 --- a/servers/vm/mem_anon_contig.c +++ b/servers/vm/mem_anon_contig.c @@ -11,7 +11,8 @@ static int anon_contig_reference(struct phys_region *, struct phys_region *); static int anon_contig_unreference(struct phys_region *pr); static int anon_contig_pagefault(struct vmproc *vmp, struct vir_region *region, - struct phys_region *ph, int write, vfs_callback_t cb, void *st, int); + struct phys_region *ph, int write, vfs_callback_t cb, void *state, + int len, int *io); static int anon_contig_sanitycheck(struct phys_region *pr, char *file, int line); static int anon_contig_writable(struct phys_region *pr); static int anon_contig_resize(struct vmproc *vmp, struct vir_region *vr, vir_bytes l); @@ -29,7 +30,8 @@ struct mem_type mem_type_anon_contig = { }; static int anon_contig_pagefault(struct vmproc *vmp, struct vir_region *region, - struct phys_region *ph, int write, vfs_callback_t cb, void *s, int l) + struct phys_region *ph, int write, vfs_callback_t cb, void *state, + int len, int *io) { panic("anon_contig_pagefault: pagefault cannot happen"); } diff --git a/servers/vm/mem_cache.c b/servers/vm/mem_cache.c index 7bc0bc24e..39f9495d5 100644 --- a/servers/vm/mem_cache.c +++ b/servers/vm/mem_cache.c @@ -29,7 +29,8 @@ static int cache_sanitycheck(struct phys_region *pr, char *file, int line); static int cache_writable(struct phys_region *pr); static int cache_resize(struct vmproc *vmp, struct vir_region *vr, vir_bytes l); static int cache_pagefault(struct vmproc *vmp, struct vir_region *region, - struct phys_region *ph, int write, vfs_callback_t cb, void *, int); + struct phys_region *ph, int write, vfs_callback_t cb, void *state, + int len, int *io); struct mem_type mem_type_cache = { .name = "cache memory", @@ -81,6 +82,7 @@ do_mapcache(message *msg) struct vir_region *vr; struct vmproc *caller; vir_bytes offset; + int io = 0; if(vm_isokendpt(msg->m_source, &n) != OK) panic("bogus source"); caller = &vmproc[n]; @@ -113,7 +115,7 @@ do_mapcache(message *msg) assert(vr->length == bytes); assert(offset < vr->length); - if(map_pf(caller, vr, offset, 1, NULL, NULL, 0) != OK) { + if(map_pf(caller, vr, offset, 1, NULL, NULL, 0, &io) != OK) { map_unmap_region(caller, vr, 0, bytes); printf("VM: map_pf failed\n"); return ENOMEM; @@ -136,7 +138,7 @@ do_mapcache(message *msg) static int cache_pagefault(struct vmproc *vmp, struct vir_region *region, struct phys_region *ph, int write, vfs_callback_t cb, - void *state, int len) + void *state, int len, int *io) { vir_bytes offset = ph->offset; assert(ph->ph->phys == MAP_NONE); diff --git a/servers/vm/mem_directphys.c b/servers/vm/mem_directphys.c index 740c6e488..306384975 100644 --- a/servers/vm/mem_directphys.c +++ b/servers/vm/mem_directphys.c @@ -17,7 +17,8 @@ static int phys_unreference(struct phys_region *pr); static int phys_writable(struct phys_region *pr); static int phys_pagefault(struct vmproc *vmp, struct vir_region *region, - struct phys_region *ph, int write, vfs_callback_t cb, void *, int); + struct phys_region *ph, int write, vfs_callback_t cb, void *state, + int len, int *io); static int phys_copy(struct vir_region *vr, struct vir_region *newvr); struct mem_type mem_type_directphys = { @@ -34,7 +35,8 @@ static int phys_unreference(struct phys_region *pr) } static int phys_pagefault(struct vmproc *vmp, struct vir_region *region, - struct phys_region *ph, int write, vfs_callback_t cb, void *st, int len) + struct phys_region *ph, int write, vfs_callback_t cb, void *state, + int len, int *io) { phys_bytes arg = region->param.phys, phmem; assert(arg != MAP_NONE); diff --git a/servers/vm/mem_file.c b/servers/vm/mem_file.c index 93b546225..9fc51140d 100644 --- a/servers/vm/mem_file.c +++ b/servers/vm/mem_file.c @@ -18,7 +18,8 @@ static void mappedfile_split(struct vmproc *vmp, struct vir_region *vr, struct vir_region *r1, struct vir_region *r2); static int mappedfile_unreference(struct phys_region *pr); static int mappedfile_pagefault(struct vmproc *vmp, struct vir_region *region, - struct phys_region *ph, int write, vfs_callback_t callback, void *, int); + struct phys_region *ph, int write, vfs_callback_t callback, void *state, + int len, int *io); static int mappedfile_sanitycheck(struct phys_region *pr, char *file, int line); static int mappedfile_writable(struct phys_region *pr); static int mappedfile_copy(struct vir_region *vr, struct vir_region *newvr); @@ -72,7 +73,7 @@ static int cow_block(struct vmproc *vmp, struct vir_region *region, static int mappedfile_pagefault(struct vmproc *vmp, struct vir_region *region, struct phys_region *ph, int write, vfs_callback_t cb, - void *state, int statelen) + void *state, int statelen, int *io) { u32_t allocflags; int procfd = region->param.file.fdref->fd; @@ -123,7 +124,7 @@ static int mappedfile_pagefault(struct vmproc *vmp, struct vir_region *region, printf("VM: mappedfile_pagefault: vfs_request failed\n"); return ENOMEM; } - + *io = 1; return SUSPEND; } diff --git a/servers/vm/mem_shared.c b/servers/vm/mem_shared.c index b7fdd4944..7a0f95fc1 100644 --- a/servers/vm/mem_shared.c +++ b/servers/vm/mem_shared.c @@ -15,7 +15,8 @@ static int shared_unreference(struct phys_region *pr); static int shared_pagefault(struct vmproc *vmp, struct vir_region *region, - struct phys_region *ph, int write, vfs_callback_t cb, void *, int); + struct phys_region *ph, int write, vfs_callback_t cb, void *state, + int len, int *io); static int shared_sanitycheck(struct phys_region *pr, char *file, int line); static int shared_writable(struct phys_region *pr); static void shared_delete(struct vir_region *region); @@ -110,7 +111,7 @@ static void shared_delete(struct vir_region *region) static int shared_pagefault(struct vmproc *vmp, struct vir_region *region, struct phys_region *ph, int write, vfs_callback_t cb, - void *state, int statelen) + void *state, int statelen, int *io) { struct vir_region *src_region; struct vmproc *src_vmp; @@ -126,7 +127,7 @@ static int shared_pagefault(struct vmproc *vmp, struct vir_region *region, if(!(pr = physblock_get(src_region, ph->offset))) { int r; if((r=map_pf(src_vmp, src_region, ph->offset, write, - NULL, NULL, 0)) != OK) + NULL, NULL, 0, io)) != OK) return r; if(!(pr = physblock_get(src_region, ph->offset))) { panic("missing region after pagefault handling"); diff --git a/servers/vm/memtype.h b/servers/vm/memtype.h index 7ff4ce9c6..f5ff38f00 100644 --- a/servers/vm/memtype.h +++ b/servers/vm/memtype.h @@ -16,7 +16,8 @@ typedef struct mem_type { int (*ev_reference)(struct phys_region *pr, struct phys_region *newpr); int (*ev_unreference)(struct phys_region *pr); int (*ev_pagefault)(struct vmproc *vmp, struct vir_region *region, - struct phys_region *ph, int write, vfs_callback_t cb, void *, int); + struct phys_region *ph, int write, vfs_callback_t cb, void *state, + int len, int *io); int (*ev_resize)(struct vmproc *vmp, struct vir_region *vr, vir_bytes len); void (*ev_split)(struct vmproc *vmp, struct vir_region *vr, struct vir_region *r1, struct vir_region *r2); diff --git a/servers/vm/pagefaults.c b/servers/vm/pagefaults.c index c945f4857..ede0ad0fa 100644 --- a/servers/vm/pagefaults.c +++ b/servers/vm/pagefaults.c @@ -70,6 +70,7 @@ static void handle_pagefault(endpoint_t ep, vir_bytes addr, u32_t err, int retry struct vir_region *region; vir_bytes offset; int p, wr = PFERR_WRITE(err); + int io = 0; if(vm_isokendpt(ep, &p) != OK) panic("handle_pagefault: endpoint wrong: %d", ep); @@ -111,7 +112,7 @@ static void handle_pagefault(endpoint_t ep, vir_bytes addr, u32_t err, int retry /* Access is allowed; handle it. */ if(retry) { - result = map_pf(vmp, region, offset, wr, NULL, NULL, 0); + result = map_pf(vmp, region, offset, wr, NULL, NULL, 0, &io); assert(result != SUSPEND); } else { struct pf_state state; @@ -119,8 +120,12 @@ static void handle_pagefault(endpoint_t ep, vir_bytes addr, u32_t err, int retry state.vaddr = addr; state.err = err; result = map_pf(vmp, region, offset, wr, pf_cont, - &state, sizeof(state)); + &state, sizeof(state), &io); } + if (io) + vmp->vm_major_page_fault++; + else + vmp->vm_minor_page_fault++; if(result == SUSPEND) { return; diff --git a/servers/vm/proto.h b/servers/vm/proto.h index f162045d2..03badb81c 100644 --- a/servers/vm/proto.h +++ b/servers/vm/proto.h @@ -143,7 +143,8 @@ int map_proc_copy_from(struct vmproc *dst, struct vmproc *src, struct struct vir_region *map_lookup(struct vmproc *vmp, vir_bytes addr, struct phys_region **pr); int map_pf(struct vmproc *vmp, struct vir_region *region, vir_bytes - offset, int write, vfs_callback_t pf_callback, void *state, int); + offset, int write, vfs_callback_t pf_callback, void *state, int len, + int *io); int map_pin_memory(struct vmproc *vmp); int map_handle_memory(struct vmproc *vmp, struct vir_region *region, vir_bytes offset, vir_bytes len, int write, vfs_callback_t cb, diff --git a/servers/vm/region.c b/servers/vm/region.c index 500056b93..8499c0812 100644 --- a/servers/vm/region.c +++ b/servers/vm/region.c @@ -73,14 +73,21 @@ void physblock_set(struct vir_region *region, vir_bytes offset, struct phys_region *newphysr) { int i; + struct vmproc *proc; assert(!(offset % VM_PAGE_SIZE)); assert(offset >= 0 && offset < region->length); i = offset/VM_PAGE_SIZE; + proc = region->parent; + assert(proc); if(newphysr) { assert(!region->physblocks[i]); assert(newphysr->offset == offset); + proc->vm_total += VM_PAGE_SIZE; + if (proc->vm_total > proc->vm_total_max) + proc->vm_total_max = proc->vm_total; } else { assert(region->physblocks[i]); + proc->vm_total -= VM_PAGE_SIZE; } region->physblocks[i] = newphysr; } @@ -671,7 +678,7 @@ u32_t vrallocflags(u32_t flags) /*===========================================================================* * map_pf * *===========================================================================*/ -int map_pf(vmp, region, offset, write, pf_callback, state, len) +int map_pf(vmp, region, offset, write, pf_callback, state, len, io) struct vmproc *vmp; struct vir_region *region; vir_bytes offset; @@ -679,6 +686,7 @@ int write; vfs_callback_t pf_callback; void *state; int len; +int *io; { struct phys_region *ph; int r = OK; @@ -725,7 +733,7 @@ int len; assert(ph->ph); if((r = ph->memtype->ev_pagefault(vmp, - region, ph, write, pf_callback, state, len)) == SUSPEND) { + region, ph, write, pf_callback, state, len, io)) == SUSPEND) { return SUSPEND; } @@ -774,6 +782,7 @@ int statelen; { vir_bytes offset, lim; int r; + int io = 0; assert(length > 0); lim = start_offset + length; @@ -781,7 +790,7 @@ int statelen; for(offset = start_offset; offset < lim; offset += VM_PAGE_SIZE) if((r = map_pf(vmp, region, offset, write, - cb, state, statelen)) != OK) + cb, state, statelen, &io)) != OK) return r; return OK; diff --git a/servers/vm/vmproc.h b/servers/vm/vmproc.h index 5e7145505..f8c6e430a 100644 --- a/servers/vm/vmproc.h +++ b/servers/vm/vmproc.h @@ -25,6 +25,10 @@ struct vmproc { #if VMSTATS int vm_bytecopies; #endif + vir_bytes vm_total; + vir_bytes vm_total_max; + u64_t vm_minor_page_fault; + u64_t vm_major_page_fault; }; /* Bits for vm_flags */