X-Git-Url: https://git.saurik.com/apple/xnu.git/blobdiff_plain/9bccf70c0258c7cac2dcb80011b2a964d884c552..55e303ae13a4cf49d70f2294092726f2fffb9ef2:/osfmk/vm/task_working_set.c diff --git a/osfmk/vm/task_working_set.c b/osfmk/vm/task_working_set.c index 90859e626..da8ecbac7 100644 --- a/osfmk/vm/task_working_set.c +++ b/osfmk/vm/task_working_set.c @@ -4,19 +4,22 @@ int startup_miss = 0; * * @APPLE_LICENSE_HEADER_START@ * - * The contents of this file constitute Original Code as defined in and - * are subject to the Apple Public Source License Version 1.1 (the - * "License"). You may not use this file except in compliance with the - * License. Please obtain a copy of the License at - * http://www.apple.com/publicsource and read it before using this file. + * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved. * - * This Original Code and all software distributed under the License are - * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License. + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. * * @APPLE_LICENSE_HEADER_END@ */ @@ -134,7 +137,7 @@ tws_hash_create( if((tws->table_ele[0] = (tws_hash_ptr_t) kalloc(sizeof(struct tws_hash_ptr) * lines * rows)) == NULL) { - kfree((vm_offset_t)tws->table[0], sizeof(tws_hash_ele_t) + kfree((vm_offset_t)tws->table[0], sizeof(tws_hash_ptr_t) * lines * rows); kfree((vm_offset_t)tws, sizeof(struct tws_hash)); return (tws_hash_t)NULL; @@ -290,8 +293,8 @@ tws_hash_line_clear( && (dump_pmap == 1)) { pmap_remove_some_phys((pmap_t) vm_map_pmap( - hash_ele->map), - p->phys_addr); + current_map()), + p->phys_page); } } local_off += PAGE_SIZE_64; @@ -322,7 +325,7 @@ tws_hash_line_clear( } kern_return_t -tws_lookup( +tws_internal_lookup( tws_hash_t tws, vm_object_offset_t offset, vm_object_t object, @@ -341,10 +344,6 @@ tws_lookup( if(object->private) return KERN_SUCCESS; - if(!tws_lock_try(tws)) { - return KERN_FAILURE; - } - index = do_tws_hash(object, offset, tws->number_of_elements, tws->number_of_lines); loop = 0; @@ -357,7 +356,6 @@ tws_lookup( age_of_cache = ((sched_tick - tws->time_of_creation) >> SCHED_TICK_SHIFT); if (age_of_cache > 35) { - tws_unlock(tws); return KERN_OPERATION_TIMED_OUT; } } @@ -370,7 +368,6 @@ tws_lookup( age_of_cache = ((sched_tick - tws->time_of_creation) >> SCHED_TICK_SHIFT); if (age_of_cache > 60) { - tws_unlock(tws); return KERN_OPERATION_TIMED_OUT; } } @@ -385,16 +382,32 @@ tws_lookup( set = cache_ele->element->line/tws->number_of_lines; ele_line = cache_ele->element->line - set; *line = &tws->cache[set][ele_line]; - tws_unlock(tws); return KERN_SUCCESS; } - tws_unlock(tws); return KERN_FAILURE; } +kern_return_t +tws_lookup( + tws_hash_t tws, + vm_object_offset_t offset, + vm_object_t object, + tws_hash_line_t *line) +{ + kern_return_t kr; + + if(!tws_lock_try(tws)) { + return KERN_FAILURE; + } + kr = tws_internal_lookup(tws, + offset, object, line); + tws_unlock(tws); + return kr; +} + kern_return_t tws_expand_working_set( vm_offset_t tws, @@ -564,14 +577,6 @@ printf("cache_lookup, result = 0x%x, addr = 0x%x, object 0x%x, offset 0x%x%x\n", ask_for_startup_cache_release = 1; } } - if((tws->startup_name != NULL) && (tws->mod == 0)) { - /* Ensure as good a working set as possible */ - pmap_remove(map->pmap, 0, GLOBAL_SHARED_TEXT_SEGMENT); - pmap_remove(map->pmap, - GLOBAL_SHARED_DATA_SEGMENT - + SHARED_DATA_REGION_SIZE, 0xFFFFF000); - } - /* This next bit of code, the and alternate hash */ /* are all made necessary because of IPC COW */ @@ -754,6 +759,10 @@ printf("cache_lookup, result = 0x%x, addr = 0x%x, object 0x%x, offset 0x%x%x\n", tws_unlock(tws); return KERN_NO_SPACE; } + /* object persistence is guaranteed by */ + /* an elevated paging or object */ + /* reference count in the caller. */ + vm_object_unlock(object); if((tws->table[set] = (tws_hash_ptr_t *) kalloc(sizeof(tws_hash_ptr_t) * tws->number_of_lines @@ -777,12 +786,12 @@ printf("cache_lookup, result = 0x%x, addr = 0x%x, object 0x%x, offset 0x%x%x\n", * tws->number_of_lines * tws->number_of_elements)) == NULL) { - kfree((vm_offset_t)tws->table_ele[set], - sizeof(tws_hash_ptr_t) + kfree((vm_offset_t)tws->table_ele[set], + sizeof(struct tws_hash_ptr) * tws->number_of_lines * tws->number_of_elements); kfree((vm_offset_t)tws->table[set], - sizeof(struct tws_hash_ptr) + sizeof(tws_hash_ptr_t) * tws->number_of_lines * tws->number_of_elements); tws->table[set] = NULL; @@ -794,16 +803,16 @@ printf("cache_lookup, result = 0x%x, addr = 0x%x, object 0x%x, offset 0x%x%x\n", (struct tws_hash_line) * tws->number_of_lines)) == NULL) { - kfree((vm_offset_t)tws->table[set], - sizeof(tws_hash_ptr_t) + kfree((vm_offset_t)tws->alt_ele[set], + sizeof(struct tws_hash_ptr) * tws->number_of_lines * tws->number_of_elements); - kfree((vm_offset_t)tws->table_ele[set], + kfree((vm_offset_t)tws->table_ele[set], sizeof(struct tws_hash_ptr) * tws->number_of_lines * tws->number_of_elements); - kfree((vm_offset_t)tws->alt_ele[set], - sizeof(struct tws_hash_ptr) + kfree((vm_offset_t)tws->table[set], + sizeof(tws_hash_ptr_t) * tws->number_of_lines * tws->number_of_elements); tws->table[set] = NULL; @@ -830,6 +839,7 @@ printf("cache_lookup, result = 0x%x, addr = 0x%x, object 0x%x, offset 0x%x%x\n", sizeof(struct tws_hash_line) * tws->number_of_lines); } + vm_object_lock(object); } else { int age_of_cache; age_of_cache = @@ -1026,8 +1036,8 @@ tws_build_cluster( int age_of_cache; int pre_heat_size; unsigned int ele_cache; - unsigned int end_cache = NULL; - unsigned int start_cache = NULL; + unsigned int end_cache = 0; + unsigned int start_cache = 0; if((object->private) || !(object->pager)) return; @@ -1040,6 +1050,10 @@ tws_build_cluster( object_size = object->size; } + if((!tws) || (!tws_lock_try(tws))) { + return; + } + age_of_cache = ((sched_tick - tws->time_of_creation) >> SCHED_TICK_SHIFT); @@ -1069,7 +1083,7 @@ tws_build_cluster( *start = *start & TWS_HASH_OFF_MASK; *end = *start + (32 * PAGE_SIZE_64); if(*end > object_size) { - *end = trunc_page(object_size); + *end = trunc_page_64(object_size); max_length = 0; if(before >= *end) { *end = after; @@ -1092,7 +1106,7 @@ tws_build_cluster( *end = after + (32 * PAGE_SIZE_64); if(*end > object_size) { - *end = trunc_page(object_size); + *end = trunc_page_64(object_size); max_length = 0; if(*start >= *end) { *end = after; @@ -1116,7 +1130,7 @@ tws_build_cluster( break; } - if(start_cache != NULL) { + if(start_cache != 0) { unsigned int mask; for (mask = 1; mask != 0; mask = mask << 1) { @@ -1128,7 +1142,7 @@ tws_build_cluster( break; } } - if(end_cache != NULL) { + if(end_cache != 0) { unsigned int mask; for (mask = 0x80000000; @@ -1145,6 +1159,7 @@ tws_build_cluster( if (*start >= *end) panic("bad clipping occurred\n"); + tws_unlock(tws); return; } } @@ -1153,12 +1168,12 @@ tws_build_cluster( (object_size >= (after + PAGE_SIZE_64))) { if(length >= pre_heat_size) { - if(tws_lookup(tws, after, object, + if(tws_internal_lookup(tws, after, object, &line) != KERN_SUCCESS) { vm_object_offset_t extend; extend = after + PAGE_SIZE_64; - if(tws_lookup(tws, extend, object, + if(tws_internal_lookup(tws, extend, object, &line) != KERN_SUCCESS) { break; } @@ -1171,10 +1186,10 @@ tws_build_cluster( } if (vm_page_lookup(object, after) != VM_PAGE_NULL) { - /* we can bridge resident pages */ - after += PAGE_SIZE_64; - length += PAGE_SIZE; - continue; + /* + * don't bridge resident pages + */ + break; } if (object->internal) { @@ -1212,7 +1227,7 @@ tws_build_cluster( before -= PAGE_SIZE_64; if(length >= pre_heat_size) { - if(tws_lookup(tws, before, object, + if(tws_internal_lookup(tws, before, object, &line) != KERN_SUCCESS) { vm_object_offset_t extend; @@ -1220,7 +1235,7 @@ tws_build_cluster( if (extend == 0) break; extend -= PAGE_SIZE_64; - if(tws_lookup(tws, extend, object, + if(tws_internal_lookup(tws, extend, object, &line) != KERN_SUCCESS) { break; } @@ -1232,10 +1247,10 @@ tws_build_cluster( } if (vm_page_lookup(object, before) != VM_PAGE_NULL) { - /* we can bridge resident pages */ - *start -= PAGE_SIZE_64; - length += PAGE_SIZE; - continue; + /* + * don't bridge resident pages + */ + break; } if (object->internal) { @@ -1266,6 +1281,7 @@ tws_build_cluster( *start -= PAGE_SIZE_64; length += PAGE_SIZE; } + tws_unlock(tws); } tws_line_signal( @@ -1690,13 +1706,11 @@ tws_handle_startup_file( return KERN_SUCCESS; } *new_info = TRUE; + error = tws_write_startup_file(task, fid, mod, app_name, uid); if(error) return error; - /* use the mod in the write case as an init */ - /* flag */ - mod = 0; } else { error = tws_read_startup_file(task, @@ -1828,13 +1842,45 @@ tws_read_startup_file( /* just in case their not, make sure we dealloc correctly */ startup->tws_hash_size = cache_size; - tws->startup_cache = startup; tws_unlock(tws); return KERN_SUCCESS; } +void +tws_hash_ws_flush(tws_hash_t tws) { + tws_startup_t scache; + if(tws == NULL) { + return; + } + tws_lock(tws); + if(tws->startup_name != NULL) { + scache = tws_create_startup_list(tws); + if(scache == NULL) { + /* dump the name cache, we'll */ + /* get it next time */ + kfree((vm_offset_t) + tws->startup_name, + tws->startup_name_length); + tws->startup_name = NULL; + tws_unlock(tws); + return; + } + bsd_write_page_cache_file(tws->uid, tws->startup_name, + scache, scache->tws_hash_size, + tws->mod, tws->fid); + kfree((vm_offset_t)scache, + scache->tws_hash_size); + kfree((vm_offset_t) + tws->startup_name, + tws->startup_name_length); + tws->startup_name = NULL; + } + tws_unlock(tws); + return; +} + void tws_hash_destroy(tws_hash_t tws) {