@@ -20,8 +20,11 @@ use alloc::{
2020 vec:: Vec ,
2121} ;
2222use bit_field:: BitField ;
23- use core:: mem;
24- use log:: { info, trace} ;
23+ use core:: {
24+ mem,
25+ str:: FromStr ,
26+ } ;
27+ use log:: { info, trace, warn} ;
2528use namespace:: { AmlName , Namespace , NamespaceLevelKind } ;
2629use object:: { FieldFlags , FieldUnit , FieldUnitKind , MethodFlags , Object , ObjectType , ReferenceKind } ;
2730use op_region:: { OpRegion , RegionHandler , RegionSpace } ;
@@ -397,6 +400,24 @@ where
397400 let [ Argument :: Object ( usec) ] = & op. arguments[ ..] else { panic ! ( ) } ;
398401 self . handler. stall( usec. as_integer( ) ?) ;
399402 }
403+ Opcode :: Acquire => {
404+ let [ Argument :: Object ( mutex) ] = & op. arguments[ ..] else { panic ! ( ) } ;
405+ let Object :: Mutex { mutex, sync_level } = * * mutex else {
406+ Err ( AmlError :: InvalidOperationOnObject { op : Operation :: Acquire , typ : mutex. typ( ) } ) ?
407+ } ;
408+ let timeout = context. next_u16( ) ?;
409+
410+ // TODO: should we do something with the sync level??
411+ self . handler. acquire( mutex, timeout) ?;
412+ }
413+ Opcode :: Release => {
414+ let [ Argument :: Object ( mutex) ] = & op. arguments[ ..] else { panic ! ( ) } ;
415+ let Object :: Mutex { mutex, sync_level } = * * mutex else {
416+ Err ( AmlError :: InvalidOperationOnObject { op : Operation :: Release , typ : mutex. typ( ) } ) ?
417+ } ;
418+ // TODO: should we do something with the sync level??
419+ self . handler. release( mutex) ;
420+ }
400421 Opcode :: InternalMethodCall => {
401422 let [ Argument :: Object ( method) , Argument :: Namestring ( method_scope) ] = & op. arguments[ 0 ..2 ]
402423 else {
@@ -711,7 +732,8 @@ where
711732 let sync_level = context. next( ) ?;
712733
713734 let name = name. resolve( & context. current_scope) ?;
714- self . namespace. lock( ) . insert( name, Arc :: new( Object :: Mutex { sync_level } ) ) ?;
735+ let mutex = self . handler. create_mutex( ) ;
736+ self . namespace. lock( ) . insert( name, Arc :: new( Object :: Mutex { mutex, sync_level } ) ) ?;
715737 }
716738 Opcode :: Event => {
717739 let name = context. namestring( ) ?;
@@ -723,11 +745,11 @@ where
723745 Opcode :: Load => todo ! ( ) ,
724746 Opcode :: Stall => context. start_in_flight_op( OpInFlight :: new( Opcode :: Stall , 1 ) ) ,
725747 Opcode :: Sleep => context. start_in_flight_op( OpInFlight :: new( Opcode :: Sleep , 1 ) ) ,
726- Opcode :: Acquire => todo ! ( ) ,
748+ Opcode :: Acquire => context. start_in_flight_op( OpInFlight :: new( opcode, 1 ) ) ,
749+ Opcode :: Release => context. start_in_flight_op( OpInFlight :: new( opcode, 1 ) ) ,
727750 Opcode :: Signal => todo ! ( ) ,
728751 Opcode :: Wait => todo ! ( ) ,
729752 Opcode :: Reset => todo ! ( ) ,
730- Opcode :: Release => todo ! ( ) ,
731753 Opcode :: FromBCD | Opcode :: ToBCD => context. start_in_flight_op( OpInFlight :: new( opcode, 2 ) ) ,
732754 Opcode :: Revision => {
733755 context. contribute_arg( Argument :: Object ( Arc :: new( Object :: Integer ( INTERPRETER_REVISION ) ) ) ) ;
@@ -2219,13 +2241,25 @@ pub enum AmlError {
22192241 InvalidResourceDescriptor ,
22202242 UnexpectedResourceType ,
22212243
2244+ MutexAquireTimeout ,
2245+
22222246 PrtInvalidAddress ,
22232247 PrtInvalidPin ,
22242248 PrtInvalidGsi ,
22252249 PrtInvalidSource ,
22262250 PrtNoEntry ,
22272251}
22282252
2253+ /// A `Handle` is an opaque reference to an object that is managed by the user of this library.
2254+ /// They should be returned by the `create_*` methods on `Handler`, and are then used by methods to
2255+ /// refer to a specific object.
2256+ ///
2257+ /// The library will treat the value of a handle as entirely opaque. You may manage handles
2258+ /// however you wish, and the same value can be used to refer to objects of different types, if
2259+ /// desired.
2260+ #[ derive( Clone , Copy , PartialEq , Eq , PartialOrd , Ord , Debug , Hash ) ]
2261+ pub struct Handle ( pub u32 ) ;
2262+
22292263/// This trait represents the interface from the `Interpreter` to the hosting kernel, and allows
22302264/// AML to interact with the underlying hardware.
22312265///
@@ -2238,10 +2272,10 @@ pub trait Handler: Send + Sync {
22382272 fn read_u32 ( & self , address : usize ) -> u32 ;
22392273 fn read_u64 ( & self , address : usize ) -> u64 ;
22402274
2241- fn write_u8 ( & mut self , address : usize , value : u8 ) ;
2242- fn write_u16 ( & mut self , address : usize , value : u16 ) ;
2243- fn write_u32 ( & mut self , address : usize , value : u32 ) ;
2244- fn write_u64 ( & mut self , address : usize , value : u64 ) ;
2275+ fn write_u8 ( & self , address : usize , value : u8 ) ;
2276+ fn write_u16 ( & self , address : usize , value : u16 ) ;
2277+ fn write_u32 ( & self , address : usize , value : u32 ) ;
2278+ fn write_u64 ( & self , address : usize , value : u64 ) ;
22452279
22462280 fn read_io_u8 ( & self , port : u16 ) -> u8 ;
22472281 fn read_io_u16 ( & self , port : u16 ) -> u16 ;
@@ -2271,6 +2305,19 @@ pub trait Handler: Send + Sync {
22712305 /// time supported, and should relinquish the processor.
22722306 fn sleep ( & self , milliseconds : u64 ) ;
22732307
2308+ fn create_mutex ( & self ) -> Handle ;
2309+
2310+ /// Acquire the mutex referred to by the given handle. `timeout` is a millisecond timeout value
2311+ /// with the following meaning:
2312+ /// - `0` - try to acquire the mutex once, in a non-blocking manner. If the mutex cannot be
2313+ /// acquired immediately, return `Err(AmlError::MutexAquireTimeout)`
2314+ /// - `1-0xfffe` - try to acquire the mutex for at least `timeout` milliseconds.
2315+ /// - `0xffff` - try to acquire the mutex indefinitely. Should not return `MutexAquireTimeout`.
2316+ ///
2317+ /// AML mutexes are **reentrant** - that is, a thread may acquire the same mutex more than once
2318+ /// without causing a deadlock.
2319+ fn acquire ( & self , mutex : Handle , timeout : u16 ) -> Result < ( ) , AmlError > ;
2320+ fn release ( & self , mutex : Handle ) ;
22742321 fn breakpoint ( & self ) { }
22752322
22762323 fn handle_debug ( & self , _object : & Object ) { }
@@ -2295,10 +2342,10 @@ mod tests {
22952342 fn read_u16 ( & self , _address : usize ) -> u16 { 0 }
22962343 fn read_u32 ( & self , _address : usize ) -> u32 { 0 }
22972344 fn read_u64 ( & self , _address : usize ) -> u64 { 0 }
2298- fn write_u8 ( & mut self , _address : usize , _value : u8 ) { }
2299- fn write_u16 ( & mut self , _address : usize , _value : u16 ) { }
2300- fn write_u32 ( & mut self , _address : usize , _value : u32 ) { }
2301- fn write_u64 ( & mut self , _address : usize , _value : u64 ) { }
2345+ fn write_u8 ( & self , _address : usize , _value : u8 ) { }
2346+ fn write_u16 ( & self , _address : usize , _value : u16 ) { }
2347+ fn write_u32 ( & self , _address : usize , _value : u32 ) { }
2348+ fn write_u64 ( & self , _address : usize , _value : u64 ) { }
23022349 fn read_io_u8 ( & self , _port : u16 ) -> u8 { 0 }
23032350 fn read_io_u16 ( & self , _port : u16 ) -> u16 { 0 }
23042351 fn read_io_u32 ( & self , _port : u16 ) -> u32 { 0 }
@@ -2314,6 +2361,9 @@ mod tests {
23142361 fn nanos_since_boot ( & self ) -> u64 { 0 }
23152362 fn stall ( & self , _microseconds : u64 ) { }
23162363 fn sleep ( & self , _milliseconds : u64 ) { }
2364+ fn create_mutex ( & self ) -> Handle { Handle ( 0 ) }
2365+ fn acquire ( & self , _mutex : Handle , _timeout : u16 ) -> Result < ( ) , AmlError > { Ok ( ( ) ) }
2366+ fn release ( & self , _mutex : Handle ) { }
23172367 }
23182368
23192369 #[ test]
0 commit comments