@@ -99,7 +99,7 @@ fn mutex_create<'tcx>(
99
99
// FIXME: might be worth changing mutex_create to take the mplace
100
100
// rather than the `OpTy`.
101
101
let address = ecx. read_pointer ( mutex_op) ?. addr ( ) . bytes ( ) ;
102
- let kind = MutexKind :: new ( kind) ;
102
+ let kind = translate_kind ( ecx , kind) ? ;
103
103
let data = Some ( AdditionalMutexData { address, kind } ) ;
104
104
ecx. mutex_create ( mutex_op, ecx. libc_ty_layout ( "pthread_mutex_t" ) , mutex_id_offset ( ecx) ?, data) ?;
105
105
Ok ( ( ) )
@@ -145,21 +145,37 @@ fn kind_from_static_initializer<'tcx>(
145
145
mutex_op : & OpTy < ' tcx > ,
146
146
) -> InterpResult < ' tcx , MutexKind > {
147
147
// Only linux has static initializers other than PTHREAD_MUTEX_DEFAULT.
148
- let offset = match & * ecx. tcx . sess . target . os {
149
- "linux" => if ecx. pointer_size ( ) . bytes ( ) == 8 { 16 } else { 12 } ,
150
- | "illumos" | "solaris" | "macos" => return Ok ( MutexKind :: new ( ecx. eval_libc_i32 ( "PTHREAD_MUTEX_DEFAULT" ) ) ) ,
148
+ let kind = match & * ecx. tcx . sess . target . os {
149
+ "linux" => {
150
+ let offset = if ecx. pointer_size ( ) . bytes ( ) == 8 { 16 } else { 12 } ;
151
+
152
+ ecx. deref_pointer_and_read (
153
+ mutex_op,
154
+ offset,
155
+ ecx. libc_ty_layout ( "pthread_mutex_t" ) ,
156
+ ecx. machine . layouts . i32 ,
157
+ ) ?
158
+ . to_i32 ( ) ?
159
+ }
160
+ | "illumos" | "solaris" | "macos" => ecx. eval_libc_i32 ( "PTHREAD_MUTEX_DEFAULT" ) ,
151
161
os => throw_unsup_format ! ( "`pthread_mutex` is not supported on {os}" ) ,
152
162
} ;
153
163
154
- let kind = ecx
155
- . deref_pointer_and_read (
156
- mutex_op,
157
- offset,
158
- ecx. libc_ty_layout ( "pthread_mutex_t" ) ,
159
- ecx. machine . layouts . i32 ,
160
- ) ?
161
- . to_i32 ( ) ?;
162
- return Ok ( MutexKind :: new ( kind) ) ;
164
+ translate_kind ( ecx, kind)
165
+ }
166
+
167
+ fn translate_kind < ' tcx > ( ecx : & MiriInterpCx < ' tcx > , kind : i32 ) -> InterpResult < ' tcx , MutexKind > {
168
+ Ok ( if is_mutex_kind_default ( ecx, kind) ? {
169
+ MutexKind :: Default
170
+ } else if is_mutex_kind_normal ( ecx, kind) ? {
171
+ MutexKind :: Normal
172
+ } else if kind == ecx. eval_libc_i32 ( "PTHREAD_MUTEX_ERRORCHECK" ) {
173
+ MutexKind :: ErrorCheck
174
+ } else if kind == ecx. eval_libc_i32 ( "PTHREAD_MUTEX_RECURSIVE" ) {
175
+ MutexKind :: Recursive
176
+ } else {
177
+ throw_unsup_format ! ( "unsupported type of mutex: {kind}" ) ;
178
+ } )
163
179
}
164
180
165
181
// pthread_rwlock_t is between 32 and 56 bytes, depending on the platform.
@@ -462,11 +478,8 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
462
478
let this = self . eval_context_mut ( ) ;
463
479
464
480
let id = mutex_get_id ( this, mutex_op) ?;
465
- let kind = this
466
- . mutex_get_data ( id)
467
- . expect ( "data should always exist for pthread mutexes" )
468
- . kind
469
- . to_i32 ( ) ;
481
+ let kind =
482
+ this. mutex_get_data ( id) . expect ( "data should always exist for pthread mutexes" ) . kind ;
470
483
471
484
let ret = if this. mutex_is_locked ( id) {
472
485
let owner_thread = this. mutex_get_owner ( id) ;
@@ -475,19 +488,19 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
475
488
return Ok ( ( ) ) ;
476
489
} else {
477
490
// Trying to acquire the same mutex again.
478
- if is_mutex_kind_default ( this , kind) ? {
479
- throw_ub_format ! ( "trying to acquire already locked default mutex" ) ;
480
- } else if is_mutex_kind_normal ( this , kind ) ? {
481
- throw_machine_stop ! ( TerminationInfo :: Deadlock ) ;
482
- } else if kind == this. eval_libc_i32 ( "PTHREAD_MUTEX_ERRORCHECK" ) {
483
- this . eval_libc_i32 ( "EDEADLK" )
484
- } else if kind == this. eval_libc_i32 ( "PTHREAD_MUTEX_RECURSIVE" ) {
485
- this . mutex_lock ( id ) ;
486
- 0
487
- } else {
488
- throw_unsup_format ! (
489
- "called pthread_mutex_lock on an unsupported type of mutex"
490
- ) ;
491
+ match kind {
492
+ MutexKind :: Default =>
493
+ throw_ub_format ! ( "trying to acquire already locked default mutex" ) ,
494
+ MutexKind :: Normal => throw_machine_stop ! ( TerminationInfo :: Deadlock ) ,
495
+ MutexKind :: ErrorCheck => this. eval_libc_i32 ( "EDEADLK" ) ,
496
+ MutexKind :: Recursive => {
497
+ this. mutex_lock ( id ) ;
498
+ 0
499
+ }
500
+ _ =>
501
+ throw_unsup_format ! (
502
+ "called pthread_mutex_lock on an unsupported type of mutex"
503
+ ) ,
491
504
}
492
505
}
493
506
} else {
@@ -503,29 +516,25 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
503
516
let this = self . eval_context_mut ( ) ;
504
517
505
518
let id = mutex_get_id ( this, mutex_op) ?;
506
- let kind = this
507
- . mutex_get_data ( id)
508
- . expect ( "data should always exist for pthread mutexes" )
509
- . kind
510
- . to_i32 ( ) ;
519
+ let kind =
520
+ this. mutex_get_data ( id) . expect ( "data should always exist for pthread mutexes" ) . kind ;
511
521
512
522
Ok ( Scalar :: from_i32 ( if this. mutex_is_locked ( id) {
513
523
let owner_thread = this. mutex_get_owner ( id) ;
514
524
if owner_thread != this. active_thread ( ) {
515
525
this. eval_libc_i32 ( "EBUSY" )
516
526
} else {
517
- if is_mutex_kind_default ( this, kind) ?
518
- || is_mutex_kind_normal ( this, kind) ?
519
- || kind == this. eval_libc_i32 ( "PTHREAD_MUTEX_ERRORCHECK" )
520
- {
521
- this. eval_libc_i32 ( "EBUSY" )
522
- } else if kind == this. eval_libc_i32 ( "PTHREAD_MUTEX_RECURSIVE" ) {
523
- this. mutex_lock ( id) ;
524
- 0
525
- } else {
526
- throw_unsup_format ! (
527
- "called pthread_mutex_trylock on an unsupported type of mutex"
528
- ) ;
527
+ match kind {
528
+ MutexKind :: Default | MutexKind :: Normal | MutexKind :: ErrorCheck =>
529
+ this. eval_libc_i32 ( "EBUSY" ) ,
530
+ MutexKind :: Recursive => {
531
+ this. mutex_lock ( id) ;
532
+ 0
533
+ }
534
+ _ =>
535
+ throw_unsup_format ! (
536
+ "called pthread_mutex_trylock on an unsupported type of mutex"
537
+ ) ,
529
538
}
530
539
}
531
540
} else {
@@ -539,11 +548,8 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
539
548
let this = self . eval_context_mut ( ) ;
540
549
541
550
let id = mutex_get_id ( this, mutex_op) ?;
542
- let kind = this
543
- . mutex_get_data ( id)
544
- . expect ( "data should always exist for pthread mutexes" )
545
- . kind
546
- . to_i32 ( ) ;
551
+ let kind =
552
+ this. mutex_get_data ( id) . expect ( "data should always exist for pthread mutexes" ) . kind ;
547
553
548
554
if let Some ( _old_locked_count) = this. mutex_unlock ( id) ? {
549
555
// The mutex was locked by the current thread.
@@ -552,20 +558,21 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
552
558
// The mutex was locked by another thread or not locked at all. See
553
559
// the “Unlock When Not Owner” column in
554
560
// https://pubs.opengroup.org/onlinepubs/9699919799/functions/pthread_mutex_unlock.html.
555
- if is_mutex_kind_default ( this, kind) ? {
556
- throw_ub_format ! (
557
- "unlocked a default mutex that was not locked by the current thread"
558
- ) ;
559
- } else if is_mutex_kind_normal ( this, kind) ? {
560
- throw_ub_format ! (
561
- "unlocked a PTHREAD_MUTEX_NORMAL mutex that was not locked by the current thread"
562
- ) ;
563
- } else if kind == this. eval_libc_i32 ( "PTHREAD_MUTEX_ERRORCHECK" )
564
- || kind == this. eval_libc_i32 ( "PTHREAD_MUTEX_RECURSIVE" )
565
- {
566
- Ok ( Scalar :: from_i32 ( this. eval_libc_i32 ( "EPERM" ) ) )
567
- } else {
568
- throw_unsup_format ! ( "called pthread_mutex_unlock on an unsupported type of mutex" ) ;
561
+ match kind {
562
+ MutexKind :: Default =>
563
+ throw_ub_format ! (
564
+ "unlocked a default mutex that was not locked by the current thread"
565
+ ) ,
566
+ MutexKind :: Normal =>
567
+ throw_ub_format ! (
568
+ "unlocked a PTHREAD_MUTEX_NORMAL mutex that was not locked by the current thread"
569
+ ) ,
570
+ MutexKind :: ErrorCheck | MutexKind :: Recursive =>
571
+ Ok ( Scalar :: from_i32 ( this. eval_libc_i32 ( "EPERM" ) ) ) ,
572
+ _ =>
573
+ throw_unsup_format ! (
574
+ "called pthread_mutex_unlock on an unsupported type of mutex"
575
+ ) ,
569
576
}
570
577
}
571
578
}
0 commit comments