2323
2424using namespace llvm ;
2525
26- using llvm_file_magic = file_magic;
27-
2826#include " julia.h"
2927#include " julia_internal.h"
3028#include " debuginfo.h"
@@ -52,11 +50,41 @@ typedef object::SymbolRef SymRef;
5250// and cannot have any interaction with the julia runtime
5351static uv_rwlock_t threadsafe;
5452
55- extern " C" void jl_init_debuginfo ()
53+ extern " C" void jl_init_debuginfo (void )
5654{
5755 uv_rwlock_init (&threadsafe);
5856}
5957
58+ extern " C" void jl_lock_profile (void )
59+ {
60+ uv_rwlock_rdlock (&threadsafe);
61+ }
62+
63+ extern " C" void jl_unlock_profile (void )
64+ {
65+ uv_rwlock_rdunlock (&threadsafe);
66+ }
67+
68+ // some actions aren't signal (especially profiler) safe so we acquire a lock
69+ // around them to establish a mutual exclusion with unwinding from a signal
70+ template <typename T>
71+ static void jl_profile_atomic (T f)
72+ {
73+ uv_rwlock_wrlock (&threadsafe);
74+ #ifndef _OS_WINDOWS_
75+ sigset_t sset;
76+ sigset_t oset;
77+ sigfillset (&sset);
78+ pthread_sigmask (SIG_BLOCK, &sset, &oset);
79+ #endif
80+ f ();
81+ #ifndef _OS_WINDOWS_
82+ pthread_sigmask (SIG_SETMASK, &oset, NULL );
83+ #endif
84+ uv_rwlock_wrunlock (&threadsafe);
85+ }
86+
87+
6088// --- storing and accessing source location metadata ---
6189
6290struct ObjectInfo {
@@ -131,13 +159,15 @@ static void create_PRUNTIME_FUNCTION(uint8_t *Code, size_t Size, StringRef fnnam
131159 JL_UNLOCK_NOGC (&jl_in_stackwalk);
132160 }
133161#if defined(_CPU_X86_64_)
134- if (!RtlAddFunctionTable (tbl, 1 , (DWORD64)Section)) {
135- static int warned = 0 ;
136- if (!warned) {
137- jl_printf (JL_STDERR, " WARNING: failed to insert function stack unwind info: %lu\n " , GetLastError ());
138- warned = 1 ;
162+ jl_profile_atomic ([&]() {
163+ if (!RtlAddFunctionTable (tbl, 1 , (DWORD64)Section)) {
164+ static int warned = 0 ;
165+ if (!warned) {
166+ jl_printf (JL_STDERR, " WARNING: failed to insert function stack unwind info: %lu\n " , GetLastError ());
167+ warned = 1 ;
168+ }
139169 }
140- }
170+ });
141171#endif
142172}
143173#endif
@@ -278,7 +308,9 @@ class JuliaJITEventListener: public JITEventListener
278308 di->u .rti .name_ptr = 0 ;
279309 di->u .rti .table_data = arm_exidx_addr;
280310 di->u .rti .table_len = arm_exidx_len;
281- _U_dyn_register (di);
311+ jl_profile_atomic ([&]() {
312+ _U_dyn_register (di);
313+ });
282314 break ;
283315 }
284316#endif
@@ -404,20 +436,20 @@ class JuliaJITEventListener: public JITEventListener
404436 codeinst = codeinst_it->second ;
405437 codeinst_in_flight.erase (codeinst_it);
406438 }
407- uv_rwlock_wrlock (&threadsafe);
408- if (codeinst)
409- linfomap[Addr] = std::make_pair (Size, codeinst->def );
410- if (first) {
411- ObjectInfo tmp = {&debugObj,
412- (size_t )SectionSize,
413- (ptrdiff_t )(SectionAddr - SectionLoadAddr),
414- *Section,
415- nullptr ,
416- };
417- objectmap[SectionLoadAddr] = tmp;
418- first = false ;
419- }
420- uv_rwlock_wrunlock (&threadsafe );
439+ jl_profile_atomic ([&]() {
440+ if (codeinst)
441+ linfomap[Addr] = std::make_pair (Size, codeinst->def );
442+ if (first) {
443+ ObjectInfo tmp = {&debugObj,
444+ (size_t )SectionSize,
445+ (ptrdiff_t )(SectionAddr - SectionLoadAddr),
446+ *Section,
447+ nullptr ,
448+ };
449+ objectmap[SectionLoadAddr] = tmp;
450+ first = false ;
451+ }
452+ } );
421453 }
422454 jl_gc_safe_leave (ptls, gc_state);
423455 }
@@ -431,14 +463,6 @@ class JuliaJITEventListener: public JITEventListener
431463 uv_rwlock_rdlock (&threadsafe);
432464 return objectmap;
433465 }
434-
435- Optional<std::map<size_t , ObjectInfo, revcomp>*> trygetObjectMap ()
436- {
437- if (0 == uv_rwlock_tryrdlock (&threadsafe)) {
438- return &objectmap;
439- }
440- return {};
441- }
442466};
443467
444468JL_DLLEXPORT void ORCNotifyObjectEmitted (JITEventListener *Listener,
@@ -482,7 +506,7 @@ static std::pair<char *, bool> jl_demangle(const char *name) JL_NOTSAFEPOINT
482506}
483507
484508static JuliaJITEventListener *jl_jit_events;
485- JITEventListener *CreateJuliaJITEventListener ()
509+ JITEventListener *CreateJuliaJITEventListener (void )
486510{
487511 jl_jit_events = new JuliaJITEventListener ();
488512 return jl_jit_events;
@@ -722,7 +746,7 @@ openDebugInfo(StringRef debuginfopath, const debug_link_info &info)
722746
723747 auto error_splitobj = object::ObjectFile::createObjectFile (
724748 SplitFile.get ().get ()->getMemBufferRef (),
725- llvm_file_magic ::unknown);
749+ file_magic ::unknown);
726750 if (!error_splitobj) {
727751 return error_splitobj.takeError ();
728752 }
@@ -873,7 +897,7 @@ static objfileentry_t &find_object_file(uint64_t fbase, StringRef fname) JL_NOTS
873897 std::unique_ptr<MemoryBuffer> membuf = MemoryBuffer::getMemBuffer (
874898 StringRef ((const char *)fbase, msize), " " , false );
875899 auto origerrorobj = llvm::object::ObjectFile::createObjectFile (
876- membuf->getMemBufferRef (), llvm_file_magic ::unknown);
900+ membuf->getMemBufferRef (), file_magic ::unknown);
877901 if (!origerrorobj)
878902 return entry;
879903
@@ -1292,28 +1316,33 @@ void register_eh_frames(uint8_t *Addr, size_t Size)
12921316 // See http://lists.cs.uiuc.edu/pipermail/llvmdev/2013-April/061768.html
12931317 processFDEs ((char *)Addr, Size, [](const char *Entry) {
12941318 if (!libc_register_frame) {
1295- libc_register_frame = (void (*)(void *))dlsym (RTLD_NEXT," __register_frame" );
1319+ libc_register_frame = (void (*)(void *))dlsym (RTLD_NEXT, " __register_frame" );
12961320 }
12971321 assert (libc_register_frame);
1298- libc_register_frame (const_cast <char *>(Entry));
1299- __register_frame (const_cast <char *>(Entry));
1322+ jl_profile_atomic ([&]() {
1323+ libc_register_frame (const_cast <char *>(Entry));
1324+ __register_frame (const_cast <char *>(Entry));
1325+ });
13001326 });
13011327}
13021328
13031329void deregister_eh_frames (uint8_t *Addr, size_t Size)
13041330{
13051331 processFDEs ((char *)Addr, Size, [](const char *Entry) {
13061332 if (!libc_deregister_frame) {
1307- libc_deregister_frame = (void (*)(void *))dlsym (RTLD_NEXT," __deregister_frame" );
1333+ libc_deregister_frame = (void (*)(void *))dlsym (RTLD_NEXT, " __deregister_frame" );
13081334 }
13091335 assert (libc_deregister_frame);
1310- libc_deregister_frame (const_cast <char *>(Entry));
1311- __deregister_frame (const_cast <char *>(Entry));
1336+ jl_profile_atomic ([&]() {
1337+ libc_deregister_frame (const_cast <char *>(Entry));
1338+ __deregister_frame (const_cast <char *>(Entry));
1339+ });
13121340 });
13131341}
13141342
13151343#elif defined(_OS_LINUX_) && \
1316- defined (JL_UNW_HAS_FORMAT_IP) && !defined(_CPU_ARM_)
1344+ defined (JL_UNW_HAS_FORMAT_IP) && \
1345+ !defined(_CPU_ARM_) // ARM does not have/use .eh_frame, so we handle this elsewhere
13171346#include < type_traits>
13181347
13191348struct unw_table_entry
@@ -1499,7 +1528,9 @@ static DW_EH_PE parseCIE(const uint8_t *Addr, const uint8_t *End)
14991528void register_eh_frames (uint8_t *Addr, size_t Size)
15001529{
15011530 // System unwinder
1502- __register_frame (Addr);
1531+ jl_profile_atomic ([&]() {
1532+ __register_frame (Addr);
1533+ });
15031534 // Our unwinder
15041535 unw_dyn_info_t *di = new unw_dyn_info_t ;
15051536 // In a shared library, this is set to the address of the PLT.
@@ -1610,7 +1641,7 @@ void register_eh_frames(uint8_t *Addr, size_t Size)
16101641 start_ips[cur_entry] = start;
16111642 cur_entry++;
16121643 });
1613- for (size_t i = 0 ;i < nentries;i++) {
1644+ for (size_t i = 0 ; i < nentries; i++) {
16141645 table[i].start_ip_offset =
16151646 safe_trunc<int32_t >((intptr_t )start_ips[i] - (intptr_t )start_ip);
16161647 }
@@ -1621,27 +1652,21 @@ void register_eh_frames(uint8_t *Addr, size_t Size)
16211652 di->start_ip = start_ip;
16221653 di->end_ip = end_ip;
16231654
1624- _U_dyn_register (di);
1655+ jl_profile_atomic ([&]() {
1656+ _U_dyn_register (di);
1657+ });
16251658}
16261659
16271660void deregister_eh_frames (uint8_t *Addr, size_t Size)
16281661{
1629- __deregister_frame (Addr);
1630- // Deregistering with our unwinder requires a lookup table to find the
1631- // the allocated entry above (or we could look in libunwind's internal
1662+ jl_profile_atomic ([&]() {
1663+ __deregister_frame (Addr);
1664+ });
1665+ // Deregistering with our unwinder (_U_dyn_cancel) requires a lookup table
1666+ // to find the allocated entry above (or looking into libunwind's internal
16321667 // data structures).
16331668}
16341669
1635- #elif defined(_CPU_ARM_)
1636-
1637- void register_eh_frames (uint8_t *Addr, size_t Size)
1638- {
1639- }
1640-
1641- void deregister_eh_frames (uint8_t *Addr, size_t Size)
1642- {
1643- }
1644-
16451670#else
16461671
16471672void register_eh_frames (uint8_t *Addr, size_t Size)
@@ -1667,22 +1692,3 @@ uint64_t jl_getUnwindInfo(uint64_t dwAddr)
16671692 uv_rwlock_rdunlock (&threadsafe);
16681693 return ipstart;
16691694}
1670-
1671- extern " C"
1672- uint64_t jl_trygetUnwindInfo (uint64_t dwAddr)
1673- {
1674- // Might be called from unmanaged thread
1675- Optional<std::map<size_t , ObjectInfo, revcomp>*> maybeobjmap = jl_jit_events->trygetObjectMap ();
1676- if (maybeobjmap) {
1677- std::map<size_t , ObjectInfo, revcomp> &objmap = **maybeobjmap;
1678- std::map<size_t , ObjectInfo, revcomp>::iterator it = objmap.lower_bound (dwAddr);
1679- uint64_t ipstart = 0 ; // ip of the start of the section (if found)
1680- if (it != objmap.end () && dwAddr < it->first + it->second .SectionSize ) {
1681- ipstart = (uint64_t )(uintptr_t )(*it).first ;
1682- }
1683- uv_rwlock_rdunlock (&threadsafe);
1684- return ipstart;
1685- }
1686- return 0 ;
1687- }
1688-
0 commit comments