* vm_object_unwire: * * For each page offset within the specified range of the given object, * find the highest-level page in the shadow chain and unwire it. A page * must exist at every page offset, and the highest-level page must be * wired. */
| 2350 | * wired. |
| 2351 | */ |
| 2352 | void |
| 2353 | vm_object_unwire(vm_object_t object, vm_ooffset_t offset, vm_size_t length, |
| 2354 | uint8_t queue) |
| 2355 | { |
| 2356 | vm_object_t tobject, t1object; |
| 2357 | vm_page_t m, tm; |
| 2358 | vm_pindex_t end_pindex, pindex, tpindex; |
| 2359 | int depth, locked_depth; |
| 2360 | |
| 2361 | KASSERT((offset & PAGE_MASK) == 0, |
| 2362 | ("vm_object_unwire: offset is not page aligned")); |
| 2363 | KASSERT((length & PAGE_MASK) == 0, |
| 2364 | ("vm_object_unwire: length is not a multiple of PAGE_SIZE")); |
| 2365 | /* The wired count of a fictitious page never changes. */ |
| 2366 | if ((object->flags & OBJ_FICTITIOUS) != 0) |
| 2367 | return; |
| 2368 | pindex = OFF_TO_IDX(offset); |
| 2369 | end_pindex = pindex + atop(length); |
| 2370 | again: |
| 2371 | locked_depth = 1; |
| 2372 | VM_OBJECT_RLOCK(object); |
| 2373 | m = vm_page_find_least(object, pindex); |
| 2374 | while (pindex < end_pindex) { |
| 2375 | if (m == NULL || pindex < m->pindex) { |
| 2376 | /* |
| 2377 | * The first object in the shadow chain doesn't |
| 2378 | * contain a page at the current index. Therefore, |
| 2379 | * the page must exist in a backing object. |
| 2380 | */ |
| 2381 | tobject = object; |
| 2382 | tpindex = pindex; |
| 2383 | depth = 0; |
| 2384 | do { |
| 2385 | tpindex += |
| 2386 | OFF_TO_IDX(tobject->backing_object_offset); |
| 2387 | tobject = tobject->backing_object; |
| 2388 | KASSERT(tobject != NULL, |
| 2389 | ("vm_object_unwire: missing page")); |
| 2390 | if ((tobject->flags & OBJ_FICTITIOUS) != 0) |
| 2391 | goto next_page; |
| 2392 | depth++; |
| 2393 | if (depth == locked_depth) { |
| 2394 | locked_depth++; |
| 2395 | VM_OBJECT_RLOCK(tobject); |
| 2396 | } |
| 2397 | } while ((tm = vm_page_lookup(tobject, tpindex)) == |
| 2398 | NULL); |
| 2399 | } else { |
| 2400 | tm = m; |
| 2401 | m = TAILQ_NEXT(m, listq); |
| 2402 | } |
| 2403 | if (vm_page_trysbusy(tm) == 0) { |
| 2404 | for (tobject = object; locked_depth >= 1; |
| 2405 | locked_depth--) { |
| 2406 | t1object = tobject->backing_object; |
| 2407 | if (tm->object != tobject) |
| 2408 | VM_OBJECT_RUNLOCK(tobject); |
| 2409 | tobject = t1object; |
no test coverage detected