[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[PATCH] Page cache accounting
From: |
Richard Braun |
Subject: |
[PATCH] Page cache accounting |
Date: |
Sat, 14 Jul 2012 17:06:37 +0200 |
If no major objection is raised (particularly about the new Mig
routine), I'll commit this patch in a few days.
The decision to add the call to the mach4 interface stems from
pragmatism. It doesn't break existing compatibility, and it doesn't add
the burden of a new interface.
---
include/mach/mach4.defs | 10 ++++++++++
include/mach/mach_types.h | 1 +
include/mach/vm_cache_statistics.h | 33 +++++++++++++++++++++++++++++++++
vm/vm_object.c | 14 ++++++++++++++
vm/vm_object.h | 19 +++++++++++++++++++
vm/vm_resident.c | 13 +++++++++++++
vm/vm_user.c | 14 ++++++++++++++
vm/vm_user.h | 2 ++
8 files changed, 106 insertions(+), 0 deletions(-)
create mode 100644 include/mach/vm_cache_statistics.h
diff --git a/include/mach/mach4.defs b/include/mach/mach4.defs
index 114edf4..8ac49e2 100644
--- a/include/mach/mach4.defs
+++ b/include/mach/mach4.defs
@@ -110,3 +110,13 @@ routine memory_object_create_proxy(
start : vm_offset_array_t;
len : vm_offset_array_t;
out proxy : mach_port_t);
+
+type vm_cache_statistics_data_t = struct[16] 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/include/mach/vm_cache_statistics.h
b/include/mach/vm_cache_statistics.h
new file mode 100644
index 0000000..6328019
--- /dev/null
+++ b/include/mach/vm_cache_statistics.h
@@ -0,0 +1,33 @@
+/*
+ * 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.
+ */
+
+#ifndef _MACH_VM_CACHE_STATISTICS_H_
+#define _MACH_VM_CACHE_STATISTICS_H_
+
+#include <mach/machine/vm_types.h>
+
+struct vm_cache_statistics {
+ integer_t object_count; /* # of cached objects */
+ integer_t page_count; /* # of cached pages */
+ integer_t _reserved[14];
+};
+
+typedef struct vm_cache_statistics *vm_cache_statistics_t;
+typedef struct vm_cache_statistics vm_cache_statistics_data_t;
+
+#endif /* _MACH_VM_CACHE_STATISTICS_H_ */
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..2786492 100644
--- a/vm/vm_object.h
+++ b/vm/vm_object.h
@@ -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..f01a9e2 100644
--- a/vm/vm_resident.c
+++ b/vm/vm_resident.c
@@ -518,6 +518,9 @@ void vm_page_insert(
object->resident_page_count++;
+ if (object->can_persist && (object->ref_count == 0))
+ vm_object_cached_pages_update(1);
+
/*
* Detect sequential access and inactivate previous page.
* We ignore busy pages.
@@ -585,6 +588,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 +623,9 @@ void vm_page_replace(
*/
object->resident_page_count++;
+
+ if (object->can_persist && (object->ref_count == 0))
+ vm_object_cached_pages_update(1);
}
/*
@@ -671,6 +681,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..ad88331 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,19 @@ 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->object_count = vm_object_cached_count;
+ stats->page_count = vm_object_cached_pages;
+ memset(stats->_reserved, 0, sizeof(stats->_reserved));
+ 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);
--
1.7.2.5
Re: [PATCH] VM cache policy change., Samuel Thibault, 2012/07/15
[PATCH] Page cache accounting,
Richard Braun <=
Re: [PATCH] Page cache accounting, Richard Braun, 2012/07/17