88#include "julia_internal.h"
99#include "julia_assert.h"
1010
11+ #ifdef _COMPILER_TSAN_ENABLED_
12+ #include <sanitizer/tsan_interface.h>
13+ #endif
14+
1115#ifdef USE_ITTAPI
1216#include "ittapi/ittnotify.h"
1317#endif
@@ -931,7 +935,16 @@ void _jl_mutex_init(jl_mutex_t *lock, const char *name) JL_NOTSAFEPOINT
931935{
932936 jl_atomic_store_relaxed (& lock -> owner , (jl_task_t * )NULL );
933937 lock -> count = 0 ;
938+ #if defined(_COMPILER_TSAN_ENABLED_ ) && defined(ENABLE_TIMINGS )
939+ __tsan_mutex_pre_divert (lock , 0 );
940+ #endif
934941 jl_profile_lock_init (lock , name );
942+ #ifdef _COMPILER_TSAN_ENABLED_
943+ #ifdef ENABLE_TIMINGS
944+ __tsan_mutex_post_divert (lock , 0 );
945+ #endif
946+ __tsan_mutex_create (lock , __tsan_mutex_write_reentrant );
947+ #endif
935948}
936949
937950void _jl_mutex_wait (jl_task_t * self , jl_mutex_t * lock , int safepoint )
@@ -941,18 +954,27 @@ void _jl_mutex_wait(jl_task_t *self, jl_mutex_t *lock, int safepoint)
941954 lock -> count ++ ;
942955 return ;
943956 }
957+ #ifdef _COMPILER_TSAN_ENABLED_
958+ __tsan_mutex_pre_divert (lock , 0 );
959+ #endif
944960 // Don't use JL_TIMING for instant acquires, results in large blowup of events
945961 jl_profile_lock_start_wait (lock );
946962 if (owner == NULL && jl_atomic_cmpswap (& lock -> owner , & owner , self )) {
947963 lock -> count = 1 ;
948964 jl_profile_lock_acquired (lock );
965+ #ifdef _COMPILER_TSAN_ENABLED_
966+ __tsan_mutex_post_divert (lock , 0 );
967+ #endif
949968 return ;
950969 }
951970 JL_TIMING (LOCK_SPIN , LOCK_SPIN );
952971 while (1 ) {
953972 if (owner == NULL && jl_atomic_cmpswap (& lock -> owner , & owner , self )) {
954973 lock -> count = 1 ;
955974 jl_profile_lock_acquired (lock );
975+ #ifdef _COMPILER_TSAN_ENABLED_
976+ __tsan_mutex_post_divert (lock , 0 );
977+ #endif
956978 return ;
957979 }
958980 if (jl_running_under_rr (0 )) {
@@ -973,6 +995,9 @@ void _jl_mutex_wait(jl_task_t *self, jl_mutex_t *lock, int safepoint)
973995 jl_cpu_suspend ();
974996 owner = jl_atomic_load_relaxed (& lock -> owner );
975997 }
998+ #ifdef _COMPILER_TSAN_ENABLED_
999+ __tsan_mutex_post_divert (lock , 0 );
1000+ #endif
9761001}
9771002
9781003static void jl_lock_frame_push (jl_task_t * self , jl_mutex_t * lock )
@@ -998,23 +1023,43 @@ static void jl_lock_frame_pop(jl_task_t *self)
9981023
9991024void _jl_mutex_lock (jl_task_t * self , jl_mutex_t * lock )
10001025{
1026+ #ifdef _COMPILER_TSAN_ENABLED_
1027+ __tsan_mutex_pre_lock (lock , __tsan_mutex_write_reentrant );
1028+ #endif
10011029 JL_SIGATOMIC_BEGIN_self ();
10021030 _jl_mutex_wait (self , lock , 1 );
10031031 jl_lock_frame_push (self , lock );
1032+ #ifdef _COMPILER_TSAN_ENABLED_
1033+ __tsan_mutex_post_lock (lock , __tsan_mutex_write_reentrant , 1 );
1034+ #endif
10041035}
10051036
10061037int _jl_mutex_trylock_nogc (jl_task_t * self , jl_mutex_t * lock )
10071038{
1039+ #ifdef _COMPILER_TSAN_ENABLED_
1040+ __tsan_mutex_pre_lock (lock , __tsan_mutex_try_lock | __tsan_mutex_write_reentrant );
1041+ #endif
10081042 jl_task_t * owner = jl_atomic_load_acquire (& lock -> owner );
1043+ int ret = 0 ;
10091044 if (owner == self ) {
10101045 lock -> count ++ ;
1011- return 1 ;
1046+ ret = 1 ;
1047+ goto done ;
10121048 }
10131049 if (owner == NULL && jl_atomic_cmpswap (& lock -> owner , & owner , self )) {
10141050 lock -> count = 1 ;
1015- return 1 ;
1051+ ret = 1 ;
1052+ goto done ;
10161053 }
1017- return 0 ;
1054+ done :
1055+ #ifdef _COMPILER_TSAN_ENABLED_
1056+ __tsan_mutex_post_lock (lock ,
1057+ __tsan_mutex_try_lock |
1058+ (ret ? 0 : __tsan_mutex_try_lock_failed ) |
1059+ __tsan_mutex_write_reentrant ,
1060+ 1 );
1061+ #endif
1062+ return ret ;
10181063}
10191064
10201065int _jl_mutex_trylock (jl_task_t * self , jl_mutex_t * lock )
@@ -1030,6 +1075,9 @@ int _jl_mutex_trylock(jl_task_t *self, jl_mutex_t *lock)
10301075void _jl_mutex_unlock_nogc (jl_mutex_t * lock )
10311076{
10321077#ifndef __clang_gcanalyzer__
1078+ #ifdef _COMPILER_TSAN_ENABLED_
1079+ __tsan_mutex_pre_unlock (lock , 0 );
1080+ #endif
10331081 assert (jl_atomic_load_relaxed (& lock -> owner ) == jl_current_task &&
10341082 "Unlocking a lock in a different thread." );
10351083 if (-- lock -> count == 0 ) {
@@ -1044,6 +1092,9 @@ void _jl_mutex_unlock_nogc(jl_mutex_t *lock)
10441092 }
10451093 jl_profile_lock_release_end (lock );
10461094 }
1095+ #ifdef _COMPILER_TSAN_ENABLED_
1096+ __tsan_mutex_post_unlock (lock , 0 );
1097+ #endif
10471098#endif
10481099}
10491100
0 commit comments