|
|
| version 1.20, 2004/05/10 11:05:13 | version 1.21, 2004/05/13 17:40:19 |
|---|---|
| Line 374 vm_page_unhold(vm_page_t mem) | Line 374 vm_page_unhold(vm_page_t mem) |
| * enter the page into the kernel's pmap. We are not allowed to block | * enter the page into the kernel's pmap. We are not allowed to block |
| * here so we *can't* do this anyway. | * here so we *can't* do this anyway. |
| * | * |
| * The object and page must be locked, and must be splhigh. | |
| * This routine may not block. | * This routine may not block. |
| * This routine must be called at splvm(). | |
| */ | */ |
| void | void |
| vm_page_insert(vm_page_t m, vm_object_t object, vm_pindex_t pindex) | vm_page_insert(vm_page_t m, vm_object_t object, vm_pindex_t pindex) |
| { | { |
| Line 389 vm_page_insert(vm_page_t m, vm_object_t | Line 388 vm_page_insert(vm_page_t m, vm_object_t |
| /* | /* |
| * Record the object/offset pair in this page | * Record the object/offset pair in this page |
| */ | */ |
| m->object = object; | m->object = object; |
| m->pindex = pindex; | m->pindex = pindex; |
| /* | /* |
| * Insert it into the object_object/offset hash table | * Insert it into the object_object/offset hash table |
| */ | */ |
| bucket = &vm_page_buckets[vm_page_hash(object, pindex)]; | bucket = &vm_page_buckets[vm_page_hash(object, pindex)]; |
| m->hnext = *bucket; | m->hnext = *bucket; |
| *bucket = m; | *bucket = m; |
| Line 431 vm_page_insert(vm_page_t m, vm_object_t | Line 428 vm_page_insert(vm_page_t m, vm_object_t |
| * table and the object page list, but do not invalidate/terminate | * table and the object page list, but do not invalidate/terminate |
| * the backing store. | * the backing store. |
| * | * |
| * The object and page must be locked, and at splhigh. | * This routine must be called at splvm() |
| * The underlying pmap entry (if any) is NOT removed here. | * The underlying pmap entry (if any) is NOT removed here. |
| * This routine may not block. | * This routine may not block. |
| */ | */ |
| void | void |
| vm_page_remove(vm_page_t m) | vm_page_remove(vm_page_t m) |
| { | { |
| Line 463 vm_page_remove(vm_page_t m) | Line 459 vm_page_remove(vm_page_t m) |
| * Note: we must NULL-out m->hnext to prevent loops in detached | * Note: we must NULL-out m->hnext to prevent loops in detached |
| * buffers with vm_page_lookup(). | * buffers with vm_page_lookup(). |
| */ | */ |
| { | { |
| struct vm_page **bucket; | struct vm_page **bucket; |
| Line 481 vm_page_remove(vm_page_t m) | Line 476 vm_page_remove(vm_page_t m) |
| /* | /* |
| * Now remove from the object's list of backed pages. | * Now remove from the object's list of backed pages. |
| */ | */ |
| TAILQ_REMOVE(&object->memq, m, listq); | TAILQ_REMOVE(&object->memq, m, listq); |
| /* | /* |
| * And show that the object has one fewer resident page. | * And show that the object has one fewer resident page. |
| */ | */ |
| object->resident_page_count--; | object->resident_page_count--; |
| object->generation++; | object->generation++; |
| Line 497 vm_page_remove(vm_page_t m) | Line 490 vm_page_remove(vm_page_t m) |
| /* | /* |
| * vm_page_lookup: | * vm_page_lookup: |
| * | * |
| * Returns the page associated with the object/offset | * Locate and return the page at (object, pindex), or NULL if the |
| * pair specified; if none is found, NULL is returned. | * page could not be found. |
| * | |
| * NOTE: the code below does not lock. It will operate properly if | |
| * an interrupt makes a change, but the generation algorithm will not | |
| * operate properly in an SMP environment where both cpu's are able to run | |
| * kernel code simultaneously. | |
| * | * |
| * The object must be locked. No side effects. | * This routine will operate properly without spl protection, but |
| * This routine may not block. | * the returned page could be in flux if it is busy. Because an |
| * This is a critical path routine | * interrupt can race a caller's busy check (unbusying and freeing the |
| * page we return before the caller is able to check the busy bit), | |
| * the caller should generally call this routine at splvm(). | |
| * | |
| * Callers may call this routine without spl protection if they know | |
| * 'for sure' that the page will not be ripped out from under them | |
| * by an interrupt. | |
| */ | */ |
| vm_page_t | vm_page_t |
| Line 1433 vm_page_dontneed(vm_page_t m) | Line 1427 vm_page_dontneed(vm_page_t m) |
| } | } |
| /* | /* |
| * Grab a page, waiting until we are waken up due to the page | * Grab a page, blocking if it is busy and allocating a page if necessary. |
| * changing state. We keep on waiting, if the page continues | * A busy page is returned or NULL. |
| * to be in the object. If the page doesn't exist, allocate it. | |
| * | * |
| * If VM_ALLOC_RETRY is specified VM_ALLOC_NORMAL must also be specified. | * If VM_ALLOC_RETRY is specified VM_ALLOC_NORMAL must also be specified. |
| * If VM_ALLOC_RETRY is not specified | |
| * | * |
| * This routine may block. | * This routine may block, but if VM_ALLOC_RETRY is not set then NULL is |
| * always returned if we had blocked. | |
| * This routine will never return NULL if VM_ALLOC_RETRY is set. | |
| * This routine may not be called from an interrupt. | |
| * The returned page may not be entirely valid. | |
| * | |
| * This routine may be called from mainline code without spl protection and | |
| * be guarenteed a busied page associated with the object at the specified | |
| * index. | |
| */ | */ |
| vm_page_t | vm_page_t |
| vm_page_grab(vm_object_t object, vm_pindex_t pindex, int allocflags) | vm_page_grab(vm_object_t object, vm_pindex_t pindex, int allocflags) |
| Line 1449 vm_page_grab(vm_object_t object, vm_pind | Line 1451 vm_page_grab(vm_object_t object, vm_pind |
| KKASSERT(allocflags & | KKASSERT(allocflags & |
| (VM_ALLOC_NORMAL|VM_ALLOC_INTERRUPT|VM_ALLOC_SYSTEM)); | (VM_ALLOC_NORMAL|VM_ALLOC_INTERRUPT|VM_ALLOC_SYSTEM)); |
| s = splvm(); | |
| retrylookup: | retrylookup: |
| if ((m = vm_page_lookup(object, pindex)) != NULL) { | if ((m = vm_page_lookup(object, pindex)) != NULL) { |
| if (m->busy || (m->flags & PG_BUSY)) { | if (m->busy || (m->flags & PG_BUSY)) { |
| generation = object->generation; | generation = object->generation; |
| s = splvm(); | |
| while ((object->generation == generation) && | while ((object->generation == generation) && |
| (m->busy || (m->flags & PG_BUSY))) { | (m->busy || (m->flags & PG_BUSY))) { |
| vm_page_flag_set(m, PG_WANTED | PG_REFERENCED); | vm_page_flag_set(m, PG_WANTED | PG_REFERENCED); |
| tsleep(m, 0, "pgrbwt", 0); | tsleep(m, 0, "pgrbwt", 0); |
| if ((allocflags & VM_ALLOC_RETRY) == 0) { | if ((allocflags & VM_ALLOC_RETRY) == 0) { |
| splx(s); | m = NULL; |
| return NULL; | goto done; |
| } | } |
| } | } |
| splx(s); | |
| goto retrylookup; | goto retrylookup; |
| } else { | } else { |
| vm_page_busy(m); | vm_page_busy(m); |
| return m; | goto done; |
| } | } |
| } | } |
| m = vm_page_alloc(object, pindex, allocflags & ~VM_ALLOC_RETRY); | m = vm_page_alloc(object, pindex, allocflags & ~VM_ALLOC_RETRY); |
| if (m == NULL) { | if (m == NULL) { |
| VM_WAIT; | VM_WAIT; |
| if ((allocflags & VM_ALLOC_RETRY) == 0) | if ((allocflags & VM_ALLOC_RETRY) == 0) |
| return NULL; | goto done; |
| goto retrylookup; | goto retrylookup; |
| } | } |
| done: | |
| return m; | splx(s); |
| return(m); | |
| } | } |
| /* | /* |