ExecutorSharedMemoryMapperService.cpp 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344
  1. //===---------- ExecutorSharedMemoryMapperService.cpp -----------*- C++ -*-===//
  2. //
  3. // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
  4. // See https://llvm.org/LICENSE.txt for license information.
  5. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  6. //
  7. //===----------------------------------------------------------------------===//
  8. #include "llvm/ExecutionEngine/Orc/TargetProcess/ExecutorSharedMemoryMapperService.h"
  9. #include "llvm/ExecutionEngine/Orc/Shared/OrcRTBridge.h"
  10. #include "llvm/Support/Process.h"
  11. #include "llvm/Support/WindowsError.h"
  12. #include <sstream>
  13. #if defined(LLVM_ON_UNIX)
  14. #include <errno.h>
  15. #include <fcntl.h>
  16. #include <sys/mman.h>
  17. #include <unistd.h>
  18. #endif
  19. namespace llvm {
  20. namespace orc {
  21. namespace rt_bootstrap {
  22. #if defined(_WIN32)
  23. static DWORD getWindowsProtectionFlags(MemProt MP) {
  24. if (MP == MemProt::Read)
  25. return PAGE_READONLY;
  26. if (MP == MemProt::Write ||
  27. MP == (MemProt::Write | MemProt::Read)) {
  28. // Note: PAGE_WRITE is not supported by VirtualProtect
  29. return PAGE_READWRITE;
  30. }
  31. if (MP == (MemProt::Read | MemProt::Exec))
  32. return PAGE_EXECUTE_READ;
  33. if (MP == (MemProt::Read | MemProt::Write | MemProt::Exec))
  34. return PAGE_EXECUTE_READWRITE;
  35. if (MP == MemProt::Exec)
  36. return PAGE_EXECUTE;
  37. return PAGE_NOACCESS;
  38. }
  39. #endif
  40. Expected<std::pair<ExecutorAddr, std::string>>
  41. ExecutorSharedMemoryMapperService::reserve(uint64_t Size) {
  42. #if (defined(LLVM_ON_UNIX) && !defined(__ANDROID__)) || defined(_WIN32)
  43. #if defined(LLVM_ON_UNIX)
  44. std::string SharedMemoryName;
  45. {
  46. std::stringstream SharedMemoryNameStream;
  47. SharedMemoryNameStream << "/jitlink_" << sys::Process::getProcessId() << '_'
  48. << (++SharedMemoryCount);
  49. SharedMemoryName = SharedMemoryNameStream.str();
  50. }
  51. int SharedMemoryFile =
  52. shm_open(SharedMemoryName.c_str(), O_RDWR | O_CREAT | O_EXCL, 0700);
  53. if (SharedMemoryFile < 0)
  54. return errorCodeToError(std::error_code(errno, std::generic_category()));
  55. // by default size is 0
  56. if (ftruncate(SharedMemoryFile, Size) < 0)
  57. return errorCodeToError(std::error_code(errno, std::generic_category()));
  58. void *Addr = mmap(nullptr, Size, PROT_NONE, MAP_SHARED, SharedMemoryFile, 0);
  59. if (Addr == MAP_FAILED)
  60. return errorCodeToError(std::error_code(errno, std::generic_category()));
  61. close(SharedMemoryFile);
  62. #elif defined(_WIN32)
  63. std::string SharedMemoryName;
  64. {
  65. std::stringstream SharedMemoryNameStream;
  66. SharedMemoryNameStream << "jitlink_" << sys::Process::getProcessId() << '_'
  67. << (++SharedMemoryCount);
  68. SharedMemoryName = SharedMemoryNameStream.str();
  69. }
  70. std::wstring WideSharedMemoryName(SharedMemoryName.begin(),
  71. SharedMemoryName.end());
  72. HANDLE SharedMemoryFile = CreateFileMappingW(
  73. INVALID_HANDLE_VALUE, NULL, PAGE_EXECUTE_READWRITE, Size >> 32,
  74. Size & 0xffffffff, WideSharedMemoryName.c_str());
  75. if (!SharedMemoryFile)
  76. return errorCodeToError(mapWindowsError(GetLastError()));
  77. void *Addr = MapViewOfFile(SharedMemoryFile,
  78. FILE_MAP_ALL_ACCESS | FILE_MAP_EXECUTE, 0, 0, 0);
  79. if (!Addr) {
  80. CloseHandle(SharedMemoryFile);
  81. return errorCodeToError(mapWindowsError(GetLastError()));
  82. }
  83. #endif
  84. {
  85. std::lock_guard<std::mutex> Lock(Mutex);
  86. Reservations[Addr].Size = Size;
  87. #if defined(_WIN32)
  88. Reservations[Addr].SharedMemoryFile = SharedMemoryFile;
  89. #endif
  90. }
  91. return std::make_pair(ExecutorAddr::fromPtr(Addr),
  92. std::move(SharedMemoryName));
  93. #else
  94. return make_error<StringError>(
  95. "SharedMemoryMapper is not supported on this platform yet",
  96. inconvertibleErrorCode());
  97. #endif
  98. }
  99. Expected<ExecutorAddr> ExecutorSharedMemoryMapperService::initialize(
  100. ExecutorAddr Reservation, tpctypes::SharedMemoryFinalizeRequest &FR) {
  101. #if (defined(LLVM_ON_UNIX) && !defined(__ANDROID__)) || defined(_WIN32)
  102. ExecutorAddr MinAddr(~0ULL);
  103. // Contents are already in place
  104. for (auto &Segment : FR.Segments) {
  105. if (Segment.Addr < MinAddr)
  106. MinAddr = Segment.Addr;
  107. #if defined(LLVM_ON_UNIX)
  108. int NativeProt = 0;
  109. if ((Segment.AG.getMemProt() & MemProt::Read) == MemProt::Read)
  110. NativeProt |= PROT_READ;
  111. if ((Segment.AG.getMemProt() & MemProt::Write) == MemProt::Write)
  112. NativeProt |= PROT_WRITE;
  113. if ((Segment.AG.getMemProt() & MemProt::Exec) == MemProt::Exec)
  114. NativeProt |= PROT_EXEC;
  115. if (mprotect(Segment.Addr.toPtr<void *>(), Segment.Size, NativeProt))
  116. return errorCodeToError(std::error_code(errno, std::generic_category()));
  117. #elif defined(_WIN32)
  118. DWORD NativeProt =
  119. getWindowsProtectionFlags(Segment.AG.getMemProt());
  120. if (!VirtualProtect(Segment.Addr.toPtr<void *>(), Segment.Size, NativeProt,
  121. &NativeProt))
  122. return errorCodeToError(mapWindowsError(GetLastError()));
  123. #endif
  124. if ((Segment.AG.getMemProt() & MemProt::Exec) == MemProt::Exec)
  125. sys::Memory::InvalidateInstructionCache(Segment.Addr.toPtr<void *>(),
  126. Segment.Size);
  127. }
  128. // Run finalization actions and get deinitlization action list.
  129. auto DeinitializeActions = shared::runFinalizeActions(FR.Actions);
  130. if (!DeinitializeActions) {
  131. return DeinitializeActions.takeError();
  132. }
  133. {
  134. std::lock_guard<std::mutex> Lock(Mutex);
  135. Allocations[MinAddr].DeinitializationActions =
  136. std::move(*DeinitializeActions);
  137. Reservations[Reservation.toPtr<void *>()].Allocations.push_back(MinAddr);
  138. }
  139. return MinAddr;
  140. #else
  141. return make_error<StringError>(
  142. "SharedMemoryMapper is not supported on this platform yet",
  143. inconvertibleErrorCode());
  144. #endif
  145. }
  146. Error ExecutorSharedMemoryMapperService::deinitialize(
  147. const std::vector<ExecutorAddr> &Bases) {
  148. Error AllErr = Error::success();
  149. {
  150. std::lock_guard<std::mutex> Lock(Mutex);
  151. for (auto Base : llvm::reverse(Bases)) {
  152. if (Error Err = shared::runDeallocActions(
  153. Allocations[Base].DeinitializationActions)) {
  154. AllErr = joinErrors(std::move(AllErr), std::move(Err));
  155. }
  156. // Remove the allocation from the allocation list of its reservation
  157. for (auto &Reservation : Reservations) {
  158. auto AllocationIt =
  159. std::find(Reservation.second.Allocations.begin(),
  160. Reservation.second.Allocations.end(), Base);
  161. if (AllocationIt != Reservation.second.Allocations.end()) {
  162. Reservation.second.Allocations.erase(AllocationIt);
  163. break;
  164. }
  165. }
  166. Allocations.erase(Base);
  167. }
  168. }
  169. return AllErr;
  170. }
  171. Error ExecutorSharedMemoryMapperService::release(
  172. const std::vector<ExecutorAddr> &Bases) {
  173. #if (defined(LLVM_ON_UNIX) && !defined(__ANDROID__)) || defined(_WIN32)
  174. Error Err = Error::success();
  175. for (auto Base : Bases) {
  176. std::vector<ExecutorAddr> AllocAddrs;
  177. size_t Size;
  178. #if defined(_WIN32)
  179. HANDLE SharedMemoryFile;
  180. #endif
  181. {
  182. std::lock_guard<std::mutex> Lock(Mutex);
  183. auto &R = Reservations[Base.toPtr<void *>()];
  184. Size = R.Size;
  185. #if defined(_WIN32)
  186. SharedMemoryFile = R.SharedMemoryFile;
  187. #endif
  188. AllocAddrs.swap(R.Allocations);
  189. }
  190. // deinitialize sub allocations
  191. if (Error E = deinitialize(AllocAddrs))
  192. Err = joinErrors(std::move(Err), std::move(E));
  193. #if defined(LLVM_ON_UNIX)
  194. if (munmap(Base.toPtr<void *>(), Size) != 0)
  195. Err = joinErrors(std::move(Err), errorCodeToError(std::error_code(
  196. errno, std::generic_category())));
  197. #elif defined(_WIN32)
  198. (void)Size;
  199. if (!UnmapViewOfFile(Base.toPtr<void *>()))
  200. Err = joinErrors(std::move(Err),
  201. errorCodeToError(mapWindowsError(GetLastError())));
  202. CloseHandle(SharedMemoryFile);
  203. #endif
  204. std::lock_guard<std::mutex> Lock(Mutex);
  205. Reservations.erase(Base.toPtr<void *>());
  206. }
  207. return Err;
  208. #else
  209. return make_error<StringError>(
  210. "SharedMemoryMapper is not supported on this platform yet",
  211. inconvertibleErrorCode());
  212. #endif
  213. }
  214. Error ExecutorSharedMemoryMapperService::shutdown() {
  215. if (Reservations.empty())
  216. return Error::success();
  217. std::vector<ExecutorAddr> ReservationAddrs;
  218. ReservationAddrs.reserve(Reservations.size());
  219. for (const auto &R : Reservations)
  220. ReservationAddrs.push_back(ExecutorAddr::fromPtr(R.getFirst()));
  221. return release(std::move(ReservationAddrs));
  222. }
  223. void ExecutorSharedMemoryMapperService::addBootstrapSymbols(
  224. StringMap<ExecutorAddr> &M) {
  225. M[rt::ExecutorSharedMemoryMapperServiceInstanceName] =
  226. ExecutorAddr::fromPtr(this);
  227. M[rt::ExecutorSharedMemoryMapperServiceReserveWrapperName] =
  228. ExecutorAddr::fromPtr(&reserveWrapper);
  229. M[rt::ExecutorSharedMemoryMapperServiceInitializeWrapperName] =
  230. ExecutorAddr::fromPtr(&initializeWrapper);
  231. M[rt::ExecutorSharedMemoryMapperServiceDeinitializeWrapperName] =
  232. ExecutorAddr::fromPtr(&deinitializeWrapper);
  233. M[rt::ExecutorSharedMemoryMapperServiceReleaseWrapperName] =
  234. ExecutorAddr::fromPtr(&releaseWrapper);
  235. }
  236. llvm::orc::shared::CWrapperFunctionResult
  237. ExecutorSharedMemoryMapperService::reserveWrapper(const char *ArgData,
  238. size_t ArgSize) {
  239. return shared::WrapperFunction<
  240. rt::SPSExecutorSharedMemoryMapperServiceReserveSignature>::
  241. handle(ArgData, ArgSize,
  242. shared::makeMethodWrapperHandler(
  243. &ExecutorSharedMemoryMapperService::reserve))
  244. .release();
  245. }
  246. llvm::orc::shared::CWrapperFunctionResult
  247. ExecutorSharedMemoryMapperService::initializeWrapper(const char *ArgData,
  248. size_t ArgSize) {
  249. return shared::WrapperFunction<
  250. rt::SPSExecutorSharedMemoryMapperServiceInitializeSignature>::
  251. handle(ArgData, ArgSize,
  252. shared::makeMethodWrapperHandler(
  253. &ExecutorSharedMemoryMapperService::initialize))
  254. .release();
  255. }
  256. llvm::orc::shared::CWrapperFunctionResult
  257. ExecutorSharedMemoryMapperService::deinitializeWrapper(const char *ArgData,
  258. size_t ArgSize) {
  259. return shared::WrapperFunction<
  260. rt::SPSExecutorSharedMemoryMapperServiceDeinitializeSignature>::
  261. handle(ArgData, ArgSize,
  262. shared::makeMethodWrapperHandler(
  263. &ExecutorSharedMemoryMapperService::deinitialize))
  264. .release();
  265. }
  266. llvm::orc::shared::CWrapperFunctionResult
  267. ExecutorSharedMemoryMapperService::releaseWrapper(const char *ArgData,
  268. size_t ArgSize) {
  269. return shared::WrapperFunction<
  270. rt::SPSExecutorSharedMemoryMapperServiceReleaseSignature>::
  271. handle(ArgData, ArgSize,
  272. shared::makeMethodWrapperHandler(
  273. &ExecutorSharedMemoryMapperService::release))
  274. .release();
  275. }
  276. } // namespace rt_bootstrap
  277. } // end namespace orc
  278. } // end namespace llvm