|
|
| version 1.13, 2004/03/29 17:30:23 | version 1.14, 2004/05/13 17:40:19 |
|---|---|
| Line 193 vm_fault(vm_map_t map, vm_offset_t vaddr | Line 193 vm_fault(vm_map_t map, vm_offset_t vaddr |
| vm_page_t marray[VM_FAULT_READ]; | vm_page_t marray[VM_FAULT_READ]; |
| int hardfault; | int hardfault; |
| int faultcount; | int faultcount; |
| int s; | |
| struct faultstate fs; | struct faultstate fs; |
| mycpu->gd_cnt.v_vm_faults++; | mycpu->gd_cnt.v_vm_faults++; |
| hardfault = 0; | hardfault = 0; |
| RetryFault:; | RetryFault: |
| /* | /* |
| * Find the backing store object and offset into it to begin the | * Find the backing store object and offset into it to begin the |
| * search. | * search. |
| Line 288 RetryFault:; | Line 288 RetryFault:; |
| } | } |
| /* | /* |
| * See if page is resident | * See if page is resident. spl protection is required |
| * to avoid an interrupt unbusy/free race against our | |
| * lookup. We must hold the protection through a page | |
| * allocation or busy. | |
| */ | */ |
| s = splvm(); | |
| fs.m = vm_page_lookup(fs.object, fs.pindex); | fs.m = vm_page_lookup(fs.object, fs.pindex); |
| if (fs.m != NULL) { | if (fs.m != NULL) { |
| int queue, s; | int queue; |
| /* | /* |
| * Wait/Retry if the page is busy. We have to do this | * Wait/Retry if the page is busy. We have to do this |
| * if the page is busy via either PG_BUSY or | * if the page is busy via either PG_BUSY or |
| Line 312 RetryFault:; | Line 315 RetryFault:; |
| */ | */ |
| if ((fs.m->flags & PG_BUSY) || fs.m->busy) { | if ((fs.m->flags & PG_BUSY) || fs.m->busy) { |
| unlock_things(&fs); | unlock_things(&fs); |
| (void)vm_page_sleep_busy(fs.m, TRUE, "vmpfw"); | vm_page_sleep_busy(fs.m, TRUE, "vmpfw"); |
| mycpu->gd_cnt.v_intrans++; | mycpu->gd_cnt.v_intrans++; |
| vm_object_deallocate(fs.first_object); | vm_object_deallocate(fs.first_object); |
| splx(s); | |
| goto RetryFault; | goto RetryFault; |
| } | } |
| queue = fs.m->queue; | queue = fs.m->queue; |
| s = splvm(); | |
| vm_page_unqueue_nowakeup(fs.m); | vm_page_unqueue_nowakeup(fs.m); |
| splx(s); | |
| if ((queue - fs.m->pc) == PQ_CACHE && vm_page_count_severe()) { | if ((queue - fs.m->pc) == PQ_CACHE && vm_page_count_severe()) { |
| vm_page_activate(fs.m); | vm_page_activate(fs.m); |
| unlock_and_deallocate(&fs); | unlock_and_deallocate(&fs); |
| VM_WAITPFAULT; | VM_WAITPFAULT; |
| splx(s); | |
| goto RetryFault; | goto RetryFault; |
| } | } |
| Line 335 RetryFault:; | Line 338 RetryFault:; |
| * pagedaemon. If it still isn't completely valid | * pagedaemon. If it still isn't completely valid |
| * (readable), jump to readrest, else break-out ( we | * (readable), jump to readrest, else break-out ( we |
| * found the page ). | * found the page ). |
| * | |
| * We can release the spl once we have marked the | |
| * page busy. | |
| */ | */ |
| vm_page_busy(fs.m); | vm_page_busy(fs.m); |
| splx(s); | |
| if (((fs.m->valid & VM_PAGE_BITS_ALL) != VM_PAGE_BITS_ALL) && | if (((fs.m->valid & VM_PAGE_BITS_ALL) != VM_PAGE_BITS_ALL) && |
| fs.m->object != kernel_object && fs.m->object != kmem_object) { | fs.m->object != kernel_object && fs.m->object != kmem_object) { |
| goto readrest; | goto readrest; |
| Line 349 RetryFault:; | Line 357 RetryFault:; |
| /* | /* |
| * Page is not resident, If this is the search termination | * Page is not resident, If this is the search termination |
| * or the pager might contain the page, allocate a new page. | * or the pager might contain the page, allocate a new page. |
| * | |
| * note: we are still in splvm(). | |
| */ | */ |
| if (TRYPAGER || fs.object == fs.first_object) { | if (TRYPAGER || fs.object == fs.first_object) { |
| if (fs.pindex >= fs.object->size) { | if (fs.pindex >= fs.object->size) { |
| splx(s); | |
| unlock_and_deallocate(&fs); | unlock_and_deallocate(&fs); |
| return (KERN_PROTECTION_FAILURE); | return (KERN_PROTECTION_FAILURE); |
| } | } |
| Line 366 RetryFault:; | Line 377 RetryFault:; |
| (fs.vp || fs.object->backing_object)? VM_ALLOC_NORMAL: VM_ALLOC_NORMAL | VM_ALLOC_ZERO); | (fs.vp || fs.object->backing_object)? VM_ALLOC_NORMAL: VM_ALLOC_NORMAL | VM_ALLOC_ZERO); |
| } | } |
| if (fs.m == NULL) { | if (fs.m == NULL) { |
| splx(s); | |
| unlock_and_deallocate(&fs); | unlock_and_deallocate(&fs); |
| VM_WAITPFAULT; | VM_WAITPFAULT; |
| goto RetryFault; | goto RetryFault; |
| } | } |
| } | } |
| splx(s); | |
| readrest: | readrest: |
| /* | /* |
| Line 381 readrest: | Line 394 readrest: |
| * Attempt to fault-in the page if there is a chance that the | * Attempt to fault-in the page if there is a chance that the |
| * pager has it, and potentially fault in additional pages | * pager has it, and potentially fault in additional pages |
| * at the same time. | * at the same time. |
| * | |
| * We are NOT in splvm here and if TRYPAGER is true then | |
| * fs.m will be non-NULL and will be PG_BUSY for us. | |
| */ | */ |
| if (TRYPAGER) { | if (TRYPAGER) { |
| Line 419 readrest: | Line 435 readrest: |
| * note: partially valid pages cannot be | * note: partially valid pages cannot be |
| * included in the lookahead - NFS piecemeal | * included in the lookahead - NFS piecemeal |
| * writes will barf on it badly. | * writes will barf on it badly. |
| */ | * |
| * spl protection is required to avoid races | |
| for(tmppindex = fs.first_pindex - 1; | * between the lookup and an interrupt |
| tmppindex >= firstpindex; | * unbusy/free sequence occuring prior to |
| --tmppindex) { | * our busy check. |
| */ | |
| s = splvm(); | |
| for (tmppindex = fs.first_pindex - 1; | |
| tmppindex >= firstpindex; | |
| --tmppindex | |
| ) { | |
| vm_page_t mt; | vm_page_t mt; |
| mt = vm_page_lookup( fs.first_object, tmppindex); | mt = vm_page_lookup( fs.first_object, tmppindex); |
| if (mt == NULL || (mt->valid != VM_PAGE_BITS_ALL)) | if (mt == NULL || (mt->valid != VM_PAGE_BITS_ALL)) |
| Line 442 readrest: | Line 464 readrest: |
| vm_page_cache(mt); | vm_page_cache(mt); |
| } | } |
| } | } |
| splx(s); | |
| ahead += behind; | ahead += behind; |
| behind = 0; | behind = 0; |
| Line 491 readrest: | Line 514 readrest: |
| * Relookup in case pager changed page. Pager | * Relookup in case pager changed page. Pager |
| * is responsible for disposition of old page | * is responsible for disposition of old page |
| * if moved. | * if moved. |
| * | |
| * XXX other code segments do relookups too. | |
| * It's a bad abstraction that needs to be | |
| * fixed/removed. | |
| */ | */ |
| fs.m = vm_page_lookup(fs.object, fs.pindex); | fs.m = vm_page_lookup(fs.object, fs.pindex); |
| if(!fs.m) { | if (fs.m == NULL) { |
| unlock_and_deallocate(&fs); | unlock_and_deallocate(&fs); |
| goto RetryFault; | goto RetryFault; |
| } | } |
| Line 1179 vm_fault_additional_pages(vm_page_t m, i | Line 1206 vm_fault_additional_pages(vm_page_t m, i |
| /* | /* |
| * scan backward for the read behind pages -- in memory | * scan backward for the read behind pages -- in memory |
| * | |
| * Assume that if the page is not found an interrupt will not | |
| * create it. Theoretically interrupts can only remove (busy) | |
| * pages, not create new associations. | |
| */ | */ |
| if (pindex > 0) { | if (pindex > 0) { |
| if (rbehind > pindex) { | if (rbehind > pindex) { |