@@ -20,8 +20,11 @@ use alloc::{
20
20
vec:: Vec ,
21
21
} ;
22
22
use 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} ;
25
28
use namespace:: { AmlName , Namespace , NamespaceLevelKind } ;
26
29
use object:: { FieldFlags , FieldUnit , FieldUnitKind , MethodFlags , Object , ObjectType , ReferenceKind } ;
27
30
use op_region:: { OpRegion , RegionHandler , RegionSpace } ;
@@ -397,6 +400,24 @@ where
397
400
let [ Argument :: Object ( usec) ] = & op. arguments[ ..] else { panic ! ( ) } ;
398
401
self . handler. stall( usec. as_integer( ) ?) ;
399
402
}
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
+ }
400
421
Opcode :: InternalMethodCall => {
401
422
let [ Argument :: Object ( method) , Argument :: Namestring ( method_scope) ] = & op. arguments[ 0 ..2 ]
402
423
else {
@@ -711,7 +732,8 @@ where
711
732
let sync_level = context. next( ) ?;
712
733
713
734
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 } ) ) ?;
715
737
}
716
738
Opcode :: Event => {
717
739
let name = context. namestring( ) ?;
@@ -723,11 +745,11 @@ where
723
745
Opcode :: Load => todo ! ( ) ,
724
746
Opcode :: Stall => context. start_in_flight_op( OpInFlight :: new( Opcode :: Stall , 1 ) ) ,
725
747
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 ) ) ,
727
750
Opcode :: Signal => todo ! ( ) ,
728
751
Opcode :: Wait => todo ! ( ) ,
729
752
Opcode :: Reset => todo ! ( ) ,
730
- Opcode :: Release => todo ! ( ) ,
731
753
Opcode :: FromBCD | Opcode :: ToBCD => context. start_in_flight_op( OpInFlight :: new( opcode, 2 ) ) ,
732
754
Opcode :: Revision => {
733
755
context. contribute_arg( Argument :: Object ( Arc :: new( Object :: Integer ( INTERPRETER_REVISION ) ) ) ) ;
@@ -2219,13 +2241,25 @@ pub enum AmlError {
2219
2241
InvalidResourceDescriptor ,
2220
2242
UnexpectedResourceType ,
2221
2243
2244
+ MutexAquireTimeout ,
2245
+
2222
2246
PrtInvalidAddress ,
2223
2247
PrtInvalidPin ,
2224
2248
PrtInvalidGsi ,
2225
2249
PrtInvalidSource ,
2226
2250
PrtNoEntry ,
2227
2251
}
2228
2252
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
+
2229
2263
/// This trait represents the interface from the `Interpreter` to the hosting kernel, and allows
2230
2264
/// AML to interact with the underlying hardware.
2231
2265
///
@@ -2238,10 +2272,10 @@ pub trait Handler: Send + Sync {
2238
2272
fn read_u32 ( & self , address : usize ) -> u32 ;
2239
2273
fn read_u64 ( & self , address : usize ) -> u64 ;
2240
2274
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 ) ;
2245
2279
2246
2280
fn read_io_u8 ( & self , port : u16 ) -> u8 ;
2247
2281
fn read_io_u16 ( & self , port : u16 ) -> u16 ;
@@ -2271,6 +2305,19 @@ pub trait Handler: Send + Sync {
2271
2305
/// time supported, and should relinquish the processor.
2272
2306
fn sleep ( & self , milliseconds : u64 ) ;
2273
2307
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 ) ;
2274
2321
fn breakpoint ( & self ) { }
2275
2322
2276
2323
fn handle_debug ( & self , _object : & Object ) { }
@@ -2295,10 +2342,10 @@ mod tests {
2295
2342
fn read_u16 ( & self , _address : usize ) -> u16 { 0 }
2296
2343
fn read_u32 ( & self , _address : usize ) -> u32 { 0 }
2297
2344
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 ) { }
2302
2349
fn read_io_u8 ( & self , _port : u16 ) -> u8 { 0 }
2303
2350
fn read_io_u16 ( & self , _port : u16 ) -> u16 { 0 }
2304
2351
fn read_io_u32 ( & self , _port : u16 ) -> u32 { 0 }
@@ -2314,6 +2361,9 @@ mod tests {
2314
2361
fn nanos_since_boot ( & self ) -> u64 { 0 }
2315
2362
fn stall ( & self , _microseconds : u64 ) { }
2316
2363
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 ) { }
2317
2367
}
2318
2368
2319
2369
#[ test]
0 commit comments