bug-hurd
[Top][All Lists]
Advanced

[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




reply via email to

[Prev in Thread] Current Thread [Next in Thread]