Skip to content

Commit 2df84a9

Browse files
committed
Make codegen memory manager threadsafe
1 parent 3bcbcb1 commit 2df84a9

File tree

1 file changed

+34
-10
lines changed

1 file changed

+34
-10
lines changed

src/cgmemmgr.cpp

Lines changed: 34 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,10 @@
2727
#endif
2828
#include "julia_assert.h"
2929

30+
#include <mutex>
31+
#include <condition_variable>
32+
#include <thread>
33+
3034
namespace {
3135

3236
static size_t get_block_size(size_t size)
@@ -763,8 +767,10 @@ class RTDyldMemoryManagerJL : public SectionMemoryManager {
763767
RWAllocator rw_alloc;
764768
std::unique_ptr<ROAllocator<false>> ro_alloc;
765769
std::unique_ptr<ROAllocator<true>> exe_alloc;
766-
bool code_allocated;
770+
std::thread::id allocating_thread;
767771
size_t total_allocated;
772+
std::mutex mutex;
773+
std::condition_variable freed;
768774

769775
public:
770776
RTDyldMemoryManagerJL()
@@ -773,8 +779,9 @@ class RTDyldMemoryManagerJL : public SectionMemoryManager {
773779
rw_alloc(),
774780
ro_alloc(),
775781
exe_alloc(),
776-
code_allocated(false),
777-
total_allocated(0)
782+
allocating_thread(),
783+
total_allocated(0),
784+
mutex()
778785
{
779786
#ifdef _OS_LINUX_
780787
if (!ro_alloc && get_self_mem_fd() != -1) {
@@ -790,7 +797,10 @@ class RTDyldMemoryManagerJL : public SectionMemoryManager {
790797
~RTDyldMemoryManagerJL() override
791798
{
792799
}
793-
size_t getTotalBytes() { return total_allocated; }
800+
size_t getTotalBytes() {
801+
std::lock_guard<std::mutex> lock(mutex);
802+
return total_allocated;
803+
}
794804
void registerEHFrames(uint8_t *Addr, uint64_t LoadAddr,
795805
size_t Size) override;
796806
#if 0
@@ -811,6 +821,7 @@ class RTDyldMemoryManagerJL : public SectionMemoryManager {
811821
template <typename DL, typename Alloc>
812822
void mapAddresses(DL &Dyld, Alloc &&allocator)
813823
{
824+
std::lock_guard<std::mutex> lock(mutex);
814825
for (auto &alloc: allocator->allocations) {
815826
if (alloc.rt_addr == alloc.wr_addr || alloc.relocated)
816827
continue;
@@ -830,6 +841,7 @@ class RTDyldMemoryManagerJL : public SectionMemoryManager {
830841
template <typename Alloc>
831842
void *lookupWriteAddressFor(void *rt_addr, Alloc &&allocator)
832843
{
844+
std::lock_guard<std::mutex> lock(mutex);
833845
for (auto &alloc: allocator->allocations) {
834846
if (alloc.rt_addr == rt_addr) {
835847
return alloc.wr_addr;
@@ -855,9 +867,13 @@ uint8_t *RTDyldMemoryManagerJL::allocateCodeSection(uintptr_t Size,
855867
unsigned SectionID,
856868
StringRef SectionName)
857869
{
858-
// allocating more than one code section can confuse libunwind.
859-
assert(!code_allocated);
860-
code_allocated = true;
870+
std::unique_lock<std::mutex> lock(mutex);
871+
if (allocating_thread != std::thread::id()) {
872+
assert(allocating_thread != std::this_thread::get_id() && "allocating more than one code section can confuse libunwind!");
873+
//Will deadlock if the above assert is removed
874+
freed.wait(lock, [&](){ return allocating_thread == std::thread::id(); });
875+
}
876+
allocating_thread = std::this_thread::get_id();
861877
total_allocated += Size;
862878
if (exe_alloc)
863879
return (uint8_t*)exe_alloc->alloc(Size, Alignment);
@@ -871,6 +887,7 @@ uint8_t *RTDyldMemoryManagerJL::allocateDataSection(uintptr_t Size,
871887
StringRef SectionName,
872888
bool isReadOnly)
873889
{
890+
std::lock_guard<std::mutex> lock(mutex);
874891
total_allocated += Size;
875892
if (!isReadOnly)
876893
return (uint8_t*)rw_alloc.alloc(Size, Alignment);
@@ -885,6 +902,7 @@ void RTDyldMemoryManagerJL::notifyObjectLoaded(RuntimeDyld &Dyld,
885902
{
886903
if (!ro_alloc) {
887904
assert(!exe_alloc);
905+
std::lock_guard<std::mutex> lock(mutex);
888906
SectionMemoryManager::notifyObjectLoaded(Dyld, Obj);
889907
return;
890908
}
@@ -894,26 +912,31 @@ void RTDyldMemoryManagerJL::notifyObjectLoaded(RuntimeDyld &Dyld,
894912

895913
bool RTDyldMemoryManagerJL::finalizeMemory(std::string *ErrMsg)
896914
{
897-
code_allocated = false;
915+
std::lock_guard<std::mutex> lock(mutex);
916+
bool failure;
917+
allocating_thread = std::thread::id();
898918
if (ro_alloc) {
899919
ro_alloc->finalize();
900920
assert(exe_alloc);
901921
exe_alloc->finalize();
902922
for (auto &frame: pending_eh)
903923
register_eh_frames(frame.addr, frame.size);
904924
pending_eh.clear();
905-
return false;
925+
failure = false;
906926
}
907927
else {
908928
assert(!exe_alloc);
909-
return SectionMemoryManager::finalizeMemory(ErrMsg);
929+
failure = SectionMemoryManager::finalizeMemory(ErrMsg);
910930
}
931+
freed.notify_one();
932+
return failure;
911933
}
912934

913935
void RTDyldMemoryManagerJL::registerEHFrames(uint8_t *Addr,
914936
uint64_t LoadAddr,
915937
size_t Size)
916938
{
939+
std::lock_guard<std::mutex> lock(mutex);
917940
if (uintptr_t(Addr) == LoadAddr) {
918941
register_eh_frames(Addr, Size);
919942
}
@@ -927,6 +950,7 @@ void RTDyldMemoryManagerJL::deregisterEHFrames(uint8_t *Addr,
927950
uint64_t LoadAddr,
928951
size_t Size)
929952
{
953+
std::lock_guard<std::mutex> lock(mutex);
930954
deregister_eh_frames((uint8_t*)LoadAddr, Size);
931955
}
932956
#endif

0 commit comments

Comments
 (0)