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();
220 memcpy(&H, HeaderContent.data(),
sizeof(H));
221 if (H.HeaderOffset != HeaderOffset)
223 std::make_error_code(std::errc::invalid_argument),
224 "specified header offset (" +
utostr(HeaderOffset) +
225 ") does not match existing config (" +
utostr(H.HeaderOffset) +
229 if (H.Capacity != Capacity)
230 Capacity = H.Capacity;
234 if (FileSize->Size < Capacity) {
236 if (std::error_code EC =
248 Result.Region = std::move(Map);
252 Result.initializeHeader(HeaderOffset);
253 if (FileSize->Size < MinCapacity) {
256 if (
Error E = NewFileConstructor(Result))
259 Result.H->HeaderOffset.exchange(HeaderOffset);
260 Result.H->Capacity.exchange(Capacity);
268 FileSize = FileSizeInfo::get(File);
271 Result.H->AllocatedSize.exchange(FileSize->AllocatedSize);
275 SharedFileLock->release();
276 return std::move(Result);
279void MappedFileRegionArena::destroyImpl() {
290 assert(SharedLockFD &&
"Must have shared lock file open");
303 auto Close = [](std::optional<int> &FD) {
316void MappedFileRegionArena::initializeHeader(uint64_t HeaderOffset) {
318 uint64_t HeaderEndOffset = HeaderOffset +
sizeof(
decltype(*H));
320 "Expected end offset to be pre-allocated");
322 "Expected end offset to be aligned");
323 H =
reinterpret_cast<decltype(H)
>(
data() + HeaderOffset);
325 uint64_t ExistingValue = 0;
326 if (!H->BumpPtr.compare_exchange_strong(ExistingValue, HeaderEndOffset))
327 assert(ExistingValue >= HeaderEndOffset &&
328 "Expected 0, or past the end of the header itself");
333 "memory mapped file allocator is out of space");
338 uint64_t OldEnd = H->BumpPtr.fetch_add(AllocSize);
339 uint64_t NewEnd = OldEnd + AllocSize;
348 (void)H->BumpPtr.exchange(OldEnd);
353 uint64_t DiskSize = H->AllocatedSize;
357 constexpr uint64_t Increment = 1 * 1024 * 1024;
361 assert(NewSize >= DiskSize + Increment);
367 while (DiskSize < NewSize)
368 H->AllocatedSize.compare_exchange_strong(DiskSize, NewSize);
374#if LLVM_ON_UNIX && defined(MAPPED_FILE_BSIZE)
376 int StatRet = ::fstat(File, &
Status);
387 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.