diff options
author | alc <alc@FreeBSD.org> | 2015-03-21 17:56:55 +0000 |
---|---|---|
committer | alc <alc@FreeBSD.org> | 2015-03-21 17:56:55 +0000 |
commit | b131a2abc80d9ea68d6ff41d2ab9bde70e6023d7 (patch) | |
tree | 165f4dc5d1f1dbe912f22d0117840f1b5a196514 | |
parent | 16676d0f06097d8080ec7a8136f25347f1653da7 (diff) | |
download | FreeBSD-src-b131a2abc80d9ea68d6ff41d2ab9bde70e6023d7.zip FreeBSD-src-b131a2abc80d9ea68d6ff41d2ab9bde70e6023d7.tar.gz |
Introduce vm_object_color() and use it in mmap(2) to set the color of
named objects to zero before the virtual address is selected. Previously,
the color setting was delayed until after the virtual address was
selected. In rtld, this delay effectively prevented the mapping of a
shared library's code section using superpages. Now, for example, we see
the first 1 MB of libc's code on armv6 mapped by a superpage after we've
gotten through the initial cold misses that bring the first 1 MB of code
into memory. (With the page clustering that we perform on read faults,
this happens quickly.)
Differential Revision: https://reviews.freebsd.org/D2013
Reviewed by: jhb, kib
Tested by: Svatopluk Kraus (armv6)
MFC after: 6 weeks
-rw-r--r-- | sys/kern/kern_exec.c | 5 | ||||
-rw-r--r-- | sys/vm/vm_fault.c | 7 | ||||
-rw-r--r-- | sys/vm/vm_mmap.c | 20 | ||||
-rw-r--r-- | sys/vm/vm_object.h | 24 | ||||
-rw-r--r-- | sys/vm/vnode_pager.c | 5 |
5 files changed, 45 insertions, 16 deletions
diff --git a/sys/kern/kern_exec.c b/sys/kern/kern_exec.c index 25335ce..388ed19 100644 --- a/sys/kern/kern_exec.c +++ b/sys/kern/kern_exec.c @@ -933,10 +933,7 @@ exec_map_first_page(imgp) return (EACCES); VM_OBJECT_WLOCK(object); #if VM_NRESERVLEVEL > 0 - if ((object->flags & OBJ_COLORED) == 0) { - object->flags |= OBJ_COLORED; - object->pg_color = 0; - } + vm_object_color(object, 0); #endif ma[0] = vm_page_grab(object, 0, VM_ALLOC_NORMAL); if (ma[0]->valid != VM_PAGE_BITS_ALL) { diff --git a/sys/vm/vm_fault.c b/sys/vm/vm_fault.c index ff18a15..536076a 100644 --- a/sys/vm/vm_fault.c +++ b/sys/vm/vm_fault.c @@ -522,11 +522,8 @@ fast_failed: fs.m = NULL; if (!vm_page_count_severe() || P_KILLED(curproc)) { #if VM_NRESERVLEVEL > 0 - if ((fs.object->flags & OBJ_COLORED) == 0) { - fs.object->flags |= OBJ_COLORED; - fs.object->pg_color = atop(vaddr) - - fs.pindex; - } + vm_object_color(fs.object, atop(vaddr) - + fs.pindex); #endif alloc_req = P_KILLED(curproc) ? VM_ALLOC_SYSTEM : VM_ALLOC_NORMAL; diff --git a/sys/vm/vm_mmap.c b/sys/vm/vm_mmap.c index 5c31222..a9ff248 100644 --- a/sys/vm/vm_mmap.c +++ b/sys/vm/vm_mmap.c @@ -45,6 +45,7 @@ __FBSDID("$FreeBSD$"); #include "opt_compat.h" #include "opt_hwpmc_hooks.h" +#include "opt_vm.h" #include <sys/param.h> #include <sys/systm.h> @@ -1387,17 +1388,22 @@ vm_mmap_vnode(struct thread *td, vm_size_t objsize, objsize = round_page(va.va_size); if (va.va_nlink == 0) flags |= MAP_NOSYNC; - if (obj->type == OBJT_VNODE) + if (obj->type == OBJT_VNODE) { obj = vm_pager_allocate(OBJT_VNODE, vp, objsize, prot, foff, cred); - else { + if (obj == NULL) { + error = ENOMEM; + goto done; + } + } else { KASSERT(obj->type == OBJT_DEFAULT || obj->type == OBJT_SWAP, ("wrong object type")); - vm_object_reference(obj); - } - if (obj == NULL) { - error = ENOMEM; - goto done; + VM_OBJECT_WLOCK(obj); + vm_object_reference_locked(obj); +#if VM_NRESERVLEVEL > 0 + vm_object_color(obj, 0); +#endif + VM_OBJECT_WUNLOCK(obj); } *objp = obj; *flagsp = flags; diff --git a/sys/vm/vm_object.h b/sys/vm/vm_object.h index d80b1d8..731c9e3 100644 --- a/sys/vm/vm_object.h +++ b/sys/vm/vm_object.h @@ -257,6 +257,30 @@ vm_object_set_flag(vm_object_t object, u_short bits) object->flags |= bits; } +/* + * Conditionally set the object's color, which (1) enables the allocation + * of physical memory reservations for anonymous objects and larger-than- + * superpage-sized named objects and (2) determines the first page offset + * within the object at which a reservation may be allocated. In other + * words, the color determines the alignment of the object with respect + * to the largest superpage boundary. When mapping named objects, like + * files or POSIX shared memory objects, the color should be set to zero + * before a virtual address is selected for the mapping. In contrast, + * for anonymous objects, the color may be set after the virtual address + * is selected. + * + * The object must be locked. + */ +static __inline void +vm_object_color(vm_object_t object, u_short color) +{ + + if ((object->flags & OBJ_COLORED) == 0) { + object->pg_color = color; + object->flags |= OBJ_COLORED; + } +} + void vm_object_clear_flag(vm_object_t object, u_short bits); void vm_object_pip_add(vm_object_t object, short i); void vm_object_pip_subtract(vm_object_t object, short i); diff --git a/sys/vm/vnode_pager.c b/sys/vm/vnode_pager.c index 3623494..c12b83d 100644 --- a/sys/vm/vnode_pager.c +++ b/sys/vm/vnode_pager.c @@ -53,6 +53,8 @@ #include <sys/cdefs.h> __FBSDID("$FreeBSD$"); +#include "opt_vm.h" + #include <sys/param.h> #include <sys/systm.h> #include <sys/proc.h> @@ -242,6 +244,9 @@ retry: VI_UNLOCK(vp); } else { object->ref_count++; +#if VM_NRESERVLEVEL > 0 + vm_object_color(object, 0); +#endif VM_OBJECT_WUNLOCK(object); } vref(vp); |