123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344 |
- //===---------- ExecutorSharedMemoryMapperService.cpp -----------*- C++ -*-===//
- //
- // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
- // See https://llvm.org/LICENSE.txt for license information.
- // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
- //
- //===----------------------------------------------------------------------===//
- #include "llvm/ExecutionEngine/Orc/TargetProcess/ExecutorSharedMemoryMapperService.h"
- #include "llvm/ExecutionEngine/Orc/Shared/OrcRTBridge.h"
- #include "llvm/Support/Process.h"
- #include "llvm/Support/WindowsError.h"
- #include <sstream>
- #if defined(LLVM_ON_UNIX)
- #include <errno.h>
- #include <fcntl.h>
- #include <sys/mman.h>
- #include <unistd.h>
- #endif
- namespace llvm {
- namespace orc {
- namespace rt_bootstrap {
- #if defined(_WIN32)
- static DWORD getWindowsProtectionFlags(MemProt MP) {
- if (MP == MemProt::Read)
- return PAGE_READONLY;
- if (MP == MemProt::Write ||
- MP == (MemProt::Write | MemProt::Read)) {
- // Note: PAGE_WRITE is not supported by VirtualProtect
- return PAGE_READWRITE;
- }
- if (MP == (MemProt::Read | MemProt::Exec))
- return PAGE_EXECUTE_READ;
- if (MP == (MemProt::Read | MemProt::Write | MemProt::Exec))
- return PAGE_EXECUTE_READWRITE;
- if (MP == MemProt::Exec)
- return PAGE_EXECUTE;
- return PAGE_NOACCESS;
- }
- #endif
- Expected<std::pair<ExecutorAddr, std::string>>
- ExecutorSharedMemoryMapperService::reserve(uint64_t Size) {
- #if (defined(LLVM_ON_UNIX) && !defined(__ANDROID__)) || defined(_WIN32)
- #if defined(LLVM_ON_UNIX)
- std::string SharedMemoryName;
- {
- std::stringstream SharedMemoryNameStream;
- SharedMemoryNameStream << "/jitlink_" << sys::Process::getProcessId() << '_'
- << (++SharedMemoryCount);
- SharedMemoryName = SharedMemoryNameStream.str();
- }
- int SharedMemoryFile =
- shm_open(SharedMemoryName.c_str(), O_RDWR | O_CREAT | O_EXCL, 0700);
- if (SharedMemoryFile < 0)
- return errorCodeToError(std::error_code(errno, std::generic_category()));
- // by default size is 0
- if (ftruncate(SharedMemoryFile, Size) < 0)
- return errorCodeToError(std::error_code(errno, std::generic_category()));
- void *Addr = mmap(nullptr, Size, PROT_NONE, MAP_SHARED, SharedMemoryFile, 0);
- if (Addr == MAP_FAILED)
- return errorCodeToError(std::error_code(errno, std::generic_category()));
- close(SharedMemoryFile);
- #elif defined(_WIN32)
- std::string SharedMemoryName;
- {
- std::stringstream SharedMemoryNameStream;
- SharedMemoryNameStream << "jitlink_" << sys::Process::getProcessId() << '_'
- << (++SharedMemoryCount);
- SharedMemoryName = SharedMemoryNameStream.str();
- }
- std::wstring WideSharedMemoryName(SharedMemoryName.begin(),
- SharedMemoryName.end());
- HANDLE SharedMemoryFile = CreateFileMappingW(
- INVALID_HANDLE_VALUE, NULL, PAGE_EXECUTE_READWRITE, Size >> 32,
- Size & 0xffffffff, WideSharedMemoryName.c_str());
- if (!SharedMemoryFile)
- return errorCodeToError(mapWindowsError(GetLastError()));
- void *Addr = MapViewOfFile(SharedMemoryFile,
- FILE_MAP_ALL_ACCESS | FILE_MAP_EXECUTE, 0, 0, 0);
- if (!Addr) {
- CloseHandle(SharedMemoryFile);
- return errorCodeToError(mapWindowsError(GetLastError()));
- }
- #endif
- {
- std::lock_guard<std::mutex> Lock(Mutex);
- Reservations[Addr].Size = Size;
- #if defined(_WIN32)
- Reservations[Addr].SharedMemoryFile = SharedMemoryFile;
- #endif
- }
- return std::make_pair(ExecutorAddr::fromPtr(Addr),
- std::move(SharedMemoryName));
- #else
- return make_error<StringError>(
- "SharedMemoryMapper is not supported on this platform yet",
- inconvertibleErrorCode());
- #endif
- }
- Expected<ExecutorAddr> ExecutorSharedMemoryMapperService::initialize(
- ExecutorAddr Reservation, tpctypes::SharedMemoryFinalizeRequest &FR) {
- #if (defined(LLVM_ON_UNIX) && !defined(__ANDROID__)) || defined(_WIN32)
- ExecutorAddr MinAddr(~0ULL);
- // Contents are already in place
- for (auto &Segment : FR.Segments) {
- if (Segment.Addr < MinAddr)
- MinAddr = Segment.Addr;
- #if defined(LLVM_ON_UNIX)
- int NativeProt = 0;
- if ((Segment.AG.getMemProt() & MemProt::Read) == MemProt::Read)
- NativeProt |= PROT_READ;
- if ((Segment.AG.getMemProt() & MemProt::Write) == MemProt::Write)
- NativeProt |= PROT_WRITE;
- if ((Segment.AG.getMemProt() & MemProt::Exec) == MemProt::Exec)
- NativeProt |= PROT_EXEC;
- if (mprotect(Segment.Addr.toPtr<void *>(), Segment.Size, NativeProt))
- return errorCodeToError(std::error_code(errno, std::generic_category()));
- #elif defined(_WIN32)
- DWORD NativeProt =
- getWindowsProtectionFlags(Segment.AG.getMemProt());
- if (!VirtualProtect(Segment.Addr.toPtr<void *>(), Segment.Size, NativeProt,
- &NativeProt))
- return errorCodeToError(mapWindowsError(GetLastError()));
- #endif
- if ((Segment.AG.getMemProt() & MemProt::Exec) == MemProt::Exec)
- sys::Memory::InvalidateInstructionCache(Segment.Addr.toPtr<void *>(),
- Segment.Size);
- }
- // Run finalization actions and get deinitlization action list.
- auto DeinitializeActions = shared::runFinalizeActions(FR.Actions);
- if (!DeinitializeActions) {
- return DeinitializeActions.takeError();
- }
- {
- std::lock_guard<std::mutex> Lock(Mutex);
- Allocations[MinAddr].DeinitializationActions =
- std::move(*DeinitializeActions);
- Reservations[Reservation.toPtr<void *>()].Allocations.push_back(MinAddr);
- }
- return MinAddr;
- #else
- return make_error<StringError>(
- "SharedMemoryMapper is not supported on this platform yet",
- inconvertibleErrorCode());
- #endif
- }
- Error ExecutorSharedMemoryMapperService::deinitialize(
- const std::vector<ExecutorAddr> &Bases) {
- Error AllErr = Error::success();
- {
- std::lock_guard<std::mutex> Lock(Mutex);
- for (auto Base : llvm::reverse(Bases)) {
- if (Error Err = shared::runDeallocActions(
- Allocations[Base].DeinitializationActions)) {
- AllErr = joinErrors(std::move(AllErr), std::move(Err));
- }
- // Remove the allocation from the allocation list of its reservation
- for (auto &Reservation : Reservations) {
- auto AllocationIt =
- std::find(Reservation.second.Allocations.begin(),
- Reservation.second.Allocations.end(), Base);
- if (AllocationIt != Reservation.second.Allocations.end()) {
- Reservation.second.Allocations.erase(AllocationIt);
- break;
- }
- }
- Allocations.erase(Base);
- }
- }
- return AllErr;
- }
- Error ExecutorSharedMemoryMapperService::release(
- const std::vector<ExecutorAddr> &Bases) {
- #if (defined(LLVM_ON_UNIX) && !defined(__ANDROID__)) || defined(_WIN32)
- Error Err = Error::success();
- for (auto Base : Bases) {
- std::vector<ExecutorAddr> AllocAddrs;
- size_t Size;
- #if defined(_WIN32)
- HANDLE SharedMemoryFile;
- #endif
- {
- std::lock_guard<std::mutex> Lock(Mutex);
- auto &R = Reservations[Base.toPtr<void *>()];
- Size = R.Size;
- #if defined(_WIN32)
- SharedMemoryFile = R.SharedMemoryFile;
- #endif
- AllocAddrs.swap(R.Allocations);
- }
- // deinitialize sub allocations
- if (Error E = deinitialize(AllocAddrs))
- Err = joinErrors(std::move(Err), std::move(E));
- #if defined(LLVM_ON_UNIX)
- if (munmap(Base.toPtr<void *>(), Size) != 0)
- Err = joinErrors(std::move(Err), errorCodeToError(std::error_code(
- errno, std::generic_category())));
- #elif defined(_WIN32)
- (void)Size;
- if (!UnmapViewOfFile(Base.toPtr<void *>()))
- Err = joinErrors(std::move(Err),
- errorCodeToError(mapWindowsError(GetLastError())));
- CloseHandle(SharedMemoryFile);
- #endif
- std::lock_guard<std::mutex> Lock(Mutex);
- Reservations.erase(Base.toPtr<void *>());
- }
- return Err;
- #else
- return make_error<StringError>(
- "SharedMemoryMapper is not supported on this platform yet",
- inconvertibleErrorCode());
- #endif
- }
- Error ExecutorSharedMemoryMapperService::shutdown() {
- if (Reservations.empty())
- return Error::success();
- std::vector<ExecutorAddr> ReservationAddrs;
- ReservationAddrs.reserve(Reservations.size());
- for (const auto &R : Reservations)
- ReservationAddrs.push_back(ExecutorAddr::fromPtr(R.getFirst()));
- return release(std::move(ReservationAddrs));
- }
- void ExecutorSharedMemoryMapperService::addBootstrapSymbols(
- StringMap<ExecutorAddr> &M) {
- M[rt::ExecutorSharedMemoryMapperServiceInstanceName] =
- ExecutorAddr::fromPtr(this);
- M[rt::ExecutorSharedMemoryMapperServiceReserveWrapperName] =
- ExecutorAddr::fromPtr(&reserveWrapper);
- M[rt::ExecutorSharedMemoryMapperServiceInitializeWrapperName] =
- ExecutorAddr::fromPtr(&initializeWrapper);
- M[rt::ExecutorSharedMemoryMapperServiceDeinitializeWrapperName] =
- ExecutorAddr::fromPtr(&deinitializeWrapper);
- M[rt::ExecutorSharedMemoryMapperServiceReleaseWrapperName] =
- ExecutorAddr::fromPtr(&releaseWrapper);
- }
- llvm::orc::shared::CWrapperFunctionResult
- ExecutorSharedMemoryMapperService::reserveWrapper(const char *ArgData,
- size_t ArgSize) {
- return shared::WrapperFunction<
- rt::SPSExecutorSharedMemoryMapperServiceReserveSignature>::
- handle(ArgData, ArgSize,
- shared::makeMethodWrapperHandler(
- &ExecutorSharedMemoryMapperService::reserve))
- .release();
- }
- llvm::orc::shared::CWrapperFunctionResult
- ExecutorSharedMemoryMapperService::initializeWrapper(const char *ArgData,
- size_t ArgSize) {
- return shared::WrapperFunction<
- rt::SPSExecutorSharedMemoryMapperServiceInitializeSignature>::
- handle(ArgData, ArgSize,
- shared::makeMethodWrapperHandler(
- &ExecutorSharedMemoryMapperService::initialize))
- .release();
- }
- llvm::orc::shared::CWrapperFunctionResult
- ExecutorSharedMemoryMapperService::deinitializeWrapper(const char *ArgData,
- size_t ArgSize) {
- return shared::WrapperFunction<
- rt::SPSExecutorSharedMemoryMapperServiceDeinitializeSignature>::
- handle(ArgData, ArgSize,
- shared::makeMethodWrapperHandler(
- &ExecutorSharedMemoryMapperService::deinitialize))
- .release();
- }
- llvm::orc::shared::CWrapperFunctionResult
- ExecutorSharedMemoryMapperService::releaseWrapper(const char *ArgData,
- size_t ArgSize) {
- return shared::WrapperFunction<
- rt::SPSExecutorSharedMemoryMapperServiceReleaseSignature>::
- handle(ArgData, ArgSize,
- shared::makeMethodWrapperHandler(
- &ExecutorSharedMemoryMapperService::release))
- .release();
- }
- } // namespace rt_bootstrap
- } // end namespace orc
- } // end namespace llvm
|