@@ -3,170 +3,26 @@ use std::time::Duration;
3
3
use rustc_target:: abi:: Size ;
4
4
5
5
use crate :: concurrency:: init_once:: InitOnceStatus ;
6
- use crate :: concurrency:: sync:: { CondvarLock , RwLockMode } ;
7
6
use crate :: concurrency:: thread:: MachineCallback ;
8
7
use crate :: * ;
9
8
10
9
impl < ' mir , ' tcx > EvalContextExtPriv < ' mir , ' tcx > for crate :: MiriInterpCx < ' mir , ' tcx > { }
11
10
trait EvalContextExtPriv < ' mir , ' tcx : ' mir > : crate :: MiriInterpCxExt < ' mir , ' tcx > {
12
- /// Try to reacquire the lock associated with the condition variable after we
13
- /// were signaled.
14
- fn reacquire_cond_lock (
15
- & mut self ,
16
- thread : ThreadId ,
17
- lock : RwLockId ,
18
- mode : RwLockMode ,
19
- ) -> InterpResult < ' tcx > {
20
- let this = self . eval_context_mut ( ) ;
21
- this. unblock_thread ( thread) ;
22
-
23
- match mode {
24
- RwLockMode :: Read =>
25
- if this. rwlock_is_write_locked ( lock) {
26
- this. rwlock_enqueue_and_block_reader ( lock, thread) ;
27
- } else {
28
- this. rwlock_reader_lock ( lock, thread) ;
29
- } ,
30
- RwLockMode :: Write =>
31
- if this. rwlock_is_locked ( lock) {
32
- this. rwlock_enqueue_and_block_writer ( lock, thread) ;
33
- } else {
34
- this. rwlock_writer_lock ( lock, thread) ;
35
- } ,
36
- }
37
-
38
- Ok ( ( ) )
39
- }
40
-
41
11
// Windows sync primitives are pointer sized.
42
12
// We only use the first 4 bytes for the id.
43
13
44
- fn srwlock_get_id (
45
- & mut self ,
46
- rwlock_op : & OpTy < ' tcx , Provenance > ,
47
- ) -> InterpResult < ' tcx , RwLockId > {
48
- let this = self . eval_context_mut ( ) ;
49
- this. rwlock_get_or_create_id ( rwlock_op, this. windows_ty_layout ( "SRWLOCK" ) , 0 )
50
- }
51
-
52
14
fn init_once_get_id (
53
15
& mut self ,
54
16
init_once_op : & OpTy < ' tcx , Provenance > ,
55
17
) -> InterpResult < ' tcx , InitOnceId > {
56
18
let this = self . eval_context_mut ( ) ;
57
19
this. init_once_get_or_create_id ( init_once_op, this. windows_ty_layout ( "INIT_ONCE" ) , 0 )
58
20
}
59
-
60
- fn condvar_get_id (
61
- & mut self ,
62
- condvar_op : & OpTy < ' tcx , Provenance > ,
63
- ) -> InterpResult < ' tcx , CondvarId > {
64
- let this = self . eval_context_mut ( ) ;
65
- this. condvar_get_or_create_id ( condvar_op, this. windows_ty_layout ( "CONDITION_VARIABLE" ) , 0 )
66
- }
67
21
}
68
22
69
23
impl < ' mir , ' tcx > EvalContextExt < ' mir , ' tcx > for crate :: MiriInterpCx < ' mir , ' tcx > { }
70
24
#[ allow( non_snake_case) ]
71
25
pub trait EvalContextExt < ' mir , ' tcx : ' mir > : crate :: MiriInterpCxExt < ' mir , ' tcx > {
72
- fn AcquireSRWLockExclusive ( & mut self , lock_op : & OpTy < ' tcx , Provenance > ) -> InterpResult < ' tcx > {
73
- let this = self . eval_context_mut ( ) ;
74
- let id = this. srwlock_get_id ( lock_op) ?;
75
- let active_thread = this. get_active_thread ( ) ;
76
-
77
- if this. rwlock_is_locked ( id) {
78
- // Note: this will deadlock if the lock is already locked by this
79
- // thread in any way.
80
- //
81
- // FIXME: Detect and report the deadlock proactively. (We currently
82
- // report the deadlock only when no thread can continue execution,
83
- // but we could detect that this lock is already locked and report
84
- // an error.)
85
- this. rwlock_enqueue_and_block_writer ( id, active_thread) ;
86
- } else {
87
- this. rwlock_writer_lock ( id, active_thread) ;
88
- }
89
-
90
- Ok ( ( ) )
91
- }
92
-
93
- fn TryAcquireSRWLockExclusive (
94
- & mut self ,
95
- lock_op : & OpTy < ' tcx , Provenance > ,
96
- ) -> InterpResult < ' tcx , Scalar < Provenance > > {
97
- let this = self . eval_context_mut ( ) ;
98
- let id = this. srwlock_get_id ( lock_op) ?;
99
- let active_thread = this. get_active_thread ( ) ;
100
-
101
- if this. rwlock_is_locked ( id) {
102
- // Lock is already held.
103
- Ok ( Scalar :: from_u8 ( 0 ) )
104
- } else {
105
- this. rwlock_writer_lock ( id, active_thread) ;
106
- Ok ( Scalar :: from_u8 ( 1 ) )
107
- }
108
- }
109
-
110
- fn ReleaseSRWLockExclusive ( & mut self , lock_op : & OpTy < ' tcx , Provenance > ) -> InterpResult < ' tcx > {
111
- let this = self . eval_context_mut ( ) ;
112
- let id = this. srwlock_get_id ( lock_op) ?;
113
- let active_thread = this. get_active_thread ( ) ;
114
-
115
- if !this. rwlock_writer_unlock ( id, active_thread) {
116
- // The docs do not say anything about this case, but it seems better to not allow it.
117
- throw_ub_format ! (
118
- "calling ReleaseSRWLockExclusive on an SRWLock that is not exclusively locked by the current thread"
119
- ) ;
120
- }
121
-
122
- Ok ( ( ) )
123
- }
124
-
125
- fn AcquireSRWLockShared ( & mut self , lock_op : & OpTy < ' tcx , Provenance > ) -> InterpResult < ' tcx > {
126
- let this = self . eval_context_mut ( ) ;
127
- let id = this. srwlock_get_id ( lock_op) ?;
128
- let active_thread = this. get_active_thread ( ) ;
129
-
130
- if this. rwlock_is_write_locked ( id) {
131
- this. rwlock_enqueue_and_block_reader ( id, active_thread) ;
132
- } else {
133
- this. rwlock_reader_lock ( id, active_thread) ;
134
- }
135
-
136
- Ok ( ( ) )
137
- }
138
-
139
- fn TryAcquireSRWLockShared (
140
- & mut self ,
141
- lock_op : & OpTy < ' tcx , Provenance > ,
142
- ) -> InterpResult < ' tcx , Scalar < Provenance > > {
143
- let this = self . eval_context_mut ( ) ;
144
- let id = this. srwlock_get_id ( lock_op) ?;
145
- let active_thread = this. get_active_thread ( ) ;
146
-
147
- if this. rwlock_is_write_locked ( id) {
148
- Ok ( Scalar :: from_u8 ( 0 ) )
149
- } else {
150
- this. rwlock_reader_lock ( id, active_thread) ;
151
- Ok ( Scalar :: from_u8 ( 1 ) )
152
- }
153
- }
154
-
155
- fn ReleaseSRWLockShared ( & mut self , lock_op : & OpTy < ' tcx , Provenance > ) -> InterpResult < ' tcx > {
156
- let this = self . eval_context_mut ( ) ;
157
- let id = this. srwlock_get_id ( lock_op) ?;
158
- let active_thread = this. get_active_thread ( ) ;
159
-
160
- if !this. rwlock_reader_unlock ( id, active_thread) {
161
- // The docs do not say anything about this case, but it seems better to not allow it.
162
- throw_ub_format ! (
163
- "calling ReleaseSRWLockShared on an SRWLock that is not locked by the current thread"
164
- ) ;
165
- }
166
-
167
- Ok ( ( ) )
168
- }
169
-
170
26
fn InitOnceBeginInitialize (
171
27
& mut self ,
172
28
init_once_op : & OpTy < ' tcx , Provenance > ,
@@ -399,131 +255,4 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
399
255
400
256
Ok ( ( ) )
401
257
}
402
-
403
- fn SleepConditionVariableSRW (
404
- & mut self ,
405
- condvar_op : & OpTy < ' tcx , Provenance > ,
406
- lock_op : & OpTy < ' tcx , Provenance > ,
407
- timeout_op : & OpTy < ' tcx , Provenance > ,
408
- flags_op : & OpTy < ' tcx , Provenance > ,
409
- dest : & MPlaceTy < ' tcx , Provenance > ,
410
- ) -> InterpResult < ' tcx , Scalar < Provenance > > {
411
- let this = self . eval_context_mut ( ) ;
412
-
413
- let condvar_id = this. condvar_get_id ( condvar_op) ?;
414
- let lock_id = this. srwlock_get_id ( lock_op) ?;
415
- let timeout_ms = this. read_scalar ( timeout_op) ?. to_u32 ( ) ?;
416
- let flags = this. read_scalar ( flags_op) ?. to_u32 ( ) ?;
417
-
418
- let timeout_time = if timeout_ms == this. eval_windows_u32 ( "c" , "INFINITE" ) {
419
- None
420
- } else {
421
- let duration = Duration :: from_millis ( timeout_ms. into ( ) ) ;
422
- Some ( this. machine . clock . now ( ) . checked_add ( duration) . unwrap ( ) )
423
- } ;
424
-
425
- let shared_mode = 0x1 ; // CONDITION_VARIABLE_LOCKMODE_SHARED is not in std
426
- let mode = if flags == 0 {
427
- RwLockMode :: Write
428
- } else if flags == shared_mode {
429
- RwLockMode :: Read
430
- } else {
431
- throw_unsup_format ! ( "unsupported `Flags` {flags} in `SleepConditionVariableSRW`" ) ;
432
- } ;
433
-
434
- let active_thread = this. get_active_thread ( ) ;
435
-
436
- let was_locked = match mode {
437
- RwLockMode :: Read => this. rwlock_reader_unlock ( lock_id, active_thread) ,
438
- RwLockMode :: Write => this. rwlock_writer_unlock ( lock_id, active_thread) ,
439
- } ;
440
-
441
- if !was_locked {
442
- throw_ub_format ! (
443
- "calling SleepConditionVariableSRW with an SRWLock that is not locked by the current thread"
444
- ) ;
445
- }
446
-
447
- this. block_thread ( active_thread) ;
448
- this. condvar_wait ( condvar_id, active_thread, CondvarLock :: RwLock { id : lock_id, mode } ) ;
449
-
450
- if let Some ( timeout_time) = timeout_time {
451
- struct Callback < ' tcx > {
452
- thread : ThreadId ,
453
- condvar_id : CondvarId ,
454
- lock_id : RwLockId ,
455
- mode : RwLockMode ,
456
- dest : MPlaceTy < ' tcx , Provenance > ,
457
- }
458
-
459
- impl < ' tcx > VisitProvenance for Callback < ' tcx > {
460
- fn visit_provenance ( & self , visit : & mut VisitWith < ' _ > ) {
461
- let Callback { thread : _, condvar_id : _, lock_id : _, mode : _, dest } = self ;
462
- dest. visit_provenance ( visit) ;
463
- }
464
- }
465
-
466
- impl < ' mir , ' tcx : ' mir > MachineCallback < ' mir , ' tcx > for Callback < ' tcx > {
467
- fn call ( & self , this : & mut MiriInterpCx < ' mir , ' tcx > ) -> InterpResult < ' tcx > {
468
- this. reacquire_cond_lock ( self . thread , self . lock_id , self . mode ) ?;
469
-
470
- this. condvar_remove_waiter ( self . condvar_id , self . thread ) ;
471
-
472
- let error_timeout = this. eval_windows ( "c" , "ERROR_TIMEOUT" ) ;
473
- this. set_last_error ( error_timeout) ?;
474
- this. write_scalar ( this. eval_windows ( "c" , "FALSE" ) , & self . dest ) ?;
475
- Ok ( ( ) )
476
- }
477
- }
478
-
479
- this. register_timeout_callback (
480
- active_thread,
481
- Time :: Monotonic ( timeout_time) ,
482
- Box :: new ( Callback {
483
- thread : active_thread,
484
- condvar_id,
485
- lock_id,
486
- mode,
487
- dest : dest. clone ( ) ,
488
- } ) ,
489
- ) ;
490
- }
491
-
492
- Ok ( this. eval_windows ( "c" , "TRUE" ) )
493
- }
494
-
495
- fn WakeConditionVariable ( & mut self , condvar_op : & OpTy < ' tcx , Provenance > ) -> InterpResult < ' tcx > {
496
- let this = self . eval_context_mut ( ) ;
497
- let condvar_id = this. condvar_get_id ( condvar_op) ?;
498
-
499
- if let Some ( ( thread, lock) ) = this. condvar_signal ( condvar_id) {
500
- if let CondvarLock :: RwLock { id, mode } = lock {
501
- this. reacquire_cond_lock ( thread, id, mode) ?;
502
- this. unregister_timeout_callback_if_exists ( thread) ;
503
- } else {
504
- panic ! ( "mutexes should not exist on windows" ) ;
505
- }
506
- }
507
-
508
- Ok ( ( ) )
509
- }
510
-
511
- fn WakeAllConditionVariable (
512
- & mut self ,
513
- condvar_op : & OpTy < ' tcx , Provenance > ,
514
- ) -> InterpResult < ' tcx > {
515
- let this = self . eval_context_mut ( ) ;
516
- let condvar_id = this. condvar_get_id ( condvar_op) ?;
517
-
518
- while let Some ( ( thread, lock) ) = this. condvar_signal ( condvar_id) {
519
- if let CondvarLock :: RwLock { id, mode } = lock {
520
- this. reacquire_cond_lock ( thread, id, mode) ?;
521
- this. unregister_timeout_callback_if_exists ( thread) ;
522
- } else {
523
- panic ! ( "mutexes should not exist on windows" ) ;
524
- }
525
- }
526
-
527
- Ok ( ( ) )
528
- }
529
258
}
0 commit comments