@@ -59,6 +59,25 @@ fn is_mutex_kind_normal<'tcx>(ecx: &MiriInterpCx<'tcx>, kind: i32) -> InterpResu
59
59
Ok ( kind == ( mutex_normal_kind | PTHREAD_MUTEX_NORMAL_FLAG ) )
60
60
}
61
61
62
+ /// The mutex kind.
63
+ #[ derive( Debug , Clone , Copy ) ]
64
+ pub enum MutexKind {
65
+ Normal ,
66
+ Default ,
67
+ Recursive ,
68
+ ErrorCheck ,
69
+ }
70
+
71
+ #[ derive( Debug ) ]
72
+ /// Additional data that we attach with each mutex instance.
73
+ pub struct AdditionalMutexData {
74
+ /// The mutex kind, used by some mutex implementations like pthreads mutexes.
75
+ pub kind : MutexKind ,
76
+
77
+ /// The address of the mutex.
78
+ pub address : u64 ,
79
+ }
80
+
62
81
// pthread_mutex_t is between 24 and 48 bytes, depending on the platform.
63
82
// We ignore the platform layout and store our own fields:
64
83
// - id: u32
@@ -100,8 +119,8 @@ fn mutex_create<'tcx>(
100
119
let mutex = ecx. deref_pointer ( mutex_ptr) ?;
101
120
let address = mutex. ptr ( ) . addr ( ) . bytes ( ) ;
102
121
let kind = translate_kind ( ecx, kind) ?;
103
- let data = Some ( AdditionalMutexData { address, kind } ) ;
104
- ecx. mutex_create ( & mutex, mutex_id_offset ( ecx) ?, data) ?;
122
+ let data = Box :: new ( AdditionalMutexData { address, kind } ) ;
123
+ ecx. mutex_create ( & mutex, mutex_id_offset ( ecx) ?, Some ( data) ) ?;
105
124
Ok ( ( ) )
106
125
}
107
126
@@ -121,11 +140,13 @@ fn mutex_get_id<'tcx>(
121
140
// an ID yet. We have to determine the mutex kind from the static initializer.
122
141
let kind = kind_from_static_initializer ( ecx, & mutex) ?;
123
142
124
- Ok ( Some ( AdditionalMutexData { kind, address } ) )
143
+ Ok ( Some ( Box :: new ( AdditionalMutexData { kind, address } ) ) )
125
144
} ) ?;
126
145
127
146
// Check that the mutex has not been moved since last use.
128
- let data = ecx. mutex_get_data ( id) . expect ( "data should be always exist for pthreads" ) ;
147
+ let data = ecx
148
+ . mutex_get_data :: < AdditionalMutexData > ( id)
149
+ . expect ( "data should always exist for pthreads" ) ;
129
150
if data. address != address {
130
151
throw_ub_format ! ( "pthread_mutex_t can't be moved after first use" )
131
152
}
@@ -171,6 +192,13 @@ fn translate_kind<'tcx>(ecx: &MiriInterpCx<'tcx>, kind: i32) -> InterpResult<'tc
171
192
// We ignore the platform layout and store our own fields:
172
193
// - id: u32
173
194
195
+ #[ derive( Debug ) ]
196
+ /// Additional data that may be used by shim implementations.
197
+ pub struct AdditionalRwLockData {
198
+ /// The address of the rwlock.
199
+ pub address : u64 ,
200
+ }
201
+
174
202
fn rwlock_id_offset < ' tcx > ( ecx : & MiriInterpCx < ' tcx > ) -> InterpResult < ' tcx , u64 > {
175
203
let offset = match & * ecx. tcx . sess . target . os {
176
204
"linux" | "illumos" | "solaris" => 0 ,
@@ -205,11 +233,13 @@ fn rwlock_get_id<'tcx>(
205
233
let address = rwlock. ptr ( ) . addr ( ) . bytes ( ) ;
206
234
207
235
let id = ecx. rwlock_get_or_create_id ( & rwlock, rwlock_id_offset ( ecx) ?, |_| {
208
- Ok ( Some ( AdditionalRwLockData { address } ) )
236
+ Ok ( Some ( Box :: new ( AdditionalRwLockData { address } ) ) )
209
237
} ) ?;
210
238
211
239
// Check that the rwlock has not been moved since last use.
212
- let data = ecx. rwlock_get_data ( id) . expect ( "data should be always exist for pthreads" ) ;
240
+ let data = ecx
241
+ . rwlock_get_data :: < AdditionalRwLockData > ( id)
242
+ . expect ( "data should always exist for pthreads" ) ;
213
243
if data. address != address {
214
244
throw_ub_format ! ( "pthread_rwlock_t can't be moved after first use" )
215
245
}
@@ -473,8 +503,10 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
473
503
let this = self . eval_context_mut ( ) ;
474
504
475
505
let id = mutex_get_id ( this, mutex_op) ?;
476
- let kind =
477
- this. mutex_get_data ( id) . expect ( "data should always exist for pthread mutexes" ) . kind ;
506
+ let kind = this
507
+ . mutex_get_data :: < AdditionalMutexData > ( id)
508
+ . expect ( "data should always exist for pthread mutexes" )
509
+ . kind ;
478
510
479
511
let ret = if this. mutex_is_locked ( id) {
480
512
let owner_thread = this. mutex_get_owner ( id) ;
@@ -492,10 +524,6 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
492
524
this. mutex_lock ( id) ;
493
525
0
494
526
}
495
- _ =>
496
- throw_unsup_format ! (
497
- "called pthread_mutex_lock on an unsupported type of mutex"
498
- ) ,
499
527
}
500
528
}
501
529
} else {
@@ -511,8 +539,10 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
511
539
let this = self . eval_context_mut ( ) ;
512
540
513
541
let id = mutex_get_id ( this, mutex_op) ?;
514
- let kind =
515
- this. mutex_get_data ( id) . expect ( "data should always exist for pthread mutexes" ) . kind ;
542
+ let kind = this
543
+ . mutex_get_data :: < AdditionalMutexData > ( id)
544
+ . expect ( "data should always exist for pthread mutexes" )
545
+ . kind ;
516
546
517
547
Ok ( Scalar :: from_i32 ( if this. mutex_is_locked ( id) {
518
548
let owner_thread = this. mutex_get_owner ( id) ;
@@ -526,10 +556,6 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
526
556
this. mutex_lock ( id) ;
527
557
0
528
558
}
529
- _ =>
530
- throw_unsup_format ! (
531
- "called pthread_mutex_trylock on an unsupported type of mutex"
532
- ) ,
533
559
}
534
560
}
535
561
} else {
@@ -543,8 +569,10 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
543
569
let this = self . eval_context_mut ( ) ;
544
570
545
571
let id = mutex_get_id ( this, mutex_op) ?;
546
- let kind =
547
- this. mutex_get_data ( id) . expect ( "data should always exist for pthread mutexes" ) . kind ;
572
+ let kind = this
573
+ . mutex_get_data :: < AdditionalMutexData > ( id)
574
+ . expect ( "data should always exist for pthread mutexes" )
575
+ . kind ;
548
576
549
577
if let Some ( _old_locked_count) = this. mutex_unlock ( id) ? {
550
578
// The mutex was locked by the current thread.
@@ -564,10 +592,6 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
564
592
) ,
565
593
MutexKind :: ErrorCheck | MutexKind :: Recursive =>
566
594
Ok ( Scalar :: from_i32 ( this. eval_libc_i32 ( "EPERM" ) ) ) ,
567
- _ =>
568
- throw_unsup_format ! (
569
- "called pthread_mutex_unlock on an unsupported type of mutex"
570
- ) ,
571
595
}
572
596
}
573
597
}
0 commit comments