54 assert_return (0 == (minimum_alignment & (minimum_alignment - 1)), {});
55 constexpr int protection = PROT_READ | PROT_WRITE;
56 constexpr int flags = MAP_PRIVATE | MAP_ANONYMOUS;
58 if (bytelength == MEM_ALIGN (bytelength, MINIMUM_HUGEPAGE) && minimum_alignment <= MINIMUM_HUGEPAGE)
60 void *memory =
mmap (
nullptr, bytelength, protection, flags | MAP_HUGETLB, -1, 0);
61 if (memory != MAP_FAILED)
63 assert_return ((
size_t (memory) & (minimum_alignment - 1)) == 0, {});
65 const int mlret =
mlock (memory, bytelength);
67 printerr (
"%s: mlock(%p,%u) failed: %s\n", __func__, memory, bytelength,
strerror (
errno));
72 if (bytelength == MEM_ALIGN (bytelength,
std::max (minimum_alignment, MINIMUM_HUGEPAGE)))
74 static const size_t pagesize =
sysconf (_SC_PAGESIZE);
75 minimum_alignment =
std::max (minimum_alignment, MINIMUM_HUGEPAGE);
76 size_t areasize = minimum_alignment - pagesize + bytelength;
77 char *memory = (
char*)
mmap (
nullptr, areasize, protection, flags, -1, 0);
82 size_t extra = MEM_ALIGN (start, minimum_alignment) - start;
83 if (extra &&
munmap (memory, extra) != 0)
84 printerr (
"%s: munmap(%p,%u) failed: %s\n", __func__, memory, extra,
strerror (
errno));
88 extra = areasize -
size_t (areasize / minimum_alignment) * minimum_alignment;
90 if (extra &&
munmap (memory + areasize, extra) != 0)
91 printerr (
"%s: munmap(%p,%u) failed: %s\n", __func__, memory + areasize, extra,
strerror (
errno));
94 assert_return ((
size_t (memory) & (minimum_alignment - 1)) == 0, {});
96 const int mlret =
mlock (memory, bytelength);
98 printerr (
"%s: mlock(%p,%u) failed: %s\n", __func__, memory, bytelength,
strerror (
errno));
99 LinuxHugePage::ReleaseF release;
101 if (madvise (memory, areasize, MADV_HUGEPAGE) >= 0)
102 release = &LinuxHugePage::unadvise_munmap_start;
104 release = &LinuxHugePage::munmap_start;
109 if (bytelength == MEM_ALIGN (bytelength, MINIMUM_HUGEPAGE) && minimum_alignment <= MINIMUM_HUGEPAGE)
114 assert_return ((
size_t (memory) & (minimum_alignment - 1)) == 0, {});
115 LinuxHugePage::ReleaseF release;
117 if (madvise (memory, bytelength, MADV_HUGEPAGE) >= 0)
118 release = &LinuxHugePage::unadvise_free_start;
120 release = &LinuxHugePage::free_start;
128 assert_return ((
size_t (memory) & (minimum_alignment - 1)) == 0, {});
145 const uint32 mem_alignment;
147 blob (newblob), mem_alignment (alignment)
151 assert_return ((
size_t (blob->mem()) & (blob->alignment() - 1)) == 0);
152 if (size() >= 1024 * 1024)
153 extents.reserve (1024);
156 area.zero (blob->mem());
162 const size_t s = sum();
163 if (s != blob->size())
164 warning (
"%s:%s: deleting area while bytes are unreleased: %zd", __FILE__, __func__, blob->size() - s);
181 for (
const auto b : extents)
190 ext.zero (blob->mem());
191 ssize_t overlaps_existing = -1, before = -1, after = -1;
192 for (
size_t i = 0; i < extents.size(); i++)
193 if (ext.start == extents[i].start + extents[i].length)
199 else if (ext.start + ext.length == extents[i].start)
205 else if (CHECK_FREE_OVERLAPS &&
206 ext.start + ext.length > extents[i].start &&
207 ext.start < extents[i].start + extents[i].length)
208 overlaps_existing = i;
213 extents[after].length += ext.length;
216 extents[after].length += extents[before].length;
217 extents.erase (extents.begin() + before);
223 extents[before].length += ext.length;
224 extents[before].start = ext.start;
228 extents.push_back (ext);
231 best_fit (
size_t length)
const
234 for (
size_t j = 0; j < extents.size(); j++)
236 const size_t i = extents.size() - 1 - j;
237 if (
ISLIKELY (length > extents[i].length))
239 if (
ISLIKELY (length == extents[i].length))
243 ISLIKELY (extents[i].length < extents[candidate].length) or
244 (
ISLIKELY (extents[i].length == extents[candidate].length) and
245 ISLIKELY (extents[i].start < extents[candidate].start)))
255 const uint32 aligned_length = MEM_ALIGN (ext.length, mem_alignment);
257 const ssize_t candidate = best_fit (aligned_length);
261 ext.start = extents[candidate].start;
262 ext.length = aligned_length;
263 if (
UNLIKELY (extents[candidate].length > aligned_length))
265 extents[candidate].start += aligned_length;
266 extents[candidate].length -= aligned_length;
271 extents[candidate] = extents.back();
272 extents.resize (extents.size() - 1);
283 return a.start < b.start;
285 std::sort (extents.begin(), extents.end(), isless_start);
286 for (
size_t i = extents.size() - 1; i > 0; i--)
287 if (extents[i-1].start + extents[i-1].length == extents[i].start)
289 extents[i-1].length += extents[i].length;
290 extents.erase (extents.begin() + i);