]> git.saurik.com Git - apple/xnu.git/blobdiff - osfmk/vm/task_working_set.c
xnu-517.11.1.tar.gz
[apple/xnu.git] / osfmk / vm / task_working_set.c
index 90859e626204b8ab7148676931cf26220da475ec..51900109d1a8fb6b3bea5664045b916cbb56178b 100644 (file)
@@ -134,7 +134,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 +290,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 +322,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 +341,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;
@@ -356,8 +352,7 @@ tws_lookup(
                int age_of_cache;
                age_of_cache = ((sched_tick 
                        - tws->time_of_creation) >> SCHED_TICK_SHIFT);
-                       if (age_of_cache > 35) {
-                       tws_unlock(tws); 
+                       if (age_of_cache > 45) {
                        return KERN_OPERATION_TIMED_OUT;
                }
        }
@@ -369,8 +364,7 @@ tws_lookup(
                        int age_of_cache;
                        age_of_cache = ((sched_tick 
                                - tws->time_of_creation) >> SCHED_TICK_SHIFT);
-                       if (age_of_cache > 60) {
-                               tws_unlock(tws); 
+                       if (age_of_cache > 45) {
                                return KERN_OPERATION_TIMED_OUT;
                        }
                }
@@ -385,16 +379,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, 
@@ -432,7 +442,7 @@ tws_expand_working_set(
                    if(entry->object != 0) {
                        paddr = 0;
                        for(page_index = 1; page_index != 0; 
-                                       page_index = page_index << 1); {
+                                       page_index = page_index << 1) {
                                if (entry->page_cache & page_index) {
                                        tws_insert(new_tws, 
                                                entry->offset+paddr,
@@ -539,7 +549,7 @@ tws_insert(
        unsigned int            startup_cache_line;
        vm_offset_t             startup_page_addr;
        int                     cache_full = 0;
-       int                     ask_for_startup_cache_release = 0;
+        int                    age_of_cache = 0;
 
 
        if(!tws_lock_try(tws)) {
@@ -549,29 +559,16 @@ tws_insert(
        current_line = 0xFFFFFFFF;
 
        startup_cache_line = 0;
-       startup_page_addr =
-                        page_addr - (offset - (offset & TWS_HASH_OFF_MASK));
-       if(tws->startup_cache) {
-             int age_of_cache;
-             age_of_cache = ((sched_tick - tws->time_of_creation) 
-                                               >> SCHED_TICK_SHIFT);
-               startup_cache_line = tws_startup_list_lookup(
-                                       tws->startup_cache, startup_page_addr);
-if(tws == test_tws) {
-printf("cache_lookup, result = 0x%x, addr = 0x%x, object 0x%x, offset 0x%x%x\n", startup_cache_line, startup_page_addr, object, offset);
-}
-               if(age_of_cache > 60) {
-                       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);
-       }
 
+       if (tws->startup_cache) {
+               vm_offset_t     startup_page_addr;
+
+               startup_page_addr = page_addr - (offset - (offset & TWS_HASH_OFF_MASK));
+
+               age_of_cache = ((sched_tick - tws->time_of_creation) >> SCHED_TICK_SHIFT);
+
+               startup_cache_line = tws_startup_list_lookup(tws->startup_cache, startup_page_addr);
+       }
        /* This next bit of code, the and alternate hash */
        /* are all made necessary because of IPC COW     */
 
@@ -608,7 +605,7 @@ printf("cache_lookup, result = 0x%x, addr = 0x%x, object 0x%x, offset 0x%x%x\n",
                                   (1<<(((vm_offset_t)
                                   (offset & TWS_INDEX_MASK))>>12));
                                tws_unlock(tws);
-                               if(ask_for_startup_cache_release)
+                               if (age_of_cache > 45)
                                        return KERN_OPERATION_TIMED_OUT;
                                return KERN_SUCCESS;
                        }
@@ -754,6 +751,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 +778,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 +795,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,30 +831,18 @@ 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 = 
-                                               ((sched_tick - 
-                                                   tws->time_of_creation) 
-                                                       >> SCHED_TICK_SHIFT);
-       
-                                     if((tws->startup_cache) && 
-                                                       (age_of_cache > 60)) {
-                                        ask_for_startup_cache_release = 1;
-                                     }
-                                     if((tws->startup_name != NULL) &&
-                                                       (age_of_cache > 15)) {
-                                               tws->current_line--;
-                                               tws_unlock(tws);
-                                               return KERN_OPERATION_TIMED_OUT;
-                                     }
-                                     if((tws->startup_name != NULL) &&
-                                                       (age_of_cache < 15)) {
-                                               /* If we are creating a */
-                                               /* cache, don't lose the */
-                                               /* early info */
+                                     if (tws->startup_name != NULL) {
                                                tws->current_line--;
+
+                                               age_of_cache = ((sched_tick - tws->time_of_creation) >> SCHED_TICK_SHIFT);
+
                                                tws_unlock(tws);
+
+                                               if (age_of_cache > 45)
+                                                       return KERN_OPERATION_TIMED_OUT;
+
                                                return KERN_FAILURE;
                                      }
                                      tws->lookup_count = 0;
@@ -932,16 +921,15 @@ printf("cache_lookup, result = 0x%x, addr = 0x%x, object 0x%x, offset 0x%x%x\n",
        target_element->map = map;
        target_element->line = 
                        current_line + (set * tws->number_of_lines);
-       if(startup_cache_line) {
-               target_element->page_cache = startup_cache_line;
-       }
-       target_element->page_cache |=
-                        1<<(((vm_offset_t)(offset & TWS_INDEX_MASK))>>12);
 
+       target_element->page_cache |= startup_cache_line;
+       target_element->page_cache |= 1<<(((vm_offset_t)(offset & TWS_INDEX_MASK))>>12);
 
        tws_unlock(tws);
-       if(ask_for_startup_cache_release)
+
+       if (age_of_cache > 45)
                return KERN_OPERATION_TIMED_OUT;
+
        return KERN_SUCCESS;
 }
 
@@ -1026,8 +1014,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,83 +1028,74 @@ 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);
 
        /* When pre-heat files are not available, resort to speculation */
        /* based on size of file */
 
-       if(tws->startup_cache || object->internal || age_of_cache > 15 || 
-               (age_of_cache > 5 && 
-                       vm_page_free_count < (vm_page_free_target * 2) )) {
-                       pre_heat_size = 0;
+       if (tws->startup_cache || object->internal || age_of_cache > 45) {
+               pre_heat_size = 0;
        } else {
                if (object_size > (vm_object_offset_t)(1024 * 1024))
-                       pre_heat_size = 8 * PAGE_SIZE;
+                       pre_heat_size = 16 * PAGE_SIZE;
                else if (object_size > (vm_object_offset_t)(128 * 1024))
-                       pre_heat_size = 4 * PAGE_SIZE;
+                       pre_heat_size = 8 * PAGE_SIZE;
                else
-                       pre_heat_size = 2 * PAGE_SIZE;
+                       pre_heat_size = 4 * PAGE_SIZE;
        }
 
-               if ((age_of_cache < 10) && (tws->startup_cache)) {
-               if ((max_length >= ((*end - *start) 
-                       + (32 * PAGE_SIZE))) &&
-                       (tws_test_for_community(tws, object, 
-                                       *start, 3, &ele_cache))) {
-                       int     expanded;
-                               start_cache = ele_cache;
+               if (tws->startup_cache) {
+
+               if (tws_test_for_community(tws, object, *start, 4, &ele_cache))
+               {
+                       start_cache = ele_cache;
                        *start = *start & TWS_HASH_OFF_MASK;
                        *end = *start + (32 * PAGE_SIZE_64);
-                       if(*end > object_size) {
-                               *end = trunc_page(object_size);
+
+                       if (*end > object_size) {
+                               *end = round_page_64(object_size);
                                max_length = 0;
-                               if(before >= *end) {
-                                       *end = after;
-                               } else {
-                                       end_cache = ele_cache;
-                               }
-                       } else {
-                               end_cache = ele_cache;
-                       }
-                       while (max_length > ((*end - *start) 
-                                               + (32 * PAGE_SIZE))) {
+                       } else
+                               end_cache = ele_cache;
+
+                       while (max_length > ((*end - *start) + (32 * PAGE_SIZE))) {
+                               int     expanded;
+
                                expanded = 0;
                                after = *end;
-                               before = *start - PAGE_SIZE_64;
-                               if((*end <= (object->size       
-                                       + (32 * PAGE_SIZE_64))) &&
-                                       (tws_test_for_community(tws, 
-                                               object, after, 
-                                               5, &ele_cache))) {
-                                       *end = after + 
-                                               (32 * PAGE_SIZE_64);
-                                       if(*end > object_size) {
-                                               *end = trunc_page(object_size);
-                                               max_length = 0;
-                                               if(*start >= *end) {
-                                                       *end = after;
-                                               }
-                                       }
+
+                               if ((after + (32 * PAGE_SIZE_64)) <= object_size &&
+                                   (tws_test_for_community(tws, object, after, 8, &ele_cache))) {
+
+                                       *end = after + (32 * PAGE_SIZE_64);
                                        end_cache = ele_cache;
                                        expanded = 1;
                                }
-                               if (max_length > ((*end - *start) 
-                                               + (32 * PAGE_SIZE_64))) {
+                               if (max_length < ((*end - *start) + (32 * PAGE_SIZE_64))) {
                                        break;
                                }
-                               if((*start >= (32 * PAGE_SIZE_64)) &&
-                                       (tws_test_for_community(tws, object, 
-                                       before, 5, &ele_cache))) {
-                                       *start = before;
-                                       start_cache = ele_cache;
-                                       expanded = 1;
+                               if (*start) {
+                                       before = (*start - PAGE_SIZE_64) & TWS_HASH_OFF_MASK;
+
+                                       if (tws_test_for_community(tws, object, before, 8, &ele_cache)) {
+
+                                               *start = before;
+                                               start_cache = ele_cache;
+                                               expanded = 1;
+                                       }
                                }
-                               if(expanded == 0)
+                               if (expanded == 0)
                                        break;
                        }
+                       if (end_cache)
+                               *end -= PAGE_SIZE_64;
 
-                       if(start_cache != NULL) {
+                       if (start_cache != 0) {
                                unsigned int mask;
 
                                for (mask = 1; mask != 0; mask = mask << 1) {
@@ -1128,23 +1107,23 @@ tws_build_cluster(
                                                break;
                                }
                        }
-                       if(end_cache != NULL) {
+                       if (end_cache != 0) {
                                unsigned int mask;
 
                                for (mask = 0x80000000; 
                                                mask != 0; mask = mask >> 1) {
                                        if (*end == original_end)
                                                 break;
-                                       if(!(end_cache & mask))
+                                       if (!(end_cache & mask))
                                                *end -= PAGE_SIZE_64;
                                        else
                                                break;
                                }
                        }
+                       tws_unlock(tws);
 
-                       if (*start >= *end)
-                         panic("bad clipping occurred\n");
-
+                       if (*end < original_end)
+                               *end = original_end;
                        return;
                }
        }
@@ -1153,12 +1132,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 +1150,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 +1191,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 +1199,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 +1211,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 +1245,7 @@ tws_build_cluster(
                *start -= PAGE_SIZE_64;
                length += PAGE_SIZE;
        }
+       tws_unlock(tws);
 }
 
 tws_line_signal(
@@ -1515,7 +1495,7 @@ tws_startup_list_lookup(
 
        hash_index = do_startup_hash(addr, startup->array_size);
 
-       if(((unsigned int)&(startup->table[hash_index])) >= startup->tws_hash_size) {
+       if(((unsigned int)&(startup->table[hash_index])) >= ((unsigned int)startup + startup->tws_hash_size)) {
                return page_cache_bits = 0;
        }
        element = (tws_startup_ptr_t)((int)startup->table[hash_index] +
@@ -1690,13 +1670,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 +1806,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)
 {