Module Name: src Committed By: thorpej Date: Sat May 9 15:13:19 UTC 2020
Modified Files: src/sys/uvm: uvm_extern.h uvm_map.c Log Message: Make the uvm_voaddr structure more compact, only occupying 2 pointers worth of space, by encoding the type in the lower bits of the object pointer. To generate a diff of this commit: cvs rdiff -u -r1.225 -r1.226 src/sys/uvm/uvm_extern.h cvs rdiff -u -r1.382 -r1.383 src/sys/uvm/uvm_map.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/sys/uvm/uvm_extern.h diff -u src/sys/uvm/uvm_extern.h:1.225 src/sys/uvm/uvm_extern.h:1.226 --- src/sys/uvm/uvm_extern.h:1.225 Mon Apr 27 02:47:26 2020 +++ src/sys/uvm/uvm_extern.h Sat May 9 15:13:19 2020 @@ -1,4 +1,4 @@ -/* $NetBSD: uvm_extern.h,v 1.225 2020/04/27 02:47:26 rin Exp $ */ +/* $NetBSD: uvm_extern.h,v 1.226 2020/05/09 15:13:19 thorpej Exp $ */ /* * Copyright (c) 1997 Charles D. Cranor and Washington University. @@ -613,8 +613,7 @@ extern struct vm_map *phys_map; * * This structure encapsulates UVM's unique virtual object address * for an individual byte inside a pageable page. Pageable pages can - * be owned by either a uvm_object (UVM_VOADDR_TYPE_OBJECT) or a - * vm_anon (UVM_VOADDR_TYPE_ANON). + * be owned by either a uvm_object or a vm_anon. * * In each case, the byte offset into the owning object * (uvm_object or vm_anon) is included in the ID, so that @@ -631,14 +630,7 @@ extern struct vm_map *phys_map; * use. */ struct uvm_voaddr { - enum { - UVM_VOADDR_TYPE_OBJECT = 1, - UVM_VOADDR_TYPE_ANON = 2, - } type; - union { - struct uvm_object *uobj; - struct vm_anon *anon; - }; + uintptr_t object; voff_t offset; }; Index: src/sys/uvm/uvm_map.c diff -u src/sys/uvm/uvm_map.c:1.382 src/sys/uvm/uvm_map.c:1.383 --- src/sys/uvm/uvm_map.c:1.382 Thu Apr 30 04:18:07 2020 +++ src/sys/uvm/uvm_map.c Sat May 9 15:13:19 2020 @@ -1,4 +1,4 @@ -/* $NetBSD: uvm_map.c,v 1.382 2020/04/30 04:18:07 thorpej Exp $ */ +/* $NetBSD: uvm_map.c,v 1.383 2020/05/09 15:13:19 thorpej Exp $ */ /* * Copyright (c) 1997 Charles D. Cranor and Washington University. @@ -66,7 +66,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: uvm_map.c,v 1.382 2020/04/30 04:18:07 thorpej Exp $"); +__KERNEL_RCSID(0, "$NetBSD: uvm_map.c,v 1.383 2020/05/09 15:13:19 thorpej Exp $"); #include "opt_ddb.h" #include "opt_pax.h" @@ -4781,6 +4781,31 @@ uvm_map_unlock_entry(struct vm_map_entry } } +#define UVM_VOADDR_TYPE_MASK 0x3UL +#define UVM_VOADDR_TYPE_UOBJ 0x1UL +#define UVM_VOADDR_TYPE_ANON 0x2UL +#define UVM_VOADDR_OBJECT_MASK ~UVM_VOADDR_TYPE_MASK + +#define UVM_VOADDR_GET_TYPE(voa) \ + ((voa)->object & UVM_VOADDR_TYPE_MASK) +#define UVM_VOADDR_GET_OBJECT(voa) \ + ((voa)->object & UVM_VOADDR_OBJECT_MASK) +#define UVM_VOADDR_SET_OBJECT(voa, obj, type) \ +do { \ + KASSERT(((uintptr_t)(obj) & UVM_VOADDR_TYPE_MASK) == 0); \ + (voa)->object = ((uintptr_t)(obj)) | (type); \ +} while (/*CONSTCOND*/0) + +#define UVM_VOADDR_GET_UOBJ(voa) \ + ((struct uvm_object *)UVM_VOADDR_GET_OBJECT(voa)) +#define UVM_VOADDR_SET_UOBJ(voa, uobj) \ + UVM_VOADDR_SET_OBJECT(voa, uobj, UVM_VOADDR_TYPE_UOBJ) + +#define UVM_VOADDR_GET_ANON(voa) \ + ((struct vm_anon *)UVM_VOADDR_GET_OBJECT(voa)) +#define UVM_VOADDR_SET_ANON(voa, anon) \ + UVM_VOADDR_SET_OBJECT(voa, anon, UVM_VOADDR_TYPE_ANON) + /* * uvm_voaddr_acquire: returns the virtual object address corresponding * to the specified virtual address. @@ -4936,8 +4961,7 @@ uvm_voaddr_acquire(struct vm_map * const anon->an_ref++; rw_obj_hold(anon->an_lock); KASSERT(anon->an_ref != 0); - voaddr->type = UVM_VOADDR_TYPE_ANON; - voaddr->anon = anon; + UVM_VOADDR_SET_ANON(voaddr, anon); voaddr->offset = va & PAGE_MASK; result = true; } @@ -4950,8 +4974,7 @@ uvm_voaddr_acquire(struct vm_map * const KASSERT(uobj != NULL); (*uobj->pgops->pgo_reference)(uobj); - voaddr->type = UVM_VOADDR_TYPE_OBJECT; - voaddr->uobj = uobj; + UVM_VOADDR_SET_UOBJ(voaddr, uobj); voaddr->offset = entry->offset + (va - entry->start); result = true; } @@ -4961,7 +4984,9 @@ uvm_voaddr_acquire(struct vm_map * const if (result) { UVMHIST_LOG(maphist, "<- done OK (type=%jd,owner=#%jx,offset=%jx)", - voaddr->type, (uintptr_t)voaddr->uobj, voaddr->offset, 0); + UVM_VOADDR_GET_TYPE(voaddr), + UVM_VOADDR_GET_OBJECT(voaddr), + voaddr->offset, 0); } else { UVMHIST_LOG(maphist,"<- done (failed)",0,0,0,0); } @@ -4977,9 +5002,9 @@ void uvm_voaddr_release(struct uvm_voaddr * const voaddr) { - switch (voaddr->type) { - case UVM_VOADDR_TYPE_OBJECT: { - struct uvm_object * const uobj = voaddr->uobj; + switch (UVM_VOADDR_GET_TYPE(voaddr)) { + case UVM_VOADDR_TYPE_UOBJ: { + struct uvm_object * const uobj = UVM_VOADDR_GET_UOBJ(voaddr); KASSERT(uobj != NULL); KASSERT(uobj->pgops->pgo_detach != NULL); @@ -4987,7 +5012,7 @@ uvm_voaddr_release(struct uvm_voaddr * c break; } case UVM_VOADDR_TYPE_ANON: { - struct vm_anon * const anon = voaddr->anon; + struct vm_anon * const anon = UVM_VOADDR_GET_ANON(voaddr); krwlock_t *lock; KASSERT(anon != NULL); @@ -5015,23 +5040,22 @@ int uvm_voaddr_compare(const struct uvm_voaddr * const voaddr1, const struct uvm_voaddr * const voaddr2) { + const uintptr_t type1 = UVM_VOADDR_GET_TYPE(voaddr1); + const uintptr_t type2 = UVM_VOADDR_GET_TYPE(voaddr2); - KASSERT(voaddr1->type == UVM_VOADDR_TYPE_OBJECT || - voaddr1->type == UVM_VOADDR_TYPE_ANON); + KASSERT(type1 == UVM_VOADDR_TYPE_UOBJ || + type1 == UVM_VOADDR_TYPE_ANON); - KASSERT(voaddr2->type == UVM_VOADDR_TYPE_OBJECT || - voaddr2->type == UVM_VOADDR_TYPE_ANON); + KASSERT(type2 == UVM_VOADDR_TYPE_UOBJ || + type2 == UVM_VOADDR_TYPE_ANON); - if (voaddr1->type < voaddr2->type) + if (type1 < type2) return -1; - if (voaddr1->type > voaddr2->type) + if (type1 > type2) return 1; - /* These fields are unioned together. */ - CTASSERT(offsetof(struct uvm_voaddr, uobj) == - offsetof(struct uvm_voaddr, anon)); - const uintptr_t addr1 = (uintptr_t)voaddr1->uobj; - const uintptr_t addr2 = (uintptr_t)voaddr2->uobj; + const uintptr_t addr1 = UVM_VOADDR_GET_OBJECT(voaddr1); + const uintptr_t addr2 = UVM_VOADDR_GET_OBJECT(voaddr2); if (addr1 < addr2) return -1;