summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRichard Braun <rbraun@sceen.net>2012-09-23 00:25:13 +0200
committerSamuel Thibault <samuel.thibault@ens-lyon.org>2012-09-23 00:28:40 +0200
commit9eacb0eab6eb8e35bb26ab3db660973fddf9e8fb (patch)
tree03d50c74d110f2bab3a8fb2ebac9eb7aca0313c4
parentf5f6f62357b90e1ce1eb24f2929314b0d84078d0 (diff)
Provide basic page cache statistics
* Makefrag.am (EXTRA_DIST): Add kern/gnumach.srv. (include_mach_HEADERS): Add include/mach/gnumach.defs and include/mach/vm_cache_statistics.h (nodist_libkernel_a_SOURCES): Add kern/gnumach.server.defs.c, kern/gnumach.server.h, kern/gnumach.server.c, kern/gnumach.server.msgids, kern/gnumach.server.defs. * include/mach/mach_types.h: Add #include <mach/vm_cache_statistics.h>. * kern/ipc_kobject.c (ipc_kobject_server): Declare and call gnumach_server_routine. * vm/vm_object.c (vm_object_cached_pages): New variable. (vm_object_cached_pages_lock_data): Likewise. (vm_object_deallocate): Update number of cached pages. (vm_object_lookup): Likewise. (vm_object_lookup_name): Likewise. (vm_object_destroy): Likewise. (vm_object_enter): Likewise. * vm/vm_object.h (ref_count): Declare as int. (resident_page_count): Likewise. (vm_object_cached_count): Add extern declaration. (vm_object_cached_pages): Likewise. (vm_object_cached_pages_lock_data): Likewise. (vm_object_cached_pages_update): New macro. * vm/vm_resident.c (vm_page_insert): Assert resident page count doesn't overflow, update number of cached pages as appropriate. (vm_page_replace): Likewise. (vm_page_remove): Update number of cached pages as appropriate. * vm/vm_user.c: Add #include <mach/vm_cache_statistics.h>. (vm_cache_statistics): New function. * vm/vm_user.h: Add #include <mach/mach_types.h>. (vm_cache_statistics): New declaration. * include/mach/gnumach.defs: New file.
-rw-r--r--Makefrag.am8
-rw-r--r--include/mach/gnumach.defs39
-rw-r--r--include/mach/mach_types.h1
-rw-r--r--kern/ipc_kobject.c2
-rw-r--r--vm/vm_object.c14
-rw-r--r--vm/vm_object.h23
-rw-r--r--vm/vm_resident.c15
-rw-r--r--vm/vm_user.c24
-rw-r--r--vm/vm_user.h2
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);