diff options
-rw-r--r-- | Makefrag.am | 8 | ||||
-rw-r--r-- | include/mach/gnumach.defs | 39 | ||||
-rw-r--r-- | include/mach/mach_types.h | 1 | ||||
-rw-r--r-- | kern/ipc_kobject.c | 2 | ||||
-rw-r--r-- | vm/vm_object.c | 14 | ||||
-rw-r--r-- | vm/vm_object.h | 23 | ||||
-rw-r--r-- | vm/vm_resident.c | 15 | ||||
-rw-r--r-- | vm/vm_user.c | 24 | ||||
-rw-r--r-- | vm/vm_user.h | 2 |
9 files changed, 126 insertions, 2 deletions
diff --git a/Makefrag.am b/Makefrag.am index 7180093..c0cb8fe 100644 --- a/Makefrag.am +++ b/Makefrag.am @@ -209,6 +209,7 @@ libkernel_a_SOURCES += \ EXTRA_DIST += \ kern/mach.srv \ kern/mach4.srv \ + kern/gnumach.srv \ kern/mach_debug.srv \ kern/mach_host.srv @@ -346,6 +347,7 @@ include_mach_HEADERS = \ include/mach/exc.defs \ include/mach/mach.defs \ include/mach/mach4.defs \ + include/mach/gnumach.defs \ include/mach/mach_host.defs \ include/mach/mach_port.defs \ include/mach/mach_types.defs \ @@ -388,6 +390,7 @@ include_mach_HEADERS = \ include/mach/time_value.h \ include/mach/version.h \ include/mach/vm_attributes.h \ + include/mach/vm_cache_statistics.h \ include/mach/vm_inherit.h \ include/mach/vm_param.h \ include/mach/vm_prot.h \ @@ -483,6 +486,7 @@ nodist_libkernel_a_SOURCES += \ nodist_lib_dep_tr_for_defs_a_SOURCES += \ kern/mach.server.defs.c \ kern/mach4.server.defs.c \ + kern/gnumach.server.defs.c \ kern/mach_debug.server.defs.c \ kern/mach_host.server.defs.c nodist_libkernel_a_SOURCES += \ @@ -492,6 +496,9 @@ nodist_libkernel_a_SOURCES += \ kern/mach4.server.h \ kern/mach4.server.c \ kern/mach4.server.msgids \ + kern/gnumach.server.h \ + kern/gnumach.server.c \ + kern/gnumach.server.msgids \ kern/mach_debug.server.h \ kern/mach_debug.server.c \ kern/mach_debug.server.msgids \ @@ -500,6 +507,7 @@ nodist_libkernel_a_SOURCES += \ kern/mach_host.server.msgids # kern/mach.server.defs # kern/mach4.server.defs +# kern/gnumach.server.defs # kern/mach_debug.server.defs # kern/mach_host.server.defs diff --git a/include/mach/gnumach.defs b/include/mach/gnumach.defs new file mode 100644 index 0000000..7331334 --- /dev/null +++ b/include/mach/gnumach.defs @@ -0,0 +1,39 @@ +/* + * Copyright (C) 2012 Free Software Foundation + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +subsystem +#if KERNEL_SERVER + KernelServer +#endif /* KERNEL_SERVER */ +#if KERNEL_USER + KernelUser +#endif /* KERNEL_USER */ + gnumach 4200; + +#include <mach/std_types.defs> +#include <mach/mach_types.defs> + +type vm_cache_statistics_data_t = struct[11] of integer_t; + +/* + * Return page cache statistics for the host on which the target task + * resides. + */ +routine vm_cache_statistics( + target_task : vm_task_t; + out vm_cache_stats : vm_cache_statistics_data_t); diff --git a/include/mach/mach_types.h b/include/mach/mach_types.h index f6ceac3..8768482 100644 --- a/include/mach/mach_types.h +++ b/include/mach/mach_types.h @@ -52,6 +52,7 @@ #include <mach/vm_inherit.h> #include <mach/vm_prot.h> #include <mach/vm_statistics.h> +#include <mach/vm_cache_statistics.h> #ifdef MACH_KERNEL #include <kern/task.h> /* for task_array_t */ diff --git a/kern/ipc_kobject.c b/kern/ipc_kobject.c index c922d7f..f094b73 100644 --- a/kern/ipc_kobject.c +++ b/kern/ipc_kobject.c @@ -152,6 +152,7 @@ ipc_kobject_server(request) device_server_routine(), device_pager_server_routine(), mach4_server_routine(); + gnumach_server_routine(); #if MACH_DEBUG extern mig_routine_t mach_debug_server_routine(); #endif @@ -170,6 +171,7 @@ ipc_kobject_server(request) || (routine = mach_debug_server_routine(&request->ikm_header)) != 0 #endif /* MACH_DEBUG */ || (routine = mach4_server_routine(&request->ikm_header)) != 0 + || (routine = gnumach_server_routine(&request->ikm_header)) != 0 #if MACH_MACHINE_ROUTINES || (routine = MACHINE_SERVER_ROUTINE(&request->ikm_header)) != 0 #endif /* MACH_MACHINE_ROUTINES */ diff --git a/vm/vm_object.c b/vm/vm_object.c index f101708..7eae3d7 100644 --- a/vm/vm_object.c +++ b/vm/vm_object.c @@ -192,6 +192,15 @@ decl_simple_lock_data(,vm_object_cached_lock_data) simple_unlock(&vm_object_cached_lock_data) /* + * Number of physical pages referenced by cached objects. + * This counter is protected by its own lock to work around + * lock ordering issues. + */ +int vm_object_cached_pages; + +decl_simple_lock_data(,vm_object_cached_pages_lock_data) + +/* * Virtual memory objects are initialized from * a template (see vm_object_allocate). * @@ -410,6 +419,7 @@ void vm_object_deallocate( queue_enter(&vm_object_cached_list, object, vm_object_t, cached_list); overflow = (++vm_object_cached_count > vm_object_cached_max); + vm_object_cached_pages_update(object->resident_page_count); vm_object_cache_unlock(); vm_object_deactivate_pages(object); @@ -1860,6 +1870,7 @@ vm_object_t vm_object_lookup( queue_remove(&vm_object_cached_list, object, vm_object_t, cached_list); vm_object_cached_count--; + vm_object_cached_pages_update(-object->resident_page_count); } object->ref_count++; @@ -1891,6 +1902,7 @@ vm_object_t vm_object_lookup_name( queue_remove(&vm_object_cached_list, object, vm_object_t, cached_list); vm_object_cached_count--; + vm_object_cached_pages_update(-object->resident_page_count); } object->ref_count++; @@ -1927,6 +1939,7 @@ void vm_object_destroy( queue_remove(&vm_object_cached_list, object, vm_object_t, cached_list); vm_object_cached_count--; + vm_object_cached_pages_update(-object->resident_page_count); } object->ref_count++; @@ -2080,6 +2093,7 @@ restart: queue_remove(&vm_object_cached_list, object, vm_object_t, cached_list); vm_object_cached_count--; + vm_object_cached_pages_update(-object->resident_page_count); } object->ref_count++; vm_object_unlock(object); diff --git a/vm/vm_object.h b/vm/vm_object.h index c992570..4e4c949 100644 --- a/vm/vm_object.h +++ b/vm/vm_object.h @@ -71,8 +71,8 @@ struct vm_object { * if internal) */ - short ref_count; /* Number of references */ - short resident_page_count; + int ref_count; /* Number of references */ + int resident_page_count; /* number of resident pages */ struct vm_object *copy; /* Object that should receive @@ -370,4 +370,23 @@ MACRO_END #define vm_object_lock_taken(object) simple_lock_taken(&(object)->Lock) #endif /* VM_OBJECT_DEBUG */ +/* + * Page cache accounting. + * + * The number of cached objects and pages can be read + * without holding any lock. + */ + +extern int vm_object_cached_count; + +extern int vm_object_cached_pages; +decl_simple_lock_data(extern,vm_object_cached_pages_lock_data) + +#define vm_object_cached_pages_update(page_count) \ + MACRO_BEGIN \ + simple_lock(&vm_object_cached_pages_lock_data); \ + vm_object_cached_pages += (page_count); \ + simple_unlock(&vm_object_cached_pages_lock_data); \ + MACRO_END + #endif /* _VM_VM_OBJECT_H_ */ diff --git a/vm/vm_resident.c b/vm/vm_resident.c index ae71a74..581a9c4 100644 --- a/vm/vm_resident.c +++ b/vm/vm_resident.c @@ -517,6 +517,10 @@ void vm_page_insert( */ object->resident_page_count++; + assert(object->resident_page_count >= 0); + + if (object->can_persist && (object->ref_count == 0)) + vm_object_cached_pages_update(1); /* * Detect sequential access and inactivate previous page. @@ -585,6 +589,10 @@ void vm_page_replace( m->tabled = FALSE; object->resident_page_count--; + if (object->can_persist + && (object->ref_count == 0)) + vm_object_cached_pages_update(-1); + /* * Return page to the free list. * Note the page is not tabled now, so this @@ -616,6 +624,10 @@ void vm_page_replace( */ object->resident_page_count++; + assert(object->resident_page_count >= 0); + + if (object->can_persist && (object->ref_count == 0)) + vm_object_cached_pages_update(1); } /* @@ -671,6 +683,9 @@ void vm_page_remove( mem->object->resident_page_count--; mem->tabled = FALSE; + + if (mem->object->can_persist && (mem->object->ref_count == 0)) + vm_object_cached_pages_update(-1); } /* diff --git a/vm/vm_user.c b/vm/vm_user.c index 59c2a36..a8ce982 100644 --- a/vm/vm_user.c +++ b/vm/vm_user.c @@ -38,6 +38,7 @@ #include <mach/vm_attributes.h> #include <mach/vm_param.h> #include <mach/vm_statistics.h> +#include <mach/vm_cache_statistics.h> #include <kern/host.h> #include <kern/task.h> #include <vm/vm_fault.h> @@ -189,6 +190,29 @@ kern_return_t vm_statistics(map, stat) return(KERN_SUCCESS); } +kern_return_t vm_cache_statistics( + vm_map_t map, + vm_cache_statistics_data_t *stats) +{ + if (map == VM_MAP_NULL) + return KERN_INVALID_ARGUMENT; + + stats->cache_object_count = vm_object_cached_count; + stats->cache_count = vm_object_cached_pages; + + /* XXX Not implemented yet */ + stats->active_tmp_count = 0; + stats->inactive_tmp_count = 0; + stats->active_perm_count = 0; + stats->inactive_perm_count = 0; + stats->dirty_count = 0; + stats->laundry_count = 0; + stats->writeback_count = 0; + stats->slab_count = 0; + stats->slab_reclaim_count = 0; + return KERN_SUCCESS; +} + /* * Handle machine-specific attributes for a mapping, such * as cachability, migrability, etc. diff --git a/vm/vm_user.h b/vm/vm_user.h index 3f15e5e..c6f20a8 100644 --- a/vm/vm_user.h +++ b/vm/vm_user.h @@ -37,6 +37,7 @@ #include <mach/kern_return.h> #include <mach/std_types.h> +#include <mach/mach_types.h> extern kern_return_t vm_allocate(vm_map_t, vm_offset_t *, vm_size_t, boolean_t); @@ -46,6 +47,7 @@ extern kern_return_t vm_inherit(vm_map_t, vm_offset_t, vm_size_t, extern kern_return_t vm_protect(vm_map_t, vm_offset_t, vm_size_t, boolean_t, vm_prot_t); extern kern_return_t vm_statistics(vm_map_t, vm_statistics_data_t *); +extern kern_return_t vm_cache_statistics(vm_map_t, vm_cache_statistics_data_t *); extern kern_return_t vm_read(vm_map_t, vm_address_t, vm_size_t, pointer_t *, vm_size_t *); extern kern_return_t vm_write(vm_map_t, vm_address_t, pointer_t, vm_size_t); |