@@ -3,170 +3,26 @@ use std::time::Duration;
33use rustc_target:: abi:: Size ;
44
55use crate :: concurrency:: init_once:: InitOnceStatus ;
6- use crate :: concurrency:: sync:: { CondvarLock , RwLockMode } ;
76use crate :: concurrency:: thread:: MachineCallback ;
87use crate :: * ;
98
109impl < ' mir , ' tcx > EvalContextExtPriv < ' mir , ' tcx > for crate :: MiriInterpCx < ' mir , ' tcx > { }
1110trait 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-
4111 // Windows sync primitives are pointer sized.
4212 // We only use the first 4 bytes for the id.
4313
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-
5214 fn init_once_get_id (
5315 & mut self ,
5416 init_once_op : & OpTy < ' tcx , Provenance > ,
5517 ) -> InterpResult < ' tcx , InitOnceId > {
5618 let this = self . eval_context_mut ( ) ;
5719 this. init_once_get_or_create_id ( init_once_op, this. windows_ty_layout ( "INIT_ONCE" ) , 0 )
5820 }
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- }
6721}
6822
6923impl < ' mir , ' tcx > EvalContextExt < ' mir , ' tcx > for crate :: MiriInterpCx < ' mir , ' tcx > { }
7024#[ allow( non_snake_case) ]
7125pub 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-
17026 fn InitOnceBeginInitialize (
17127 & mut self ,
17228 init_once_op : & OpTy < ' tcx , Provenance > ,
@@ -399,131 +255,4 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
399255
400256 Ok ( ( ) )
401257 }
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- }
529258}
0 commit comments