@@ -37,7 +37,12 @@ use alloc::{
37
37
vec:: Vec ,
38
38
} ;
39
39
use bit_field:: BitField ;
40
- use core:: { mem, slice, str:: FromStr , sync:: atomic:: Ordering } ;
40
+ use core:: {
41
+ mem,
42
+ slice,
43
+ str:: FromStr ,
44
+ sync:: atomic:: { AtomicU64 , Ordering } ,
45
+ } ;
41
46
use log:: { info, trace, warn} ;
42
47
use namespace:: { AmlName , Namespace , NamespaceLevelKind } ;
43
48
use object:: {
@@ -464,6 +469,91 @@ where
464
469
context. contribute_arg ( Argument :: Object ( result) ) ;
465
470
context. retire_op ( op) ;
466
471
}
472
+ Opcode :: Reset => {
473
+ let [ Argument :: Object ( sync_object) ] = & op. arguments [ ..] else {
474
+ panic ! ( ) ;
475
+ } ;
476
+ let sync_object = sync_object. clone ( ) . unwrap_reference ( ) ;
477
+
478
+ if let Object :: Event ( ref counter) = * sync_object {
479
+ counter. store ( 0 , Ordering :: Release ) ;
480
+ } else {
481
+ return Err ( AmlError :: InvalidOperationOnObject {
482
+ op : Operation :: ResetEvent ,
483
+ typ : sync_object. typ ( ) ,
484
+ } ) ;
485
+ }
486
+ }
487
+ Opcode :: Signal => {
488
+ let [ Argument :: Object ( sync_object) ] = & op. arguments [ ..] else {
489
+ panic ! ( ) ;
490
+ } ;
491
+ let sync_object = sync_object. clone ( ) . unwrap_reference ( ) ;
492
+
493
+ if let Object :: Event ( ref counter) = * sync_object {
494
+ counter. fetch_add ( 1 , Ordering :: AcqRel ) ;
495
+ } else {
496
+ return Err ( AmlError :: InvalidOperationOnObject {
497
+ op : Operation :: SignalEvent ,
498
+ typ : sync_object. typ ( ) ,
499
+ } ) ;
500
+ }
501
+ }
502
+ Opcode :: Wait => {
503
+ let [ Argument :: Object ( sync_object) , Argument :: Object ( timeout) ] = & op. arguments [ ..] else {
504
+ panic ! ( ) ;
505
+ } ;
506
+ let sync_object = sync_object. clone ( ) . unwrap_reference ( ) ;
507
+ let timeout = u64:: min ( timeout. as_integer ( ) ?, 0xffff ) ;
508
+
509
+ if let Object :: Event ( ref counter) = * sync_object {
510
+ /*
511
+ * `Wait` returns a non-zero value if a timeout occurs and the event
512
+ * was not signaled, and zero if it was. Timeout is specified in
513
+ * milliseconds, should relinquish processor control (we use
514
+ * `Handler::sleep` to do so) and a value of `0xffff` specifies that
515
+ * the operation should wait indefinitely.
516
+ */
517
+ let mut remaining_sleep = timeout;
518
+ let mut timed_out = true ;
519
+
520
+ ' signaled: while remaining_sleep > 0 {
521
+ loop {
522
+ /*
523
+ * Try to decrement the counter. If it's zero after a load, we
524
+ * haven't been signalled and should wait for a bit. If it's
525
+ * non-zero, we were signalled and should stop waiting.
526
+ */
527
+ let value = counter. load ( Ordering :: Acquire ) ;
528
+ if value == 0 {
529
+ break ;
530
+ }
531
+ if counter
532
+ . compare_exchange ( value, value - 1 , Ordering :: AcqRel , Ordering :: Acquire )
533
+ . is_ok ( )
534
+ {
535
+ timed_out = false ;
536
+ break ' signaled;
537
+ }
538
+ }
539
+
540
+ let to_sleep = u64:: min ( timeout, 10 ) ;
541
+ if timeout < 0xffff {
542
+ remaining_sleep -= to_sleep
543
+ }
544
+ self . handler . sleep ( to_sleep) ;
545
+ }
546
+
547
+ context. contribute_arg ( Argument :: Object (
548
+ Object :: Integer ( if timed_out { u64:: MAX } else { 0 } ) . wrap ( ) ,
549
+ ) ) ;
550
+ } else {
551
+ return Err ( AmlError :: InvalidOperationOnObject {
552
+ op : Operation :: WaitEvent ,
553
+ typ : sync_object. typ ( ) ,
554
+ } ) ;
555
+ }
556
+ }
467
557
Opcode :: FromBCD => self . do_from_bcd ( & mut context, op) ?,
468
558
Opcode :: ToBCD => self . do_to_bcd ( & mut context, op) ?,
469
559
Opcode :: Name => {
@@ -1150,17 +1240,17 @@ where
1150
1240
let name = context. namestring ( ) ?;
1151
1241
1152
1242
let name = name. resolve ( & context. current_scope ) ?;
1153
- self . namespace . lock ( ) . insert ( name, Object :: Event . wrap ( ) ) ?;
1243
+ self . namespace . lock ( ) . insert ( name, Object :: Event ( Arc :: new ( AtomicU64 :: new ( 0 ) ) ) . wrap ( ) ) ?;
1154
1244
}
1155
1245
Opcode :: LoadTable => todo ! ( ) ,
1156
1246
Opcode :: Load => todo ! ( ) ,
1157
1247
Opcode :: Stall => context. start_in_flight_op ( OpInFlight :: new ( Opcode :: Stall , 1 ) ) ,
1158
1248
Opcode :: Sleep => context. start_in_flight_op ( OpInFlight :: new ( Opcode :: Sleep , 1 ) ) ,
1159
1249
Opcode :: Acquire => context. start_in_flight_op ( OpInFlight :: new ( opcode, 1 ) ) ,
1160
1250
Opcode :: Release => context. start_in_flight_op ( OpInFlight :: new ( opcode, 1 ) ) ,
1161
- Opcode :: Signal => todo ! ( ) ,
1162
- Opcode :: Wait => todo ! ( ) ,
1163
- Opcode :: Reset => todo ! ( ) ,
1251
+ Opcode :: Signal => context . start_in_flight_op ( OpInFlight :: new ( opcode , 1 ) ) ,
1252
+ Opcode :: Wait => context . start_in_flight_op ( OpInFlight :: new ( opcode , 2 ) ) ,
1253
+ Opcode :: Reset => context . start_in_flight_op ( OpInFlight :: new ( opcode , 1 ) ) ,
1164
1254
Opcode :: Notify => todo ! ( ) ,
1165
1255
Opcode :: FromBCD | Opcode :: ToBCD => context. start_in_flight_op ( OpInFlight :: new ( opcode, 2 ) ) ,
1166
1256
Opcode :: Revision => {
@@ -1944,7 +2034,7 @@ where
1944
2034
Object :: Buffer ( bytes) => String :: from_utf8_lossy ( bytes) . into_owned ( ) ,
1945
2035
Object :: BufferField { .. } => "[Buffer Field]" . to_string ( ) ,
1946
2036
Object :: Device => "[Device]" . to_string ( ) ,
1947
- Object :: Event => "[Event]" . to_string ( ) ,
2037
+ Object :: Event ( _ ) => "[Event]" . to_string ( ) ,
1948
2038
Object :: FieldUnit ( _) => "[Field]" . to_string ( ) ,
1949
2039
Object :: Integer ( value) => value. to_string ( ) ,
1950
2040
Object :: Method { .. } | Object :: NativeMethod { .. } => "[Control Method]" . to_string ( ) ,
@@ -3033,6 +3123,10 @@ pub enum Operation {
3033
3123
LogicalOp ,
3034
3124
DecodePrt ,
3035
3125
ParseResource ,
3126
+
3127
+ ResetEvent ,
3128
+ SignalEvent ,
3129
+ WaitEvent ,
3036
3130
}
3037
3131
3038
3132
#[ derive( Clone , PartialEq , Debug ) ]
0 commit comments