==== //depot/user/kris/contention/sys/vm/vm_map.c#15 - /zoo/kris/contention/vm/vm_map.c ==== @@ -92,6 +92,9 @@ #include #include +#undef KTR_SPARE1 +#define KTR_SPARE1 KTR_VM + /* * Virtual memory maps provide for the mapping, protection, * and sharing of virtual memory objects. In addition, @@ -220,6 +223,7 @@ map = (vm_map_t)mem; mtx_destroy(&map->system_mtx); + mtx_destroy(&map->root_mtx); sx_destroy(&map->lock); } @@ -232,7 +236,8 @@ map->nentries = 0; map->size = 0; mtx_init(&map->system_mtx, "system map", NULL, MTX_DEF | MTX_DUPOK); - sx_init(&map->lock, "user map"); + mtx_init(&map->root_mtx, "map root", NULL, MTX_DEF | MTX_DUPOK); + sx_init_flags(&map->lock, "user map", SX_DUPOK); return (0); } @@ -451,6 +456,8 @@ else (void)_sx_xlock(&map->lock, 0, file, line); map->timestamp++; + CTR5(KTR_SPARE1, "vm_map_lock %p(%d, %p) @ %s:%d", map, map->system_map, &map->lock, file, line); + } void @@ -461,6 +468,7 @@ _mtx_unlock_flags(&map->system_mtx, 0, file, line); else _sx_xunlock(&map->lock, file, line); + CTR5(KTR_SPARE1, "vm_map_unlock %p(%d, %p) @ %s:%d", map, map->system_map, &map->lock, file, line); } void @@ -470,7 +478,7 @@ if (map->system_map) _mtx_lock_flags(&map->system_mtx, 0, file, line); else - (void)_sx_xlock(&map->lock, 0, file, line); + (void)_sx_slock(&map->lock, 0, file, line); } void @@ -480,7 +488,8 @@ if (map->system_map) _mtx_unlock_flags(&map->system_mtx, 0, file, line); else - _sx_xunlock(&map->lock, file, line); + _sx_sunlock(&map->lock, file, line); + CTR5(KTR_SPARE1, "vm_map_unlock_read %p(%d, %p) @ %s:%d", map, map->system_map, &map->lock, file, line); } int @@ -493,6 +502,7 @@ !_sx_try_xlock(&map->lock, file, line); if (error == 0) map->timestamp++; + CTR5(KTR_SPARE1, "vm_map_trylock %p(%d, %p) @ %s:%d", map, map->system_map, &map->lock, file, line); return (error == 0); } @@ -503,7 +513,8 @@ error = map->system_map ? !_mtx_trylock(&map->system_mtx, 0, file, line) : - !_sx_try_xlock(&map->lock, file, line); + !_sx_try_slock(&map->lock, file, line); + CTR5(KTR_SPARE1, "vm_map_trylock_read %p(%d, %p) @ %s:%d", map, map->system_map, &map->lock, file, line); return (error == 0); } @@ -511,12 +522,22 @@ _vm_map_lock_upgrade(vm_map_t map, const char *file, int line) { +#if 0 #ifdef INVARIANTS if (map->system_map) { _mtx_assert(&map->system_mtx, MA_OWNED, file, line); } else _sx_assert(&map->lock, SX_XLOCKED, file, line); #endif +#endif + if (!(map->system_map)) { + if (!_sx_try_upgrade(&map->lock, file, line)) { + _sx_sunlock(&map->lock, file, line); + CTR5(KTR_SPARE1, "vm_map_lock_upgrade %p(%d, %p) @ %s:%d", map, map->system_map, &map->lock, file, line); + return (1); + } + } + map->timestamp++; return (0); } @@ -525,12 +546,18 @@ _vm_map_lock_downgrade(vm_map_t map, const char *file, int line) { +#if 0 #ifdef INVARIANTS if (map->system_map) { _mtx_assert(&map->system_mtx, MA_OWNED, file, line); } else _sx_assert(&map->lock, SX_XLOCKED, file, line); #endif +#endif + if (!(map->system_map)) { + _sx_downgrade(&map->lock, file, line); + } + CTR5(KTR_SPARE1, "vm_map_lock_downgrade %p(%d, %p) @ %s:%d", map, map->system_map, &map->lock, file, line); } /* @@ -617,7 +644,8 @@ { _vm_map_init(map, min, max); mtx_init(&map->system_mtx, "system map", NULL, MTX_DEF | MTX_DUPOK); - sx_init(&map->lock, "user map"); + mtx_init(&map->root_mtx, "map root", NULL, MTX_DEF | MTX_DUPOK); + sx_init_flags(&map->lock, "user map", SX_DUPOK); } /* @@ -802,15 +830,19 @@ vm_map_entry_t entry) { - CTR4(KTR_VM, + if (!(map->system_map)) { + sx_assert(&map->lock, SX_XLOCKED); + } + map->nentries++; + CTR4(KTR_SPARE1, "vm_map_entry_link: map %p, nentries %d, entry %p, after %p", map, map->nentries, entry, after_where); - map->nentries++; entry->prev = after_where; entry->next = after_where->next; entry->next->prev = entry; after_where->next = entry; + mtx_lock(&map->root_mtx); if (after_where != &map->header) { if (after_where != map->root) vm_map_entry_splay(after_where->start, map->root); @@ -827,6 +859,7 @@ entry->next->start) - entry->end; vm_map_entry_set_max_free(entry); map->root = entry; + mtx_unlock(&map->root_mtx); } static void @@ -835,6 +868,10 @@ { vm_map_entry_t next, prev, root; + if (!(map->system_map)) { + sx_assert(&map->lock, SX_XLOCKED); + } + mtx_lock(&map->root_mtx); if (entry != map->root) vm_map_entry_splay(entry->start, map->root); if (entry->left == NULL) @@ -847,13 +884,17 @@ vm_map_entry_set_max_free(root); } map->root = root; + mtx_unlock(&map->root_mtx); prev = entry->prev; next = entry->next; next->prev = prev; prev->next = next; map->nentries--; - CTR3(KTR_VM, "vm_map_entry_unlink: map %p, nentries %d, entry %p", map, + if (!(map->system_map)) { + sx_assert(&map->lock, SX_XLOCKED); + } + CTR3(KTR_SPARE1, "vm_map_entry_unlink: map %p, nentries %d, entry %p", map, map->nentries, entry); } @@ -876,8 +917,14 @@ * max_free up the tree is done by moving the entry to the * root and making the change there. */ + + if (!(map->system_map)) { + sx_assert(&map->lock, SX_XLOCKED); + } + mtx_lock(&map->root_mtx); if (entry != map->root) map->root = vm_map_entry_splay(entry->start, map->root); + mtx_unlock(&map->root_mtx); entry->adj_free = (entry->next == &map->header ? map->max_offset : entry->next->start) - entry->end; @@ -902,11 +949,14 @@ { vm_map_entry_t cur; + mtx_lock(&map->root_mtx); cur = vm_map_entry_splay(address, map->root); - if (cur == NULL) + if (cur == NULL) { *entry = &map->header; - else { + mtx_unlock(&map->root_mtx); + } else { map->root = cur; + mtx_unlock(&map->root_mtx); if (address >= cur->start) { *entry = cur; @@ -940,6 +990,9 @@ vm_map_entry_t temp_entry; vm_eflags_t protoeflags; + if (!(map->system_map)) { + sx_assert(&map->lock, SX_XLOCKED); + } /* * Check that the start and end points are not bogus. */ @@ -1054,6 +1107,7 @@ /* * Insert the new entry into the list */ + CTR3(KTR_SPARE1, "%p %p %p", map, prev_entry, new_entry); vm_map_entry_link(map, prev_entry, new_entry); map->size += new_entry->end - new_entry->start; @@ -1111,9 +1165,14 @@ if (start + length > map->max_offset || start + length < start) return (1); + if (!(map->system_map)) { + sx_assert(&map->lock, SX_XLOCKED); + } /* Empty tree means wide open address space. */ + mtx_lock(&map->root_mtx); if (map->root == NULL) { *addr = start; + mtx_unlock(&map->root_mtx); goto found; } @@ -1124,6 +1183,7 @@ map->root = vm_map_entry_splay(start, map->root); if (start + length <= map->root->start) { *addr = start; + mtx_unlock(&map->root_mtx); goto found; } @@ -1135,11 +1195,13 @@ st = (start > map->root->end) ? start : map->root->end; if (length <= map->root->end + map->root->adj_free - st) { *addr = st; + mtx_unlock(&map->root_mtx); goto found; } /* With max_free, can immediately tell if no solution. */ entry = map->root->right; + mtx_unlock(&map->root_mtx); if (entry == NULL || length > entry->max_free) return (1); @@ -1339,6 +1401,7 @@ entry->offset += (start - entry->start); entry->start = start; + CTR3(KTR_SPARE1, "%p %p %p", map, entry->prev, new_entry); vm_map_entry_link(map, entry->prev, new_entry); if ((entry->eflags & MAP_ENTRY_IS_SUB_MAP) == 0) { @@ -1392,6 +1455,7 @@ new_entry->start = entry->end = end; new_entry->offset += (end - entry->start); + CTR3(KTR_SPARE1, "%p %p %p", map, entry, new_entry); vm_map_entry_link(map, entry, new_entry); if ((entry->eflags & MAP_ENTRY_IS_SUB_MAP) == 0) { @@ -2328,7 +2392,7 @@ int vm_map_delete(vm_map_t map, vm_offset_t start, vm_offset_t end) { - vm_map_entry_t entry; + vm_map_entry_t entry, e; vm_map_entry_t first_entry; /* @@ -2341,6 +2405,14 @@ vm_map_clip_start(map, entry, start); } + CTR3(KTR_SPARE1, "vm_map_delete %p %x %x", map, start, end); + + for (e = map->header.next; e != &map->header; + e = e->next) { + CTR3(KTR_SPARE1, "map entry %p: start=%p, end=%p\n", + (void *)e, (void *)e->start, (void *)e->end); + } + /* * Step through all entries in this region */ @@ -2600,6 +2672,7 @@ vm2->vm_daddr = vm1->vm_daddr; vm2->vm_maxsaddr = vm1->vm_maxsaddr; new_map = &vm2->vm_map; /* XXX */ + vm_map_lock(new_map); new_map->timestamp = 1; old_entry = old_map->header.next; @@ -2656,6 +2729,7 @@ * Insert the entry into the new map -- we know we're * inserting at the end of the new map. */ + CTR3(KTR_SPARE1, "insert @ end %p %p %p" , new_map, new_map->header.prev, new_entry); vm_map_entry_link(new_map, new_map->header.prev, new_entry); vmspace_map_entry_forked(vm1, vm2, new_entry); @@ -2678,6 +2752,7 @@ new_entry->eflags &= ~MAP_ENTRY_USER_WIRED; new_entry->wired_count = 0; new_entry->object.vm_object = NULL; + CTR3(KTR_SPARE1, "%p %p %p", new_map, new_map->header.prev, new_entry); vm_map_entry_link(new_map, new_map->header.prev, new_entry); vmspace_map_entry_forked(vm1, vm2, new_entry); @@ -2687,6 +2762,8 @@ } old_entry = old_entry->next; } + vm_map_unlock(new_map); + unlock_and_return: vm_map_unlock(old_map); @@ -2810,6 +2887,7 @@ size_t grow_amount, max_grow; rlim_t stacklim, vmemlim; int is_procstack, rv; + int xlock = 0; Retry: PROC_RLOCK(p); @@ -2817,11 +2895,17 @@ vmemlim = lim_cur(p, RLIMIT_VMEM); PROC_RUNLOCK(p); - vm_map_lock_read(map); + if (xlock) + vm_map_lock(map); + else + vm_map_lock_read(map); /* If addr is already in the entry range, no need to grow.*/ if (vm_map_lookup_entry(map, addr, &prev_entry)) { - vm_map_unlock_read(map); + if (xlock) + vm_map_unlock(map); + else + vm_map_unlock_read(map); return (KERN_SUCCESS); } @@ -2834,7 +2918,10 @@ * never a growable entry, so it suffices to check the flags. */ if (!(next_entry->eflags & MAP_ENTRY_GROWS_DOWN)) { - vm_map_unlock_read(map); + if (xlock) + vm_map_unlock(map); + else + vm_map_unlock_read(map); return (KERN_SUCCESS); } stack_entry = next_entry; @@ -2875,7 +2962,10 @@ } if (grow_amount > stack_entry->avail_ssize) { - vm_map_unlock_read(map); + if (xlock) + vm_map_unlock(map); + else + vm_map_unlock_read(map); return (KERN_NO_SPACE); } @@ -2889,8 +2979,10 @@ * intended by limiting the stack size. */ if (grow_amount > max_grow) { - if (vm_map_lock_upgrade(map)) + if (!xlock && vm_map_lock_upgrade(map)) { + xlock = 1; goto Retry; + } stack_entry->avail_ssize = max_grow; @@ -2905,7 +2997,10 @@ * limit. */ if (is_procstack && (ctob(vm->vm_ssize) + grow_amount > stacklim)) { - vm_map_unlock_read(map); + if (xlock) + vm_map_unlock(map); + else + vm_map_unlock_read(map); return (KERN_NO_SPACE); } @@ -2919,12 +3014,17 @@ /* If we would blow our VMEM resource limit, no go */ if (map->size + grow_amount > vmemlim) { - vm_map_unlock_read(map); + if (xlock) + vm_map_unlock(map); + else + vm_map_unlock_read(map); return (KERN_NO_SPACE); } - if (vm_map_lock_upgrade(map)) + if (!xlock && vm_map_lock_upgrade(map)) { + xlock = 1; goto Retry; + } if (stack_entry == next_entry) { /* @@ -3105,16 +3205,23 @@ vm_map_t map = *var_map; vm_prot_t prot; vm_prot_t fault_type = fault_typea; + int xlock = 0; RetryLookup:; /* * Lookup the faulting address. */ - vm_map_lock_read(map); + if (xlock) + vm_map_lock(map); + else + vm_map_lock_read(map); #define RETURN(why) \ { \ - vm_map_unlock_read(map); \ + if (xlock) \ + vm_map_lock(map); \ + else; \ + vm_map_unlock_read(map); \ return (why); \ } @@ -3143,7 +3250,11 @@ vm_map_t old_map = map; *var_map = map = entry->object.sub_map; - vm_map_unlock_read(old_map); + if (xlock) + vm_map_unlock(old_map); + else + vm_map_unlock_read(old_map); + xlock = 0; goto RetryLookup; } @@ -3194,8 +3305,10 @@ * -- one just moved from the map to the new * object. */ - if (vm_map_lock_upgrade(map)) + if (!xlock && vm_map_lock_upgrade(map)) { + xlock = 1; goto RetryLookup; + } vm_object_shadow( &entry->object.vm_object, @@ -3204,6 +3317,7 @@ entry->eflags &= ~MAP_ENTRY_NEEDS_COPY; vm_map_lock_downgrade(map); + xlock = 0; } else { /* * We're attempting to read a copy-on-write page -- @@ -3218,12 +3332,15 @@ */ if (entry->object.vm_object == NULL && !map->system_map) { - if (vm_map_lock_upgrade(map)) + if (!xlock && vm_map_lock_upgrade(map)) { + xlock = 1; goto RetryLookup; + } entry->object.vm_object = vm_object_allocate(OBJT_DEFAULT, atop(entry->end - entry->start)); entry->offset = 0; vm_map_lock_downgrade(map); + xlock = 0; } /* @@ -3234,6 +3351,9 @@ *object = entry->object.vm_object; *out_prot = prot; + + if (xlock) + vm_map_lock_downgrade(map); return (KERN_SUCCESS); #undef RETURN ==== //depot/user/kris/contention/sys/vm/vm_map.h#3 - /zoo/kris/contention/vm/vm_map.h ==== @@ -189,6 +189,7 @@ u_char system_map; /* Am I a system map? */ vm_flags_t flags; /* flags for this vm_map */ vm_map_entry_t root; /* Root of a binary search tree */ + struct mtx root_mtx; /* Protect updates to root */ pmap_t pmap; /* (c) Physical map */ #define min_offset header.start /* (c) */ #define max_offset header.end /* (c) */