1 /*
2 * Copyright 2010-2013, Ingo Weinhold, ingo_weinhold@gmx.de.
3 * Copyright 2024, Haiku, Inc. All rights reserved.
4 * Distributed under the terms of the MIT license.
5 */
6 #ifndef CACHE_SUPPORT_H
7 #define CACHE_SUPPORT_H
8
9
10 static void
cache_get_pages(VMCache * cache,off_t offset,off_t length,bool isWrite,vm_page ** pages)11 cache_get_pages(VMCache* cache, off_t offset, off_t length, bool isWrite, vm_page** pages)
12 {
13 // get the pages, we already have
14 AutoLocker<VMCache> locker(cache);
15
16 size_t pageCount = length / B_PAGE_SIZE;
17 size_t index = 0;
18 size_t missingPages = 0;
19
20 while (length > 0) {
21 vm_page* page = cache->LookupPage(offset);
22 if (page != NULL) {
23 if (page->busy) {
24 cache->WaitForPageEvents(page, PAGE_EVENT_NOT_BUSY, true);
25 continue;
26 }
27
28 page->busy = true;
29 } else
30 missingPages++;
31
32 pages[index++] = page;
33 offset += B_PAGE_SIZE;
34 length -= B_PAGE_SIZE;
35 }
36
37 locker.Unlock();
38
39 // For a write we need to reserve the missing pages.
40 if (isWrite && missingPages > 0) {
41 vm_page_reservation reservation;
42 vm_page_reserve_pages(&reservation, missingPages,
43 VM_PRIORITY_SYSTEM);
44
45 for (size_t i = 0; i < pageCount; i++) {
46 if (pages[i] != NULL)
47 continue;
48
49 pages[i] = vm_page_allocate_page(&reservation, VM_PAGE_ALLOC_CLEAR
50 | PAGE_STATE_WIRED | VM_PAGE_ALLOC_BUSY);
51
52 if (--missingPages == 0)
53 break;
54 }
55
56 vm_page_unreserve_pages(&reservation);
57 }
58 }
59
60
61 static void
cache_put_pages(VMCache * cache,off_t offset,off_t length,vm_page ** pages,bool success)62 cache_put_pages(VMCache* cache, off_t offset, off_t length, vm_page** pages, bool success)
63 {
64 AutoLocker<VMCache> locker(cache);
65
66 // Mark all pages unbusy. On error free the newly allocated pages.
67 size_t index = 0;
68
69 while (length > 0) {
70 vm_page* page = pages[index++];
71 if (page != NULL) {
72 if (page->CacheRef() == NULL) {
73 if (success) {
74 cache->InsertPage(page, offset);
75 cache->MarkPageUnbusy(page);
76 DEBUG_PAGE_ACCESS_END(page);
77 } else
78 vm_page_free(NULL, page);
79 } else {
80 cache->MarkPageUnbusy(page);
81 }
82 }
83
84 offset += B_PAGE_SIZE;
85 length -= B_PAGE_SIZE;
86 }
87 }
88
89
90 #endif // CACHE_SUPPORT_H
91