diff options
Diffstat (limited to 'sys/vm')
-rw-r--r-- | sys/vm/vm_map.c | 42 | ||||
-rw-r--r-- | sys/vm/vm_map.h | 5 | ||||
-rw-r--r-- | sys/vm/vm_mmap.c | 16 | ||||
-rw-r--r-- | sys/vm/vm_page.c | 9 |
4 files changed, 59 insertions, 13 deletions
diff --git a/sys/vm/vm_map.c b/sys/vm/vm_map.c index 35552a6..1a51af8 100644 --- a/sys/vm/vm_map.c +++ b/sys/vm/vm_map.c @@ -671,6 +671,41 @@ vm_map_wakeup(vm_map_t map) wakeup(&map->root); } +void +vm_map_busy(vm_map_t map) +{ + + VM_MAP_ASSERT_LOCKED(map); + map->busy++; +} + +void +vm_map_unbusy(vm_map_t map) +{ + + VM_MAP_ASSERT_LOCKED(map); + KASSERT(map->busy, ("vm_map_unbusy: not busy")); + if (--map->busy == 0 && (map->flags & MAP_BUSY_WAKEUP)) { + vm_map_modflags(map, 0, MAP_BUSY_WAKEUP); + wakeup(&map->busy); + } +} + +void +vm_map_wait_busy(vm_map_t map) +{ + + VM_MAP_ASSERT_LOCKED(map); + while (map->busy) { + vm_map_modflags(map, MAP_BUSY_WAKEUP, 0); + if (map->system_map) + msleep(&map->busy, &map->system_mtx, 0, "mbusy", 0); + else + sx_sleep(&map->busy, &map->lock, 0, "mbusy", 0); + } + map->timestamp++; +} + long vmspace_resident_count(struct vmspace *vmspace) { @@ -718,6 +753,7 @@ _vm_map_init(vm_map_t map, pmap_t pmap, vm_offset_t min, vm_offset_t max) map->flags = 0; map->root = NULL; map->timestamp = 0; + map->busy = 0; } void @@ -2382,12 +2418,14 @@ vm_map_wire(vm_map_t map, vm_offset_t start, vm_offset_t end, entry->object.vm_object->type == OBJT_SG); /* * Release the map lock, relying on the in-transition - * mark. + * mark. Mark the map busy for fork. */ + vm_map_busy(map); vm_map_unlock(map); rv = vm_fault_wire(map, saved_start, saved_end, fictitious); vm_map_lock(map); + vm_map_unbusy(map); if (last_timestamp + 1 != map->timestamp) { /* * Look again for the entry because the map was @@ -2995,6 +3033,8 @@ vmspace_fork(struct vmspace *vm1, vm_ooffset_t *fork_charge) int locked; vm_map_lock(old_map); + if (old_map->busy) + vm_map_wait_busy(old_map); vm2 = vmspace_alloc(old_map->min_offset, old_map->max_offset); if (vm2 == NULL) goto unlock_and_return; diff --git a/sys/vm/vm_map.h b/sys/vm/vm_map.h index f7fc5f5..fecbffe 100644 --- a/sys/vm/vm_map.h +++ b/sys/vm/vm_map.h @@ -187,12 +187,14 @@ struct vm_map { pmap_t pmap; /* (c) Physical map */ #define min_offset header.start /* (c) */ #define max_offset header.end /* (c) */ + int busy; }; /* * vm_flags_t values */ #define MAP_WIREFUTURE 0x01 /* wire all future pages */ +#define MAP_BUSY_WAKEUP 0x02 #ifdef _KERNEL static __inline vm_offset_t @@ -275,6 +277,9 @@ int _vm_map_lock_upgrade(vm_map_t map, const char *file, int line); void _vm_map_lock_downgrade(vm_map_t map, const char *file, int line); int vm_map_locked(vm_map_t map); void vm_map_wakeup(vm_map_t map); +void vm_map_busy(vm_map_t map); +void vm_map_unbusy(vm_map_t map); +void vm_map_wait_busy(vm_map_t map); #define vm_map_lock(map) _vm_map_lock(map, LOCK_FILE, LOCK_LINE) #define vm_map_unlock(map) _vm_map_unlock(map, LOCK_FILE, LOCK_LINE) diff --git a/sys/vm/vm_mmap.c b/sys/vm/vm_mmap.c index f2dba2c..a73e03a 100644 --- a/sys/vm/vm_mmap.c +++ b/sys/vm/vm_mmap.c @@ -276,14 +276,14 @@ mmap(td, uap) if (addr + size < addr) return (EINVAL); } else { - /* - * XXX for non-fixed mappings where no hint is provided or - * the hint would fall in the potential heap space, - * place it after the end of the largest possible heap. - * - * There should really be a pmap call to determine a reasonable - * location. - */ + /* + * XXX for non-fixed mappings where no hint is provided or + * the hint would fall in the potential heap space, + * place it after the end of the largest possible heap. + * + * There should really be a pmap call to determine a reasonable + * location. + */ PROC_LOCK(td->td_proc); if (addr == 0 || (addr >= round_page((vm_offset_t)vms->vm_taddr) && diff --git a/sys/vm/vm_page.c b/sys/vm/vm_page.c index 863b842..1208ea0 100644 --- a/sys/vm/vm_page.c +++ b/sys/vm/vm_page.c @@ -430,11 +430,12 @@ vm_page_startup(vm_offset_t vaddr) */ new_end = vm_reserv_startup(&vaddr, new_end, high_water); #endif -#ifdef __amd64__ +#if defined(__amd64__) || defined(__mips__) /* - * pmap_map on amd64 comes out of the direct-map, not kvm like i386, - * so the pages must be tracked for a crashdump to include this data. - * This includes the vm_page_array and the early UMA bootstrap pages. + * pmap_map on amd64 and mips can come out of the direct-map, not kvm + * like i386, so the pages must be tracked for a crashdump to include + * this data. This includes the vm_page_array and the early UMA + * bootstrap pages. */ for (pa = new_end; pa < phys_avail[biggestone + 1]; pa += PAGE_SIZE) dump_add_page(pa); |