From 1ab69421a5da2ce82763244456ffc6ce102fac4d Mon Sep 17 00:00:00 2001 From: Justus Winter <4winter@informatik.uni-hamburg.de> Date: Mon, 17 Aug 2015 15:00:28 +0200 Subject: [PATCH gnumach 12/12] fu_locking_issues --- vm/memory_object.c | 7 ++++--- vm/vm_fault.c | 39 ++++++++++++++++++++++++++++++--------- vm/vm_object.c | 10 +++++----- 3 files changed, 39 insertions(+), 17 deletions(-) diff --git a/vm/memory_object.c b/vm/memory_object.c index 2f1cb1c..0a07429 100644 --- a/vm/memory_object.c +++ b/vm/memory_object.c @@ -101,6 +101,7 @@ kern_return_t memory_object_data_supply( vm_page_t *page_list; boolean_t was_absent; vm_map_copy_t orig_copy = data_copy; + pager_request_t pager_request; /* * Look for bogus arguments @@ -270,6 +271,7 @@ retry_lookup: /* * Send reply if one was requested. */ + pager_request = object->pager_request; vm_object_paging_end(object); vm_object_unlock(object); @@ -279,7 +281,7 @@ retry_lookup: if (IP_VALID(reply_to)) { memory_object_supply_completed( reply_to, reply_to_type, - object->pager_request, + pager_request, original_offset, original_length, result, @@ -861,8 +863,7 @@ MACRO_END } if (IP_VALID(reply_to)) { - memory_object_control_t pager_request = - object->pager_request; + pager_request_t pager_request = object->pager_request; vm_object_unlock(object); /* consumes our naked send-once/send right for reply_to */ diff --git a/vm/vm_fault.c b/vm/vm_fault.c index 46779f6..101ebce 100644 --- a/vm/vm_fault.c +++ b/vm/vm_fault.c @@ -229,6 +229,17 @@ vm_fault_return_t vm_fault_page( boolean_t look_for_page; vm_prot_t access_required; + /* We need to unlock an object before making requests to a + memory manager. We use this object to temporarily store + object attributes needed for the request to avoid accessing + the object while it is unlocked. */ + struct + { + struct ipc_port * pager; + pager_request_t pager_request; + vm_offset_t paging_offset; + } obj; + if (resume) { vm_fault_state_t *state = (vm_fault_state_t *) current_thread()->ith_other; @@ -510,11 +521,16 @@ vm_fault_return_t vm_fault_page( new_unlock_request = m->unlock_request = (access_required | m->unlock_request); + obj.pager = object->pager; + obj.pager_request = + object->pager_request; + obj.paging_offset = + object->paging_offset; vm_object_unlock(object); if ((rc = memory_object_data_unlock( - object->pager, - object->pager_request, - offset + object->paging_offset, + obj.pager, + obj.pager_request, + offset + obj.paging_offset, PAGE_SIZE, new_unlock_request)) != KERN_SUCCESS) { @@ -633,6 +649,11 @@ vm_fault_return_t vm_fault_page( m->absent = TRUE; object->absent_count++; + /* Save attributes for the request. */ + obj.pager = object->pager; + obj.pager_request = object->pager_request; + obj.paging_offset = object->paging_offset; + /* * We have a busy page, so we can * release the object lock. @@ -647,16 +668,16 @@ vm_fault_return_t vm_fault_page( vm_stat_sample(SAMPLED_PC_VM_PAGEIN_FAULTS); current_task()->pageins++; - if ((rc = memory_object_data_request(object->pager, - object->pager_request, - m->offset + object->paging_offset, + if ((rc = memory_object_data_request(obj.pager, + obj.pager_request, + m->offset + obj.paging_offset, PAGE_SIZE, access_required)) != KERN_SUCCESS) { if (rc != MACH_SEND_INTERRUPTED) printf("%s(0x%p, 0x%p, 0x%lx, 0x%x, 0x%x) failed, %x\n", "memory_object_data_request", - object->pager, - object->pager_request, - m->offset + object->paging_offset, + obj.pager, + obj.pager_request, + m->offset + obj.paging_offset, PAGE_SIZE, access_required, rc); /* * Don't want to leave a busy page around, diff --git a/vm/vm_object.c b/vm/vm_object.c index 59e4959..1d3e727 100644 --- a/vm/vm_object.c +++ b/vm/vm_object.c @@ -545,9 +545,9 @@ void vm_object_terminate( { vm_page_t p; vm_object_t shadow_object; - memory_object_t pager; - memory_object_control_t pager_request; - memory_object_name_t pager_name; + struct ipc_port *pager; + pager_request_t pager_request; + struct ipc_port *pager_name; #if MACH_PAGEMAP vm_external_t existence_info; #endif /* MACH_PAGEMAP */ @@ -2104,8 +2104,8 @@ restart: if (must_init) { vm_size_t pager_size; - memory_object_control_t pager_request; - memory_object_name_t pager_name; + pager_request_t pager_request; + struct ipc_port *pager_name; /* * Copy the naked send right we were given. -- 2.1.4