@@ -37,7 +37,12 @@ use alloc::{
3737 vec:: Vec ,
3838} ;
3939use 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+ } ;
4146use log:: { info, trace, warn} ;
4247use namespace:: { AmlName , Namespace , NamespaceLevelKind } ;
4348use object:: {
@@ -464,6 +469,91 @@ where
464469 context. contribute_arg ( Argument :: Object ( result) ) ;
465470 context. retire_op ( op) ;
466471 }
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+ }
467557 Opcode :: FromBCD => self . do_from_bcd ( & mut context, op) ?,
468558 Opcode :: ToBCD => self . do_to_bcd ( & mut context, op) ?,
469559 Opcode :: Name => {
@@ -1150,17 +1240,17 @@ where
11501240 let name = context. namestring ( ) ?;
11511241
11521242 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 ( ) ) ?;
11541244 }
11551245 Opcode :: LoadTable => todo ! ( ) ,
11561246 Opcode :: Load => todo ! ( ) ,
11571247 Opcode :: Stall => context. start_in_flight_op ( OpInFlight :: new ( Opcode :: Stall , 1 ) ) ,
11581248 Opcode :: Sleep => context. start_in_flight_op ( OpInFlight :: new ( Opcode :: Sleep , 1 ) ) ,
11591249 Opcode :: Acquire => context. start_in_flight_op ( OpInFlight :: new ( opcode, 1 ) ) ,
11601250 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 ) ) ,
11641254 Opcode :: Notify => todo ! ( ) ,
11651255 Opcode :: FromBCD | Opcode :: ToBCD => context. start_in_flight_op ( OpInFlight :: new ( opcode, 2 ) ) ,
11661256 Opcode :: Revision => {
@@ -1944,7 +2034,7 @@ where
19442034 Object :: Buffer ( bytes) => String :: from_utf8_lossy ( bytes) . into_owned ( ) ,
19452035 Object :: BufferField { .. } => "[Buffer Field]" . to_string ( ) ,
19462036 Object :: Device => "[Device]" . to_string ( ) ,
1947- Object :: Event => "[Event]" . to_string ( ) ,
2037+ Object :: Event ( _ ) => "[Event]" . to_string ( ) ,
19482038 Object :: FieldUnit ( _) => "[Field]" . to_string ( ) ,
19492039 Object :: Integer ( value) => value. to_string ( ) ,
19502040 Object :: Method { .. } | Object :: NativeMethod { .. } => "[Control Method]" . to_string ( ) ,
@@ -3033,6 +3123,10 @@ pub enum Operation {
30333123 LogicalOp ,
30343124 DecodePrt ,
30353125 ParseResource ,
3126+
3127+ ResetEvent ,
3128+ SignalEvent ,
3129+ WaitEvent ,
30363130}
30373131
30383132#[ derive( Clone , PartialEq , Debug ) ]
0 commit comments