Home | History | Annotate | Line # | Download | only in uvm
uvm_aobj.c revision 1.1
      1 /*	$Id: uvm_aobj.c,v 1.1 1998/02/05 06:25:10 mrg Exp $	*/
      2 
      3 /* copyright here */
      4 
      5 #include <sys/param.h>
      6 #include <sys/systm.h>
      7 #include <sys/proc.h>
      8 #include <sys/malloc.h>
      9 
     10 #include <vm/vm.h>
     11 #include <vm/vm_page.h>
     12 #include <vm/vm_kern.h>
     13 
     14 #include <uvm/uvm.h>
     15 
     16 /*
     17  * uvm_aobj.c: anonymous-memory backed uvm_object
     18  */
     19 
     20 /*
     21  * an aobj manages anonymous-memory backed uvm_objects.   in addition
     22  * to keeping the list of resident pages, it also keeps a list of
     23  * allocated swap blocks.  depending on the size of the aobj this list
     24  * of allocated swap blocks is either stored in an array (small objects)
     25  * or in a hash table (large objects).
     26  */
     27 
     28 /*
     29  * local structures
     30  */
     31 
     32 /*
     33  * for hash tables, we break the address space of the aobj into blocks
     34  * of UAO_SWHASH_CLUSTER_SIZE pages.   we require the cluster size to
     35  * be a power of two.
     36  */
     37 
     38 #define UAO_SWHASH_CLUSTER_SHIFT 4
     39 #define UAO_SWHASH_CLUSTER_SIZE (1 << UAO_SWHASH_CLUSTER_SHIFT)
     40 
     41 /* get the "tag" for this page index */
     42 #define UAO_SWHASH_ELT_TAG(PAGEIDX) \
     43 	((PAGEIDX) >> UAO_SWHASH_CLUSTER_SHIFT)
     44 
     45 /* given an ELT and a page index, find the swap slot */
     46 #define UAO_SWHASH_ELT_PAGESLOT(ELT, PAGEIDX) \
     47 	((ELT)->slots[(PAGEIDX) & (UAO_SWHASH_CLUSTER_SIZE - 1)])
     48 
     49 /* given an ELT, return its pageidx base */
     50 #define UAO_SWHASH_ELT_PAGEIDX_BASE(ELT) \
     51 	((ELT)->tag << UAO_SWHASH_CLUSTER_SHIFT)
     52 
     53 /*
     54  * the swhash hash function
     55  */
     56 #define UAO_SWHASH_HASH(AOBJ, PAGEIDX) \
     57 	(&(AOBJ)->u_swhash[(((PAGEIDX) >> UAO_SWHASH_CLUSTER_SHIFT) \
     58 			    & (AOBJ)->u_swhashmask)])
     59 
     60 /*
     61  * the swhash threshhold determines if we will use an array or a
     62  * hash table to store the list of allocated swap blocks.
     63  */
     64 
     65 #define UAO_SWHASH_THRESHOLD (UAO_SWHASH_CLUSTER_SIZE * 4)
     66 #define UAO_USES_SWHASH(AOBJ) \
     67 	((AOBJ)->u_pages > UAO_SWHASH_THRESHOLD)	/* use hash? */
     68 
     69 /*
     70  * the number of buckets in a swhash, with and upper bound
     71  */
     72 #define UAO_SWHASH_MAXBUCKETS 256
     73 #define UAO_SWHASH_BUCKETS(AOBJ) \
     74 	(min((AOBJ)->u_pages >> UAO_SWHASH_CLUSTER_SHIFT, \
     75 	     UAO_SWHASH_MAXBUCKETS))
     76 
     77 
     78 /* XXXCHS until the deadlock is fixed */
     79 #undef UAO_USES_SWHASH
     80 #define UAO_USES_SWHASH(AOBJ) 0
     81 
     82 
     83 /*
     84  * uao_swhash_elt: when a hash table is being used, this structure defines
     85  * the format of an entry in the bucket list.
     86  */
     87 
     88 struct uao_swhash_elt {
     89   LIST_ENTRY(uao_swhash_elt) list;	/* the hash list */
     90   vm_offset_t tag;			/* our 'tag' */
     91   int count;				/* our number of active slots */
     92   int slots[UAO_SWHASH_CLUSTER_SIZE];	/* the slots */
     93 };
     94 
     95 /*
     96  * uao_swhash: the swap hash table structure
     97  */
     98 
     99 LIST_HEAD(uao_swhash, uao_swhash_elt);
    100 
    101 
    102 /*
    103  * uvm_aobj: the actual anon-backed uvm_object
    104  *
    105  * => the uvm_object is at the top of the structure, this allows
    106  *   (struct uvm_device *) == (struct uvm_object *)
    107  * => only one of u_swslots and u_swhash is used in any given aobj
    108  */
    109 
    110 struct uvm_aobj {
    111   struct uvm_object u_obj;	/* has: lock, pgops, memq, #pages, #refs */
    112   vm_size_t u_pages;		/* number of pages in entire object */
    113   int u_flags;			/* the flags (see uvm_aobj.h) */
    114   int *u_swslots;		/* array of offset->swapslot mappings */
    115   struct uao_swhash *u_swhash;	/* hashtable of offset->swapslot mappings */
    116   				/*  (u_swhash is an array of bucket heads) */
    117   u_long u_swhashmask;		/* mask for hashtable */
    118   LIST_ENTRY(uvm_aobj) u_list;	/* global list of aobjs */
    119 };
    120 
    121 /*
    122  * local functions
    123  */
    124 
    125 static void			 uao_init __P((void));
    126 static struct uao_swhash_elt	*uao_find_swhash_elt __P((struct uvm_aobj *,
    127 							  int, boolean_t));
    128 static int			 uao_find_swslot __P((struct uvm_aobj *,
    129 						      vm_offset_t));
    130 static boolean_t		 uao_flush __P((struct uvm_object *,
    131 						vm_offset_t, vm_offset_t,
    132 						int));
    133 static void			 uao_free __P((struct uvm_aobj *));
    134 static int			 uao_get __P((struct uvm_object *, vm_offset_t,
    135 					      vm_page_t *, int *, int,
    136 					      vm_prot_t, int, int));
    137 static boolean_t		 uao_releasepg __P((struct vm_page *,
    138 						    struct vm_page **));
    139 
    140 
    141 
    142 /*
    143  * aobj_pager
    144  *
    145  * note that some functions (e.g. put) are handled elsewhere
    146  */
    147 
    148 struct uvm_pagerops aobj_pager = {
    149   uao_init,		/* init */
    150   NULL,			/* attach */
    151   uao_reference,	/* reference */
    152   uao_detach,		/* detach */
    153   NULL,			/* fault */
    154   uao_flush,		/* flush */
    155   uao_get,		/* get */
    156   NULL,			/* asyncget */
    157   NULL,			/* put (done by pagedaemon) */
    158   NULL,			/* cluster */
    159   NULL,			/* mk_pcluster */
    160   uvm_shareprot,	/* shareprot */
    161   NULL,			/* aiodone */
    162   uao_releasepg		/* releasepg */
    163 };
    164 
    165 /*
    166  * uao_list: global list of active aobjs, locked by uao_list_lock
    167  */
    168 
    169 static LIST_HEAD(aobjlist, uvm_aobj) uao_list;
    170 #if NCPU > 1
    171 static simple_lock_data_t uao_list_lock;
    172 #endif
    173 
    174 
    175 /*
    176  * functions
    177  */
    178 
    179 /*
    180  * hash table/array related functions
    181  */
    182 
    183 /*
    184  * uao_find_swhash_elt: find (or create) a hash table entry for a page
    185  * offset.
    186  *
    187  * => the object should be locked by the caller
    188  */
    189 
    190 static struct uao_swhash_elt *uao_find_swhash_elt(aobj, pageidx, create)
    191 
    192 struct uvm_aobj *aobj;
    193 int pageidx;
    194 boolean_t create;
    195 
    196 {
    197   struct uao_swhash *swhash;
    198   struct uao_swhash_elt *elt;
    199   int page_tag;
    200 
    201   swhash = UAO_SWHASH_HASH(aobj, pageidx);	/* first hash to get bucket */
    202   page_tag = UAO_SWHASH_ELT_TAG(pageidx);	/* tag to search for */
    203 
    204   /*
    205    * now search the bucket for the requested tag
    206    */
    207   for (elt = swhash->lh_first; elt != NULL; elt = elt->list.le_next) {
    208     if (elt->tag == page_tag)
    209       return(elt);
    210   }
    211 
    212   /* fail now if we are not allowed to create a new entry in the bucket */
    213   if (!create)
    214     return NULL;
    215 
    216 
    217   /*
    218    * malloc a new entry for the bucket and init/insert it in
    219    */
    220   MALLOC(elt, struct uao_swhash_elt *, sizeof(*elt), M_UVMAOBJ, M_WAITOK);
    221   elt->tag = page_tag;
    222   bzero(elt->slots, sizeof(elt->slots));
    223   LIST_INSERT_HEAD(swhash, elt, list);
    224 
    225   return(elt);
    226 }
    227 
    228 /*
    229  * uao_find_swslot: find the swap slot number for an aobj/pageidx
    230  *
    231  * => object must be locked by caller
    232  */
    233 
    234 __inline static int uao_find_swslot(aobj, pageidx)
    235 
    236 struct uvm_aobj *aobj;
    237 vm_offset_t pageidx;
    238 
    239 {
    240   /*
    241    * if noswap flag is set, then we never return a slot
    242    */
    243 
    244   if (aobj->u_flags & UAO_FLAG_NOSWAP)
    245     return(0);
    246 
    247   /*
    248    * if hashing, look in hash table.
    249    */
    250 
    251   if (UAO_USES_SWHASH(aobj)) {
    252     struct uao_swhash_elt *elt = uao_find_swhash_elt(aobj, pageidx, FALSE);
    253 
    254     if (elt)
    255       return(UAO_SWHASH_ELT_PAGESLOT(elt, pageidx));
    256     else
    257       return(NULL);
    258   }
    259 
    260   /*
    261    * otherwise, look in the array
    262    */
    263   return(aobj->u_swslots[pageidx]);
    264 }
    265 
    266 /*
    267  * uao_set_swslot: set the swap slot for a page in an aobj.
    268  *
    269  * => setting a slot to zero frees the slot
    270  * => object must be locked by caller
    271  */
    272 
    273 int uao_set_swslot(uobj, pageidx, slot)
    274 
    275 struct uvm_object *uobj;
    276 int pageidx, slot;
    277 
    278 {
    279   struct uvm_aobj *aobj = (struct uvm_aobj *)uobj;
    280   int oldslot;
    281   UVMHIST_FUNC("uao_set_swslot"); UVMHIST_CALLED(pdhist);
    282   UVMHIST_LOG(pdhist, "aobj %p pageidx %d slot %d", aobj, pageidx, slot, 0);
    283 
    284   /*
    285    * if noswap flag is set, then we can't set a slot
    286    */
    287 
    288   if (aobj->u_flags & UAO_FLAG_NOSWAP) {
    289 
    290     if (slot == 0)
    291       return(0);		/* a clear is ok */
    292 
    293     /* but a set is not */
    294     printf("uao_set_swslot: uobj = %p\n", uobj);
    295     panic("uao_set_swslot: attempt to set a slot on a NOSWAP object");
    296   }
    297 
    298   /*
    299    * are we using a hash table?  if so, add it in the hash.
    300    */
    301 
    302   if (UAO_USES_SWHASH(aobj)) {
    303     struct uao_swhash_elt *elt = uao_find_swhash_elt(aobj, pageidx, TRUE);
    304 
    305     oldslot = UAO_SWHASH_ELT_PAGESLOT(elt, pageidx);
    306     UAO_SWHASH_ELT_PAGESLOT(elt, pageidx) = slot;
    307 
    308     /*
    309      * now adjust the elt's reference counter and free it if we've dropped
    310      * it to zero.
    311      */
    312 
    313     if (slot) {		/* an allocation? */
    314 
    315       if (oldslot == 0)
    316 	elt->count++;
    317 
    318     } else {		/* freeing slot ... */
    319 
    320       if (oldslot)	/* to be safe (who would replace zero with zero?) */
    321 	elt->count--;
    322 
    323       if (elt->count == 0) {
    324 	LIST_REMOVE(elt, list);
    325 	FREE(elt, M_UVMAOBJ);
    326       }
    327     }
    328 
    329   } else {
    330 
    331     /* we are using an array */
    332     oldslot = aobj->u_swslots[pageidx];
    333     aobj->u_swslots[pageidx] = slot;
    334 
    335   }
    336 
    337     return(oldslot);
    338 }
    339 
    340 /*
    341  * end of hash/array functions
    342  */
    343 
    344 /*
    345  * uao_free: free all resources held by an aobj, and then free the aobj
    346  *
    347  * => the aobj should be dead
    348  */
    349 
    350 static void
    351 uao_free(aobj)
    352 struct uvm_aobj *aobj;
    353 {
    354 
    355 
    356   if (UAO_USES_SWHASH(aobj)) {
    357     int i, hashbuckets = aobj->u_swhashmask + 1;
    358 
    359     /*
    360      * free the swslots from each hash bucket,
    361      * then the hash bucket, and finally the hash table itself.
    362      */
    363     for (i = 0; i < hashbuckets; i++) {
    364       struct uao_swhash_elt *elt, *next;
    365 
    366       for (elt = aobj->u_swhash[i].lh_first; elt != NULL; elt = next) {
    367 	int j;
    368 
    369 	for (j = 0; j < UAO_SWHASH_CLUSTER_SIZE; j++)
    370 	{
    371 	    int slot = elt->slots[j];
    372 
    373 	    if (slot)
    374 	    {
    375 		uvm_swap_free(slot, 1);
    376 	    }
    377 	}
    378 
    379 	next = elt->list.le_next;
    380 	FREE(elt, M_UVMAOBJ);
    381       }
    382     }
    383     FREE(aobj->u_swhash, M_UVMAOBJ);
    384   } else {
    385     int i;
    386 
    387     /*
    388      * free the array
    389      */
    390 
    391     for (i = 0; i < aobj->u_pages; i++)
    392     {
    393 	int slot = aobj->u_swslots[i];
    394 
    395 	if (slot)
    396 	{
    397 	    uvm_swap_free(slot, 1);
    398 	}
    399     }
    400 
    401     FREE(aobj->u_swslots, M_UVMAOBJ);
    402   }
    403 
    404   /*
    405    * finally free the aobj itself
    406    */
    407   FREE(aobj, M_UVMAOBJ);
    408 }
    409 
    410 
    411 /*
    412  * pager functions
    413  */
    414 
    415 /*
    416  * uao_create: create an aobj of the given size and return its uvm_object.
    417  *
    418  * => for normal use, flags are always zero
    419  * => for the kernel object, the flags are:
    420  *	UAO_FLAG_KERNOBJ - allocate the kernel object (can only happen once)
    421  *	UAO_FLAG_KERNSWAP - enable swapping of kernel object ("           ")
    422  */
    423 
    424 struct uvm_object *uao_create(size, flags)
    425 
    426 vm_size_t size;
    427 int flags;
    428 
    429 {
    430   static struct uvm_aobj kernel_object_store;	/* home of kernel_object */
    431   static int kobj_alloced = 0;			/* not allocated yet */
    432   int pages = round_page(size) / PAGE_SIZE;
    433   struct uvm_aobj *aobj;
    434 
    435   /*
    436    * malloc a new aobj unless we are asked for the kernel object
    437    */
    438   if (flags & UAO_FLAG_KERNOBJ) {		/* want kernel object? */
    439     if (kobj_alloced)
    440       panic("uao_create: kernel object already allocated");
    441 
    442     aobj = &kernel_object_store;
    443     aobj->u_pages = pages;
    444     aobj->u_flags = UAO_FLAG_NOSWAP;	/* no swap to start */
    445     aobj->u_obj.uo_refs = UVM_OBJ_KERN; /* we are special, we never die */
    446     kobj_alloced = UAO_FLAG_KERNOBJ;
    447 
    448   } else if (flags & UAO_FLAG_KERNSWAP) {
    449 
    450     aobj = &kernel_object_store;
    451     if (kobj_alloced != UAO_FLAG_KERNOBJ)
    452       panic("uao_create: asked to enable swap on kernel object");
    453     kobj_alloced = UAO_FLAG_KERNSWAP;
    454 
    455   } else {	/* normal object */
    456 
    457     MALLOC(aobj, struct uvm_aobj *, sizeof(*aobj), M_UVMAOBJ, M_WAITOK);
    458     aobj->u_pages = pages;
    459     aobj->u_flags = 0;		/* normal object */
    460     aobj->u_obj.uo_refs = 1;	/* start with 1 reference */
    461 
    462   }
    463 
    464   /*
    465    * allocate hash/array if necessary
    466    *
    467    * note: in the KERNSWAP case no need to worry about locking since
    468    * we are still booting we should be the only thread around.
    469    *
    470    * XXXCHS: WAITOK is wrong for kernel object - we should panic rather
    471    * than wait... but hashinit() doesn't take a malloc wait flag.
    472    */
    473 
    474   if (flags == 0 || (flags & UAO_FLAG_KERNSWAP) != 0) {
    475 
    476     /* allocate hash table or array depending on object size */
    477     if (UAO_USES_SWHASH(aobj)) {
    478       aobj->u_swhash = hashinit(UAO_SWHASH_BUCKETS(aobj), M_UVMAOBJ,
    479 					&aobj->u_swhashmask);
    480     } else {
    481       MALLOC(aobj->u_swslots, int *, pages * sizeof(int), M_UVMAOBJ, M_WAITOK);
    482       bzero(aobj->u_swslots, pages * sizeof(int));
    483     }
    484 
    485     if (flags) {
    486       aobj->u_flags &= ~UAO_FLAG_NOSWAP;	/* clear noswap */
    487       return(&aobj->u_obj);
    488       /* done! */
    489     }
    490   }
    491 
    492   /*
    493    * init aobj fields
    494    */
    495   simple_lock_init(&aobj->u_obj.vmobjlock);
    496   aobj->u_obj.pgops = &aobj_pager;
    497   TAILQ_INIT(&aobj->u_obj.memq);
    498   aobj->u_obj.uo_npages = 0;
    499 
    500   /*
    501    * now that aobj is ready, add it to the global list
    502    * XXXCHS: uao_init hasn't been called'd in the KERNOBJ case, do we really
    503    * need the kernel object on this list anyway?
    504    */
    505   simple_lock(&uao_list_lock);
    506   LIST_INSERT_HEAD(&uao_list, aobj, u_list);
    507   simple_unlock(&uao_list_lock);
    508 
    509   /*
    510    * done!
    511    */
    512   return(&aobj->u_obj);
    513 }
    514 
    515 
    516 
    517 /*
    518  * uao_init: set up aobj pager subsystem
    519  *
    520  * => called at boot time from uvm_pager_init()
    521  */
    522 
    523 static void uao_init()
    524 
    525 {
    526   LIST_INIT(&uao_list);
    527   simple_lock_init(&uao_list_lock);
    528 }
    529 
    530 /*
    531  * uao_reference: add a ref to an aobj
    532  *
    533  * => aobj must be unlocked (we will lock it)
    534  */
    535 
    536 void uao_reference(uobj)
    537 
    538 struct uvm_object *uobj;
    539 
    540 {
    541   UVMHIST_FUNC("uao_reference"); UVMHIST_CALLED(maphist);
    542 
    543   /*
    544    * kernel_object already has plenty of references, leave it alone.
    545    */
    546 
    547   if (uobj->uo_refs == UVM_OBJ_KERN) {
    548     return;
    549   }
    550 
    551   simple_lock(&uobj->vmobjlock);
    552   uobj->uo_refs++;		/* bump! */
    553   UVMHIST_LOG(maphist, "<- done (uobj=0x%x, ref = %d)",
    554 	uobj, uobj->uo_refs,0,0);
    555   simple_unlock(&uobj->vmobjlock);
    556 }
    557 
    558 /*
    559  * uao_detach: drop a reference to an aobj
    560  *
    561  * => aobj must be unlocked, we will lock it
    562  */
    563 
    564 void uao_detach(uobj)
    565 
    566 struct uvm_object *uobj;
    567 
    568 {
    569   struct uvm_aobj *aobj = (struct uvm_aobj *)uobj;
    570   struct vm_page *pg;
    571   boolean_t busybody;
    572   UVMHIST_FUNC("uao_detach"); UVMHIST_CALLED(maphist);
    573 
    574   /*
    575    * detaching from kernel_object is a noop.
    576    */
    577 
    578   if (uobj->uo_refs == UVM_OBJ_KERN) {
    579     return;
    580   }
    581 
    582   simple_lock(&uobj->vmobjlock);
    583 
    584   UVMHIST_LOG(maphist,"  (uobj=0x%x)  ref=%d", uobj,uobj->uo_refs,0,0);
    585   uobj->uo_refs--;				/* drop ref! */
    586   if (uobj->uo_refs) {				/* still more refs? */
    587     simple_unlock(&uobj->vmobjlock);
    588     UVMHIST_LOG(maphist, "<- done (rc>0)", 0,0,0,0);
    589     return;
    590   }
    591 
    592   /*
    593    * remove the aobj from the global list.
    594    */
    595   simple_lock(&uao_list_lock);
    596   LIST_REMOVE(aobj, u_list);
    597   simple_unlock(&uao_list_lock);
    598 
    599   /*
    600    * free all the pages that aren't PG_BUSY, mark for release any that are.
    601    */
    602 
    603   busybody = FALSE;
    604   for (pg = uobj->memq.tqh_first ; pg != NULL ; pg = pg->listq.tqe_next) {
    605     int swslot;
    606 
    607     if (pg->flags & PG_BUSY) {
    608       pg->flags |= PG_RELEASED;
    609       busybody = TRUE;
    610       continue;
    611     }
    612 
    613     /* zap the mappings, free the page, free the swap slot (if any) */
    614     pmap_page_protect(PMAP_PGARG(pg), VM_PROT_NONE);
    615     uvm_lock_pageq();
    616     uvm_pagefree(pg);
    617     uvm_unlock_pageq();
    618 
    619     swslot = uao_set_swslot(&aobj->u_obj, pg->offset / PAGE_SIZE, 0);
    620     if (swslot)	{
    621       uvm_swap_free(swslot, 1);
    622     }
    623   }
    624 
    625   /*
    626    * if we found any busy pages, we're done for now.
    627    * mark the aobj for death, releasepg will finish up for us.
    628    */
    629   if (busybody) {
    630     aobj->u_flags |= UAO_FLAG_KILLME;
    631     simple_unlock(&aobj->u_obj.vmobjlock);
    632     return;
    633   }
    634 
    635   /*
    636    * finally, free the rest.
    637    */
    638   uao_free(aobj);
    639 }
    640 
    641 
    642 
    643 /*
    644  * uao_flush: uh, yea, sure it's flushed.  really!
    645  */
    646 boolean_t uao_flush(uobj, start, end, flags)
    647 
    648 struct uvm_object *uobj;
    649 vm_offset_t start, end;
    650 int flags;
    651 
    652 {
    653   /*
    654    * anonymous memory doesn't "flush"
    655    */
    656   /*
    657    * XXX
    658    * deal with PGO_DEACTIVATE (for madvise(MADV_SEQUENTIAL))
    659    * and PGO_FREE (for msync(MSINVALIDATE))
    660    */
    661   return TRUE;
    662 }
    663 
    664 /*
    665  * uao_get: fetch me a page
    666  *
    667  * we have three cases:
    668  * 1: page is resident     -> just return the page.
    669  * 2: page is zero-fill    -> allocate a new page and zero it.
    670  * 3: page is swapped out  -> fetch the page from swap.
    671  *
    672  * cases 1 and 2 can be handled with PGO_LOCKED, case 3 cannot.
    673  * so, if the "center" page hits case 3 (or any page, with PGO_ALLPAGES),
    674  * then we will need to return VM_PAGER_UNLOCK.
    675  *
    676  * => prefer map unlocked (not required)
    677  * => object must be locked!  we will _unlock_ it before starting any I/O.
    678  * => flags: PGO_ALLPAGES: get all of the pages
    679  *           PGO_LOCKED: fault data structures are locked
    680  * => NOTE: offset is the offset of pps[0], _NOT_ pps[centeridx]
    681  * => NOTE: caller must check for released pages!!
    682  */
    683 
    684 static int uao_get(uobj, offset, pps, npagesp, centeridx, access_type,
    685 		   advice, flags)
    686 
    687 struct uvm_object *uobj;
    688 vm_offset_t offset;
    689 struct vm_page **pps;
    690 int *npagesp;
    691 int centeridx, advice, flags;
    692 vm_prot_t access_type;
    693 
    694 {
    695   struct uvm_aobj *aobj = (struct uvm_aobj *)uobj;
    696   vm_offset_t current_offset;
    697   vm_page_t ptmp;
    698   int lcv, gotpages, maxpages, swslot, rv;
    699   boolean_t done;
    700   UVMHIST_FUNC("uao_get"); UVMHIST_CALLED(pdhist);
    701 
    702   UVMHIST_LOG(pdhist, "aobj=%p flags=%d", aobj, flags,0,0);
    703 
    704   /*
    705    * get number of pages
    706    */
    707 
    708   maxpages = *npagesp;
    709 
    710   /*
    711    * step 1: handled the case where fault data structures are locked.
    712    */
    713 
    714   if (flags & PGO_LOCKED) {
    715 
    716     /*
    717      * step 1a: get pages that are already resident.   only do this
    718      * if the data structures are locked (i.e. the first time through).
    719      */
    720 
    721     done = TRUE;	/* be optimistic */
    722     gotpages = 0;	/* # of pages we got so far */
    723 
    724     for (lcv = 0, current_offset = offset ;
    725 	 lcv < maxpages ; lcv++, current_offset += PAGE_SIZE) {
    726 
    727       /* do we care about this page?  if not, skip it */
    728       if (pps[lcv] == PGO_DONTCARE)
    729 	continue;
    730 
    731       ptmp = uvm_pagelookup(uobj, current_offset);
    732 
    733       /*
    734        * if page is new, attempt to allocate the page, then zero-fill it.
    735        */
    736       if (ptmp == NULL &&
    737 	  uao_find_swslot(aobj, current_offset / PAGE_SIZE) == 0) {
    738 
    739 	ptmp = uvm_pagealloc(uobj, current_offset, NULL);
    740 	if (ptmp) {
    741 	  ptmp->flags &= ~(PG_BUSY|PG_FAKE);	/* new page */
    742 	  ptmp->pqflags |= PQ_AOBJ;
    743 	  UVM_PAGE_OWN(ptmp, NULL);
    744 	  uvm_pagezero(ptmp);
    745 	}
    746       }
    747 
    748       /* to be useful must get a non-busy, non-released page */
    749       if (ptmp == NULL || (ptmp->flags & (PG_BUSY|PG_RELEASED)) != 0) {
    750 	if (lcv == centeridx || (flags & PGO_ALLPAGES) != 0)
    751 	  done = FALSE;		/* need to do a wait or I/O! */
    752 	continue;
    753       }
    754 
    755       /* useful page: busy/lock it and plug it in our result array */
    756       ptmp->flags |= PG_BUSY;		/* caller must un-busy this page */
    757       UVM_PAGE_OWN(ptmp, "uao_get1");
    758       pps[lcv] = ptmp;
    759       gotpages++;
    760 
    761     }	/* "for" lcv loop */
    762 
    763     /*
    764      * step 1b: now we've either done everything needed or we to unlock
    765      * and do some waiting or I/O.
    766      */
    767 
    768     UVMHIST_LOG(pdhist, "<- done (done=%d)", done, 0,0,0);
    769 
    770     *npagesp = gotpages;
    771     if (done)
    772       return(VM_PAGER_OK);		/* bingo! */
    773     else
    774       return(VM_PAGER_UNLOCK);		/* EEK!   Need to unlock and I/O */
    775   }
    776 
    777   /*
    778    * step 2: get non-resident or busy pages.
    779    * object is locked.   data structures are unlocked.
    780    */
    781 
    782   for (lcv = 0, current_offset = offset ;
    783        lcv < maxpages ;
    784        lcv++, current_offset += PAGE_SIZE) {
    785 
    786     /* skip over pages we've already gotten or don't want */
    787     /* skip over pages we don't _have_ to get */
    788     if (pps[lcv] != NULL ||
    789 	(lcv != centeridx && (flags & PGO_ALLPAGES) == 0))
    790       continue;
    791 
    792     /*
    793      * we have yet to locate the current page (pps[lcv]).   we first
    794      * look for a page that is already at the current offset.   if we
    795      * find a page, we check to see if it is busy or released.  if that
    796      * is the case, then we sleep on the page until it is no longer busy
    797      * or released and repeat the lookup.    if the page we found is
    798      * neither busy nor released, then we busy it (so we own it) and
    799      * plug it into pps[lcv].   this 'break's the following while loop
    800      * and indicates we are ready to move on to the next page in the
    801      * "lcv" loop above.
    802      *
    803      * if we exit the while loop with pps[lcv] still set to NULL, then
    804      * it means that we allocated a new busy/fake/clean page ptmp in the
    805      * object and we need to do I/O to fill in the data.
    806      */
    807 
    808     while (pps[lcv] == NULL) {		/* top of "pps" while loop */
    809 
    810       /* look for a resident page */
    811       ptmp = uvm_pagelookup(uobj, current_offset);
    812 
    813       /* not resident?   allocate one now (if we can) */
    814       if (ptmp == NULL) {
    815 
    816 	ptmp = uvm_pagealloc(uobj, current_offset, NULL);	/* alloc */
    817 
    818 	/* out of RAM? */
    819 	if (ptmp == NULL) {
    820 	  simple_unlock(&uobj->vmobjlock);
    821 	  UVMHIST_LOG(pdhist, "sleeping, ptmp == NULL\n",0,0,0,0);
    822 	  uvm_wait("uao_getpage");
    823 	  simple_lock(&uobj->vmobjlock);
    824 	  continue;		/* goto top of pps while loop */
    825 	}
    826 
    827 	/* safe with PQ's unlocked: because we just alloc'd the page */
    828 	ptmp->pqflags |= PQ_AOBJ;
    829 
    830 	/*
    831 	 * got new page ready for I/O.  break pps while loop.  pps[lcv] is
    832 	 * still NULL.
    833 	 */
    834 	break;
    835       }
    836 
    837       /* page is there, see if we need to wait on it */
    838       if ((ptmp->flags & (PG_BUSY|PG_RELEASED)) != 0) {
    839 	ptmp->flags |= PG_WANTED;
    840 	UVMHIST_LOG(pdhist, "sleeping, ptmp->flags 0x%x\n",ptmp->flags,0,0,0);
    841 	UVM_UNLOCK_AND_WAIT(ptmp,&uobj->vmobjlock,0,"uao_get",0);
    842 	simple_lock(&uobj->vmobjlock);
    843 	continue;		/* goto top of pps while loop */
    844       }
    845 
    846       /*
    847        * if we get here then the page has become resident and unbusy
    848        * between steps 1 and 2.  we busy it now (so we own it) and set
    849        * pps[lcv] (so that we exit the while loop).
    850        */
    851       ptmp->flags |= PG_BUSY;	/* we own it, caller must un-busy */
    852       UVM_PAGE_OWN(ptmp, "uao_get2");
    853       pps[lcv] = ptmp;
    854     }
    855 
    856     /*
    857      * if we own the valid page at the correct offset, pps[lcv] will
    858      * point to it.   nothing more to do except go to the next page.
    859      */
    860 
    861     if (pps[lcv])
    862       continue;			/* next lcv */
    863 
    864     /*
    865      * we have a "fake/busy/clean" page that we just allocated.
    866      * do the needed "i/o", either reading from swap or zeroing.
    867      */
    868 
    869     swslot = uao_find_swslot(aobj, current_offset / PAGE_SIZE);
    870 
    871     /*
    872      * just zero the page if there's nothing in swap.
    873      */
    874     if (swslot == 0)
    875     {
    876 	/*
    877 	 * page hasn't existed before, just zero it.
    878 	 */
    879 	uvm_pagezero(ptmp);
    880     }
    881     else
    882     {
    883 	UVMHIST_LOG(pdhist, "pagein from swslot %d", swslot, 0,0,0);
    884 
    885 	/*
    886 	 * page in the swapped-out page.
    887 	 * unlock object for i/o, relock when done.
    888 	 */
    889 	simple_unlock(&uobj->vmobjlock);
    890 	rv = uvm_swap_get(ptmp, swslot, PGO_SYNCIO);
    891 	simple_lock(&uobj->vmobjlock);
    892 
    893 	/*
    894 	 * I/O done.  check for errors.
    895 	 */
    896 	if (rv != VM_PAGER_OK)
    897 	{
    898 	    UVMHIST_LOG(pdhist, "<- done (error=%d)",rv,0,0,0);
    899 	    if (ptmp->flags & PG_WANTED)
    900 		thread_wakeup(ptmp);		/* object lock still held */
    901 	    ptmp->flags &= ~(PG_WANTED|PG_BUSY);
    902 	    UVM_PAGE_OWN(ptmp, NULL);
    903 	    uvm_lock_pageq();
    904 	    uvm_pagefree(ptmp);
    905 	    uvm_unlock_pageq();
    906 	    simple_unlock(&uobj->vmobjlock);
    907 	    return rv;
    908 	}
    909     }
    910 
    911     /*
    912      * we got the page!   clear the fake flag (indicates valid data now
    913      * in page) and plug into our result array.   note that page is still
    914      * busy.
    915      *
    916      * it is the callers job to:
    917      * => check if the page is released
    918      * => unbusy the page
    919      * => activate the page
    920      */
    921 
    922     ptmp->flags &= ~PG_FAKE;			/* data is valid ... */
    923     pmap_clear_modify(PMAP_PGARG(ptmp));	/* ... and clean */
    924     pps[lcv] = ptmp;
    925 
    926   }	/* lcv loop */
    927 
    928   /*
    929    * finally, unlock object and return.
    930    */
    931 
    932   simple_unlock(&uobj->vmobjlock);
    933   UVMHIST_LOG(pdhist, "<- done (OK)",0,0,0,0);
    934   return(VM_PAGER_OK);
    935 }
    936 
    937 /*
    938  * uao_releasepg: handle released page in an aobj
    939  *
    940  * => "pg" is a PG_BUSY [caller owns it], PG_RELEASED page that we need
    941  *      to dispose of.
    942  * => caller must handle PG_WANTED case
    943  * => called with page's object locked, pageq's unlocked
    944  * => returns TRUE if page's object is still alive, FALSE if we
    945  *      killed the page's object.    if we return TRUE, then we
    946  *      return with the object locked.
    947  * => if (nextpgp != NULL) => we return pageq.tqe_next here, and return
    948  *                              with the page queues locked [for pagedaemon]
    949  * => if (nextpgp == NULL) => we return with page queues unlocked [normal case]
    950  * => we kill the aobj if it is not referenced and we are suppose to
    951  *      kill it ("KILLME").
    952  */
    953 
    954 static boolean_t uao_releasepg(pg, nextpgp)
    955 
    956 struct vm_page *pg;
    957 struct vm_page **nextpgp;	/* OUT */
    958 
    959 {
    960   struct uvm_aobj *aobj = (struct uvm_aobj *) pg->uobject;
    961   int slot;
    962 
    963 #ifdef DIAGNOSTIC
    964   if ((pg->flags & PG_RELEASED) == 0)
    965     panic("uao_releasepg: page not released!");
    966 #endif
    967 
    968   /*
    969    * dispose of the page [caller handles PG_WANTED]
    970    */
    971   pmap_page_protect(PMAP_PGARG(pg), VM_PROT_NONE);
    972   uvm_lock_pageq();
    973   if (nextpgp)
    974     *nextpgp = pg->pageq.tqe_next;	/* next page for daemon */
    975   uvm_pagefree(pg);
    976   if (!nextpgp)
    977     uvm_unlock_pageq();			/* keep locked for daemon */
    978 
    979   /*
    980    * free the swap slot for this page, if any.
    981    */
    982   slot = uao_set_swslot(&aobj->u_obj, pg->offset / PAGE_SIZE, 0);
    983   if (slot)
    984     uvm_swap_free(slot, 1);
    985 
    986   /*
    987    * if we're not killing the object, we're done.
    988    */
    989   if ((aobj->u_flags & UAO_FLAG_KILLME) == 0)
    990     return TRUE;
    991 
    992 #ifdef DIAGNOSTIC
    993   if (aobj->u_obj.uo_refs)
    994     panic("uvm_km_releasepg: kill flag set on referenced object!");
    995 #endif
    996 
    997   /*
    998    * if there are still pages in the object, we're done for now.
    999    */
   1000   if (aobj->u_obj.uo_npages != 0)
   1001     return TRUE;
   1002 
   1003 #ifdef DIAGNOSTIC
   1004   if (aobj->u_obj.memq.tqh_first)
   1005     panic("uvn_releasepg: pages in object with npages == 0");
   1006 #endif
   1007 
   1008   /*
   1009    * finally, free the rest.
   1010    */
   1011   uao_free(aobj);
   1012 
   1013   return FALSE;
   1014 }
   1015