From 18b1b1acf3cd85050c5305831f5cb6ff678273f9 Mon Sep 17 00:00:00 2001 From: Justus Winter <4winter@informatik.uni-hamburg.de> Date: Sun, 16 Aug 2015 12:54:41 +0200 Subject: [PATCH gnumach 01/12] vm: fix locking issues * vm/vm_map.c (vm_map_submap): Properly lock object. * vm/vm_object.c (_vm_object_setup): Likewise. (vm_object_allocate): Likewise. (vm_object_enter): Likewise. --- vm/vm_map.c | 24 ++++++++++++++---------- vm/vm_object.c | 44 ++++++++++++++++++++++++++++++++------------ 2 files changed, 46 insertions(+), 22 deletions(-) diff --git a/vm/vm_map.c b/vm/vm_map.c index ae3ce21..a26eaff 100644 --- a/vm/vm_map.c +++ b/vm/vm_map.c @@ -1182,16 +1182,20 @@ kern_return_t vm_map_submap( if ((entry->vme_start == start) && (entry->vme_end == end) && (!entry->is_sub_map) && - ((object = entry->object.vm_object) == vm_submap_object) && - (object->resident_page_count == 0) && - (object->copy == VM_OBJECT_NULL) && - (object->shadow == VM_OBJECT_NULL) && - (!object->pager_created)) { - entry->object.vm_object = VM_OBJECT_NULL; - vm_object_deallocate(object); - entry->is_sub_map = TRUE; - vm_map_reference(entry->object.sub_map = submap); - result = KERN_SUCCESS; + ((object = entry->object.vm_object) == vm_submap_object)) { + vm_object_lock(object); + if ((object->resident_page_count == 0) && + (object->copy == VM_OBJECT_NULL) && + (object->shadow == VM_OBJECT_NULL) && + (!object->pager_created)) { + vm_object_unlock(object); + entry->object.vm_object = VM_OBJECT_NULL; + vm_object_deallocate(object); + entry->is_sub_map = TRUE; + vm_map_reference(entry->object.sub_map = submap); + result = KERN_SUCCESS; + } else + vm_object_unlock(object); } vm_map_unlock(map); diff --git a/vm/vm_object.c b/vm/vm_object.c index deac0c2..94fa48f 100644 --- a/vm/vm_object.c +++ b/vm/vm_object.c @@ -217,9 +217,11 @@ static void _vm_object_setup( vm_size_t size) { *object = vm_object_template; - queue_init(&object->memq); vm_object_lock_init(object); + vm_object_lock(object); + queue_init(&object->memq); object->size = size; + vm_object_unlock(object); } vm_object_t _vm_object_allocate( @@ -244,8 +246,11 @@ vm_object_t vm_object_allocate( port = ipc_port_alloc_kernel(); if (port == IP_NULL) panic("vm_object_allocate"); + + vm_object_lock(object); object->pager_name = port; ipc_kobject_set(port, (ipc_kobject_t) object, IKOT_PAGING_NAME); + vm_object_unlock(object); return object; } @@ -2053,8 +2058,10 @@ restart: object = (po == IKOT_PAGER) ? (vm_object_t) pager->ip_kobject : VM_OBJECT_NULL; - if ((object != VM_OBJECT_NULL) && !must_init) { + if (object != VM_OBJECT_NULL) vm_object_lock(object); + + if ((object != VM_OBJECT_NULL) && !must_init) { if (object->ref_count == 0) { queue_remove(&vm_object_cached_list, object, vm_object_t, cached_list); @@ -2062,10 +2069,9 @@ restart: vm_object_cached_pages_update(-object->resident_page_count); } object->ref_count++; - vm_object_unlock(object); - vm_stat.hits++; } + assert((object == VM_OBJECT_NULL) || (object->ref_count > 0) || ((object->paging_in_progress != 0) && internal)); @@ -2085,6 +2091,10 @@ restart: return(object); if (must_init) { + vm_size_t pager_size; + memory_object_control_t pager_request; + memory_object_name_t pager_name; + /* * Copy the naked send right we were given. */ @@ -2112,6 +2122,11 @@ restart: * Let the pager know we're using it. */ + /* Store attributes while we're holding the lock. */ + pager_size = object->size; + pager_request = object->pager_request; + pager_name = object->pager_name; + if (internal) { /* acquire a naked send right for the DMM */ ipc_port_t DMM = memory_manager_default_reference(); @@ -2123,12 +2138,15 @@ restart: /* default-pager objects are ready immediately */ object->pager_ready = TRUE; + /* Unlock object across call to memory manager. */ + vm_object_unlock(object); + /* consumes the naked send right for DMM */ (void) memory_object_create(DMM, pager, - object->size, - object->pager_request, - object->pager_name, + pager_size, + pager_request, + pager_name, PAGE_SIZE); } else { /* the object is external and not temporary */ @@ -2138,13 +2156,16 @@ restart: /* user pager objects are not ready until marked so */ object->pager_ready = FALSE; + /* Unlock object across call to memory manager. */ + vm_object_unlock(object); + (void) memory_object_init(pager, - object->pager_request, - object->pager_name, + pager_request, + pager_name, PAGE_SIZE); - } + /* Object was unlocked across call to memory manager. */ vm_object_lock(object); object->pager_initialized = TRUE; @@ -2152,9 +2173,8 @@ restart: object->pager_ready = TRUE; vm_object_wakeup(object, VM_OBJECT_EVENT_INITIALIZED); - } else { - vm_object_lock(object); } + /* * [At this point, the object must be locked] */ -- 2.1.4