@@ -80,7 +80,8 @@ fn mutexattr_set_kind<'mir, 'tcx: 'mir>(
80
80
// bytes 8-11: when count > 0, id of the owner thread as a u32
81
81
// bytes 12-15 or 16-19 (depending on platform): mutex kind, as an i32
82
82
// (the kind has to be at its offset for compatibility with static initializer macros)
83
- // bytes 20-23: when count > 0, id of the blockset in which the blocked threads are waiting.
83
+ // bytes 20-23: when count > 0, id of the blockset in which the blocked threads
84
+ // are waiting or 0 if blockset is not yet assigned.
84
85
85
86
const PTHREAD_MUTEX_T_MIN_SIZE : u64 = 24 ;
86
87
@@ -170,9 +171,9 @@ fn mutex_get_or_create_blockset<'mir, 'tcx: 'mir>(
170
171
// bytes 4-7: reader count, as a u32
171
172
// bytes 8-11: writer count, as a u32
172
173
// bytes 12-15: when writer or reader count > 0, id of the blockset in which the
173
- // blocked writers are waiting.
174
+ // blocked writers are waiting or 0 if blockset is not yet assigned .
174
175
// bytes 16-20: when writer count > 0, id of the blockset in which the blocked
175
- // readers are waiting.
176
+ // readers are waiting or 0 if blockset is not yet assigned .
176
177
177
178
const PTHREAD_RWLOCK_T_MIN_SIZE : u64 = 20 ;
178
179
@@ -342,8 +343,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
342
343
Ok ( 0 )
343
344
} else {
344
345
// The mutex is locked. Let's check by whom.
345
- let owner_thread: ThreadId =
346
- mutex_get_owner ( this, mutex_op) ?. not_undef ( ) ?. to_u32 ( ) ?. into ( ) ;
346
+ let owner_thread: ThreadId = mutex_get_owner ( this, mutex_op) ?. to_u32 ( ) ?. into ( ) ;
347
347
if owner_thread != active_thread {
348
348
// Block the active thread.
349
349
let blockset = mutex_get_or_create_blockset ( this, mutex_op) ?;
@@ -425,6 +425,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
425
425
mutex_set_owner ( this, mutex_op, new_owner. to_u32_scalar ( ) ) ?;
426
426
} else {
427
427
// No thread is waiting on this mutex.
428
+ mutex_set_owner ( this, mutex_op, Scalar :: from_u32 ( 0 ) ) ?;
428
429
mutex_set_locked_count ( this, mutex_op, Scalar :: from_u32 ( 0 ) ) ?;
429
430
}
430
431
Ok ( 0 )
@@ -550,10 +551,13 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
550
551
Ok ( 0 )
551
552
} else if writers != 0 {
552
553
let reader_blockset = rwlock_get_or_create_reader_blockset ( this, rwlock_op) ?;
553
- rwlock_set_writers ( this, rwlock_op, Scalar :: from_u32 ( 0 ) ) ?;
554
+ // We are prioritizing writers here against the readers. As a
555
+ // result, not only readers can starve writers, but also writers can
556
+ // starve readers.
554
557
if let Some ( _writer) = this. unblock_some_thread ( writer_blockset) ? {
555
558
rwlock_set_writers ( this, rwlock_op, Scalar :: from_u32 ( 1 ) ) ?;
556
559
} else {
560
+ rwlock_set_writers ( this, rwlock_op, Scalar :: from_u32 ( 0 ) ) ?;
557
561
let mut readers = 0 ;
558
562
while let Some ( _reader) = this. unblock_some_thread ( reader_blockset) ? {
559
563
readers += 1 ;
0 commit comments