8
8
#include "julia_internal.h"
9
9
#include "julia_assert.h"
10
10
11
+ #ifdef _COMPILER_TSAN_ENABLED_
12
+ #include <sanitizer/tsan_interface.h>
13
+ #endif
14
+
11
15
#ifdef USE_ITTAPI
12
16
#include "ittapi/ittnotify.h"
13
17
#endif
@@ -931,7 +935,16 @@ void _jl_mutex_init(jl_mutex_t *lock, const char *name) JL_NOTSAFEPOINT
931
935
{
932
936
jl_atomic_store_relaxed (& lock -> owner , (jl_task_t * )NULL );
933
937
lock -> count = 0 ;
938
+ #if defined(_COMPILER_TSAN_ENABLED_ ) && defined(ENABLE_TIMINGS )
939
+ __tsan_mutex_pre_divert (lock , 0 );
940
+ #endif
934
941
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
935
948
}
936
949
937
950
void _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)
941
954
lock -> count ++ ;
942
955
return ;
943
956
}
957
+ #ifdef _COMPILER_TSAN_ENABLED_
958
+ __tsan_mutex_pre_divert (lock , 0 );
959
+ #endif
944
960
// Don't use JL_TIMING for instant acquires, results in large blowup of events
945
961
jl_profile_lock_start_wait (lock );
946
962
if (owner == NULL && jl_atomic_cmpswap (& lock -> owner , & owner , self )) {
947
963
lock -> count = 1 ;
948
964
jl_profile_lock_acquired (lock );
965
+ #ifdef _COMPILER_TSAN_ENABLED_
966
+ __tsan_mutex_post_divert (lock , 0 );
967
+ #endif
949
968
return ;
950
969
}
951
970
JL_TIMING (LOCK_SPIN , LOCK_SPIN );
952
971
while (1 ) {
953
972
if (owner == NULL && jl_atomic_cmpswap (& lock -> owner , & owner , self )) {
954
973
lock -> count = 1 ;
955
974
jl_profile_lock_acquired (lock );
975
+ #ifdef _COMPILER_TSAN_ENABLED_
976
+ __tsan_mutex_post_divert (lock , 0 );
977
+ #endif
956
978
return ;
957
979
}
958
980
if (jl_running_under_rr (0 )) {
@@ -973,6 +995,9 @@ void _jl_mutex_wait(jl_task_t *self, jl_mutex_t *lock, int safepoint)
973
995
jl_cpu_suspend ();
974
996
owner = jl_atomic_load_relaxed (& lock -> owner );
975
997
}
998
+ #ifdef _COMPILER_TSAN_ENABLED_
999
+ __tsan_mutex_post_divert (lock , 0 );
1000
+ #endif
976
1001
}
977
1002
978
1003
static 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)
998
1023
999
1024
void _jl_mutex_lock (jl_task_t * self , jl_mutex_t * lock )
1000
1025
{
1026
+ #ifdef _COMPILER_TSAN_ENABLED_
1027
+ __tsan_mutex_pre_lock (lock , __tsan_mutex_write_reentrant );
1028
+ #endif
1001
1029
JL_SIGATOMIC_BEGIN_self ();
1002
1030
_jl_mutex_wait (self , lock , 1 );
1003
1031
jl_lock_frame_push (self , lock );
1032
+ #ifdef _COMPILER_TSAN_ENABLED_
1033
+ __tsan_mutex_post_lock (lock , __tsan_mutex_write_reentrant , 1 );
1034
+ #endif
1004
1035
}
1005
1036
1006
1037
int _jl_mutex_trylock_nogc (jl_task_t * self , jl_mutex_t * lock )
1007
1038
{
1039
+ #ifdef _COMPILER_TSAN_ENABLED_
1040
+ __tsan_mutex_pre_lock (lock , __tsan_mutex_try_lock | __tsan_mutex_write_reentrant );
1041
+ #endif
1008
1042
jl_task_t * owner = jl_atomic_load_acquire (& lock -> owner );
1043
+ int ret = 0 ;
1009
1044
if (owner == self ) {
1010
1045
lock -> count ++ ;
1011
- return 1 ;
1046
+ ret = 1 ;
1047
+ goto done ;
1012
1048
}
1013
1049
if (owner == NULL && jl_atomic_cmpswap (& lock -> owner , & owner , self )) {
1014
1050
lock -> count = 1 ;
1015
- return 1 ;
1051
+ ret = 1 ;
1052
+ goto done ;
1016
1053
}
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 ;
1018
1063
}
1019
1064
1020
1065
int _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)
1030
1075
void _jl_mutex_unlock_nogc (jl_mutex_t * lock )
1031
1076
{
1032
1077
#ifndef __clang_gcanalyzer__
1078
+ #ifdef _COMPILER_TSAN_ENABLED_
1079
+ __tsan_mutex_pre_unlock (lock , 0 );
1080
+ #endif
1033
1081
assert (jl_atomic_load_relaxed (& lock -> owner ) == jl_current_task &&
1034
1082
"Unlocking a lock in a different thread." );
1035
1083
if (-- lock -> count == 0 ) {
@@ -1044,6 +1092,9 @@ void _jl_mutex_unlock_nogc(jl_mutex_t *lock)
1044
1092
}
1045
1093
jl_profile_lock_release_end (lock );
1046
1094
}
1095
+ #ifdef _COMPILER_TSAN_ENABLED_
1096
+ __tsan_mutex_post_unlock (lock , 0 );
1097
+ #endif
1047
1098
#endif
1048
1099
}
1049
1100
0 commit comments