From ab9874687996a14973f175a1fc714ee2ba37dacd Mon Sep 17 00:00:00 2001 From: Connor Wood Date: Sat, 29 Jul 2017 12:39:08 +0300 Subject: [PATCH] Moved lock manipulation into context --- src/acpi/aml/parser.rs | 114 +++++++++++++++++++++++++++++++++++- src/acpi/aml/type1opcode.rs | 31 +--------- src/acpi/aml/type2opcode.rs | 56 +++++------------- 3 files changed, 130 insertions(+), 71 deletions(-) diff --git a/src/acpi/aml/parser.rs b/src/acpi/aml/parser.rs index 758dd17..e8a1865 100644 --- a/src/acpi/aml/parser.rs +++ b/src/acpi/aml/parser.rs @@ -30,7 +30,8 @@ pub struct AmlExecutionContext { pub arg_vars: [AmlValue; 8], pub state: ExecutionState, pub namespace_delta: Vec, - pub ctx_id: u64 + pub ctx_id: u64, + pub sync_level: u8 } impl AmlExecutionContext { @@ -60,9 +61,118 @@ impl AmlExecutionContext { AmlValue::Uninitialized], state: ExecutionState::EXECUTING, namespace_delta: vec!(), - ctx_id: id + ctx_id: id, + sync_level: 0 } } + + pub fn release_mutex(&mut self, mutex_ptr: AmlValue) -> Result<(), AmlError> { + let id = self.ctx_id; + + let mut namespace_ptr = self.prelock(); + let mut namespace = match *namespace_ptr { + Some(ref mut n) => n, + None => return Err(AmlError::AmlHardFatal) + }; + + let mutex_idx = match mutex_ptr { + AmlValue::String(ref s) => s.clone(), + AmlValue::ObjectReference(ref o) => match *o { + ObjectReference::Object(ref s) => s.clone(), + _ => return Err(AmlError::AmlValueError) + }, + _ => return Err(AmlError::AmlValueError) + }; + + let mutex = match namespace.get(&mutex_idx) { + Some(s) => s.clone(), + None => return Err(AmlError::AmlValueError) + }; + + match mutex { + AmlValue::Mutex((sync_level, owner)) => { + if let Some(o) = owner { + if o == id { + if sync_level == self.sync_level { + namespace.insert(mutex_idx, AmlValue::Mutex((sync_level, None))); + return Ok(()); + } else { + return Err(AmlError::AmlValueError); + } + } else { + return Err(AmlError::AmlHardFatal); + } + } + }, + AmlValue::OperationRegion(ref region) => { + if let Some(o) = region.accessed_by { + if o == id { + let mut new_region = region.clone(); + new_region.accessed_by = None; + + namespace.insert(mutex_idx, AmlValue::OperationRegion(new_region)); + return Ok(()); + } else { + return Err(AmlError::AmlHardFatal); + } + } + }, + _ => return Err(AmlError::AmlValueError) + } + + Ok(()) + } + + pub fn acquire_mutex(&mut self, mutex_ptr: AmlValue, timeout: u16) -> Result { + let id = self.ctx_id; + + + let mut namespace_ptr = self.prelock(); + let mut namespace = match *namespace_ptr { + Some(ref mut n) => n, + None => return Err(AmlError::AmlHardFatal) + }; + let mutex_idx = match mutex_ptr { + AmlValue::String(ref s) => s.clone(), + AmlValue::ObjectReference(ref o) => match *o { + ObjectReference::Object(ref s) => s.clone(), + _ => return Err(AmlError::AmlValueError) + }, + _ => return Err(AmlError::AmlValueError) + }; + + let mutex = match namespace.get(&mutex_idx) { + Some(s) => s.clone(), + None => return Err(AmlError::AmlValueError) + }; + + match mutex { + AmlValue::Mutex((sync_level, owner)) => { + if owner == None { + if sync_level < self.sync_level { + return Err(AmlError::AmlValueError); + } + + namespace.insert(mutex_idx, AmlValue::Mutex((sync_level, Some(id)))); + self.sync_level = sync_level; + + return Ok(true); + } + }, + AmlValue::OperationRegion(ref o) => { + if o.accessed_by == None { + let mut new_region = o.clone(); + new_region.accessed_by = Some(id); + + namespace.insert(mutex_idx, AmlValue::OperationRegion(new_region)); + return Ok(true); + } + }, + _ => return Err(AmlError::AmlValueError) + } + + Ok(false) + } pub fn add_to_namespace(&mut self, name: String, value: AmlValue) -> Result<(), AmlError> { let mut namespace = ACPI_TABLE.namespace.write(); diff --git a/src/acpi/aml/type1opcode.rs b/src/acpi/aml/type1opcode.rs index 9d74a5f..c277b32 100644 --- a/src/acpi/aml/type1opcode.rs +++ b/src/acpi/aml/type1opcode.rs @@ -202,35 +202,8 @@ fn parse_def_release(data: &[u8], parser_opcode_extended!(data, 0x27); let obj = parse_super_name(&data[2..], ctx)?; - - let mut namespace = ctx.prelock(); - let mutex = ctx.get(obj.val.clone()); - - match mutex { - AmlValue::Mutex((sync_level, owner)) => { - if let Some(o) = owner { - if o == ctx.ctx_id { - ctx.modify(obj.val.clone(), AmlValue::Mutex((sync_level, None))); - } else { - return Err(AmlError::AmlHardFatal); - } - } - }, - AmlValue::OperationRegion(ref region) => { - if let Some(o) = region.accessed_by { - if o == ctx.ctx_id { - let mut new_region = region.clone(); - new_region.accessed_by = None; - - ctx.modify(obj.val.clone(), AmlValue::OperationRegion(new_region)); - } else { - return Err(AmlError::AmlHardFatal); - } - } - }, - _ => return Err(AmlError::AmlValueError) - } - + ctx.release_mutex(obj.val); + Ok(AmlParseType { val: AmlValue::None, len: 2 + obj.len diff --git a/src/acpi/aml/type2opcode.rs b/src/acpi/aml/type2opcode.rs index e2880dd..2ff6017 100644 --- a/src/acpi/aml/type2opcode.rs +++ b/src/acpi/aml/type2opcode.rs @@ -328,50 +328,26 @@ fn parse_def_acquire(data: &[u8], let (seconds, nanoseconds) = monotonic(); let starting_time_ns = nanoseconds + (seconds * 1000000000); - let id = ctx.ctx_id; - loop { - { - let mut namespace = ctx.prelock(); - let mutex = ctx.get(obj.val.clone()); - - match mutex { - AmlValue::Mutex((sync_level, owner)) => { - if owner == None { - ctx.modify(obj.val.clone(), AmlValue::Mutex((sync_level, Some(id)))); - return Ok(AmlParseType { - val: AmlValue::Integer(0), - len: 4 + obj.len - }); - } - }, - AmlValue::OperationRegion(ref o) => { - if o.accessed_by == None { - let mut new_region = o.clone(); - new_region.accessed_by = Some(id); - - ctx.modify(obj.val.clone(), AmlValue::OperationRegion(new_region)); - return Ok(AmlParseType { - val: AmlValue::Integer(0), - len: 4 + obj.len - }); - } - }, - _ => return Err(AmlError::AmlValueError) - } - } - - if timeout == 0xFFFF { - // TODO: Brief sleep here - } else { - let (seconds, nanoseconds) = monotonic(); - let current_time_ns = nanoseconds + (seconds * 1000000000); - - if current_time_ns - starting_time_ns > timeout as u64 * 1000000 { + match ctx.acquire_mutex(obj.val.clone(), timeout) { + Err(e) => return Err(e), + Ok(b) => if b { return Ok(AmlParseType { - val: AmlValue::Integer(1), + val: AmlValue::Integer(0), len: 4 + obj.len }); + } else if timeout == 0xFFFF { + // TODO: Brief sleep here + } else { + let (seconds, nanoseconds) = monotonic(); + let current_time_ns = nanoseconds + (seconds * 1000000000); + + if current_time_ns - starting_time_ns > timeout as u64 * 1000000 { + return Ok(AmlParseType { + val: AmlValue::Integer(1), + len: 4 + obj.len + }); + } } } }