1#include "pedigree/kernel/process/Process.h"
4#include "pedigree/kernel/LockGuard.h"
5#include "pedigree/kernel/Log.h"
6#include "pedigree/kernel/processor/VirtualAddressSpace.h"
7#include "pedigree/kernel/utilities/Pointers.h"
10struct ReservationRange {
16bool Process::snapshotUserReservations(UserReservationSnapshot& result) {
18 return m_pVforkOwner->snapshotUserReservations(result);
20 size_t capacity = 0, normalCount = 0, dynamicCount = 0;
21 uint64_t generation = 0;
22#if PEDIGREE_BENCHMARK_VM_DIAGNOSTICS
23 size_t storageAllocations = 0;
31 if (normalCount > (~
size_t{0} /
sizeof(ReservationRange)) ||
32 dynamicCount > (~size_t{0} /
sizeof(ReservationRange)) - normalCount) {
35 needed = normalCount + dynamicCount;
36 if (needed <= capacity) {
37 MemoryAllocator::Range range(0, 0);
38 for (
size_t i = 0; i < normalCount; ++i) {
40 ranges.get()[i] = {range.address, range.length};
42 for (
size_t i = 0; i < dynamicCount; ++i) {
44 ranges.get()[normalCount + i] = {range.address, range.length};
46 generation = m_UserReservationGeneration;
55#if PEDIGREE_BENCHMARK_VM_DIAGNOSTICS
61#if PEDIGREE_BENCHMARK_VM_DIAGNOSTICS
62 recordBenchmarkVmCounter(VmReservationSnapshots);
63 recordBenchmarkVmCounter(VmReservationExtents, normalCount + dynamicCount);
64 recordBenchmarkVmCounter(VmReservationScratchAllocations, storageAllocations);
67 UserReservationSnapshot snapshot;
68 for (
size_t i = 0; i < normalCount; ++i) {
69 const auto& range = ranges.get()[i];
70 if (range.length && !snapshot.normal.tryFree(range.address, range.length,
false)) {
74 for (
size_t i = 0; i < dynamicCount; ++i) {
75 const auto& range = ranges.get()[normalCount + i];
76 if (range.length && !snapshot.dynamic.tryFree(range.address, range.length,
false)) {
80 result.normal.swap(snapshot.normal);
81 result.dynamic.swap(snapshot.dynamic);
82 result.generation = generation;
91 if (m_UserReservationGeneration != expectedGeneration) {
96 ++m_UserReservationGeneration;
97 replacement.generation = m_UserReservationGeneration;
101bool Process::allocateUserRange(
UserRegion region,
size_t length, uintptr_t& address) {
103 return m_pVforkOwner->allocateUserRange(region, length, address);
111 if (allocator.allocateWithoutAllocation(length, address)) {
112 ++m_UserReservationGeneration;
116 UserReservationSnapshot snapshot;
117 if (!snapshotUserReservations(snapshot)) {
120 MemoryAllocator& allocator = region == UserRegion::Dynamic ? snapshot.dynamic : snapshot.normal;
121 uintptr_t candidate = 0;
122 if (!allocator.
allocate(length, candidate)) {
132bool Process::allocateSpecificUserRange(
UserRegion region, uintptr_t address,
size_t length) {
134 return m_pVforkOwner->allocateSpecificUserRange(region, address, length);
135 if (!length || length > ~uintptr_t{0} - address) {
142 if (allocator.allocateSpecificWithoutAllocation(address, length)) {
143 ++m_UserReservationGeneration;
147 UserReservationSnapshot snapshot;
148 if (!snapshotUserReservations(snapshot)) {
151 MemoryAllocator& allocator = region == UserRegion::Dynamic ? snapshot.dynamic : snapshot.normal;
161void Process::freeUserRange(
UserRegion region, uintptr_t address,
size_t length) {
163 m_pVforkOwner->freeUserRange(region, address, length);
169 if (length > ~uintptr_t{0} - address) {
170 FATAL(
"Invalid process reservation release");
177 ++m_UserReservationGeneration;
183 UserReservationSnapshot snapshot;
184 if (!snapshotUserReservations(snapshot)) {
185 FATAL(
"Cannot grow process reservation metadata during release");
187 MemoryAllocator& allocator = region == UserRegion::Dynamic ? snapshot.dynamic : snapshot.normal;
188 if (!allocator.tryFree(address, length)) {
189 FATAL(
"Cannot grow process reservation metadata during release");
197void Process::resetUserReservations() {
198 assert(!m_pVforkOwner);
200 UserReservationSnapshot snapshot;
203 snapshot.generation = m_UserReservationGeneration;
205 snapshot.normal.free(
209 snapshot.dynamic.free(
VirtualAddressSpace * getAddressSpace()
MemoryAllocator m_DynamicSpaceAllocator
MemoryAllocator m_SpaceAllocator
bool commitUserReservations(uint64_t expectedGeneration, UserReservationSnapshot &replacement)
bool getRange(size_t index, Range &range) const
bool allocate(T length, T &address)
void swap(RangeList &other) noexcept
bool freeWithoutAllocation(T address, T length)
bool allocateSpecific(T address, T length)