+/*
+ * Routine: vm_fault_tws_insert
+ * Purpose:
+ * Add fault information to the task working set.
+ * Implementation:
+ * We always insert the base object/offset pair
+ * rather the actual object/offset.
+ * Assumptions:
+ * Map and real_map locked.
+ * Object locked and referenced.
+ * Returns:
+ * TRUE if startup file should be written.
+ * With object locked and still referenced.
+ * But we may drop the object lock temporarily.
+ */
+static boolean_t
+vm_fault_tws_insert(
+ vm_map_t map,
+ vm_map_t real_map,
+ vm_map_offset_t vaddr,
+ vm_object_t object,
+ vm_object_offset_t offset)
+{
+ tws_hash_line_t line;
+ task_t task;
+ kern_return_t kr;
+ boolean_t result = FALSE;
+
+ /* Avoid possible map lock deadlock issues */
+ if (map == kernel_map || map == kalloc_map ||
+ real_map == kernel_map || real_map == kalloc_map)
+ return result;
+
+ task = current_task();
+ if (task->dynamic_working_set != 0) {
+ vm_object_t base_object;
+ vm_object_t base_shadow;
+ vm_object_offset_t base_offset;
+ base_object = object;
+ base_offset = offset;
+ while ((base_shadow = base_object->shadow)) {
+ vm_object_lock(base_shadow);
+ vm_object_unlock(base_object);
+ base_offset +=
+ base_object->shadow_offset;
+ base_object = base_shadow;
+ }
+ kr = tws_lookup(
+ task->dynamic_working_set,
+ base_offset, base_object,
+ &line);
+ if (kr == KERN_OPERATION_TIMED_OUT){
+ result = TRUE;
+ if (base_object != object) {
+ vm_object_unlock(base_object);
+ vm_object_lock(object);
+ }
+ } else if (kr != KERN_SUCCESS) {
+ if(base_object != object)
+ vm_object_reference_locked(base_object);
+ kr = tws_insert(
+ task->dynamic_working_set,
+ base_offset, base_object,
+ vaddr, real_map);
+ if(base_object != object) {
+ vm_object_unlock(base_object);
+ vm_object_deallocate(base_object);
+ }
+ if(kr == KERN_NO_SPACE) {
+ if (base_object == object)
+ vm_object_unlock(object);
+ tws_expand_working_set(
+ task->dynamic_working_set,
+ TWS_HASH_LINE_COUNT,
+ FALSE);
+ if (base_object == object)
+ vm_object_lock(object);
+ } else if(kr == KERN_OPERATION_TIMED_OUT) {
+ result = TRUE;
+ }
+ if(base_object != object)
+ vm_object_lock(object);
+ } else if (base_object != object) {
+ vm_object_unlock(base_object);
+ vm_object_lock(object);
+ }
+ }
+ return result;
+}
+