@@ -202,6 +202,7 @@ fn condattr_set_clock_id<'mir, 'tcx: 'mir>(
202202// Our chosen memory layout for the emulated conditional variable (does not have
203203// to match the platform layout!):
204204
205+ // bytes 0-3: reserved for signature on macOS
205206// bytes 4-7: the conditional variable id as u32 or 0 if id is not assigned yet.
206207// bytes 8-11: the clock id constant as i32
207208
@@ -275,19 +276,13 @@ fn release_cond_mutex<'mir, 'tcx: 'mir>(
275276 active_thread : ThreadId ,
276277 mutex : MutexId ,
277278) -> InterpResult < ' tcx > {
278- if let Some ( ( owner_thread , current_locked_count ) ) = ecx. mutex_unlock ( mutex) {
279- if current_locked_count != 0 {
280- throw_unsup_format ! ( "awaiting on multiple times acquired lock is not supported" ) ;
279+ if let Some ( ( old_owner_thread , old_locked_count ) ) = ecx. mutex_unlock ( mutex) ? {
280+ if old_locked_count != 1 {
281+ throw_unsup_format ! ( "awaiting on a lock acquired multiple times is not supported" ) ;
281282 }
282- if owner_thread != active_thread {
283+ if old_owner_thread != active_thread {
283284 throw_ub_format ! ( "awaiting on a mutex owned by a different thread" ) ;
284285 }
285- if let Some ( thread) = ecx. mutex_dequeue ( mutex) {
286- // We have at least one thread waiting on this mutex. Transfer
287- // ownership to it.
288- ecx. mutex_lock ( mutex, thread) ;
289- ecx. unblock_thread ( thread) ?;
290- }
291286 } else {
292287 throw_ub_format ! ( "awaiting on unlocked mutex" ) ;
293288 }
@@ -349,7 +344,9 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
349344 mutexattr_get_kind ( this, attr_op) ?. not_undef ( ) ?
350345 } ;
351346
352- let _ = mutex_get_or_create_id ( this, mutex_op) ?;
347+ // Write 0 to use the same code path as the static initializers.
348+ mutex_set_id ( this, mutex_op, Scalar :: from_i32 ( 0 ) ) ?;
349+
353350 mutex_set_kind ( this, mutex_op, kind) ?;
354351
355352 Ok ( 0 )
@@ -427,19 +424,10 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
427424 let kind = mutex_get_kind ( this, mutex_op) ?. not_undef ( ) ?;
428425 let id = mutex_get_or_create_id ( this, mutex_op) ?;
429426
430- if let Some ( ( owner_thread , current_locked_count ) ) = this. mutex_unlock ( id) {
431- if owner_thread != this. get_active_thread ( ) ? {
427+ if let Some ( ( old_owner_thread , _old_locked_count ) ) = this. mutex_unlock ( id) ? {
428+ if old_owner_thread != this. get_active_thread ( ) ? {
432429 throw_ub_format ! ( "called pthread_mutex_unlock on a mutex owned by another thread" ) ;
433430 }
434- if current_locked_count == 0 {
435- // The mutex is unlocked.
436- if let Some ( thread) = this. mutex_dequeue ( id) {
437- // We have at least one thread waiting on this mutex. Transfer
438- // ownership to it.
439- this. mutex_lock ( id, thread) ;
440- this. unblock_thread ( thread) ?;
441- }
442- }
443431 Ok ( 0 )
444432 } else {
445433 if kind == this. eval_libc ( "PTHREAD_MUTEX_NORMAL" ) ? {
@@ -476,11 +464,10 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
476464 let active_thread = this. get_active_thread ( ) ?;
477465
478466 if this. rwlock_is_write_locked ( id) {
479- this. rwlock_enqueue_reader ( id, active_thread) ;
480- this. block_thread ( active_thread) ?;
467+ this. rwlock_enqueue_and_block_reader ( id, active_thread) ?;
481468 Ok ( 0 )
482469 } else {
483- this. rwlock_reader_add ( id, active_thread) ;
470+ this. rwlock_reader_lock ( id, active_thread) ;
484471 Ok ( 0 )
485472 }
486473 }
@@ -494,7 +481,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
494481 if this. rwlock_is_write_locked ( id) {
495482 this. eval_libc_i32 ( "EBUSY" )
496483 } else {
497- this. rwlock_reader_add ( id, active_thread) ;
484+ this. rwlock_reader_lock ( id, active_thread) ;
498485 Ok ( 0 )
499486 }
500487 }
@@ -506,10 +493,9 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
506493 let active_thread = this. get_active_thread ( ) ?;
507494
508495 if this. rwlock_is_locked ( id) {
509- this. block_thread ( active_thread) ?;
510- this. rwlock_enqueue_writer ( id, active_thread) ;
496+ this. rwlock_enqueue_and_block_writer ( id, active_thread) ?;
511497 } else {
512- this. rwlock_writer_set ( id, active_thread) ;
498+ this. rwlock_writer_lock ( id, active_thread) ;
513499 }
514500
515501 Ok ( 0 )
@@ -524,7 +510,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
524510 if this. rwlock_is_locked ( id) {
525511 this. eval_libc_i32 ( "EBUSY" )
526512 } else {
527- this. rwlock_writer_set ( id, active_thread) ;
513+ this. rwlock_writer_lock ( id, active_thread) ;
528514 Ok ( 0 )
529515 }
530516 }
@@ -535,18 +521,18 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
535521 let id = rwlock_get_or_create_id ( this, rwlock_op) ?;
536522 let active_thread = this. get_active_thread ( ) ?;
537523
538- if this. rwlock_reader_remove ( id, active_thread) {
524+ if this. rwlock_reader_unlock ( id, active_thread) {
539525 // The thread was a reader.
540526 if this. rwlock_is_locked ( id) {
541527 // No more readers owning the lock. Give it to a writer if there
542528 // is any.
543529 if let Some ( writer) = this. rwlock_dequeue_writer ( id) {
544530 this. unblock_thread ( writer) ?;
545- this. rwlock_writer_set ( id, writer) ;
531+ this. rwlock_writer_lock ( id, writer) ;
546532 }
547533 }
548534 Ok ( 0 )
549- } else if Some ( active_thread) == this. rwlock_writer_remove ( id) {
535+ } else if Some ( active_thread) == this. rwlock_writer_unlock ( id) {
550536 // The thread was a writer.
551537 //
552538 // We are prioritizing writers here against the readers. As a
@@ -555,12 +541,12 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
555541 if let Some ( writer) = this. rwlock_dequeue_writer ( id) {
556542 // Give the lock to another writer.
557543 this. unblock_thread ( writer) ?;
558- this. rwlock_writer_set ( id, writer) ;
544+ this. rwlock_writer_lock ( id, writer) ;
559545 } else {
560546 // Give the lock to all readers.
561547 while let Some ( reader) = this. rwlock_dequeue_reader ( id) {
562548 this. unblock_thread ( reader) ?;
563- this. rwlock_reader_add ( id, reader) ;
549+ this. rwlock_reader_lock ( id, reader) ;
564550 }
565551 }
566552 Ok ( 0 )
@@ -586,6 +572,9 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
586572 fn pthread_condattr_init ( & mut self , attr_op : OpTy < ' tcx , Tag > ) -> InterpResult < ' tcx , i32 > {
587573 let this = self . eval_context_mut ( ) ;
588574
575+ // The default value of the clock attribute shall refer to the system
576+ // clock.
577+ // https://pubs.opengroup.org/onlinepubs/9699919799/functions/pthread_condattr_setclock.html
589578 let default_clock_id = this. eval_libc ( "CLOCK_REALTIME" ) ?;
590579 condattr_set_clock_id ( this, attr_op, default_clock_id) ?;
591580
@@ -647,7 +636,9 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
647636 condattr_get_clock_id ( this, attr_op) ?. not_undef ( ) ?
648637 } ;
649638
650- let _ = cond_get_or_create_id ( this, cond_op) ?;
639+ // Write 0 to use the same code path as the static initializers.
640+ cond_set_id ( this, cond_op, Scalar :: from_i32 ( 0 ) ) ?;
641+
651642 cond_set_clock_id ( this, cond_op, clock_id) ?;
652643
653644 Ok ( 0 )
0 commit comments