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"
@@ -55,11 +53,41 @@ typedef object::SymbolRef SymRef;
5553// and cannot have any interaction with the julia runtime
5654static uv_rwlock_t threadsafe;
5755
58- extern " C" void jl_init_debuginfo ()
56+ extern " C" void jl_init_debuginfo (void )
5957{
6058 uv_rwlock_init (&threadsafe);
6159}
6260
61+ extern " C" void jl_lock_profile (void )
62+ {
63+ uv_rwlock_rdlock (&threadsafe);
64+ }
65+
66+ extern " C" void jl_unlock_profile (void )
67+ {
68+ uv_rwlock_rdunlock (&threadsafe);
69+ }
70+
71+ // some actions aren't signal (especially profiler) safe so we acquire a lock
72+ // around them to establish a mutual exclusion with unwinding from a signal
73+ template <typename T>
74+ static void jl_profile_atomic (T f)
75+ {
76+ uv_rwlock_wrlock (&threadsafe);
77+ #ifndef _OS_WINDOWS_
78+ sigset_t sset;
79+ sigset_t oset;
80+ sigfillset (&sset);
81+ pthread_sigmask (SIG_BLOCK, &sset, &oset);
82+ #endif
83+ f ();
84+ #ifndef _OS_WINDOWS_
85+ pthread_sigmask (SIG_SETMASK, &oset, NULL );
86+ #endif
87+ uv_rwlock_wrunlock (&threadsafe);
88+ }
89+
90+
6391// --- storing and accessing source location metadata ---
6492
6593struct ObjectInfo {
@@ -135,13 +163,15 @@ static void create_PRUNTIME_FUNCTION(uint8_t *Code, size_t Size, StringRef fnnam
135163 jl_in_stackwalk = 0 ;
136164 }
137165#if defined(_CPU_X86_64_)
138- if (!RtlAddFunctionTable (tbl, 1 , (DWORD64)Section)) {
139- static int warned = 0 ;
140- if (!warned) {
141- jl_printf (JL_STDERR, " WARNING: failed to insert function stack unwind info: %lu\n " , GetLastError ());
142- warned = 1 ;
166+ jl_profile_atomic ([&]() {
167+ if (!RtlAddFunctionTable (tbl, 1 , (DWORD64)Section)) {
168+ static int warned = 0 ;
169+ if (!warned) {
170+ jl_printf (JL_STDERR, " WARNING: failed to insert function stack unwind info: %lu\n " , GetLastError ());
171+ warned = 1 ;
172+ }
143173 }
144- }
174+ });
145175#endif
146176}
147177#endif
@@ -279,7 +309,9 @@ class JuliaJITEventListener: public JITEventListener
279309 di->u .rti .name_ptr = 0 ;
280310 di->u .rti .table_data = arm_exidx_addr;
281311 di->u .rti .table_len = arm_exidx_len;
282- _U_dyn_register (di);
312+ jl_profile_atomic ([&]() {
313+ _U_dyn_register (di);
314+ });
283315 break ;
284316 }
285317#endif
@@ -405,20 +437,20 @@ class JuliaJITEventListener: public JITEventListener
405437 codeinst = codeinst_it->second ;
406438 codeinst_in_flight.erase (codeinst_it);
407439 }
408- uv_rwlock_wrlock (&threadsafe);
409- if (codeinst)
410- linfomap[Addr] = std::make_pair (Size, codeinst->def );
411- if (first) {
412- ObjectInfo tmp = {&debugObj,
413- (size_t )SectionSize,
414- (ptrdiff_t )(SectionAddr - SectionLoadAddr),
415- *Section,
416- nullptr ,
417- };
418- objectmap[SectionLoadAddr] = tmp;
419- first = false ;
420- }
421- uv_rwlock_wrunlock (&threadsafe );
440+ jl_profile_atomic ([&]() {
441+ if (codeinst)
442+ linfomap[Addr] = std::make_pair (Size, codeinst->def );
443+ if (first) {
444+ ObjectInfo tmp = {&debugObj,
445+ (size_t )SectionSize,
446+ (ptrdiff_t )(SectionAddr - SectionLoadAddr),
447+ *Section,
448+ nullptr ,
449+ };
450+ objectmap[SectionLoadAddr] = tmp;
451+ first = false ;
452+ }
453+ } );
422454 }
423455 jl_gc_safe_leave (ptls, gc_state);
424456 }
@@ -432,14 +464,6 @@ class JuliaJITEventListener: public JITEventListener
432464 uv_rwlock_rdlock (&threadsafe);
433465 return objectmap;
434466 }
435-
436- Optional<std::map<size_t , ObjectInfo, revcomp>*> trygetObjectMap ()
437- {
438- if (0 == uv_rwlock_tryrdlock (&threadsafe)) {
439- return &objectmap;
440- }
441- return {};
442- }
443467};
444468
445469JL_DLLEXPORT void ORCNotifyObjectEmitted (JITEventListener *Listener,
@@ -483,7 +507,7 @@ static std::pair<char *, bool> jl_demangle(const char *name) JL_NOTSAFEPOINT
483507}
484508
485509static JuliaJITEventListener *jl_jit_events;
486- JITEventListener *CreateJuliaJITEventListener ()
510+ JITEventListener *CreateJuliaJITEventListener (void )
487511{
488512 jl_jit_events = new JuliaJITEventListener ();
489513 return jl_jit_events;
@@ -723,7 +747,7 @@ openDebugInfo(StringRef debuginfopath, const debug_link_info &info)
723747
724748 auto error_splitobj = object::ObjectFile::createObjectFile (
725749 SplitFile.get ().get ()->getMemBufferRef (),
726- llvm_file_magic ::unknown);
750+ file_magic ::unknown);
727751 if (!error_splitobj) {
728752 return error_splitobj.takeError ();
729753 }
@@ -874,7 +898,7 @@ static objfileentry_t &find_object_file(uint64_t fbase, StringRef fname) JL_NOTS
874898 std::unique_ptr<MemoryBuffer> membuf = MemoryBuffer::getMemBuffer (
875899 StringRef ((const char *)fbase, msize), " " , false );
876900 auto origerrorobj = llvm::object::ObjectFile::createObjectFile (
877- membuf->getMemBufferRef (), llvm_file_magic ::unknown);
901+ membuf->getMemBufferRef (), file_magic ::unknown);
878902 if (!origerrorobj)
879903 return entry;
880904
@@ -1295,28 +1319,33 @@ void register_eh_frames(uint8_t *Addr, size_t Size)
12951319 // See http://lists.cs.uiuc.edu/pipermail/llvmdev/2013-April/061768.html
12961320 processFDEs ((char *)Addr, Size, [](const char *Entry) {
12971321 if (!libc_register_frame) {
1298- libc_register_frame = (void (*)(void *))dlsym (RTLD_NEXT," __register_frame" );
1322+ libc_register_frame = (void (*)(void *))dlsym (RTLD_NEXT, " __register_frame" );
12991323 }
13001324 assert (libc_register_frame);
1301- libc_register_frame (const_cast <char *>(Entry));
1302- __register_frame (const_cast <char *>(Entry));
1325+ jl_profile_atomic ([&]() {
1326+ libc_register_frame (const_cast <char *>(Entry));
1327+ __register_frame (const_cast <char *>(Entry));
1328+ });
13031329 });
13041330}
13051331
13061332void deregister_eh_frames (uint8_t *Addr, size_t Size)
13071333{
13081334 processFDEs ((char *)Addr, Size, [](const char *Entry) {
13091335 if (!libc_deregister_frame) {
1310- libc_deregister_frame = (void (*)(void *))dlsym (RTLD_NEXT," __deregister_frame" );
1336+ libc_deregister_frame = (void (*)(void *))dlsym (RTLD_NEXT, " __deregister_frame" );
13111337 }
13121338 assert (libc_deregister_frame);
1313- libc_deregister_frame (const_cast <char *>(Entry));
1314- __deregister_frame (const_cast <char *>(Entry));
1339+ jl_profile_atomic ([&]() {
1340+ libc_deregister_frame (const_cast <char *>(Entry));
1341+ __deregister_frame (const_cast <char *>(Entry));
1342+ });
13151343 });
13161344}
13171345
13181346#elif defined(_OS_LINUX_) && \
1319- defined (JL_UNW_HAS_FORMAT_IP) && !defined(_CPU_ARM_)
1347+ defined (JL_UNW_HAS_FORMAT_IP) && \
1348+ !defined(_CPU_ARM_) // ARM does not have/use .eh_frame, so we handle this elsewhere
13201349#include < type_traits>
13211350
13221351struct unw_table_entry
@@ -1502,7 +1531,9 @@ static DW_EH_PE parseCIE(const uint8_t *Addr, const uint8_t *End)
15021531void register_eh_frames (uint8_t *Addr, size_t Size)
15031532{
15041533 // System unwinder
1505- __register_frame (Addr);
1534+ jl_profile_atomic ([&]() {
1535+ __register_frame (Addr);
1536+ });
15061537 // Our unwinder
15071538 unw_dyn_info_t *di = new unw_dyn_info_t ;
15081539 // In a shared library, this is set to the address of the PLT.
@@ -1613,7 +1644,7 @@ void register_eh_frames(uint8_t *Addr, size_t Size)
16131644 start_ips[cur_entry] = start;
16141645 cur_entry++;
16151646 });
1616- for (size_t i = 0 ;i < nentries;i++) {
1647+ for (size_t i = 0 ; i < nentries; i++) {
16171648 table[i].start_ip_offset =
16181649 safe_trunc<int32_t >((intptr_t )start_ips[i] - (intptr_t )start_ip);
16191650 }
@@ -1624,27 +1655,21 @@ void register_eh_frames(uint8_t *Addr, size_t Size)
16241655 di->start_ip = start_ip;
16251656 di->end_ip = end_ip;
16261657
1627- _U_dyn_register (di);
1658+ jl_profile_atomic ([&]() {
1659+ _U_dyn_register (di);
1660+ });
16281661}
16291662
16301663void deregister_eh_frames (uint8_t *Addr, size_t Size)
16311664{
1632- __deregister_frame (Addr);
1633- // Deregistering with our unwinder requires a lookup table to find the
1634- // the allocated entry above (or we could look in libunwind's internal
1665+ jl_profile_atomic ([&]() {
1666+ __deregister_frame (Addr);
1667+ });
1668+ // Deregistering with our unwinder (_U_dyn_cancel) requires a lookup table
1669+ // to find the allocated entry above (or looking into libunwind's internal
16351670 // data structures).
16361671}
16371672
1638- #elif defined(_CPU_ARM_)
1639-
1640- void register_eh_frames (uint8_t *Addr, size_t Size)
1641- {
1642- }
1643-
1644- void deregister_eh_frames (uint8_t *Addr, size_t Size)
1645- {
1646- }
1647-
16481673#else
16491674
16501675void register_eh_frames (uint8_t *Addr, size_t Size)
@@ -1670,22 +1695,3 @@ uint64_t jl_getUnwindInfo(uint64_t dwAddr)
16701695 uv_rwlock_rdunlock (&threadsafe);
16711696 return ipstart;
16721697}
1673-
1674- extern " C"
1675- uint64_t jl_trygetUnwindInfo (uint64_t dwAddr)
1676- {
1677- // Might be called from unmanaged thread
1678- Optional<std::map<size_t , ObjectInfo, revcomp>*> maybeobjmap = jl_jit_events->trygetObjectMap ();
1679- if (maybeobjmap) {
1680- std::map<size_t , ObjectInfo, revcomp> &objmap = **maybeobjmap;
1681- std::map<size_t , ObjectInfo, revcomp>::iterator it = objmap.lower_bound (dwAddr);
1682- uint64_t ipstart = 0 ; // ip of the start of the section (if found)
1683- if (it != objmap.end () && dwAddr < it->first + it->second .SectionSize ) {
1684- ipstart = (uint64_t )(uintptr_t )(*it).first ;
1685- }
1686- uv_rwlock_rdunlock (&threadsafe);
1687- return ipstart;
1688- }
1689- return 0 ;
1690- }
1691-
0 commit comments