summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMaksym Planeta <mcsim.planeta@gmail.com>2012-10-08 16:01:13 +0200
committerMaksym Planeta <mcsim.planeta@gmail.com>2012-10-28 12:23:14 +0100
commite70ecc311676b9f30cbc5ca7c2029b7f522cbb25 (patch)
treec55707e26f15135bf9cd6b565f2528690c4c5a60
parent6a08b518a60bd0e9448278f88f6f55681a5b9c6c (diff)
Add IPC functions that allow user to manipulate with memory advice.
* include/mach/mach_types.defs (vm_advice_t): New type definition. * include/mach/mach.defs (vm_advise): New RPC definition. (memory_object_set_advice): Likewise. (memory_object_get_advice): Likewise. * kern/ipc_mig.c (syscall_vm_advice): New function. This is optimization function for RPC that is processed by kernel. * kern/syscall_sw.c (syscall_vm_advice): Add function prototype. (mach_trap_table): Add syscall_vm_advice to trap table. * vm/memory_object.c (memory_object_set_advice): New function. Sets memory advice for memory object. (memory_object_get_advice): New function. Returns memory advice of memory object. * vm/vm_user.c (vm_advise): New function. Wrapper for vm_map_advice. * vm/vm_map.h (vm_map_advice): Add function prototype. * vm/vm_map.c (vm_map_advice): New function. Sets memory advice for memory range.
-rw-r--r--include/mach/mach.defs23
-rw-r--r--include/mach/mach_types.defs1
-rw-r--r--kern/ipc_mig.c20
-rw-r--r--kern/syscall_sw.c3
-rw-r--r--vm/memory_object.c43
-rw-r--r--vm/vm_map.c40
-rw-r--r--vm/vm_map.h3
-rw-r--r--vm/vm_user.c26
8 files changed, 155 insertions, 4 deletions
diff --git a/include/mach/mach.defs b/include/mach/mach.defs
index 58510805..c5ffbc05 100644
--- a/include/mach/mach.defs
+++ b/include/mach/mach.defs
@@ -282,7 +282,18 @@ routine vm_statistics(
target_task : vm_task_t;
out vm_stats : vm_statistics_data_t);
-skip; /* old task_by_u*x_pid */
+
+/*
+ * Set the page fault policy attribute for the specified range
+ * of the virtual address space of the target task.
+ * The advice value is either random or sequential, and
+ * specifies how kernel should consider access to lacking page.
+ */
+routine vm_advise(
+ target_task : vm_task_t;
+ address : vm_address_t;
+ size : vm_size_t;
+ advice : vm_advice_t);
skip; /* old vm_pageable */
/*
@@ -681,8 +692,14 @@ simpleroutine memory_object_change_attributes(
MACH_MSG_TYPE_MAKE_SEND_ONCE|polymorphic);
skip; /* old host_callout_statistics_reset */
-skip; /* old port_set_select */
-skip; /* old port_set_backup */
+
+simpleroutine memory_object_set_advice(
+ memory_control : memory_object_control_t;
+ advice : vm_advice_t);
+
+routine memory_object_get_advice(
+ memory_control : memory_object_control_t;
+ out advice : vm_advice_t);
/*
* Set/Get special properties of memory associated
diff --git a/include/mach/mach_types.defs b/include/mach/mach_types.defs
index 607d5d92..12c4b7c7 100644
--- a/include/mach/mach_types.defs
+++ b/include/mach/mach_types.defs
@@ -117,6 +117,7 @@ type vm_offset_t = natural_t;
type vm_size_t = natural_t;
type vm_prot_t = int;
type vm_inherit_t = int;
+type vm_advice_t = int;
type vm_statistics_data_t = struct[13] of integer_t;
type vm_machine_attribute_t = int;
type vm_machine_attribute_val_t = int;
diff --git a/kern/ipc_mig.c b/kern/ipc_mig.c
index 3f55da7c..38f74136 100644
--- a/kern/ipc_mig.c
+++ b/kern/ipc_mig.c
@@ -704,6 +704,26 @@ kern_return_t syscall_vm_deallocate(target_map, start, size)
return result;
}
+kern_return_t
+syscall_vm_advise(
+ mach_port_t target_map,
+ vm_offset_t address,
+ vm_size_t length,
+ vm_advice_t advice,
+ vm_size_t cluster_size)
+{
+ vm_map_t map;
+ kern_return_t result;
+
+ map = port_name_to_map(target_map);
+ if (map == VM_MAP_NULL)
+ return MACH_SEND_INTERRUPTED;
+
+ result = vm_advise(map, address, length, advice, cluster_size);
+
+ return result;
+}
+
kern_return_t syscall_task_create(parent_task, inherit_memory, child_task)
mach_port_t parent_task;
boolean_t inherit_memory;
diff --git a/kern/syscall_sw.c b/kern/syscall_sw.c
index b2e20e66..659cac89 100644
--- a/kern/syscall_sw.c
+++ b/kern/syscall_sw.c
@@ -73,6 +73,7 @@ kern_return_t kern_invalid()
extern kern_return_t syscall_vm_map();
extern kern_return_t syscall_vm_allocate();
extern kern_return_t syscall_vm_deallocate();
+extern kern_return_t syscall_vm_advise();
extern kern_return_t syscall_task_create();
extern kern_return_t syscall_task_terminate();
@@ -164,7 +165,7 @@ mach_trap_t mach_trap_table[] = {
MACH_TRAP(syscall_vm_map, 11), /* 64 */
MACH_TRAP(syscall_vm_allocate, 4), /* 65 */
MACH_TRAP(syscall_vm_deallocate, 3), /* 66 */
- MACH_TRAP(kern_invalid, 0), /* 67 */
+ MACH_TRAP(syscall_vm_advise, 5), /* 67 */
MACH_TRAP(syscall_task_create, 3), /* 68 */
MACH_TRAP(syscall_task_terminate, 1), /* 69 */
diff --git a/vm/memory_object.c b/vm/memory_object.c
index e281c6a3..090b58eb 100644
--- a/vm/memory_object.c
+++ b/vm/memory_object.c
@@ -1037,6 +1037,49 @@ kern_return_t memory_object_get_attributes(object, object_ready,
return(KERN_SUCCESS);
}
+kern_return_t
+memory_object_set_advice(vm_object_t object, vm_advice_t advice)
+{
+ if (object == VM_OBJECT_NULL)
+ return(KERN_INVALID_ARGUMENT);
+
+ switch(advice) {
+ case VM_ADVICE_DEFAULT:
+ case VM_ADVICE_RANDOM:
+ case VM_ADVICE_SEQUENTIAL:
+ case VM_ADVICE_NORMAL:
+ case VM_ADVICE_KEEP:
+ break;
+ default:
+ vm_object_deallocate(object);
+ return(KERN_INVALID_ARGUMENT);
+ }
+
+ vm_object_lock(object);
+ if (advice != VM_ADVICE_KEEP)
+ object->advice = advice;
+ vm_object_unlock(object);
+
+ vm_object_deallocate(object);
+
+ return(KERN_SUCCESS);
+}
+
+kern_return_t
+memory_object_get_advice(vm_object_t object, vm_advice_t *advice)
+{
+ if (object == VM_OBJECT_NULL)
+ return(KERN_INVALID_ARGUMENT);
+
+ vm_object_lock(object);
+ *advice = object->advice;
+ vm_object_unlock(object);
+
+ vm_object_deallocate(object);
+
+ return(KERN_SUCCESS);
+}
+
/*
* If successful, consumes the supplied naked send right.
*/
diff --git a/vm/vm_map.c b/vm/vm_map.c
index 22fe0eae..0afaff29 100644
--- a/vm/vm_map.c
+++ b/vm/vm_map.c
@@ -1346,6 +1346,46 @@ kern_return_t vm_map_inherit(map, start, end, new_inheritance)
}
/*
+ * vm_map_advise:
+ *
+ * Sets the page fault advice of the specified
+ * address range in the target map. Advice
+ * affects how the page fault will be
+ * handled at the time of vm_fault.
+ */
+kern_return_t
+vm_map_advise(vm_map_t map, vm_offset_t address,
+ vm_size_t length, vm_advice_t advice)
+{
+ register vm_map_entry_t entry;
+ vm_map_entry_t temp_entry;
+ vm_offset_t end = address + length;
+
+ vm_map_lock(map);
+
+ VM_MAP_RANGE_CHECK(map, address, end);
+
+ if (vm_map_lookup_entry(map, address, &temp_entry)) {
+ entry = temp_entry;
+ vm_map_clip_start(map, entry, address);
+ }
+ else
+ entry = temp_entry->vme_next;
+
+ while ((entry != vm_map_to_entry(map))
+ && (entry->vme_start < end)) {
+ vm_map_clip_end(map, entry, end);
+
+ entry->advice = advice;
+
+ entry = entry->vme_next;
+ }
+
+ vm_map_unlock(map);
+ return(KERN_SUCCESS);
+}
+
+/*
* vm_map_pageable_common:
*
* Sets the pageability of the specified address
diff --git a/vm/vm_map.h b/vm/vm_map.h
index af7588ba..96c0bcbf 100644
--- a/vm/vm_map.h
+++ b/vm/vm_map.h
@@ -397,6 +397,9 @@ extern kern_return_t vm_map_protect(vm_map_t, vm_offset_t, vm_offset_t,
/* Change inheritance */
extern kern_return_t vm_map_inherit(vm_map_t, vm_offset_t, vm_offset_t,
vm_inherit_t);
+/* Change page fault policy */
+extern kern_return_t vm_map_advise(vm_map_t, vm_offset_t, vm_size_t,
+ vm_advice_t);
/* Debugging: print a map */
extern void vm_map_print(vm_map_t);
diff --git a/vm/vm_user.c b/vm/vm_user.c
index 59c2a36e..c5530a69 100644
--- a/vm/vm_user.c
+++ b/vm/vm_user.c
@@ -171,6 +171,32 @@ kern_return_t vm_protect(map, start, size, set_maximum, new_protection)
set_maximum));
}
+
+/*
+ * vm_advise sets page fault handling policy of the specified range
+ * in the specified map.
+ */
+
+kern_return_t
+vm_advise(vm_map_t map, vm_offset_t address,
+ vm_size_t length, vm_advice_t advice)
+{
+ if (map == VM_MAP_NULL)
+ return(KERN_INVALID_ARGUMENT);
+
+ switch(advice) {
+ case VM_ADVICE_DEFAULT:
+ case VM_ADVICE_RANDOM:
+ case VM_ADVICE_SEQUENTIAL:
+ case VM_ADVICE_NORMAL:
+ break;
+ default:
+ return(KERN_INVALID_ARGUMENT);
+ }
+
+ return(vm_map_advise(map, address, length, advice));
+}
+
kern_return_t vm_statistics(map, stat)
vm_map_t map;
vm_statistics_data_t *stat;