@@ -464,6 +464,91 @@ where
464
464
context. contribute_arg ( Argument :: Object ( result) ) ;
465
465
context. retire_op ( op) ;
466
466
}
467
+ Opcode :: Reset => {
468
+ let [ Argument :: Object ( sync_object) ] = & op. arguments [ ..] else {
469
+ panic ! ( ) ;
470
+ } ;
471
+ let sync_object = sync_object. clone ( ) . unwrap_reference ( ) ;
472
+
473
+ if let Object :: Event ( ref counter) = * sync_object {
474
+ counter. store ( 0 , Ordering :: Release ) ;
475
+ } else {
476
+ return Err ( AmlError :: InvalidOperationOnObject {
477
+ op : Operation :: ResetEvent ,
478
+ typ : sync_object. typ ( ) ,
479
+ } ) ;
480
+ }
481
+ }
482
+ Opcode :: Signal => {
483
+ let [ Argument :: Object ( sync_object) ] = & op. arguments [ ..] else {
484
+ panic ! ( ) ;
485
+ } ;
486
+ let sync_object = sync_object. clone ( ) . unwrap_reference ( ) ;
487
+
488
+ if let Object :: Event ( ref counter) = * sync_object {
489
+ counter. fetch_add ( 1 , Ordering :: AcqRel ) ;
490
+ } else {
491
+ return Err ( AmlError :: InvalidOperationOnObject {
492
+ op : Operation :: SignalEvent ,
493
+ typ : sync_object. typ ( ) ,
494
+ } ) ;
495
+ }
496
+ }
497
+ Opcode :: Wait => {
498
+ let [ Argument :: Object ( sync_object) , Argument :: Object ( timeout) ] = & op. arguments [ ..] else {
499
+ panic ! ( ) ;
500
+ } ;
501
+ let sync_object = sync_object. clone ( ) . unwrap_reference ( ) ;
502
+ let timeout = u64:: min ( timeout. as_integer ( ) ?, 0xffff ) ;
503
+
504
+ if let Object :: Event ( ref counter) = * sync_object {
505
+ /*
506
+ * `Wait` returns a non-zero value if a timeout occurs and the event
507
+ * was not signaled, and zero if it was. Timeout is specified in
508
+ * milliseconds, should relinquish processor control (we use
509
+ * `Handler::sleep` to do so) and a value of `0xffff` specifies that
510
+ * the operation should wait indefinitely.
511
+ */
512
+ let mut remaining_sleep = timeout;
513
+ let mut timed_out = true ;
514
+
515
+ ' signaled: while remaining_sleep > 0 {
516
+ loop {
517
+ /*
518
+ * Try to decrement the counter. If it's zero after a load, we
519
+ * haven't been signalled and should wait for a bit. If it's
520
+ * non-zero, we were signalled and should stop waiting.
521
+ */
522
+ let value = counter. load ( Ordering :: Acquire ) ;
523
+ if value == 0 {
524
+ break ;
525
+ }
526
+ if counter
527
+ . compare_exchange ( value, value - 1 , Ordering :: AcqRel , Ordering :: Acquire )
528
+ . is_ok ( )
529
+ {
530
+ timed_out = false ;
531
+ break ' signaled;
532
+ }
533
+ }
534
+
535
+ let to_sleep = u64:: min ( timeout, 10 ) ;
536
+ if timeout < 0xffff {
537
+ remaining_sleep -= to_sleep
538
+ }
539
+ self . handler . sleep ( to_sleep) ;
540
+ }
541
+
542
+ context. contribute_arg ( Argument :: Object (
543
+ Object :: Integer ( if timed_out { u64:: MAX } else { 0 } ) . wrap ( ) ,
544
+ ) ) ;
545
+ } else {
546
+ return Err ( AmlError :: InvalidOperationOnObject {
547
+ op : Operation :: WaitEvent ,
548
+ typ : sync_object. typ ( ) ,
549
+ } ) ;
550
+ }
551
+ }
467
552
Opcode :: FromBCD => self . do_from_bcd ( & mut context, op) ?,
468
553
Opcode :: ToBCD => self . do_to_bcd ( & mut context, op) ?,
469
554
Opcode :: Name => {
@@ -1158,9 +1243,9 @@ where
1158
1243
Opcode :: Sleep => context. start_in_flight_op ( OpInFlight :: new ( Opcode :: Sleep , 1 ) ) ,
1159
1244
Opcode :: Acquire => context. start_in_flight_op ( OpInFlight :: new ( opcode, 1 ) ) ,
1160
1245
Opcode :: Release => context. start_in_flight_op ( OpInFlight :: new ( opcode, 1 ) ) ,
1161
- Opcode :: Signal => todo ! ( ) ,
1162
- Opcode :: Wait => todo ! ( ) ,
1163
- Opcode :: Reset => todo ! ( ) ,
1246
+ Opcode :: Signal => context . start_in_flight_op ( OpInFlight :: new ( opcode , 1 ) ) ,
1247
+ Opcode :: Wait => context . start_in_flight_op ( OpInFlight :: new ( opcode , 2 ) ) ,
1248
+ Opcode :: Reset => context . start_in_flight_op ( OpInFlight :: new ( opcode , 1 ) ) ,
1164
1249
Opcode :: Notify => todo ! ( ) ,
1165
1250
Opcode :: FromBCD | Opcode :: ToBCD => context. start_in_flight_op ( OpInFlight :: new ( opcode, 2 ) ) ,
1166
1251
Opcode :: Revision => {
@@ -3033,6 +3118,10 @@ pub enum Operation {
3033
3118
LogicalOp ,
3034
3119
DecodePrt ,
3035
3120
ParseResource ,
3121
+
3122
+ ResetEvent ,
3123
+ SignalEvent ,
3124
+ WaitEvent ,
3036
3125
}
3037
3126
3038
3127
#[ derive( Clone , PartialEq , Debug ) ]
0 commit comments