@@ -48,29 +48,43 @@ typedef object::SymbolRef SymRef;
48
48
// while holding this lock.
49
49
// Certain functions in this file might be called from an unmanaged thread
50
50
// and cannot have any interaction with the julia runtime
51
- static uv_rwlock_t threadsafe;
51
+ // They also may be re-entrant, and operating while threads are paused, so we
52
+ // separately manage the re-entrant count behavior for safety across platforms
53
+ // Note that we cannot safely upgrade read->write
54
+ static uv_rwlock_t debuginfo_asyncsafe;
55
+ static pthread_key_t debuginfo_asyncsafe_held;
52
56
53
57
extern " C" void jl_init_debuginfo (void )
54
58
{
55
- uv_rwlock_init (&threadsafe);
59
+ uv_rwlock_init (&debuginfo_asyncsafe);
60
+ if (pthread_key_create (&debuginfo_asyncsafe_held, NULL ))
61
+ jl_error (" fatal: pthread_key_create failed" );
56
62
}
57
63
58
64
extern " C" void jl_lock_profile (void )
59
65
{
60
- uv_rwlock_rdlock (&threadsafe);
66
+ uintptr_t held = (uintptr_t )pthread_getspecific (debuginfo_asyncsafe_held);
67
+ if (held++ == 0 )
68
+ uv_rwlock_rdlock (&debuginfo_asyncsafe);
69
+ pthread_setspecific (debuginfo_asyncsafe_held, (void *)held);
61
70
}
62
71
63
72
extern " C" void jl_unlock_profile (void )
64
73
{
65
- uv_rwlock_rdunlock (&threadsafe);
74
+ uintptr_t held = (uintptr_t )pthread_getspecific (debuginfo_asyncsafe_held);
75
+ assert (held);
76
+ if (--held == 0 )
77
+ uv_rwlock_rdunlock (&debuginfo_asyncsafe);
78
+ pthread_setspecific (debuginfo_asyncsafe_held, (void *)held);
66
79
}
67
80
68
81
// some actions aren't signal (especially profiler) safe so we acquire a lock
69
82
// around them to establish a mutual exclusion with unwinding from a signal
70
83
template <typename T>
71
84
static void jl_profile_atomic (T f)
72
85
{
73
- uv_rwlock_wrlock (&threadsafe);
86
+ assert (0 == (uintptr_t )pthread_getspecific (debuginfo_asyncsafe_held));
87
+ uv_rwlock_wrlock (&debuginfo_asyncsafe);
74
88
#ifndef _OS_WINDOWS_
75
89
sigset_t sset;
76
90
sigset_t oset;
@@ -81,7 +95,7 @@ static void jl_profile_atomic(T f)
81
95
#ifndef _OS_WINDOWS_
82
96
pthread_sigmask (SIG_SETMASK, &oset, NULL );
83
97
#endif
84
- uv_rwlock_wrunlock (&threadsafe );
98
+ uv_rwlock_wrunlock (&debuginfo_asyncsafe );
85
99
}
86
100
87
101
@@ -197,12 +211,12 @@ class JuliaJITEventListener: public JITEventListener
197
211
198
212
jl_method_instance_t *lookupLinfo (size_t pointer) JL_NOTSAFEPOINT
199
213
{
200
- uv_rwlock_rdlock (&threadsafe );
214
+ jl_lock_profile ( );
201
215
auto region = linfomap.lower_bound (pointer);
202
216
jl_method_instance_t *linfo = NULL ;
203
217
if (region != linfomap.end () && pointer < region->first + region->second .first )
204
218
linfo = region->second .second ;
205
- uv_rwlock_rdunlock (&threadsafe );
219
+ jl_unlock_profile ( );
206
220
return linfo;
207
221
}
208
222
@@ -525,9 +539,10 @@ static int lookup_pointer(
525
539
526
540
// DWARFContext/DWARFUnit update some internal tables during these queries, so
527
541
// a lock is needed.
528
- uv_rwlock_wrlock (&threadsafe);
542
+ assert (0 == (uintptr_t )pthread_getspecific (debuginfo_asyncsafe_held));
543
+ uv_rwlock_wrlock (&debuginfo_asyncsafe);
529
544
auto inlineInfo = context->getInliningInfoForAddress (makeAddress (Section, pointer + slide), infoSpec);
530
- uv_rwlock_wrunlock (&threadsafe );
545
+ uv_rwlock_wrunlock (&debuginfo_asyncsafe );
531
546
532
547
int fromC = (*frames)[0 ].fromC ;
533
548
int n_frames = inlineInfo.getNumberOfFrames ();
@@ -550,9 +565,9 @@ static int lookup_pointer(
550
565
info = inlineInfo.getFrame (i);
551
566
}
552
567
else {
553
- uv_rwlock_wrlock (&threadsafe );
568
+ uv_rwlock_wrlock (&debuginfo_asyncsafe );
554
569
info = context->getLineInfoForAddress (makeAddress (Section, pointer + slide), infoSpec);
555
- uv_rwlock_wrunlock (&threadsafe );
570
+ uv_rwlock_wrunlock (&debuginfo_asyncsafe );
556
571
}
557
572
558
573
jl_frame_t *frame = &(*frames)[i];
@@ -1208,7 +1223,8 @@ int jl_DI_for_fptr(uint64_t fptr, uint64_t *symsize, int64_t *slide,
1208
1223
object::SectionRef *Section, llvm::DIContext **context) JL_NOTSAFEPOINT
1209
1224
{
1210
1225
int found = 0 ;
1211
- uv_rwlock_wrlock (&threadsafe);
1226
+ assert (0 == (uintptr_t )pthread_getspecific (debuginfo_asyncsafe_held));
1227
+ uv_rwlock_wrlock (&debuginfo_asyncsafe);
1212
1228
std::map<size_t , ObjectInfo, revcomp> &objmap = jl_jit_events->getObjectMap ();
1213
1229
std::map<size_t , ObjectInfo, revcomp>::iterator fit = objmap.lower_bound (fptr);
1214
1230
@@ -1224,7 +1240,7 @@ int jl_DI_for_fptr(uint64_t fptr, uint64_t *symsize, int64_t *slide,
1224
1240
}
1225
1241
found = 1 ;
1226
1242
}
1227
- uv_rwlock_wrunlock (&threadsafe );
1243
+ uv_rwlock_wrunlock (&debuginfo_asyncsafe );
1228
1244
return found;
1229
1245
}
1230
1246
@@ -1669,13 +1685,13 @@ extern "C"
1669
1685
uint64_t jl_getUnwindInfo (uint64_t dwAddr)
1670
1686
{
1671
1687
// Might be called from unmanaged thread
1672
- uv_rwlock_rdlock (&threadsafe );
1688
+ jl_lock_profile ( );
1673
1689
std::map<size_t , ObjectInfo, revcomp> &objmap = jl_jit_events->getObjectMap ();
1674
1690
std::map<size_t , ObjectInfo, revcomp>::iterator it = objmap.lower_bound (dwAddr);
1675
1691
uint64_t ipstart = 0 ; // ip of the start of the section (if found)
1676
1692
if (it != objmap.end () && dwAddr < it->first + it->second .SectionSize ) {
1677
1693
ipstart = (uint64_t )(uintptr_t )(*it).first ;
1678
1694
}
1679
- uv_rwlock_rdunlock (&threadsafe );
1695
+ jl_unlock_profile ( );
1680
1696
return ipstart;
1681
1697
}
0 commit comments