@@ -589,6 +589,7 @@ static void jl_check_tls(void)
589589JL_DLLEXPORT const int jl_tls_elf_support = 0 ;
590590#endif
591591
592+ #define SLEEP_LOCK_BIT ((uint32_t)(1ull << 31))
592593#define SLEEP_HASH_BITS 6
593594#define SLEEP_IGNORED_BITS 8
594595static uv_mutex_t sleep_locks [1 << SLEEP_HASH_BITS ];
@@ -737,28 +738,32 @@ JL_DLLEXPORT void jl_exit_threaded_region(void)
737738 }
738739}
739740
741+ static int is_spin_mutex (void * lock )
742+ {
743+ return (jl_atomic_load_relaxed (& ((jl_spin_mutex_t * )lock )-> count ) & SLEEP_LOCK_BIT ) == 0 ;
744+ }
745+
740746JL_DLLEXPORT void _jl_spin_mutex_init (jl_spin_mutex_t * lock , const char * name ) JL_NOTSAFEPOINT
741747{
742- lock -> count = 0 ;
743- // high bit of padding identifies this as a spin lock
744- jl_atomic_store_relaxed (& lock -> padding , 0 );
748+ // high bit of count unset identifies this as a spin lock
749+ jl_atomic_store_relaxed (& lock -> count , 0 );
745750 jl_atomic_store_release (& lock -> owner , (jl_task_t * )NULL );
746751 jl_profile_lock_init (lock , name );
747752}
748753
749754JL_DLLEXPORT void _jl_spin_mutex_wait (jl_task_t * self , jl_spin_mutex_t * lock , int safepoint )
750755{
751- assert (jl_atomic_load_relaxed ( & lock -> padding ) == 0 && "Spin lock not initialized !" );
756+ assert (is_spin_mutex ( lock ) && "Spin lock corrupted !" );
752757 jl_task_t * owner = jl_atomic_load_relaxed (& lock -> owner );
753758 if (owner == self ) {
754- lock -> count ++ ;
759+ jl_atomic_store_relaxed ( & lock -> count , jl_atomic_load_relaxed ( & lock -> count ) + 1 ) ;
755760 return ;
756761 }
757762 JL_TIMING (LOCK_SPIN , LOCK_SPIN );
758763 jl_profile_lock_start_wait (lock );
759764 while (1 ) {
760765 if (owner == NULL && jl_atomic_cmpswap (& lock -> owner , & owner , self )) {
761- lock -> count = 1 ;
766+ jl_atomic_store_relaxed ( & lock -> count , 1 ) ;
762767 jl_profile_lock_acquired (lock );
763768 return ;
764769 }
@@ -807,14 +812,14 @@ JL_DLLEXPORT void _jl_spin_mutex_lock(jl_task_t *self, jl_spin_mutex_t *lock)
807812
808813JL_DLLEXPORT int _jl_spin_mutex_trylock_nogc (jl_task_t * self , jl_spin_mutex_t * lock )
809814{
810- assert (jl_atomic_load_relaxed ( & lock -> padding ) == 0 && "Spin lock not initialized !" );
815+ assert (is_spin_mutex ( lock ) && "Spin lock corrupted !" );
811816 jl_task_t * owner = jl_atomic_load_acquire (& lock -> owner );
812817 if (owner == self ) {
813- lock -> count ++ ;
818+ jl_atomic_store_relaxed ( & lock -> count , jl_atomic_load_relaxed ( & lock -> count ) + 1 ) ;
814819 return 1 ;
815820 }
816821 if (owner == NULL && jl_atomic_cmpswap (& lock -> owner , & owner , self )) {
817- lock -> count = 1 ;
822+ jl_atomic_store_relaxed ( & lock -> count , 1 ) ;
818823 return 1 ;
819824 }
820825 return 0 ;
@@ -832,11 +837,13 @@ JL_DLLEXPORT int _jl_spin_mutex_trylock(jl_task_t *self, jl_spin_mutex_t *lock)
832837
833838JL_DLLEXPORT void _jl_spin_mutex_unlock_nogc (jl_spin_mutex_t * lock )
834839{
835- assert (jl_atomic_load_relaxed ( & lock -> padding ) == 0 && "Spin lock not initialized !" );
840+ assert (is_spin_mutex ( lock ) && "Spin lock corrupted !" );
836841#ifndef __clang_gcanalyzer__
837842 assert (jl_atomic_load_relaxed (& lock -> owner ) == jl_current_task &&
838843 "Unlocking a lock in a different thread." );
839- if (-- lock -> count == 0 ) {
844+ uint32_t count = jl_atomic_load_relaxed (& lock -> count );
845+ jl_atomic_store_relaxed (& lock -> count , count - 1 );
846+ if (count == 1 ) {
840847 jl_profile_lock_release_start (lock );
841848 jl_atomic_store_release (& lock -> owner , (jl_task_t * )NULL );
842849 jl_cpu_wake ();
@@ -861,8 +868,6 @@ JL_DLLEXPORT void _jl_spin_mutex_unlock(jl_task_t *self, jl_spin_mutex_t *lock)
861868 }
862869}
863870
864- #define SLEEP_LOCK_BIT ((uint32_t)(1ull << 31))
865-
866871JL_DLLEXPORT void _jl_sleep_mutex_init (jl_sleep_mutex_t * lock , const char * name ) JL_NOTSAFEPOINT
867872{
868873 // waiters is overloaded:
@@ -877,8 +882,10 @@ JL_DLLEXPORT void _jl_sleep_mutex_init(jl_sleep_mutex_t *lock, const char *name)
877882
878883JL_DLLEXPORT void _jl_sleep_mutex_wait (jl_task_t * self , jl_sleep_mutex_t * lock , int safepoint )
879884{
880- // high bit of padding identifies this as a spin lock
881- assert ((jl_atomic_load_relaxed (& lock -> waiters ) & SLEEP_LOCK_BIT ) && "Unexpected spin lock in sleeping wait!" );
885+ // high bit of waiters identifies this as a sleep lock
886+ // call out the uninitialized case specially
887+ assert (jl_atomic_load_relaxed (& lock -> waiters ) != 0 && "Sleep lock not initialized!" );
888+ assert (!is_spin_mutex (lock ) && "Unexpected spin lock in sleeping wait!" );
882889 uint32_t old_waiters = SLEEP_LOCK_BIT ;
883890 if (jl_atomic_cmpswap_acqrel (& lock -> waiters , & old_waiters , SLEEP_LOCK_BIT | 1 )) {
884891 // no one is waiting, we just took the lock
@@ -930,8 +937,10 @@ JL_DLLEXPORT void _jl_sleep_mutex_lock(jl_task_t *self, jl_sleep_mutex_t *lock)
930937
931938JL_DLLEXPORT int _jl_sleep_mutex_trylock_nogc (jl_task_t * self , jl_sleep_mutex_t * lock )
932939{
933- // high bit of padding identifies this as a spin lock
934- assert ((jl_atomic_load_relaxed (& lock -> waiters ) & SLEEP_LOCK_BIT ) && "Unexpected spin lock in sleeping trylock!" );
940+ // high bit of waiters identifies this as a sleep lock
941+ // call out the uninitialized case specially
942+ assert (jl_atomic_load_relaxed (& lock -> waiters ) != 0 && "Sleep lock not initialized!" );
943+ assert (!is_spin_mutex (lock ) && "Unexpected spin lock in trylock!" );
935944 uint32_t none = SLEEP_LOCK_BIT ;
936945 if (jl_atomic_cmpswap_acqrel (& lock -> waiters , & none , SLEEP_LOCK_BIT | 1 )) {
937946 // no one is waiting, we just took the lock
@@ -959,8 +968,10 @@ JL_DLLEXPORT int _jl_sleep_mutex_trylock(jl_task_t *self, jl_sleep_mutex_t *lock
959968
960969JL_DLLEXPORT void _jl_sleep_mutex_unlock_nogc (jl_sleep_mutex_t * lock )
961970{
962- // high bit of padding identifies this as a spin lock
963- assert ((jl_atomic_load_relaxed (& lock -> waiters ) & SLEEP_LOCK_BIT ) && "Unexpected spin lock in sleeping unlock!" );
971+ // high bit of waiters identifies this as a sleep lock
972+ // call out the uninitialized case specially
973+ assert (jl_atomic_load_relaxed (& lock -> waiters ) != 0 && "Sleep lock not initialized!" );
974+ assert (!is_spin_mutex (lock ) && "Unexpected spin lock in unlock!" );
964975 if (-- lock -> count == 0 ) {
965976 //Do the release
966977 jl_profile_lock_release_start (lock );
@@ -1006,8 +1017,7 @@ JL_DLLEXPORT void _jl_sleep_mutex_unlock(jl_task_t *self, jl_sleep_mutex_t *lock
10061017
10071018void _jl_dyn_mutex_unlock (jl_task_t * self , void * lock )
10081019{
1009- int is_sleep_mutex = jl_atomic_load_relaxed (& ((jl_spin_mutex_t * )lock )-> padding ) & SLEEP_LOCK_BIT ;
1010- if (is_sleep_mutex ) {
1020+ if (!is_spin_mutex (lock )) {
10111021 _jl_sleep_mutex_unlock (self , (jl_sleep_mutex_t * )lock );
10121022 } else {
10131023 _jl_spin_mutex_unlock (self , (jl_spin_mutex_t * )lock );
@@ -1016,8 +1026,7 @@ void _jl_dyn_mutex_unlock(jl_task_t *self, void *lock)
10161026
10171027void _jl_dyn_mutex_unlock_nogc (void * lock )
10181028{
1019- int is_sleep_mutex = jl_atomic_load_relaxed (& ((jl_spin_mutex_t * )lock )-> padding ) & SLEEP_LOCK_BIT ;
1020- if (is_sleep_mutex ) {
1029+ if (!is_spin_mutex (lock )) {
10211030 _jl_sleep_mutex_unlock_nogc ((jl_sleep_mutex_t * )lock );
10221031 } else {
10231032 _jl_spin_mutex_unlock_nogc ((jl_spin_mutex_t * )lock );
0 commit comments