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 /vm | |
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.
Diffstat (limited to 'vm')
-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 |
4 files changed, 112 insertions, 0 deletions
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; |