diff options
author | Maksym Planeta <mcsim.planeta@gmail.com> | 2012-10-08 16:01:13 +0200 |
---|---|---|
committer | Maksym Planeta <mcsim.planeta@gmail.com> | 2012-10-28 12:23:14 +0100 |
commit | e70ecc311676b9f30cbc5ca7c2029b7f522cbb25 (patch) | |
tree | c55707e26f15135bf9cd6b565f2528690c4c5a60 | |
parent | 6a08b518a60bd0e9448278f88f6f55681a5b9c6c (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.defs | 23 | ||||
-rw-r--r-- | include/mach/mach_types.defs | 1 | ||||
-rw-r--r-- | kern/ipc_mig.c | 20 | ||||
-rw-r--r-- | kern/syscall_sw.c | 3 | ||||
-rw-r--r-- | vm/memory_object.c | 43 | ||||
-rw-r--r-- | vm/vm_map.c | 40 | ||||
-rw-r--r-- | vm/vm_map.h | 3 | ||||
-rw-r--r-- | vm/vm_user.c | 26 |
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; |