* Locklessly attempt to acquire a page given a (object, pindex) tuple * and an optional previous page to avoid the radix lookup. The resulting * page will be validated against the identity tuple and busied or wired * as requested. A NULL *mp return guarantees that the page was not in * radix at the time of the call but callers must perform higher level * synchronization or retry the operati
| 4494 | * (false, *mp == NULL) - WAITFAIL or NOWAIT prevented acquisition. |
| 4495 | */ |
| 4496 | static bool |
| 4497 | vm_page_acquire_unlocked(vm_object_t object, vm_pindex_t pindex, |
| 4498 | vm_page_t prev, vm_page_t *mp, int allocflags) |
| 4499 | { |
| 4500 | vm_page_t m; |
| 4501 | |
| 4502 | vm_page_grab_check(allocflags); |
| 4503 | MPASS(prev == NULL || vm_page_busied(prev) || vm_page_wired(prev)); |
| 4504 | |
| 4505 | *mp = NULL; |
| 4506 | for (;;) { |
| 4507 | /* |
| 4508 | * We may see a false NULL here because the previous page |
| 4509 | * has been removed or just inserted and the list is loaded |
| 4510 | * without barriers. Switch to radix to verify. |
| 4511 | */ |
| 4512 | if (prev == NULL || (m = TAILQ_NEXT(prev, listq)) == NULL || |
| 4513 | QMD_IS_TRASHED(m) || m->pindex != pindex || |
| 4514 | atomic_load_ptr(&m->object) != object) { |
| 4515 | prev = NULL; |
| 4516 | /* |
| 4517 | * This guarantees the result is instantaneously |
| 4518 | * correct. |
| 4519 | */ |
| 4520 | m = vm_radix_lookup_unlocked(&object->rtree, pindex); |
| 4521 | } |
| 4522 | if (m == NULL) |
| 4523 | return (true); |
| 4524 | if (vm_page_trybusy(m, allocflags)) { |
| 4525 | if (m->object == object && m->pindex == pindex) |
| 4526 | break; |
| 4527 | /* relookup. */ |
| 4528 | vm_page_busy_release(m); |
| 4529 | cpu_spinwait(); |
| 4530 | continue; |
| 4531 | } |
| 4532 | if (!vm_page_grab_sleep(object, m, pindex, "pgnslp", |
| 4533 | allocflags, false)) |
| 4534 | return (false); |
| 4535 | } |
| 4536 | if ((allocflags & VM_ALLOC_WIRED) != 0) |
| 4537 | vm_page_wire(m); |
| 4538 | vm_page_grab_release(m, allocflags); |
| 4539 | *mp = m; |
| 4540 | return (true); |
| 4541 | } |
| 4542 | |
| 4543 | /* |
| 4544 | * Try to locklessly grab a page and fall back to the object lock if NOCREAT |
no test coverage detected