61#if __has_include(<sys/param.h>)
65#define MAPPED_FILE_BSIZE DEV_BSIZE
67#define MAPPED_FILE_BSIZE 512
79 std::optional<sys::fs::LockKind> Locked;
82 FileWithLock(std::string PathStr,
Error &
E) : Path(std::
move(PathStr)) {
83 ErrorAsOutParameter EOP(&
E);
90 FileWithLock(FileWithLock &) =
delete;
91 FileWithLock(FileWithLock &&
Other) {
92 Path = std::move(
Other.Path);
95 Locked =
Other.Locked;
96 Other.Locked = std::nullopt;
101 static Expected<FileWithLock> open(StringRef Path) {
103 FileWithLock
Result(Path.str(),
E);
106 return std::move(Result);
110 assert(!Locked &&
"already locked");
118 assert(Locked &&
"not locked");
119 if (
auto E = unlock())
127 Locked = std::nullopt;
135 bool tryLockExclusive() {
136 assert(!Locked &&
"can only try to lock if not locked");
138 Locked = sys::fs::LockKind::Exclusive;
147 Locked = std::nullopt;
154 uint64_t AllocatedSize;
164 if (Capacity < MinCapacity)
166 std::make_error_code(std::errc::invalid_argument),
167 "capacity is too small to hold MappedFileRegionArena");
170 Result.Path = Path.str();
174 SharedFilePath.
append(
".shared");
176 auto SharedFileLock = FileWithLock::open(SharedFilePath);
178 return SharedFileLock.takeError();
179 Result.SharedLockFD = SharedFileLock->FD;
187 auto MainFile = FileWithLock::open(Result.Path);
189 return MainFile.takeError();
192 Result.FD = MainFile->FD;
195 auto FileSize = FileSizeInfo::get(File);
201 if (FileSize->Size < Capacity) {
206 FileSize = FileSizeInfo::get(File);
211 if (FileSize->Size >= MinCapacity) {
217 return Size.takeError();
219 Header *H =
reinterpret_cast<Header *
>(HeaderContent.data());
220 if (H->HeaderOffset != HeaderOffset)
222 std::make_error_code(std::errc::invalid_argument),
223 "specified header offset (" +
utostr(HeaderOffset) +
224 ") does not match existing config (" +
utostr(H->HeaderOffset) +
228 if (H->Capacity != Capacity)
229 Capacity = H->Capacity;
233 if (FileSize->Size < Capacity) {
235 if (std::error_code EC =
247 Result.Region = std::move(Map);
251 Result.initializeHeader(HeaderOffset);
252 if (FileSize->Size < MinCapacity) {
255 if (
Error E = NewFileConstructor(Result))
258 Result.H->HeaderOffset.exchange(HeaderOffset);
259 Result.H->Capacity.exchange(Capacity);
267 FileSize = FileSizeInfo::get(File);
270 Result.H->AllocatedSize.exchange(FileSize->AllocatedSize);
274 SharedFileLock->release();
275 return std::move(Result);
278void MappedFileRegionArena::destroyImpl() {
289 assert(SharedLockFD &&
"Must have shared lock file open");
302 auto Close = [](std::optional<int> &FD) {
315void MappedFileRegionArena::initializeHeader(uint64_t HeaderOffset) {
317 uint64_t HeaderEndOffset = HeaderOffset +
sizeof(
decltype(*H));
319 "Expected end offset to be pre-allocated");
321 "Expected end offset to be aligned");
322 H =
reinterpret_cast<decltype(H)
>(
data() + HeaderOffset);
324 uint64_t ExistingValue = 0;
325 if (!H->BumpPtr.compare_exchange_strong(ExistingValue, HeaderEndOffset))
326 assert(ExistingValue >= HeaderEndOffset &&
327 "Expected 0, or past the end of the header itself");
332 "memory mapped file allocator is out of space");
337 uint64_t OldEnd = H->BumpPtr.fetch_add(AllocSize);
338 uint64_t NewEnd = OldEnd + AllocSize;
347 (void)H->BumpPtr.exchange(OldEnd);
352 uint64_t DiskSize = H->AllocatedSize;
356 constexpr uint64_t Increment = 1 * 1024 * 1024;
360 assert(NewSize >= DiskSize + Increment);
366 while (DiskSize < NewSize)
367 H->AllocatedSize.compare_exchange_strong(DiskSize, NewSize);
373#if LLVM_ON_UNIX && defined(MAPPED_FILE_BSIZE)
375 int StatRet = ::fstat(File, &
Status);
386 return FileSizeInfo{
Status.getSize(),
Status.getSize()};
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
#define LLVM_UNLIKELY(EXPR)
static Error createAllocatorOutOfSpaceError()
This file declares interface for MappedFileRegionArena, a bump pointer allocator, backed by a memory-...
Represents either an error or a value T.
Lightweight error class with error context and mandatory checking.
static ErrorSuccess success()
Create a success value.
Tagged union holding either a T or a Error.
SmallString - A SmallString is just a SmallVector with methods and accessors that make it work better...
void append(StringRef RHS)
Append from a StringRef.
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
MappedFileRegionArena()=default
uint64_t capacity() const
Expected< int64_t > allocateOffset(uint64_t AllocSize)
Allocate, returning the offset from data() instead of a pointer.
static Expected< MappedFileRegionArena > create(const Twine &Path, uint64_t Capacity, uint64_t HeaderOffset, function_ref< Error(MappedFileRegionArena &)> NewFileConstructor)
Create a MappedFileRegionArena.
static constexpr Align getAlign()
Minimum alignment for allocations, currently hardcoded to 8B.
An efficient, type-erasing, non-owning reference to a callable.
Represents the result of a call to sys::fs::status().
This class represents a memory mapped file.
@ readwrite
May access map via data and modify it. Written to path.
std::error_code lockFileThreadSafe(int FD, llvm::sys::fs::LockKind Kind)
Thread-safe alternative to sys::fs::lockFile.
std::error_code unlockFileThreadSafe(int FD)
Thread-safe alternative to sys::fs::unlockFile.
std::error_code tryLockFileThreadSafe(int FD, std::chrono::milliseconds Timeout=std::chrono::milliseconds(0), llvm::sys::fs::LockKind Kind=llvm::sys::fs::LockKind::Exclusive)
Thread-safe alternative to sys::fs::tryLockFile.
Expected< size_t > preallocateFileTail(int FD, size_t CurrentSize, size_t NewSize)
Allocate space for the file FD on disk, if the filesystem supports it.
LLVM_ABI std::error_code closeFile(file_t &F)
Close the file object.
std::error_code openFileForReadWrite(const Twine &Name, int &ResultFD, CreationDisposition Disp, OpenFlags Flags, unsigned Mode=0666)
Opens the file with the given name in a write-only or read-write mode, returning its open file descri...
@ CD_OpenAlways
CD_OpenAlways - When opening a file:
LLVM_ABI Expected< size_t > readNativeFileSlice(file_t FileHandle, MutableArrayRef< char > Buf, uint64_t Offset)
Reads Buf.size() bytes from FileHandle at offset Offset into Buf.
LLVM_ABI std::error_code resize_file_sparse(int FD, uint64_t Size)
Resize path to size with sparse files explicitly enabled.
LockKind
An enumeration for the lock kind.
LLVM_ABI std::error_code resize_file(int FD, uint64_t Size)
Resize path to size.
LLVM_ABI file_t convertFDToNativeFile(int FD)
Converts from a Posix file descriptor number to a native file handle.
LLVM_ABI std::error_code status(const Twine &path, file_status &result, bool follow=true)
Get file status as if by POSIX stat().
This is an optimization pass for GlobalISel generic memory operations.
Error createFileError(const Twine &F, Error E)
Concatenate a source file path and/or name with an Error.
bool isAligned(Align Lhs, uint64_t SizeInBytes)
Checks that SizeInBytes is a multiple of the alignment.
std::string utostr(uint64_t X, bool isNeg=false)
Error createStringError(std::error_code EC, char const *Fmt, const Ts &... Vals)
Create formatted StringError object.
decltype(auto) get(const PointerIntPair< PointerTy, IntBits, IntType, PtrTraits, Info > &Pair)
uint64_t alignTo(uint64_t Size, Align A)
Returns a multiple of A needed to store Size bytes.
OutputIt move(R &&Range, OutputIt Out)
Provide wrappers to std::move which take ranges instead of having to pass begin/end explicitly.
std::error_code errnoAsErrorCode()
Helper to get errno as an std::error_code.
void consumeError(Error Err)
Consume a Error without doing anything.
static constexpr Align Of()
Allow constructions of constexpr Align from types.