Module Name: src Committed By: rmind Date: Fri Sep 14 18:56:15 UTC 2012
Modified Files: src/sys/uvm: uvm_aobj.c uvm_aobj.h Log Message: - Describe uvm_aobj and the lock order. - Remove unnecessary uao_dropswap_range1() wrapper. - KNF. Sprinkle some __cacheline_aligned. To generate a diff of this commit: cvs rdiff -u -r1.116 -r1.117 src/sys/uvm/uvm_aobj.c cvs rdiff -u -r1.21 -r1.22 src/sys/uvm/uvm_aobj.h 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_aobj.c diff -u src/sys/uvm/uvm_aobj.c:1.116 src/sys/uvm/uvm_aobj.c:1.117 --- src/sys/uvm/uvm_aobj.c:1.116 Tue Sep 6 16:41:55 2011 +++ src/sys/uvm/uvm_aobj.c Fri Sep 14 18:56:15 2012 @@ -1,4 +1,4 @@ -/* $NetBSD: uvm_aobj.c,v 1.116 2011/09/06 16:41:55 matt Exp $ */ +/* $NetBSD: uvm_aobj.c,v 1.117 2012/09/14 18:56:15 rmind Exp $ */ /* * Copyright (c) 1998 Chuck Silvers, Charles D. Cranor and @@ -38,7 +38,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: uvm_aobj.c,v 1.116 2011/09/06 16:41:55 matt Exp $"); +__KERNEL_RCSID(0, "$NetBSD: uvm_aobj.c,v 1.117 2012/09/14 18:56:15 rmind Exp $"); #include "opt_uvmhist.h" @@ -52,66 +52,55 @@ __KERNEL_RCSID(0, "$NetBSD: uvm_aobj.c,v #include <uvm/uvm.h> /* - * an aobj manages anonymous-memory backed uvm_objects. in addition - * to keeping the list of resident pages, it also keeps a list of - * allocated swap blocks. depending on the size of the aobj this list - * of allocated swap blocks is either stored in an array (small objects) - * or in a hash table (large objects). - */ - -/* - * local structures + * An anonymous UVM object (aobj) manages anonymous-memory. In addition to + * keeping the list of resident pages, it may also keep a list of allocated + * swap blocks. Depending on the size of the object, this list is either + * stored in an array (small objects) or in a hash table (large objects). + * + * Lock order + * + * uvm_object::vmobjlock -> + * uao_list_lock */ /* - * for hash tables, we break the address space of the aobj into blocks - * of UAO_SWHASH_CLUSTER_SIZE pages. we require the cluster size to - * be a power of two. + * Note: for hash tables, we break the address space of the aobj into blocks + * of UAO_SWHASH_CLUSTER_SIZE pages, which shall be a power of two. */ -#define UAO_SWHASH_CLUSTER_SHIFT 4 -#define UAO_SWHASH_CLUSTER_SIZE (1 << UAO_SWHASH_CLUSTER_SHIFT) +#define UAO_SWHASH_CLUSTER_SHIFT 4 +#define UAO_SWHASH_CLUSTER_SIZE (1 << UAO_SWHASH_CLUSTER_SHIFT) -/* get the "tag" for this page index */ -#define UAO_SWHASH_ELT_TAG(PAGEIDX) \ - ((PAGEIDX) >> UAO_SWHASH_CLUSTER_SHIFT) +/* Get the "tag" for this page index. */ +#define UAO_SWHASH_ELT_TAG(idx) ((idx) >> UAO_SWHASH_CLUSTER_SHIFT) +#define UAO_SWHASH_ELT_PAGESLOT_IDX(idx) \ + ((idx) & (UAO_SWHASH_CLUSTER_SIZE - 1)) -#define UAO_SWHASH_ELT_PAGESLOT_IDX(PAGEIDX) \ - ((PAGEIDX) & (UAO_SWHASH_CLUSTER_SIZE - 1)) +/* Given an ELT and a page index, find the swap slot. */ +#define UAO_SWHASH_ELT_PAGESLOT(elt, idx) \ + ((elt)->slots[UAO_SWHASH_ELT_PAGESLOT_IDX(idx)]) -/* given an ELT and a page index, find the swap slot */ -#define UAO_SWHASH_ELT_PAGESLOT(ELT, PAGEIDX) \ - ((ELT)->slots[UAO_SWHASH_ELT_PAGESLOT_IDX(PAGEIDX)]) +/* Given an ELT, return its pageidx base. */ +#define UAO_SWHASH_ELT_PAGEIDX_BASE(ELT) \ + ((elt)->tag << UAO_SWHASH_CLUSTER_SHIFT) -/* given an ELT, return its pageidx base */ -#define UAO_SWHASH_ELT_PAGEIDX_BASE(ELT) \ - ((ELT)->tag << UAO_SWHASH_CLUSTER_SHIFT) +/* The hash function. */ +#define UAO_SWHASH_HASH(aobj, idx) \ + (&(aobj)->u_swhash[(((idx) >> UAO_SWHASH_CLUSTER_SHIFT) \ + & (aobj)->u_swhashmask)]) /* - * the swhash hash function - */ - -#define UAO_SWHASH_HASH(AOBJ, PAGEIDX) \ - (&(AOBJ)->u_swhash[(((PAGEIDX) >> UAO_SWHASH_CLUSTER_SHIFT) \ - & (AOBJ)->u_swhashmask)]) - -/* - * the swhash threshhold determines if we will use an array or a + * The threshold which determines whether we will use an array or a * hash table to store the list of allocated swap blocks. */ - -#define UAO_SWHASH_THRESHOLD (UAO_SWHASH_CLUSTER_SIZE * 4) -#define UAO_USES_SWHASH(AOBJ) \ - ((AOBJ)->u_pages > UAO_SWHASH_THRESHOLD) /* use hash? */ - -/* - * the number of buckets in a swhash, with an upper bound - */ - -#define UAO_SWHASH_MAXBUCKETS 256 -#define UAO_SWHASH_BUCKETS(AOBJ) \ - (MIN((AOBJ)->u_pages >> UAO_SWHASH_CLUSTER_SHIFT, \ - UAO_SWHASH_MAXBUCKETS)) +#define UAO_SWHASH_THRESHOLD (UAO_SWHASH_CLUSTER_SIZE * 4) +#define UAO_USES_SWHASH(aobj) \ + ((aobj)->u_pages > UAO_SWHASH_THRESHOLD) + +/* The number of buckets in a hash, with an upper bound. */ +#define UAO_SWHASH_MAXBUCKETS 256 +#define UAO_SWHASH_BUCKETS(aobj) \ + (MIN((aobj)->u_pages >> UAO_SWHASH_CLUSTER_SHIFT, UAO_SWHASH_MAXBUCKETS)) /* * uao_swhash_elt: when a hash table is being used, this structure defines @@ -135,7 +124,7 @@ LIST_HEAD(uao_swhash, uao_swhash_elt); * uao_swhash_elt_pool: pool of uao_swhash_elt structures. * Note: pages for this pool must not come from a pageable kernel map. */ -static struct pool uao_swhash_elt_pool; +static struct pool uao_swhash_elt_pool __cacheline_aligned; /* * uvm_aobj: the actual anon-backed uvm_object @@ -159,10 +148,6 @@ struct uvm_aobj { LIST_ENTRY(uvm_aobj) u_list; /* global list of aobjs */ }; -/* - * local functions - */ - static void uao_free(struct uvm_aobj *); static int uao_get(struct uvm_object *, voff_t, struct vm_page **, int *, int, vm_prot_t, int, int); @@ -177,7 +162,6 @@ static struct uao_swhash_elt *uao_find_s static bool uao_pagein(struct uvm_aobj *, int, int); static bool uao_pagein_page(struct uvm_aobj *, int); -static void uao_dropswap_range1(struct uvm_aobj *, voff_t, voff_t); #endif /* defined(VMSWAP) */ /* @@ -197,12 +181,8 @@ const struct uvm_pagerops aobj_pager = { * uao_list: global list of active aobjs, locked by uao_list_lock */ -static LIST_HEAD(aobjlist, uvm_aobj) uao_list; -static kmutex_t uao_list_lock; - -/* - * functions - */ +static LIST_HEAD(aobjlist, uvm_aobj) uao_list __cacheline_aligned; +static kmutex_t uao_list_lock __cacheline_aligned; /* * hash table/array related functions @@ -272,7 +252,7 @@ uao_find_swslot(struct uvm_object *uobj, */ if (aobj->u_flags & UAO_FLAG_NOSWAP) - return(0); + return 0; /* * if hashing, look in hash table. @@ -280,17 +260,14 @@ uao_find_swslot(struct uvm_object *uobj, if (UAO_USES_SWHASH(aobj)) { elt = uao_find_swhash_elt(aobj, pageidx, false); - if (elt) - return(UAO_SWHASH_ELT_PAGESLOT(elt, pageidx)); - else - return(0); + return elt ? UAO_SWHASH_ELT_PAGESLOT(elt, pageidx) : 0; } /* * otherwise, look in the array */ - return(aobj->u_swslots[pageidx]); + return aobj->u_swslots[pageidx]; } /* @@ -319,11 +296,8 @@ uao_set_swslot(struct uvm_object *uobj, */ if (aobj->u_flags & UAO_FLAG_NOSWAP) { - if (slot == 0) - return(0); - - printf("uao_set_swslot: uobj = %p\n", uobj); - panic("uao_set_swslot: NOSWAP object"); + KASSERTMSG(slot == 0, "uao_set_swslot: no swap object"); + return 0; } /* @@ -368,7 +342,7 @@ uao_set_swslot(struct uvm_object *uobj, oldslot = aobj->u_swslots[pageidx]; aobj->u_swslots[pageidx] = slot; } - return (oldslot); + return oldslot; } #endif /* defined(VMSWAP) */ @@ -386,12 +360,10 @@ uao_set_swslot(struct uvm_object *uobj, static void uao_free(struct uvm_aobj *aobj) { + struct uvm_object *uobj = &aobj->u_obj; -#if defined(VMSWAP) - uao_dropswap_range1(aobj, 0, 0); -#endif /* defined(VMSWAP) */ - - mutex_exit(aobj->u_obj.vmobjlock); + uao_dropswap_range(aobj, 0, 0); + mutex_exit(uobj->vmobjlock); #if defined(VMSWAP) if (UAO_USES_SWHASH(aobj)) { @@ -415,7 +387,7 @@ uao_free(struct uvm_aobj *aobj) * finally free the aobj itself */ - uvm_obj_destroy(&aobj->u_obj, true); + uvm_obj_destroy(uobj, true); kmem_free(aobj, sizeof(struct uvm_aobj)); } @@ -493,7 +465,7 @@ uao_create(vsize_t size, int flags) if (flags) { aobj->u_flags &= ~UAO_FLAG_NOSWAP; /* clear noswap */ - return(&aobj->u_obj); + return &aobj->u_obj; } } @@ -519,8 +491,6 @@ uao_create(vsize_t size, int flags) return(&aobj->u_obj); } - - /* * uao_init: set up aobj pager subsystem * @@ -915,9 +885,6 @@ static int uao_get(struct uvm_object *uobj, voff_t offset, struct vm_page **pps, int *npagesp, int centeridx, vm_prot_t access_type, int advice, int flags) { -#if defined(VMSWAP) - struct uvm_aobj *aobj = (struct uvm_aobj *)uobj; -#endif /* defined(VMSWAP) */ voff_t current_offset; struct vm_page *ptmp = NULL; /* Quell compiler warning */ int lcv, gotpages, maxpages, swslot, pageidx; @@ -959,7 +926,7 @@ uao_get(struct uvm_object *uobj, voff_t * zero-fill'd. */ - if (ptmp == NULL && uao_find_swslot(&aobj->u_obj, + if (ptmp == NULL && uao_find_swslot(uobj, current_offset >> PAGE_SHIFT) == 0) { ptmp = uvm_pagealloc(uobj, current_offset, NULL, UVM_FLAG_COLORMATCH|UVM_PGA_ZERO); @@ -1122,7 +1089,7 @@ gotpage: * do the needed "i/o", either reading from swap or zeroing. */ - swslot = uao_find_swslot(&aobj->u_obj, pageidx); + swslot = uao_find_swslot(uobj, pageidx); /* * just zero the page if there's nothing in swap. @@ -1391,30 +1358,31 @@ restart: } /* - * page in a page from an aobj. used for swap_off. - * returns true if pagein was aborted due to lack of memory. + * uao_pagein_page: page in a single page from an anonymous UVM object. * - * => aobj must be locked and is returned locked. + * => Returns true if pagein was aborted due to lack of memory. + * => Object must be locked and is returned locked. */ static bool uao_pagein_page(struct uvm_aobj *aobj, int pageidx) { + struct uvm_object *uobj = &aobj->u_obj; struct vm_page *pg; int rv, npages; pg = NULL; npages = 1; - /* locked: aobj */ - rv = uao_get(&aobj->u_obj, pageidx << PAGE_SHIFT, - &pg, &npages, 0, VM_PROT_READ|VM_PROT_WRITE, 0, PGO_SYNCIO); - /* unlocked: aobj */ + + KASSERT(mutex_owned(uobj->vmobjlock)); + rv = uao_get(uobj, pageidx << PAGE_SHIFT, &pg, &npages, + 0, VM_PROT_READ | VM_PROT_WRITE, 0, PGO_SYNCIO); /* * relock and finish up. */ - mutex_enter(aobj->u_obj.vmobjlock); + mutex_enter(uobj->vmobjlock); switch (rv) { case 0: break; @@ -1468,17 +1436,10 @@ void uao_dropswap_range(struct uvm_object *uobj, voff_t start, voff_t end) { struct uvm_aobj *aobj = (struct uvm_aobj *)uobj; + int swpgonlydelta = 0; KASSERT(mutex_owned(uobj->vmobjlock)); - uao_dropswap_range1(aobj, start, end); -} - -static void -uao_dropswap_range1(struct uvm_aobj *aobj, voff_t start, voff_t end) -{ - int swpgonlydelta = 0; - if (end == 0) { end = INT64_MAX; } Index: src/sys/uvm/uvm_aobj.h diff -u src/sys/uvm/uvm_aobj.h:1.21 src/sys/uvm/uvm_aobj.h:1.22 --- src/sys/uvm/uvm_aobj.h:1.21 Wed Feb 2 15:28:38 2011 +++ src/sys/uvm/uvm_aobj.h Fri Sep 14 18:56:15 2012 @@ -1,4 +1,4 @@ -/* $NetBSD: uvm_aobj.h,v 1.21 2011/02/02 15:28:38 chuck Exp $ */ +/* $NetBSD: uvm_aobj.h,v 1.22 2012/09/14 18:56:15 rmind Exp $ */ /* * Copyright (c) 1998 Chuck Silvers, Charles D. Cranor and @@ -40,37 +40,31 @@ #define _UVM_UVM_AOBJ_H_ /* - * flags + * Flags for uao_create: UAO_FLAG_KERNOBJ and UAO_FLAG_KERNSWAP are + * used only once, to initialise UVM. */ - -/* flags for uao_create: can only be used one time (at bootup) */ -#define UAO_FLAG_KERNOBJ 0x1 /* create kernel object */ -#define UAO_FLAG_KERNSWAP 0x2 /* enable kernel swap */ - -/* internal flags */ -#define UAO_FLAG_NOSWAP 0x8 /* aobj can't swap (kernel obj only!) */ +#define UAO_FLAG_KERNOBJ 0x1 /* create kernel object */ +#define UAO_FLAG_KERNSWAP 0x2 /* enable kernel swap */ +#define UAO_FLAG_NOSWAP 0x8 /* aobj may not swap */ #ifdef _KERNEL #if defined(_KERNEL_OPT) #include "opt_vmswap.h" #endif -/* - * prototypes - */ +void uao_init(void); +int uao_set_swslot(struct uvm_object *, int, int); -void uao_init(void); -int uao_set_swslot(struct uvm_object *, int, int); -#if defined(VMSWAP) -int uao_find_swslot(struct uvm_object *, int); -void uao_dropswap(struct uvm_object *, int); -bool uao_swap_off(int, int); -void uao_dropswap_range(struct uvm_object *, voff_t, voff_t); -#else /* defined(VMSWAP) */ +#if defined(VMSWAP) +int uao_find_swslot(struct uvm_object *, int); +void uao_dropswap(struct uvm_object *, int); +bool uao_swap_off(int, int); +void uao_dropswap_range(struct uvm_object *, voff_t, voff_t); +#else #define uao_find_swslot(obj, off) 0 #define uao_dropswap(obj, off) /* nothing */ #define uao_dropswap_range(obj, lo, hi) /* nothing */ -#endif /* defined(VMSWAP) */ +#endif #endif /* _KERNEL */