The Pedigree Project 0.1
SlamBitmap.cc
1#include "pedigree/kernel/core/SlamBitmap.h"
2#include "pedigree/kernel/utilities/utility.h"
3
4void SlamBitmap::useMemory(void* memory, size_t entryCount, size_t pageCount) {
5 m_reserved = static_cast<uint64_t*>(adjust_pointer(memory, 0));
6 m_mapped = static_cast<uint64_t*>(adjust_pointer(memory, entryCount * sizeof(uint64_t)));
7 m_ready = static_cast<uint64_t*>(adjust_pointer(memory, entryCount * sizeof(uint64_t) * 2));
8 // m_Entries = static_cast<Entry*>(memory);
9 m_EntryCount = entryCount;
10 m_PageCount = pageCount;
11 m_FirstFreeEntry = 0;
12}
13
14uint64_t SlamBitmap::reservedBits(size_t entry) const {
15 return m_reserved[entry]; // m_Entries[entry].reserved;
16}
17
18uintptr_t SlamBitmap::metadataAddress(size_t entry) const {
19 // return reinterpret_cast<uintptr_t>(&m_Entries[entry]);
20 // TODO: check this is sensible?
21 return reinterpret_cast<uintptr_t>(&m_reserved[entry]);
22}
23
24static bool hasFreePage(uint64_t reserved, size_t firstPage, size_t pageCount) {
25 const size_t bits = pageCount - firstPage < 64 ? pageCount - firstPage : 64;
26 const uint64_t valid = bits == 64 ? ~uint64_t(0) : (uint64_t(1) << bits) - 1;
27 return (reserved & valid) != valid;
28}
29
30size_t SlamBitmap::findFreeRun(size_t pageCount) const {
31 size_t runStart = 0;
32 size_t runLength = 0;
33 for (size_t entryIndex = m_FirstFreeEntry; entryIndex < m_EntryCount; ++entryIndex) {
34 const size_t entryBase = entryIndex * 64;
35 const size_t bits = (m_PageCount - entryBase < 64) ? m_PageCount - entryBase : 64;
36 const uint64_t bitmap = m_reserved[entryIndex]; // m_Entries[entryIndex].reserved;
37 if (!bitmap) {
38 if (!runLength)
39 runStart = entryBase;
40 runLength += bits;
41 if (runLength >= pageCount)
42 return runStart;
43 continue;
44 }
45 if (bitmap == ~uint64_t(0)) {
46 runLength = 0;
47 continue;
48 }
49 for (size_t bit = 0; bit < bits;) {
50 const uint64_t remaining = bitmap >> bit;
51 if (remaining & 1) {
52 runLength = 0;
53 bit += (remaining == ~uint64_t(0)) ? bits - bit : __builtin_ctzll(~remaining);
54 } else {
55 const size_t freeBits = remaining ? __builtin_ctzll(remaining) : bits - bit;
56 const size_t span = freeBits < bits - bit ? freeBits : bits - bit;
57 if (!runLength)
58 runStart = entryBase + bit;
59 runLength += span;
60 if (runLength >= pageCount)
61 return runStart;
62 bit += span;
63 }
64 }
65 }
66 return static_cast<size_t>(-1);
67}
68
69void SlamBitmap::reserve(size_t firstPage, size_t pageCount) {
70 for (size_t i = 0; i < pageCount; ++i)
71 // m_Entries[(firstPage + i) / 64].reserved |= uint64_t(1) << ((firstPage + i) % 64);
72 m_reserved[(firstPage + i) / 64] |= uint64_t(1) << ((firstPage + i) % 64);
73
74 while (m_FirstFreeEntry < m_EntryCount &&
75 !hasFreePage(m_reserved[m_FirstFreeEntry], m_FirstFreeEntry * 64, m_PageCount))
76 ++m_FirstFreeEntry;
77}
78
79void SlamBitmap::release(size_t firstPage, size_t pageCount) {
80 for (size_t i = 0; i < pageCount; ++i) {
81 const uint64_t bit = uint64_t(1) << ((firstPage + i) % 64);
82 size_t index = (firstPage + i) / 64;
83 m_mapped[index] &= ~bit;
84 m_ready[index] &= ~bit;
85 m_reserved[index] &= ~bit;
86 if (index < m_FirstFreeEntry)
87 m_FirstFreeEntry = index;
88 /*
89 Entry& entry = m_Entries[(firstPage + i) / 64];
90 entry.mapped &= ~bit;
91 entry.ready &= ~bit;
92 entry.reserved &= ~bit;
93 */
94 }
95}
96
97void SlamBitmap::setMapped(size_t page) {
98 // m_Entries[page / 64].mapped |= uint64_t(1) << (page % 64);
99 m_mapped[page / 64] |= uint64_t(1) << (page % 64);
100}
101
102void SlamBitmap::clearMappedAndReady(size_t page) {
103 const uint64_t bit = uint64_t(1) << (page % 64);
104 size_t index = page / 64;
105 m_mapped[index] &= ~bit;
106 m_ready[index] &= ~bit;
107 /*
108 Entry& entry = m_Entries[page / 64];
109 entry.mapped &= ~bit;
110 entry.ready &= ~bit;
111 */
112}
113
114bool SlamBitmap::isReserved(size_t page) const {
115 // return m_Entries[page / 64].reserved & (uint64_t(1) << (page % 64));
116 return m_reserved[page / 64] & (uint64_t(1) << (page % 64));
117}
118
119bool SlamBitmap::isMapped(size_t page) const {
120 // return m_Entries[page / 64].mapped & (uint64_t(1) << (page % 64));
121 return m_mapped[page / 64] & (uint64_t(1) << (page % 64));
122}
123
124bool SlamBitmap::isReady(size_t page) const {
125 // return m_Entries[page / 64].ready & (uint64_t(1) << (page % 64));
126 return m_ready[page / 64] & (uint64_t(1) << (page % 64));
127}
128
129void SlamBitmap::setReady(size_t page) {
130 // m_Entries[page / 64].ready |= uint64_t(1) << (page % 64);
131 m_ready[page / 64] |= uint64_t(1) << (page % 64);
132}