@@ -110,6 +110,15 @@ struct PthreadMutex {
110110}
111111
112112impl SyncObj for PthreadMutex {
113+ fn on_access < ' tcx > ( & self , access_kind : AccessKind ) -> InterpResult < ' tcx > {
114+ if !self . mutex_ref . queue_is_empty ( ) {
115+ throw_ub_format ! (
116+ "{access_kind} to `pthread_mutex_t` is forbidden while the queue is non-empty"
117+ ) ;
118+ }
119+ interp_ok ( ( ) )
120+ }
121+
113122 fn delete_on_write ( & self ) -> bool {
114123 true
115124 }
@@ -230,6 +239,15 @@ struct PthreadRwLock {
230239}
231240
232241impl SyncObj for PthreadRwLock {
242+ fn on_access < ' tcx > ( & self , access_kind : AccessKind ) -> InterpResult < ' tcx > {
243+ if !self . rwlock_ref . queue_is_empty ( ) {
244+ throw_ub_format ! (
245+ "{access_kind} to `pthread_rwlock_t` is forbidden while the queue is non-empty"
246+ ) ;
247+ }
248+ interp_ok ( ( ) )
249+ }
250+
233251 fn delete_on_write ( & self ) -> bool {
234252 true
235253 }
@@ -361,6 +379,15 @@ struct PthreadCondvar {
361379}
362380
363381impl SyncObj for PthreadCondvar {
382+ fn on_access < ' tcx > ( & self , access_kind : AccessKind ) -> InterpResult < ' tcx > {
383+ if !self . condvar_ref . queue_is_empty ( ) {
384+ throw_ub_format ! (
385+ "{access_kind} to `pthread_cond_t` is forbidden while the queue is non-empty"
386+ ) ;
387+ }
388+ interp_ok ( ( ) )
389+ }
390+
364391 fn delete_on_write ( & self ) -> bool {
365392 true
366393 }
@@ -900,7 +927,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
900927 // Reading the field also has the side-effect that we detect double-`destroy`
901928 // since we make the field uninit below.
902929 let condvar = & cond_get_data ( this, cond_op) ?. condvar_ref ;
903- if condvar. is_awaited ( ) {
930+ if ! condvar. queue_is_empty ( ) {
904931 throw_ub_format ! ( "destroying an awaited conditional variable" ) ;
905932 }
906933
0 commit comments